JChristensen / DS3232RTC

Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks
GNU General Public License v3.0
392 stars 135 forks source link

ALM1_MATCH_DATE works. ALM1_MATCH_DAY doesn't work #72

Closed trigora closed 4 years ago

trigora commented 4 years ago

Good day, Jack! Thank you for your library very much!

All the library works well in my project. “ALM1_MATCH_DATE” works well too. But at the same time one of ALARM_TYPES doesn’t work – “ALM1_MATCH_DAY”.

I read about the previous mistake in the library: “if (alarmType & 0x10) hours |= _BV(DYDT); should be: if (alarmType & 0x10) daydate |= _BV(DYDT);”

At December 2019 I setup last version of the library and check it up: `if (alarmType & 0x04) hours |= _BV(A1M3);

if (alarmType & 0x10) daydate |= _BV(DYDT);

if (alarmType & 0x08) daydate |= _BV(A1M4);`

It seems like all it’s OK. But “ALM1_MATCH_DAY” doesn’t occur the alarm.

And I ask you to help if you can – what’s wrong with my version of “ALM1_MATCH_DAY”? There is minimum of my code (of course, it’s your code from the examples with my slight alternates), where “ALM1_MATCH_DATE” works and “ALM1_MATCH_DAY” doesn’t work:

/////////////////////////////////////////////// START OF THE SKETCH //////////////////////////////

include

const time_t ALARM1_INTERVAL(10); // alarm interval in seconds const time_t ALARM2_INTERVAL(60); // alarm interval in seconds

void setup() { Serial.begin(9600);
setSyncProvider(RTC.get); // the function to get the time from the RTC

if(timeStatus() != timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time");

// initialize the alarms to known values, clear the alarm flags, clear the alarm interrupt flags
RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);

RTC.alarm(ALARM_1);
RTC.alarm(ALARM_2);

RTC.alarmInterrupt(ALARM_1, false);
RTC.alarmInterrupt(ALARM_2, false);
RTC.squareWave(SQWAVE_NONE);

time_t tm = RTC.get();
time_t alarmTime1 = tm + ALARM1_INTERVAL;    // calculate the alarm time
time_t alarmTime2 = tm + ALARM2_INTERVAL;    // calculate the alarm time

// set the alarm
RTC.setAlarm(ALM1_MATCH_DAY, minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1)); // doesn't work
// RTC.setAlarm(ALM1_MATCH_DAY, 10, 10, 3); // without seconds doesn't work too
// RTC.setAlarm(ALM1_MATCH_DAY, 0, 10, 10, 3); // with seconds doesn't work too

RTC.setAlarm(ALM2_MATCH_DATE, minute(alarmTime2), hour(alarmTime2), day(alarmTime2)); // works 

// clear the alarm flag
RTC.alarm(ALARM_1);
RTC.alarm(ALARM_2);

}

void loop() {

      // check to see if the alarm flag is set (also resets the flag if set)

if ( RTC.alarm(ALARM_1) )
{
    // get the current time
    time_t t = RTC.get();
    // calculate the next alarm time
    time_t alarmTime = t + ALARM1_INTERVAL;
    // set the alarm
    RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime), minute(alarmTime), hour(alarmTime), weekday(alarmTime));
    Serial.println("A1");
}          

if ( RTC.alarm(ALARM_2) )
{
    // get the current time
    time_t t = RTC.get();
    // calculate the next alarm time
    time_t alarmTime = t + ALARM2_INTERVAL;
    // set the alarm
    RTC.setAlarm(ALM2_MATCH_HOURS, second(alarmTime), minute(alarmTime), hour(alarmTime), 0);
    Serial.println("A2");
}

}

/////////////////////////////////////////////// END OF THE SKETCH //////////////////////////////

Thank you!

JChristensen commented 4 years ago

In setup(), alarmTime1 is set to the current time plus 10 seconds. But then, if setAlarm() is called without the seconds parameter (or with zero as the seconds parameter, which is the same thing), then the alarm is set to a time in the past, and will never fire (actually in this case, due to using ALM1_MATCH_DAY, it will fire in just under seven days.)

To fix this, in setup(), change the setAlarm() call to:

RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime1), minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1));

The setAlarm() call in loop() already includes the seconds parameter so subsequent alarm settings are fine.

trigora commented 4 years ago

This sketch is supposed to learning purposes – just to learn the library and the RTC module. I plan to use it in mу future projects. About the absence of the seconds parameter and “ALARM1_INTERVAL(10)” parameter – yes, you are right: it’s my mistake. I tried out a lot of different options for “RTC.setAlarm(ALM1_MATCH_DAY” and 1 of my attempts was with this mistake. And unfortunately, I send it to you. But others variants do not work too. RTC.setAlarm(ALM2_MATCH_DATE, minute(alarmTime2), hour(alarmTime2), day(alarmTime2)); // works But “RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime1), minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1));” - doesn’t work Just now I tried: /////////////////////////////// START OF VARIANTS /////////////////////////////////////////////////////////////// Variant 1. const time_t ALARM1_INTERVAL(90); and RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime1), minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1));

Variant 2. const time_t ALARM1_INTERVAL(90); and RTC.setAlarm(ALM1_MATCH_DAY, minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1));

Variant 3. const time_t ALARM1_INTERVAL(90); and RTC.setAlarm(ALM1_MATCH_DAY, 0, 48, 23, 4); // I set the right time for my country - doesn't work too

Variant 4. const time_t ALARM1_INTERVAL(90); and RTC.setAlarm(ALM1_MATCH_DAY, 48, 23, 4); // I set the right time for my country - doesn't work too /////////////////////////////// END OF VARIANTS /////////////////////////////////////////////////////////////// If you please, can you write down code of some working sketch with “RTC.setAlarm(ALM1_MATCH_DAY” for example!

I have no other ideas. Maybe my ds3231 module doesn’t support “ALM1_MATCH_DAY”. Anyway, thank you for the library and for the answer!

Full my sketch: /////////////////////////////////////////////// START OF THE SKETCH //////////////////////////////

include

const time_t ALARM1_INTERVAL(90); // alarm interval in seconds const time_t ALARM2_INTERVAL(60); // alarm interval in seconds

void setup() { Serial.begin(9600); setSyncProvider(RTC.get); // the function to get the time from the RTC

if(timeStatus() != timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time");

// initialize the alarms to known values, clear the alarm flags, clear the alarm interrupt flags RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1); RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);

RTC.alarm(ALARM_1); RTC.alarm(ALARM_2);

RTC.alarmInterrupt(ALARM_1, false); RTC.alarmInterrupt(ALARM_2, false); RTC.squareWave(SQWAVE_NONE);

time_t tm = RTC.get(); time_t alarmTime1 = tm + ALARM1_INTERVAL; // calculate the alarm time time_t alarmTime2 = tm + ALARM2_INTERVAL; // calculate the alarm time

// set the alarm //RTC.setAlarm(ALM1_MATCH_DAY, minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1)); // doesn't work RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime1), minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1)); // doesn't work // RTC.setAlarm(ALM1_MATCH_DAY, 8, 0, 5); // without seconds doesn't work too // RTC.setAlarm(ALM1_MATCH_DAY, 0, 8, 0, 5); // with seconds doesn't work too

RTC.setAlarm(ALM2_MATCH_DATE, minute(alarmTime2), hour(alarmTime2), day(alarmTime2)); // works // RTC.setAlarm(ALM2_MATCH_DATE, 0, 7, 0, 26); // works

// clear the alarm flag RTC.alarm(ALARM_1); RTC.alarm(ALARM_2);

}

void loop() {

  // check to see if the alarm flag is set (also resets the flag if set)

if ( RTC.alarm(ALARM_1) ) { // get the current time time_t t = RTC.get(); // calculate the next alarm time time_t alarmTime = t + ALARM1_INTERVAL; // set the alarm RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime), minute(alarmTime), hour(alarmTime), weekday(alarmTime)); Serial.println("A1"); }

if ( RTC.alarm(ALARM_2) ) { // get the current time time_t t = RTC.get(); // calculate the next alarm time time_t alarmTime = t + ALARM2_INTERVAL; // set the alarm RTC.setAlarm(ALM2_MATCH_HOURS, second(alarmTime), minute(alarmTime), hour(alarmTime), 0); Serial.println("A2"); }

}

/////////////////////////////////////////////// END OF THE SKETCH //////////////////////////////

JChristensen commented 4 years ago

First of all, Merry Christmas!

Second, I prefer that issues be raised here only for problems with the library itself, not for problems with user code. I do not have time to solve problems with everyone's code. Please use the Arduino forum or other such venue for that purpose. You will learn much more by fixing your own code than you will if someone else fixes it for you.

If you really think there is an issue with the library, I prefer that you raise an issue containing a minimal but complete sketch, and clearly state the expected behavior and also the actual behavior. Please see http://www.sscce.org/ for guidelines. Just saying "does not work" is insufficient.

Also please realize that this library is fairly popular and if it contained obvious errors, I would surely know about them by now. There are over a dozen example sketches included with this library, over half of which deal with alarms, plus I have written a primer on use of the DS3231 alarms. Please use these resources along with the datasheet to help improve your knowledge and your code.

Happy coding! ... Jack

trigora commented 4 years ago

   Jack, Merry Christmas!    In my country Holiday of Christmas will be celebrated on 7th of January that’s why I missed to congratulate you yesterday. I hope today is not too late :)    I’ll continue to find source of problem.    Maybe sometimes you will have time to add one more example: with “ALM1_MATCH_DAY” :)    Your library is very useful.    Thank you very much!  

Четверг, 26 декабря 2019, 0:42 +03:00 от Jack Christensen notifications@github.com:   First of all, Merry Christmas! Second, I prefer that issues be raised here only for problems with the library itself, not for problems with user code. I do not have time to solve problems with everyone's code. Please use the Arduino forum or other such venue for that purpose. You will learn much more by fixing your own code than you will if someone else fixes it for you. If you really think there is an issue with the library, I prefer that you raise an issue containing a minimal but complete sketch, and clearly state the expected behavior and also the actual behavior. Please see http://www.sscce.org/ for guidelines. Just saying "does not work" is insufficient. Also please realize that this library is fairly popular and if it contained obvious errors, I would surely know about them by now. There are over a dozen example sketches included with this library, over half of which deal with alarms, plus I have written a primer on use of the DS3231 alarms . Please use these resources along with the datasheet to help improve your knowledge and your code. Happy coding! ... Jack — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub , or unsubscribe .    

Сергей Аз  

JChristensen commented 4 years ago

The original sketch you posted is a good example of ALM1_MATCH_DAY, it just needs the seconds parameter added to the setAlarm() call in setup().

trigora commented 4 years ago

To compete the question. The problem was in the order of the days of week in the “weekday()” function from the “Time” library and in my RTC module with regional settings. These orders are different. The “weekday()” function from the “Time” library returns 6 for Friday. And Friday is day 5 in my country. So RTC module with regional settings of my country returns 5 for Friday. Thus, code “RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime1), minute(alarmTime1), hour(alarmTime1), weekday(alarmTime1));” never could work because of returned wrong value of weekday() function for the RTC module. Some addings to code and the problem was solved :))) Jack, thank you for the library one more time.

JChristensen commented 4 years ago

Hello Sergey, I hope I have your name right. I just used Google translate. I'm curious, what country are you in? If Friday is 5 there, that might be something that I should be aware of. Glad that the library is useful to you. Regards ... Jack

JChristensen commented 4 years ago

For example, I see that the Russian calendar runs from Monday through Sunday, as opposed to Sunday through Saturday here in the USA.

trigora commented 4 years ago

Hello, Jack! Yes, you are right - Russia is my homeland :)

Some addings in sketch - maybe useful for somebody.

RTC.setAlarm(ALM1_MATCH_DAY, second(alarmTime1), minute(alarmTime1), hour(alarmTime1), weekdayRus(weekday(alarmTime1)));

// function to convert format of weekday from Sunday 1-st day to Monday 1-st day byte weekdayRus(byte dayOfweek) { return ((dayOfweek == 1) ? 7 : --dayOfweek); }

Best regards! Sergey.

JChristensen commented 4 years ago

Hello Sergey, One of the cool things about GitHub is hearing from folks all over the world. Great to hear from Russia! I was thinking some more about this. Here is something to try: It might not be necessary to use constants 1-7 for day of week. Instead, try using the names defined in the Time library:

typedef enum {
    dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
} timeDayOfWeek_t;

So rather than:

RTC.setAlarm(ALM1_MATCH_DAY, 0, 10, 10, 3);

Code this instead:

RTC.setAlarm(ALM1_MATCH_DAY, 0, 10, 10, dowWednesday);

This would mean that internally, the days of the week might not be coded the way you would choose, but you shouldn't have to deal with it at that level; everything should be consistent and I think will work OK.

Cheers ... Jack

trigora commented 4 years ago

Hello, Jack!

Thank you! It’s interesting idea and I need some time to grasp it and the cases of its’ optimal usage. At first glance both of two ways are can be useful for their tasks.

Meanwhile I congratulate you and all of “github world” with new year!!! I wish good health, happiness of family, peaceful sky over the head to all of us!

Best regards! Sergey.

JChristensen commented 4 years ago

Hello, Sergey!

Thank you for the well wishes! Same to you and yours from us here!

Another thing occurred to me. If the RTC is set with RTC.set(), then it uses the Time library to calculate the day of the week. So that will result in the day being set to one more that you might want. The time could instead be set with RTC.write() but then that might require additional calculations to modify the day.

Also when calling makeTime() or breakTime() from the Time library, adjustments may be needed. So I wonder if it might be easiest not to fight it. It's all under the covers pretty much so doesn't really matter much.

Good luck, have fun! Best regards and peace always, Jack