Example needed for DS3231 AT24C32 IIC Precision RTC

I am trying to find some code that will show me how to use the above to make an alarm clock. I seem to find article that talk around the point but nothing that is helping me understand.

Any suggestions?

http://forum.arduino.cc/index.php/topic,211409.0.html
http://playground.arduino.cc/Code/I2CEEPROM24C1024#.UxMweON5PoE

Thanks, I also just found this: http://misclab.umeoce.maine.edu/boss/Arduino/bensguides/DS3231_Arduino_Clock_Instructions.pdf

I also use this device, and i need to set an alarm to be triggered each hour o´clock (minutes = 0; seconds = 0).

I don´t undersand how to do it exactly, if i can set once the alarm in my code, or it require to be setted each time it was trigetter in order to be ready for the next hour...

So, any help will be wellcome!

Table 2 on page 12 of the datasheet shows what is required to get an alarm once an hour. You can set Alarm1 to interrupt whenever minutes and seconds match (set them both to zero) or set Alarm2 to interrupt whenever the minutes match (set it to zero).
When the clock interrupts you must reset the A1F or A2F alarm flag (but not from within the interrupt routine).

Pete

Thanks @el_supremo,

But this is exactly my problem. I know the table from the datasheet, and also from the library, but i do not know how to move from the teory to the practice.

I found a quite good and new library where it is to easy to do it:

However, i can´t use it because it is so heavy for my settings. My code is so long, and i cant use this library because it completely fill the memory. Then, i use this other library what is lighter:

Then, to set the alarm, the library have these functions:

void DS3231::setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM)

void DS3231::setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM)

Firs, i don´t know how to fill the second part of each funcion ( byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM and byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM), and second, it seems to me that i need to set the day, hour, minute, (and second in case of the Alarm 1), each time the alarm is triggered. The problem is at the end of the day. if time now is 23h, and i must to set the next alarm to the 00:00h of the next day, i must add a day to the actual date, and if i am at the last day of the month? I must take this also into account to calculate the numbers of days in the present month?

It is really such as complex?

So, you can see that i am completely lost.

it seems to me that i need to set the day, hour, minute, (and second in case of the Alarm 1), each time the alarm is triggered

No, you only need to set those values once. The clock then compares the current time against the values in the registers and an alarm/interrupt is generated if all the specified ones match. For an alarm once an hour I think you will need:

setA1Time(0, 0, 0, 0, b1100, 0, false, false)

The values for day and hour will be ignored.
You will still need to clear the A1F or A2F alarm flag after each interrupt but that is all that's required. The clock will keep ticking and comparing the time against the alarm registers and fire off another interrupt when there's a match which will be one hour later.

Pete

Thanks @el_supremo,

Now i see what bytes means, and the meaning of the table:

So, if i am right, for the different options in the table i should set the bytes such as:

Alarm 1:
b1111 Alarm once per second
b1110 Alarm when seconds match
b1100 Alarm when minutes and seconds match
b11000 Alarm when hours, minutes, and seconds match
0b0000 Alarm when date, hours, minutes, and seconds match
1b0000 Alarm when day, hours, minutes, and seconds match

Alarm 2:
b111 Alarm once per minute (00 seconds of every minute)
b110 Alarm when minutes match
b100 Alarm when hours and minutes match
0b000 Alarm when date, hours, and minutes match
1b000 Alarm when day, hours, and minutes match

About to clear the A1F and A2F, i suposse that you are talking about to add this function to the code depending of if the used alarm was 1 or 2:

Clock.turnOffAlarm(1);
Clock.turnOffAlarm(2);

Am i right?

Trying to apply the previous ideas, i wrote this function:

void SetNewAlarm(){
  Clock.setA2Time(0, 0, 0, 0b111, 0, false, false);
  Clock.turnOnAlarm(2);
}

The idea is to trigger the alarm once per minute (for testing purposes), but nothing happends... the alarm is not triggered.
i use an attachinterrupt function to capture the alarm from the rtc.

I added a 0 before the b111 because otherwise the code does not compile.

What is wrong?

I added a 0 before the b111

Yeah, my bad.

Clock.turnOffAlarm(1);

No, that turns off the alarm altogether (in control register 0x0E). You only need to reset the alarm flag in control register 0x0F. The function that does that for you is Clock.checkIfAlarm(1) (for alarm 1). It checks whether the alarm has occurred and, if it has, it resets the alarm flag.

Pete

Here is an alarm setting sketch using a different library from Jack Christensen.

It is written for the DS3232 and DS3231 and seems pretty straightforward.

#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)

tmElements_t tm;
const byte rtcAlarmPin =8;

void setup(void)
{
  pinMode(rtcAlarmPin,INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("DS3231RTC Alarm Test");
  setSyncProvider(RTC.get);   // the function to get the unix time from the RTC
  if(timeStatus() != timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  Serial.println(); 
  
  //enable alarm interrupts on match; also sets status flags A1F,A2F

  RTC.alarmInterrupt(1,1);//enable alarm 1 interrupt A1IE
  RTC.alarmInterrupt(2,1);//enable alarm 2 interrupt A2IE

  //enable or disable the square wave output,
  // no square wave (NONE) sets ITCN bit=1  
  //enables alarm interrupt on square wave pin set from A1F, A2F
  //digitalRead with INPUT_PULLUP; LOW is alarm interrupt

  RTC.squareWave(SQWAVE_NONE);

  
  /*Alarm_Types defined in RTC3232.h.............................................
  
    ALM1_EVERY_SECOND 
    ALM1_MATCH_SECONDS
    ALM1_MATCH_MINUTES     //match minutes *and* seconds
    ALM1_MATCH_HOURS       //match hours *and* minutes, seconds
    ALM1_MATCH_DATE        //match date *and* hours, minutes, seconds
    ALM1_MATCH_DAY         //match day *and* hours, minutes, seconds
    ALM2_EVERY_MINUTE 
    ALM2_MATCH_MINUTES     //match minutes
    ALM2_MATCH_HOURS       //match hours *and* minutes
    ALM2_MATCH_DATE       //match date *and* hours, minutes
    ALM2_MATCH_DAY        //match day *and* hours, minutes
  */
   //setAlarm Format (Alarm_Type, seconds, minutes, hours, date(or day))
  RTC.setAlarm(ALM2_EVERY_MINUTE, 0,0,0,0);
  RTC.setAlarm(ALM1_MATCH_SECONDS,30,0,0,0);

}
void loop()
{
  TimeDateDisplay();
  Serial.print("rtcAlarmPin   ");
  Serial.println(digitalRead(rtcAlarmPin));//resets with status reset
  Serial.print("Alarm1 status  ");
  Serial.println(RTC.alarm(1));//reads and resets status
  Serial.print("Alarm2 status  ");
  Serial.println(RTC.alarm(2));//reads and resets status
  Serial.println();
  delay(5000);
}

void TimeDateDisplay(void)
{
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits)
{
  // utility function for TimeDateDisplay prints preceding colon and leading 0
  Serial.print(':');
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Thanks @cattledogs

I already have this library, but i didn´t have an example to configure an alarm, what seems to be more easy.

My problem is that i am out of memory, so, by the use of DS3232RTC library (and the required time library), as well as the new full DS3231 library, i completelly fill the memory of the arduino, and my code does not upload.

For that reason i am using the other simple library, what leaves to me 4 Kb to allow my code to work. So, my unique problem at this stage is to have runing the alarm... what is my pain now.

Anyway, thanks so much for the example code, because it is so interesting and useful. i am sure i will use it in other projects.

@el_supremo,
Thanks so much. However, i still do not have it working... It is killing me. I post here my code (still many things need to be pulished). Could you see what i am doing wrong?
Thanks!

Permarduino_Camera_01b.ino (18.5 KB)

Too late, but...

abasel:
I am trying to find some code that will show me how to use the above to make an alarm clock.... Any suggestions?

PIPNI s.r.o. - 404 Error Page I2C scanner reads data from RTC and AT24Cxx memory

Not to late at all!!

I tested your I2CScanner code, and it is great!

This is what it returns from the DS3231 reading:

Dump of NVRAM content (19 bytes) from I2C device at address 0x68 (104)
The information is apply only for chip DS3231, partially for chips DS1337 and DS1307 (and maybe for another similar chips)
0x00 Seconds = 45
0x01 Minutes = 32
0x02 Hours = 21
0x03 Weekday = 1
0x04 Day = 11
0x05 Month/Century = 8
0x06 Year = 2014
0x07 Alarm 1 Seconds = 0
0x08 Alarm 1 Minutes = 80
0x09 Alarm 1 Hours = 80
0x0A Alarm 1 Day&Date = 80
0x0B Alarm 2 Minutes = 0
0x0C Alarm 2 Hours = 0
0x0D Alarm 2 Day&Date = 0
0x0E Control = 11100
0x0F Control/Status = 1001
0x10 Aging Offset = 0
0x11 Temperature MSB+LSB = 30.75°C

Then, it seems that my testing code to set the alarm is not working:

Clock.setA2Time(0, 0, 0, 0b111, 0, false, false)

(to have an alarm each minute to testing purposes)

and neither the real code i want to establish:

Clock.setA1(0,0,0,0, 0b1100, 0, false, false);

(to have an alarm each hour o'clock)
This one because of the unreal values of hours, minutes and seconds of alarm 1 (80, 80, 80).

madepablo--

The values of 80 you are seeing in your register dump are HEX 0x80 which is BIN 10000000. You may not have the Alarm 1 register mask bits correct.

I don't know how much memory you will save, but you should be able to execute the RTC reads and alarms without the DS3231 library and using only Wire.h. It won't be as easy as using the library, but if you are needing every byte of code space, it may be worth it.

You can use the basic Wire.read function and BCD conversion used by the library to read the lower seven timekeeping registers, and you will use Wire.write do the bit writes for all the alarm functions in registers 0x07 through 0x0F.

The data sheet will be your friend http://datasheets.maximintegrated.com/en/ds/DS3231.pdf

Pay close attention to Figure 1 Timekeeping Registers, and Figure 2 Alarm Mask Bits.

You can use a simple RTC write byte function to place the Alarm bits in the upper registers.

void writeRTC(byte location, byte data) // writes data to location
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(location); 
  Wire.write(data);
  Wire.endTransmission();  
}

You can #define the Alarm, Control, and Status Registers to help

// definition for register addresses
#define A1M1 0x07
#define A1M2 0x08
#define A1M3 0x09
#define A1M4 0x0A

#define A2M2 0x0B
#define A2M3 0x0C
#define A2M4 0x0D

#define CONREG 0x0E
#define STAREG 0x0F

Setting Alarm2 for once per minute will be

writeRTC(A2M4, B10000000);
writeRTC(A2M3, B10000000);
writeRTC(A2M2, B10000000);
writeRTC(CONREG, B00000110);//enable alarm 2 and square wave pin for interrupt

You can use an RTC read byte function to get at the the A1F and A2F flags in bits 0 and 1 of the Status register. After reading, you will need to set them low with a write.

byte readRTC(byte location)
{
  byte result;
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(location); 
  Wire.endTransmission();  
  Wire.requestFrom(DS3231_I2C_ADDRESS, 1);//only 1 byte, does not need wire.available
  result = Wire.read();
  return result;
}

Here is a simple function to do a complete DS3231 register dump in Binary, printing the full 8 bits. Use it with the read RTC function.

for (int a=0x00; a<0x13; a++)
  {
  byte b=readRTC(a);
  Serial.print(a, HEX);
  Serial.print("\t");
  for (int i = 0; i < 8; i++)//routine for printing full 8 bits, leading zeros
{
      if (b < pow(2, i))
       Serial.print(B0);
}
  Serial.println(b, BIN);
  delay(250);

@Cattledog

Thanks so much for your explanations and example pieces of code. I really appreciate.

My problem is that my knowledge at this level of coding is pretty poor.... One of my task in the to-do-list is to learn about data transfer to be able to use this kind of coding (to do things like this one you explain or, to write-read an eeprom). Read and write bits is at this moment out of my knowledge limits... this is why i ever use libraries... But to have this knowledge will allow to me to modify libraries to use only the procedures i require, or directñy communicate with devices at this low level.

Anyway, i really appreciate your ideas, and i will save this information for my next learning steps. THANKS!!

I finally located otherlibrary for ds3231 RTC, what mades easy what i am loking for, but also saving memory.

This is the library i located: http://kevinrye.net/resources/E-Paper-Clock-Source-V1.zip from an interesting webpage of an arduino user what develop many interesting proyects:
http://kevinrye.net/
He designed this library for his e-ink paper clock.

Just for your interest, i leave here his library, and my code, where you could see what i did with it.

Thanks so much guys for your ideas and comments! I will apply what i learned from you in my future projects.
Cheers!

Permarduino_Camera_03.ino (17.7 KB)

DS3231 Library.zip (11.9 KB)

BTW,

Here you have other library what could be used with DS3231 RTC:

It is a modification of the famous RTCLib what include more functions some of them focused on DS3231 RTC.
It comes with different examples for this (and others) RTC, so, maybe it could be useful for others.

Cheers,