system
November 6, 2013, 10:26am
1
I've been all over the datasheet trying to find what I am missing. I set INTCN and A2IE on the control register. I retrieve that byte in the loop and display it, and all that is set is A1IE. Also, A1F is set in the status register, though I don't know why. I have my alarm mask set right, I think. Here is my code:
#include <Wire.h>
#define DS3231 0x68
byte seconds;
byte minutes;
byte hours;
byte day;
byte month;
byte year;
int alarmhour;
int alarmminute;
void setup () {
pinMode(A3, OUTPUT);
pinMode(A2, OUTPUT);
digitalWrite(A3, HIGH);
digitalWrite(A2, LOW);
attachInterrupt(0, alarm, LOW); //set up alarm interrupt, and call alarm function
Serial.begin(9600);
Wire.begin();
//clear status register
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.write(0x00);
Wire.endTransmission();
setTime();
setAlarm();
Wire.beginTransmission(0x68); // address DS3231
Wire.write(0x0E); // select register
Wire.write(0x06); // write register bitmap, bit 7 is /EOSC
Wire.endTransmission();
//clear alarm flags
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.write(0x00);
Wire.endTransmission();
//set alarm mask, match hours and minutes
Wire.beginTransmission(DS3231);
Wire.write(0x0D);
Wire.write(010000000);
Wire.endTransmission();
}
void loop() {
getTime();
getDate();
getAlarm();
Serial.print(bcdToDec(hours));
Serial.print(":");
Serial.print(bcdToDec(minutes));
Serial.print(":");
Serial.print(bcdToDec(seconds));
Serial.print(" ");
Serial.print(bcdToDec(month));
Serial.print("-");
Serial.print(bcdToDec(day));
Serial.print("-");
Serial.println(bcdToDec(year));
Serial.print(bcdToDec(alarmhour));
Serial.print(":");
Serial.println(bcdToDec(alarmminute));
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.endTransmission();
int status = Wire.requestFrom(DS3231, 1);
Serial.println(status, BIN);
Wire.beginTransmission(DS3231);
Wire.write(0x0E);
Wire.endTransmission();
int control = Wire.requestFrom(DS3231, 1);
Serial.println(control, BIN);
delay(1000);
}
//GET TIME
void getTime() {
Wire.beginTransmission(DS3231);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231, 3);
while(Wire.available())
{
seconds = Wire.read();
minutes = Wire.read();
hours = Wire.read();
}
}
//GET DATE
void getDate() {
Wire.beginTransmission(DS3231);
Wire.write(0x04);
Wire.endTransmission();
Wire.requestFrom(DS3231, 3);
while(Wire.available())
{
day = Wire.read();
month = Wire.read();
year = Wire.read();
}
}
//GET ALARM
void getAlarm() {
Wire.beginTransmission(DS3231);
Wire.write(0x0B);
Wire.endTransmission();
Wire.requestFrom(DS3231, 2);
while(Wire.available())
{
alarmminute = Wire.read();
alarmhour = Wire.read();
}
bitClear(alarmminute, 7);
bitClear(alarmhour, 7);
bitClear(alarmhour, 6);
}
//SET TIME
void setTime() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x00);
Wire.write(B00110000);
Wire.write(B01011001);
Wire.write(B00100010);
Wire.endTransmission();
}
//SET DATE
void setDate() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x04);
Wire.write(B00000010);
Wire.write(B00010001);
Wire.write(B00010011);
Wire.endTransmission();
}
void setAlarm() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x0B);// alarm2
Wire.write(B10000000);
Wire.write(B11100011);
Wire.write(B10000000);
Wire.endTransmission();
}
void alarm() {
Serial.begin(9600);
Serial.println("ALARM");
digitalWrite(13, HIGH);
//clear interrupt flag to shut alarm off
delay(1000);
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
system
November 6, 2013, 8:18pm
2
When you set the alarm
Wire.write(010000000);
there's a missing b (for binary). It should read
Wire.write(0b10000000);
system
November 6, 2013, 8:55pm
3
I've thought of additional issues after replying a few minutes ago:
You should attach the interrupt on FALLING instead of LOW. Your interrupt pin must be connected to the INT/SQW pin of DS3231. Just in case, remember to use a pull-up resistor , as the INT/SQW is an open-drain pin. I use a 4,7K and it works ok.
The Serial.begin() In the interrupt function "alarm" should be in Setup() , and I would reset the 2nd alarm at the beginning of the "alarm" function , reading the 0x0f byte and ANDing ( &) its content with 0b11111101
To make it easier to debug your code while you are testing, I would use the Alarm once per minute mode, setting the alarm (in setAlarm) this way:
Wire.write(uint8_t(0x0b));
Wire.write(uint8_t(0b10000000));
Wire.write(uint8_t(0b10000000)); // this would be the change in your code
Wire.write(uint8_t(0b10000000));
I'm a bit confused as to why you are changing the setting for both alarms (ok, I've not studied your code too closely, but from reading your comments).
But anyway, this is what I do (Alarm2):
Set alarm time to 0x0B and 0x0C
Set the A2M4 flag. I personally read the register first, OR it with the appropriate value (in this case 0b10000000) and then write it back.
Set the A2IE flag (same method...)
Clear A2F (and again...)
I would also advocate using FALLING interrupts.
system
November 7, 2013, 9:13am
5
Ok, along with what has already been suggested, I had to fix a few things. I got the DS3231 to send an interrupt at the correct time and the arduino responds, but it seems like it just freezes, because the LED never lights, and I get no serial output past the second before the interrupt is sent (22:59:59). Also, is it necessary to call loop() at the end of the alarm function or will it automatically go back to loop?
#include <Wire.h>
#define DS3231 0x68
byte seconds;
byte minutes;
byte hours;
byte day;
byte month;
byte year;
byte alarmhour;
byte alarmminute;
void setup () {
pinMode(13, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(A2, OUTPUT);
digitalWrite(A3, HIGH);
digitalWrite(A2, LOW);
attachInterrupt(0, alarm, FALLING); //set up alarm interrupt, and call alarm function
Serial.begin(9600);
Wire.begin();
setTime();
setAlarm();
Wire.beginTransmission(0x68); // address DS3231
Wire.write(0x0E); // select register
Wire.write(B00000110); // write register bitmap, bit 7 is /EOSC
Wire.endTransmission();
clearA2F();
}
void loop() {
getTime();
getDate();
getAlarm();
Serial.print(bcdToDec(hours));
Serial.print(":");
Serial.print(bcdToDec(minutes));
Serial.print(":");
Serial.print(bcdToDec(seconds));
Serial.print(" ");
Serial.print(bcdToDec(month));
Serial.print("-");
Serial.print(bcdToDec(day));
Serial.print("-");
Serial.println(bcdToDec(year));
Serial.print(bcdToDec(alarmhour));
Serial.print(":");
Serial.println(bcdToDec(alarmminute));
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.endTransmission();
byte status = Wire.requestFrom(DS3231, 1);
Serial.println(status, BIN);
Wire.beginTransmission(DS3231);
Wire.write(0x0E);
Wire.endTransmission();
byte control = Wire.requestFrom(DS3231, 1);
Serial.println(control, BIN);
delay(1000);
}
//GET TIME
void getTime() {
Wire.beginTransmission(DS3231);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231, 3);
while(Wire.available()) {
seconds = Wire.read();
minutes = Wire.read();
hours = Wire.read();
}
}
//GET DATE
void getDate() {
Wire.beginTransmission(DS3231);
Wire.write(0x04);
Wire.endTransmission();
Wire.requestFrom(DS3231, 3);
while(Wire.available()) {
day = Wire.read();
month = Wire.read();
year = Wire.read();
}
}
//GET ALARM
void getAlarm() {
Wire.beginTransmission(DS3231);
Wire.write(0x0B);
Wire.endTransmission();
Wire.requestFrom(DS3231, 2);
while(Wire.available())
{
alarmminute = Wire.read();
alarmhour = Wire.read();
}
bitClear(alarmminute, 7);
bitClear(alarmhour, 7);
bitClear(alarmhour, 6);
}
//SET TIME
void setTime() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x00);
Wire.write(B00110000);
Wire.write(B01011001);
Wire.write(B00100010);
Wire.endTransmission();
}
//SET DATE
void setDate() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x04);
Wire.write(B00000010);
Wire.write(B00010001);
Wire.write(B00010011);
Wire.endTransmission();
}
void setAlarm() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x0B);// alarm2
Wire.write(B00000000);
Wire.write(B00100011);
Wire.write(B10000000);// alarm mask, match minutes and hours
Wire.endTransmission();
}
void alarm() {
clearA2F();
Serial.println("ALARM");
digitalWrite(13, HIGH);
//clear interrupt flag to shut alarm off TODO
delay(1000);
}
//clear A2F
void clearA2F() {
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.requestFrom(DS3231, 1);
while(Wire.available()) {
byte tmp = Wire.read();
bitClear(tmp, 1);
Wire.write(tmp);
}
Wire.endTransmission();
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
You should just use the interrupt service routine to set a flag, nothing more. Then act upon the setting of that flag within loop().
And don't forget to make your flag volatile.
system
November 8, 2013, 10:39am
7
Bingo! Works great!
#include <Wire.h>
#define DS3231 0x68
byte seconds;
byte minutes;
byte hours;
byte day;
byte month;
byte year;
byte alarmhour;
byte alarmminute;
volatile bool alarmflag = 0;
void setup () {
pinMode(12, INPUT_PULLUP);
pinMode(13, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(A2, OUTPUT);
digitalWrite(A3, HIGH);
digitalWrite(A2, LOW);
attachInterrupt(0, alarm, FALLING); //set up alarm interrupt, and call alarm function
Serial.begin(9600);
Wire.begin();
setTime();
setAlarm();
Wire.beginTransmission(0x68); // address DS3231
Wire.write(0x0E); // select register
Wire.write(B00000110); // write register bitmap, bit 7 is /EOSC
Wire.endTransmission();
clearA2F();
}
void loop() {
if (alarmflag == 1) {
clearA2F();
while (digitalRead(12) == HIGH) {
Serial.println("ALARM");
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
}
alarmflag = 0;
}
getTime();
getDate();
getAlarm();
Serial.print(bcdToDec(hours));
Serial.print(":");
Serial.print(bcdToDec(minutes));
Serial.print(":");
Serial.print(bcdToDec(seconds));
Serial.print(" ");
Serial.print(bcdToDec(month));
Serial.print("-");
Serial.print(bcdToDec(day));
Serial.print("-");
Serial.println(bcdToDec(year));
Serial.print(bcdToDec(alarmhour));
Serial.print(":");
Serial.println(bcdToDec(alarmminute));
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.endTransmission();
byte status = Wire.requestFrom(DS3231, 1);
Serial.println(status, BIN);
Wire.beginTransmission(DS3231);
Wire.write(0x0E);
Wire.endTransmission();
byte control = Wire.requestFrom(DS3231, 1);
Serial.println(control, BIN);
delay(1000);
}
//GET TIME
void getTime() {
Wire.beginTransmission(DS3231);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231, 3);
while(Wire.available()) {
seconds = Wire.read();
minutes = Wire.read();
hours = Wire.read();
}
}
//GET DATE
void getDate() {
Wire.beginTransmission(DS3231);
Wire.write(0x04);
Wire.endTransmission();
Wire.requestFrom(DS3231, 3);
while(Wire.available()) {
day = Wire.read();
month = Wire.read();
year = Wire.read();
}
}
//GET ALARM
void getAlarm() {
Wire.beginTransmission(DS3231);
Wire.write(0x0B);
Wire.endTransmission();
Wire.requestFrom(DS3231, 2);
while(Wire.available())
{
alarmminute = Wire.read();
alarmhour = Wire.read();
}
bitClear(alarmminute, 7);
bitClear(alarmhour, 7);
bitClear(alarmhour, 6);
}
//SET TIME
void setTime() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x00);
Wire.write(B00110000);
Wire.write(B01011001);
Wire.write(B00100010);
Wire.endTransmission();
}
//SET DATE
void setDate() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x04);
Wire.write(B00000010);
Wire.write(B00010001);
Wire.write(B00010011);
Wire.endTransmission();
}
void setAlarm() {
//write temporary bytes to register
Wire.beginTransmission(DS3231);
Wire.write(0x0B);// alarm2
Wire.write(B00000000);
Wire.write(B00100011);
Wire.write(B10000000);// alarm mask, match minutes and hours
Wire.endTransmission();
}
void alarm() {
alarmflag = 1;
}
//clear A2F
void clearA2F() {
Wire.beginTransmission(DS3231);
Wire.write(0x0F);
Wire.requestFrom(DS3231, 1);
while(Wire.available()) {
byte tmp = Wire.read();
bitClear(tmp, 1);
Wire.write(tmp);
}
Wire.endTransmission();
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}