Author Topic: Can't disable alarms on DS3231 RTC module  (Read 1328 times)

0 Members and 1 Guest are viewing this topic.

Offline kuzm1nsk1Topic starter

  • Contributor
  • Posts: 30
  • Country: hr
Can't disable alarms on DS3231 RTC module
« on: April 29, 2024, 11:27:24 pm »
Hi, after some troubleshooting I realised that the function to disable the alarm on DS3231 doesn't work. I'm using Adafruit's RTClib and to try it out their example code for DS3231_alarm. Even if I write rtc.disableAlarm(1); and rtc.disableAlarm(2); somehow alarm still triggers. Is my module faulty or am I doing something wrong. I tried using different library but I got the same results. Does anybody have DS3231 to confirm or deny my results?

Code: [Select]
/* Example implementation of an alarm using DS3231
 *
 * VCC and GND of RTC should be connected to some power source
 * SDA, SCL of RTC should be connected to SDA, SCL of arduino
 * SQW should be connected to CLOCK_INTERRUPT_PIN
 * CLOCK_INTERRUPT_PIN needs to work with interrupts
 */

#include <RTClib.h>
// #include <Wire.h>

RTC_DS3231 rtc;

// the pin that is connected to SQW
#define CLOCK_INTERRUPT_PIN 2

void setup() {
    Serial.begin(9600);

    // initializing the rtc
    if(!rtc.begin()) {
        Serial.println("Couldn't find RTC!");
        Serial.flush();
        while (1) delay(10);
    }

    if(rtc.lostPower()) {
        // this will adjust to the date and time at compilation
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    }

    //we don't need the 32K Pin, so disable it
    rtc.disable32K();

    // Making it so, that the alarm will trigger an interrupt
    pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING);

    // set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far)
    // if not done, this easily leads to problems, as both register aren't reset on reboot/recompile
    rtc.clearAlarm(1);
    rtc.clearAlarm(2);

    // stop oscillating signals at SQW Pin
    // otherwise setAlarm1 will fail
    rtc.writeSqwPinMode(DS3231_OFF);

    // turn off alarm 2 (in case it isn't off already)
    // again, this isn't done at reboot, so a previously set alarm could easily go overlooked
    rtc.disableAlarm(2);
    rtc.disableAlarm(1);

    // schedule an alarm 10 seconds in the future
    if(!rtc.setAlarm1(
            rtc.now() + TimeSpan(10),
            DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options
    )) {
        Serial.println("Error, alarm wasn't set!");
    }else {
        Serial.println("Alarm will happen in 10 seconds!");
    }
}

void loop() {
    // print current time
    char date[10] = "hh:mm:ss";
    rtc.now().toString(date);
    Serial.print(date);

    // the stored alarm value + mode
    DateTime alarm1 = rtc.getAlarm1();
    Ds3231Alarm1Mode alarm1mode = rtc.getAlarm1Mode();
    char alarm1Date[12] = "DD hh:mm:ss";
    alarm1.toString(alarm1Date);
    Serial.print(" [Alarm1: ");
    Serial.print(alarm1Date);
    Serial.print(", Mode: ");
    switch (alarm1mode) {
      case DS3231_A1_PerSecond: Serial.print("PerSecond"); break;
      case DS3231_A1_Second: Serial.print("Second"); break;
      case DS3231_A1_Minute: Serial.print("Minute"); break;
      case DS3231_A1_Hour: Serial.print("Hour"); break;
      case DS3231_A1_Date: Serial.print("Date"); break;
      case DS3231_A1_Day: Serial.print("Day"); break;
    }

    // the value at SQW-Pin (because of pullup 1 means no alarm)
    Serial.print("] SQW: ");
    Serial.print(digitalRead(CLOCK_INTERRUPT_PIN));

    // whether a alarm fired
    Serial.print(" Fired: ");
    Serial.print(rtc.alarmFired(1));

    // Serial.print(" Alarm2: ");
    // Serial.println(rtc.alarmFired(2));
    // control register values (see https://datasheets.maximintegrated.com/en/ds/DS3231.pdf page 13)
    // Serial.print(" Control: 0b");
    // Serial.println(read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), BIN);

    // resetting SQW and alarm 1 flag
    // using setAlarm1, the next alarm could now be configurated
    if (rtc.alarmFired(1)) {
        rtc.clearAlarm(1);
        Serial.print(" - Alarm cleared");
    }
    Serial.println();

    delay(2000);
}

void onAlarm() {
    Serial.println("Alarm occured!");
}

/*static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
    Wire.beginTransmission(addr);
    Wire.write((byte)reg);
    Wire.endTransmission();

    Wire.requestFrom(addr, (byte)1);
    return Wire.read();
}*/
« Last Edit: April 29, 2024, 11:41:35 pm by kuzm1nsk1 »
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2038
  • Country: us
Re: Can't disable alarms on DS3231 RTC module
« Reply #1 on: April 30, 2024, 02:58:05 am »
The only time you disable the alarms in your code is immediately followed by setting alarm1 again.

Code: [Select]
    rtc.disableAlarm(2);
    rtc.disableAlarm(1);

    // schedule an alarm 10 seconds in the future
    if(!rtc.setAlarm1(
            rtc.now() + TimeSpan(10),
            DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options
    )) {

ClearAlarm only clears the alarm flag, letting the INT pin go back high.  It doesn't disable the alarm.

 

Offline kuzm1nsk1Topic starter

  • Contributor
  • Posts: 30
  • Country: hr
Re: Can't disable alarms on DS3231 RTC module
« Reply #2 on: April 30, 2024, 06:43:03 am »
I can comment this and it wont make a difference, even if you put disable alarm in the loop, it still triggers. Reading garrysblog, he also said that you can't disable it. I figured out that disable alarms only disables SQW but you will always get true if you test alarmFired(1).
https://garrysblog.com/2020/07/05/using-the-ds3231-real-time-clock-alarm-with-the-adafruit-rtclib-library/
« Last Edit: April 30, 2024, 07:45:20 am by kuzm1nsk1 »
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2038
  • Country: us
Re: Can't disable alarms on DS3231 RTC module
« Reply #3 on: April 30, 2024, 09:07:16 pm »
I'm not sure what the problem is, but as of today, the library function that disables an alarm is as follows:

Code: [Select]
void RTC_DS3231::disableAlarm(uint8_t alarm_num) {
  uint8_t ctrl = read_register(DS3231_CONTROL);
  ctrl &= ~(1 << (alarm_num - 1));
  write_register(DS3231_CONTROL, ctrl);
}

That's taken from the file RTC_DS3231.cpp in the Adafruit library.  It looks like it should work.  It clears the interrupt enable bit for the alarm in the Control register, which means when the time matches the alarm setting, nothing will happen on the INT/SQW pin.

But a match will always set the interrupt flag bit in the Status register.  So maybe the problem is attempting to use the alarmFired function to determine if the alarm has triggered.  For that to work you would also have to confirm that the interrupt enable bit in the control register is set.  Without that, alarmFired only means the time matched the alarm, not that anything actually happened as a result, like triggering an interrupt.  But this library doesn't appear to offer a function to read the Control register.


 
The following users thanked this post: kuzm1nsk1

Offline kuzm1nsk1Topic starter

  • Contributor
  • Posts: 30
  • Country: hr
Re: Can't disable alarms on DS3231 RTC module
« Reply #4 on: May 01, 2024, 08:35:08 am »
That was exactly my problem until I figured out that disableAlarm only disables SQW. I was testing alarmFired and it would always return true. Honestly, it would make more sense if you disabled the alarm that it disables everything.
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2038
  • Country: us
Re: Can't disable alarms on DS3231 RTC module
« Reply #5 on: May 01, 2024, 10:46:53 pm »
I wonder if it might be possible to prevent the alarm time from ever matching the actual time.  Maybe you could set the alarm seconds to 61 or something like that that isn't a valid time.  Then alarmFired would never return true unless you enter a valid alarm time which eventually triggers.
 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3029
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: Can't disable alarms on DS3231 RTC module
« Reply #6 on: May 02, 2024, 12:52:40 am »
Here is how I disable the alarms in my DS3231_Simple Arduino library


Code: [Select]
uint8_t DS3231_Simple::disableAlarms()
{
  // There's no way to actually disable the alarms from triggering, so
  // we have to set them to some unreachable date
  // (NB: you can disable the alarms from putting the SQW pin low, but they still trigger
  //   in the register itself, you can't stop that, hence this tom-foolery).
  #if 0
  DateTime invalid = { 0,0,0,0,31,2,0 };
  #else
  // This saves 4 bytes interestingly (assuming you are already going to be using read() somewhere)
  DateTime invalid = read();
  invalid.Day = 31;
  invalid.Month = 2;
  #endif
  setAlarm(invalid, ALARM_MATCH_MINUTE_HOUR_DATE);
  setAlarm(invalid, ALARM_MATCH_SECOND_MINUTE_HOUR_DATE);
  checkAlarms(); // A dummy check alarm to kill the alarm flags.
 
  return 1; 
}
~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2038
  • Country: us
Re: Can't disable alarms on DS3231 RTC module
« Reply #7 on: May 02, 2024, 04:01:06 pm »
I guess I need to study your library, but I don't understand your code at all.  Starting with #if 0.  Also where does month 2 come into this?  Neither alarm includes the month.  Well, as I said, I need to look through your library.

 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3029
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: Can't disable alarms on DS3231 RTC module
« Reply #8 on: May 02, 2024, 10:56:49 pm »
Starting with #if 0.

`#if 0` is disabled code, the `#else` code following is used instead.

Now, the rest of your comment... ahhh... yeah, I suspect that is a bug indeed. I guess I forgot the alarms don't check month (probably should have named the define ..._DOM instead of ..._DATE).

Funny nobody has ever reported it in however many years.  Probably nobody checks for alarms if they are not setting alarms I suppose.

Anyway, long and short, you can't disable the alarm in the register.  Maybe if you set an invalid Day of Month or Hour it might work.  I don't have one around to test with now.







~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2038
  • Country: us
Re: Can't disable alarms on DS3231 RTC module
« Reply #9 on: May 02, 2024, 11:09:00 pm »
Starting with #if 0.

`#if 0` is disabled code, the `#else` code following is used instead.

Now, the rest of your comment... ahhh... yeah, I suspect that is a bug indeed. I guess I forgot the alarms don't check month (probably should have named the define ..._DOM instead of ..._DATE).

Funny nobody has ever reported it in however many years.  Probably nobody checks for alarms if they are not setting alarms I suppose.

Anyway, long and short, you can't disable the alarm in the register.  Maybe if you set an invalid Day of Month or Hour it might work.  I don't have one around to test with now.

I have several to test with.  I guess the advantage of Feb 31 is that it has no value that is illegal per se, only invalid in combination.  Well, my guess is that in the alarm fields illegal values won't be modified.  I'll try to test that later today.  But if that's true, then you could set the alarm seconds or minutes value to 61, and a match would never happen, so the flag bits wouldn't be set.

But you know, I've used these RTCs for years, and don't think I've ever tested the alarm flag bits.  I've cleared them, but never tested them.  If I'm using alarm interrupts, then INT/SQW will be low if there's been an alarm.  So I don't see why would you need to see if the flags have been set.
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2038
  • Country: us
Re: Can't disable alarms on DS3231 RTC module
« Reply #10 on: May 03, 2024, 02:08:33 am »
Ok, I did a test writing the value 97 into register 7, which is the seconds register of Alarm1.  97 is 0b01100001, which is 61 in binary coded decimal.  Then I read back the value in register 7 once a second to see if it changed.  In more than a minute, it did not.  I also read back the status register to see if the alarm flags were ever set.  They were not.  So it seems you can write an invalid number into an alarm register, and it will not be error-checked or changed.  So since the actual time will never contain such an invalid number, no match will ever occur, and the alarm flags will never be set.

To do this test, I had to clear the A1M1 bit in register 7, and set the A1M2 - A1M4 bits in registers 8, 9 and 0xA.  If A1M1 is also set, it will match every second no matter what value is in register 7.
 

Offline kuzm1nsk1Topic starter

  • Contributor
  • Posts: 30
  • Country: hr
Re: Can't disable alarms on DS3231 RTC module
« Reply #11 on: May 04, 2024, 04:01:47 pm »
Quote
If I'm using alarm interrupts, then INT/SQW will be low if there's been an alarm.  So I don't see why would you need to see if the flags have been set.

I'm already using 1Hz SQW signal to update the display when second changes, so checking alarms using interrupts is not really possible. Writing invalid value to the alarm would be my first approach but I wanted to test if you could clear all alarms so that wouldn't be necessary.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf