Setting the date and time of the clock-en
Setting the date and time of the clock
One of the necessary functions of the watch is the ability for the user to set the date and time. We organize the control of this function by means of an encoder.
To control the encoder, connect the library:
#include // Arduino library for working with the encoder
SimpleRotary rotary(7, 8, 4); // 7, 8, 4 — pins to which we connect the encoder
Let’s set the value of two variables:
s_mode = 0; // variable defining the device mode «time display»
a_mode = 0; // a variable that determines the transfer of the device to the time setting mode
In the time display mode, both variables are zero.
To enter the clock device into the date and time setting mode, you need to press the encoder, after which we assign the value «1» to the s_mode variable and proceed to the date and time setting routine «set_param»:
int rBtn = rotary.push();
if ( rBtn == 1 )
{
if (s_mode == 0) {
s_mode = 1;
set_param();
}
}
Now let’s look at the subroutine that controls the clock device mode «setting the date and time»:
void set_param()
{
// first, we will set the initial values of the variables, which will contain the new date and time values. In the future, the values of these variables will be changed to new ones by the user himself, by controlling the encoder:
byte Set_Hours = time.Hours; // the initial value of the variable «hour»
byte Set_minutes = time.minutes; // the initial value of the variable «minutes»
byte Set_day = time.day; // the initial value of the variable «day»
byte Set_month = time.month; // the initial value of the «month» variable
byte Set_year = time.year; // the initial value of the variable «year»
byte ned; // the value of the «day of the week» variable will be calculated during the date setting
Immediately after entering the clock device into the setting mode (by pressing the encoder), we will begin adjusting the date and time in the following sequence:
adjusting the «year» value;
adjusting the «month» value;
adjusting the «day» value;
calculating the day of the week;
adjusting the «hour» value;
adjusting the «minute» value.
correction of the «stroke correction» value.
After each click on the encoder, we will display the corrected value on the clock display: «year», «month», «day», «hour», minutes», «stroke correction». We will change the value itself by rotating the encoder handle. With the subsequent click, we go to the next corrected value. After setting the «stroke correction» value and pressing the encoder, we set the new date and time and switch the clock device from the date and time setting mode to the «time display» mode.
The first corrected value is «year».
In the setting mode, the corrected parameter will be displayed on the clock display, which consists of two components: 1. the abbreviated designation of the parameter (for example, when adjusting the year «Y:») and 2. the parameter value itself (for example, «22»). The «change_param» subroutine will be responsible for displaying the corrected parameters on the display, to the input of which we pass the string variable c_par:
// subroutine change_param:
void change_param(String c_par) {
matrix.fillScreen(LOW);
int y = (matrix.height() — 8) / 2; // Centering the text Vertically
for ( int i = 0 ; i < c_par.length(); i++ ) {matrix.drawChar(i * (width), y, c_par[i], HIGH, LOW, 1); }
matrix.write();} // Output to the display
//
We continue to study the time and date setting routine. The first parameter that will be displayed for adjustment is «Year».
c_par = utf8rus(«Г:») + String (Set_year);// we set the value of the variable c_par, which at the initial moment will look like «Y: 22″
change_param(c_par); // we display the corrected value of the year on the display
Let’s organize a loop that will be executed until the value of the variable «s_mode» is set to «0».
while (s_mode != 0) {
int rDir = rotary.rotate(); // variable controlling the rotation of the encoder
int rBtn = rotary.push(); // variable controlling the click on the encoder
// in case of a short press on the encoder
if ( rBtn == 1 )
{
if (s_mode == 6) { // if the variable «s_mode» was equal to «6», then all parameters are set. In this case, we assign the value «0» to the variable «s_mode» (to switch the clock device to the time display mode) and enter new date and time values into the device:
s_mode = 0;
time.Hours = Set_Hours;
time.minutes = Set_minutes;
time.day = Set_day;
time.month = Set_month;
time.year = Set_year;
time.weekday = ned;
time.settime(0, time.minutes, time.Hours, time.day, time.month, time.year, time.weekday);
time.gettime(«d-m-Y, H:i:s, D»);
// we write the date and hour of the last time adjustment, as well as the value of the daily adjustment of the clock, into the non-volatile memory of the clock device:
dd2 = time.day;
mm2 = time.month;
gg2 = time.year;
hr2 = time.Hours;
delay(100);
EEPROM.write(0, Corr_time);
EEPROM.write(1, dd2);
EEPROM.write(2, mm2);
EEPROM.write(3, gg2);
EEPROM.write(4, hr2);
}
else if (s_mode == 5) { // if the encoder is pressed when adjusting the value of «minutes», we proceed to adjust the value of «correction of the passage of time»
s_mode = 6;
}
else if (s_mode == 4) {// if the encoder is pressed when adjusting the «hour» value, we proceed to adjusting the «minute» value
s_mode = 5;
}
else if (s_mode == 3) {// if the encoder is pressed when adjusting the «day» value, we proceed to adjusting the «hour» value
s_mode = 4;
}
else if (s_mode == 2) {// if the encoder is pressed when adjusting the «month» value, we proceed to adjusting the «day» value
s_mode = 3;
}
else if (s_mode == 1) {// if the encoder is pressed when adjusting the «year» value, we proceed to adjusting the «month» value
s_mode = 2;
}
}
// setting a string variable containing the corrected value:
if (s_mode == 1) {
c_par = «Y:» + String (Set_year);
}
else if (s_mode == 2) {
c_par = «M:» + String (Set_month);
}
else if (s_mode == 3) {
c_par = «D:» + String (Set_day);
}
else if (s_mode == 4) {
c_par = «H:»)+ String (Set_Hours);
}
else if (s_mode == 5) {
c_par = «M:» + String (Set_minutes);
}
else if (s_mode == 6) {
c_par = «Kp» + String (int(Corr_time));
}
change_param(c_par); // we display the corrected value
/////////////////////////
//we determine that there was a rotation of the encoder
if ( rDir != 0 ) {
// CW
if (s_mode == 1) { //with each rotation of the encoder, we will increase or decrease (depending on the direction of rotation of the encoder) the initial value of the year. If you increase the value of the year to «51», reset the value of the year to «20». When reducing the year value to «19», reset the year value to «50».
if ( rDir == 1 ) {
if (Set_year > 50)
{
Set_year = 20;
}
else
{
Set_year ++;
}
}
if ( rDir == 2 ) {
if (Set_year < 20)
{
Set_year = 50;
}
else
{
Set_year —;
}
}
delay(100);
}
else if (s_mode == 2) { //with each rotation of the encoder, we will increase or decrease (depending on the direction of rotation of the encoder) the initial value of the month. When increasing the month value to «12», reset the month value to «1». When reducing the month value to «1», reset the month value to «12».
if ( rDir == 1 ) {
if (Set_month == 12)
{
Set_month = 1;
}
else
{
Set_month ++;
}
}
if ( rDir == 2 ) {
if (Set_month == 1)
{
Set_month = 12;
}
else
{
Set_month —;
}
}
delay(100);
}
else
if (s_mode == 3) {//It should be taken into account that each month has a different number of days. Including in February, there may be 28 and 29 days. Therefore, we will determine the sign of a leap year and take into account the previously set month:
if (Set_month == 2) {
LeapYear = 0; //first you need to determine whether the current year is a leap year or not
if ( (((2000 + int(Set_year)) % 4) == 0) & (((2000 + int(Set_year)) % 100) != 0) || (((2000 + int(Set_year)) % 400) == 0) ) {
LeapYear = 1; // a sign of a leap year
}
else {
LeapYear = 0;// a sign of a non-leap year
}
}
if ( rDir == 1 ) { //with each rotation of the encoder, we will increase or decrease (depending on the direction of rotation of the encoder) the initial value of the day. If we increase the value of the day to the last one in this month, we will reset the value of the day to «1». When reducing the value of the month to «1», we reset the value of the day to the last value in this month.
if ((Set_day == 31) & (Set_month == 1 || Set_month == 3 || Set_month == 5 || Set_month == 7 || Set_month == 8 || Set_month == 10 || Set_month == 12)) {
Set_day = 1;
}
else if ((Set_day == 30) & (Set_month == 4 || Set_month == 6 || Set_month == 9 || Set_month == 11)) {
Set_day = 1;
}
else if ((Set_day == 29) & (Set_month == 2)) {
Set_day = 1;
}
else if ((Set_day == 28) & (Set_month == 2) & (LeapYear == 0) ) {
Set_day = 1;
}
else
{
Set_day ++;
}
}
if ( rDir == 2 ) {
if (Set_day == 1)
{
if ((Set_month == 1 || Set_month == 3 || Set_month == 5 || Set_month == 7 || Set_month == 8 || Set_month == 10 || Set_month == 12)) {
Set_day = 31;
}
else if ((Set_month == 4 || Set_month == 6 || Set_month == 9 || Set_month == 11)) {
Set_day = 30;
}
else if (Set_month == 2) {
Set_day = 29;
}
else if ((Set_month == 2) & (LeapYear == 0) ) {
Set_day = 28;
}
}
else
{
Set_day —;
}
}
//In this part of the subroutine, the calculation of the day of the week:
byte a = f_div((14 — int(Set_month)), 12);
unsigned int y = (2000 + int(Set_year)) — a;
byte m = int(Set_month) + 12 * a — 2;
unsigned int y4 = f_div(y, 4);
byte y100 = f_div(y, 100);
byte y400 = f_div(y, 400);
byte x = f_div(31 * m, 12);
ned = (int(Set_day) + y + y4 — y100 + y400 + x) % 7; //the result in the «ned» variable
delay(100);
}
//////////////////
unsigned int f_div(unsigned int x, unsigned int y) {
unsigned int result;
result = (x — (x % y)) / y;
return result;
}
///////////////////
else if (s_mode == 4) {//with each rotation of the encoder, we will increase or decrease (depending on the direction of rotation of the encoder) the initial value of the hour. When increasing the hour value to «23», reset the hour value to «1». When reducing the hour value to «0», reset the hour value to «23».
if ( rDir == 1 ) {
if (Set_Hours == 23)
{
Set_Hours = 0;
}
else
{
Set_Hours ++;
}
}
if ( rDir == 2 ) {
if (Set_Hours == 0)
{
Set_Hours = 23;
}
else
{
Set_Hours —;
}
}
delay(100);
}
else if (s_mode == 5) {//with each rotation of the encoder, we will increase or decrease (depending on the direction of rotation of the encoder) the initial value of minutes. When increasing the minutes value to «59», reset the minutes value to «1». When reducing the minutes value to «0», reset the minutes value to «59».
if ( rDir == 1 ) {
if (Set_minutes == 59)
{
Set_minutes = 0;
}
else
{
Set_minutes ++;
}
}
if ( rDir == 2 ) {
if (Set_minutes == 0)
{
Set_minutes = 59;
}
else
{
Set_minutes —;
}
}
delay(100);
}
else if (s_mode == 6) {//with each rotation of the encoder, we will increase or decrease (depending on the direction of rotation of the encoder) the initial value of the clock stroke correction. When increasing the value to «59», reset the value to «1». When reducing the value to «0», reset the value to «59».
if ( rDir == 1 ) {
if (Corr_time == 59)
{
Corr_time = -59;
}
else
{
Corr_time++;
}
}
if ( rDir == 2 ) {
if (Corr_time == -59)
{
Corr_time = 59;
}
else
{
Corr_time —;
}
}
delay(100);
}
}
/////////////////////////
}//end while
}