Pages: [1]   Go Down
Author Topic: Problems with DS3231 Library  (Read 1589 times)
0 Members and 1 Guest are viewing this topic.
Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm wondering if anyone is using this library that Eric Ayars released quite some time ago.  I modified it so it would compile under v1.0.x of the IDE.  Everything I've tried to do with this library so far worked without a problem, from setting the clock, setting simple alarms, reading the clock, etc., etc.  Till now.  I've run into what seems to be a bug but I can't verify that it is a bug or not, or if the example file provided with the library has a problem.

Basically, when setting the alarms, the syntax for Alarm 1 is:
Code:
Clock.setA1Time(DoW, Hour, Minute+1, Second, 0x0, true, false, false);
... and the syntax for Alarm 2 is similar except it doesn't have a "Second" variable to pass.  Alarm 2 doesn't support that.

The issue here is that whatever I put in for the AlarmBits part (in the above example it's the 0x0) for Alarm 2, it seems to get overwritten by whatever the bits are for Alarm 1.  In the _set example file, I changed the setA1Time() syntax to have 0b1000 as AlarmBits and setA2Time syntax to have 0b111.  However when I read it back, both of them had 0b1000 in them.

I thought it was a fluke so I changed the bits only on Alarm 2 but nothing changed when I read the data back.  Then I changed the bits on Alarm 1 and sure enough, reading the data back and both alarms have the same information, namely what I just changed Alarm 1 to.

So at this point I don't know where the problem sits.  For one, the AlarmBits for Alarm 2 should only be 0b000 to 0b111, so why do I see 0b0000 (four digits), I don't know.  And second I don't understand why it's copying whatever the bits are for Alarm 1 into Alarm 2.

I've attached the library here in the hopes that someone can look over it and figure out what may be the problem.  The author doesn't seem to be responding or supporting it anymore.  At least, his last posting was early last year and I haven't gotten a response from him from the messages I've sent.

* DS3231.zip (9.24 KB - downloaded 28 times.)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a problem with adding attachments to posts this week. Can you post a link to where you got the library?
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Of course.  The original download came from Eric Ayars' website, located here
http://hacks.ayars.org/2011/04/ds3231-real-time-clock.html

Keep in mind that it was written pre 1.0x, so you have to make the necessary changes to the example files.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The AlarmBits variable defines the bits for BOTH alarms. You need to use bitRead() and bitWrite() to diddle with the bits for each alarm individually.

Code:
/* Retrieves everything you could want to know about alarm
 * one.
 * A1Dy true makes the alarm go on A1Day = Day of Week,
 * A1Dy false makes the alarm go on A1Day = Date of month.
 *
 * byte AlarmBits sets the behavior of the alarms:
 * Dy A1M4 A1M3 A1M2 A1M1 Rate
 * X 1 1 1 1 Once per second
 * X 1 1 1 0 Alarm when seconds match
 * X 1 1 0 0 Alarm when min, sec match
 * X 1 0 0 0 Alarm when hour, min, sec match
 * 0 0 0 0 0 Alarm when date, h, m, s match
 * 1 0 0 0 0 Alarm when DoW, h, m, s match
 *
 * Dy A2M4 A2M3 A2M2 Rate
 * X 1 1 1 Once per minute (at seconds = 00)
 * X 1 1 0 Alarm when minutes match
 * X 1 0 0 Alarm when hours and minutes match
 * 0 0 0 0 Alarm when date, hour, min match
 * 1 0 0 0 Alarm when DoW, hour, min match
 */
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It shouldn't be.  At least, if I understand the code correctly, it's not.  If I read the top of A1's setA1Time function, I see this:
Code:
void DS3231::setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM) {
// Sets the alarm-1 date and time on the DS3231, using A1* information
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x07); // A1 starts at 07h
// Send A1 second and A1M1
Wire.write(decToBcd(A1Second) | ((AlarmBits & 0b00000001) << 7));
// Send A1 Minute and A1M2
Wire.write(decToBcd(A1Minute) | ((AlarmBits & 0b00000010) << 6));
        ...
}
And for A2:
Code:
void DS3231::setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM) {
// Sets the alarm-2 date and time on the DS3231, using A2* information
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x0b); // A1 starts at 0bh    <-- this should read A2 starts at 0bh
// Send A2 Minute and A2M2
Wire.write(decToBcd(A2Minute) | ((AlarmBits & 0b00010000) << 3));
        ...
}
So it appears that they each use the AlarmBits passed to their respective function as opposed to copying from A1.  So what am I missing?  Where does it set both Alarmbits to the same thing?

And even if, let's say A1 is already set to some previous value, and I only set A2, it completely ignores whatever I put in for AlarmBits.  The time gets set properly, but AlarmBits does not.

<note_to_self>Dude, it's time to learn C/C++ ... get a book.</note_to_self>
« Last Edit: January 15, 2013, 12:00:36 pm by KirAsh4 » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It seems easy enough to test. Create a variable. Set the bits for alarm 1. Set the bits for alarm 2. Call the setA1Time() method. Call the setA2Time() method. Call the getA1Time() method. Check the flags for both alarms. Call the getA2Time() method. Check the flags for both alarms.
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's exactly how I figured out that there's a problem.  I created two different variables in my sketch, ARLM1 and ALRM2, with different bits in each (one had 0b1111 and the other 0b100) and passed those variables to setA1Time and setA2Time.  Setting A2 never takes the AlarmBits into account.  When I read things back, A2 reported its bits as 0b1111 (or whatever A1 is set as.)
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The only other thing I can think of attempting is modifying the .cpp file to use two different variables, for example A1AlarmBits and A2Alarmbits as opposed to one single one.  But I still can't figure out why it's not working right now, as written.
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Anyone else feel like taking a stab at this before I start my attempt at hacking the library, hoping I know what I'm actually doing and figure out what's going on?
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, having changed the variables in the different routines to specifically say Alarm1Bits and Alarm2Bits did not make a difference.  Now what I'm seeing is, when I try to read the data back, the bits for Alarm1 get set, but Alarm 2 remains at 0.  Nothing's set.  So, I'm still stuck.

The relevant lines in my sketch that sets the alarms is:
Code:
      Clock.setA1Time(Clock.getDoW(), Clock.getHour(h12, PM), Clock.getMinute(), 30, ALRM1_SET, true, false, false);
      Clock.setA2Time(Clock.getDate(), Clock.getHour(h12, PM), Clock.getMinute(), ALRM2_SET, false, false, false);
      // Turn alarms on
      Clock.turnOnAlarm(1);
      Clock.turnOnAlarm(2);

The variables ALRM1_SET and ALRM2_SET are 0b1000 and 0b111 respectively.  Alarm1 is set properly.  Alarm2 returns 0 when I read the bits back.  The relevant part in the .cpp is:
Code:
void DS3231::setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte Alarm1Bits, bool A1Dy, bool A1h12, bool A1PM) {
// Sets the alarm-1 date and time on the DS3231, using A1* information
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x07); // A1 starts at 07h
// Send A1 second and A1M1
Wire.write(decToBcd(A1Second) | ((Alarm1Bits & 0b00000001) << 7));
// Send A1 Minute and A1M2
Wire.write(decToBcd(A1Minute) | ((Alarm1Bits & 0b00000010) << 6));
// Figure out A1 hour
if (A1h12) {
// Start by converting existing time to h12 if it was given in 24h.
if (A1Hour > 12) {
// well, then, this obviously isn't a h12 time, is it?
A1Hour = A1Hour - 12;
A1PM = true;
}
if (A1PM) {
// Afternoon
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A1Hour) | 0b01100000;
} else {
// Morning
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A1Hour) | 0b01000000;
}
} else {
// Now for 24h
temp_buffer = decToBcd(A1Hour);
}
temp_buffer = temp_buffer | ((Alarm1Bits & 0b00000100)<<5);
// A1 hour is figured out, send it
Wire.write(temp_buffer);
// Figure out A1 day/date and A1M4
temp_buffer = ((Alarm1Bits & 0b00001000)<<4) | decToBcd(A1Day);
if (A1Dy) {
// Set A1 Day/Date flag (Otherwise it's zero)
temp_buffer = temp_buffer | 0b01000000;
}
Wire.write(temp_buffer);
// All done!
Wire.endTransmission();
}

void DS3231::setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte Alarm2Bits, bool A2Dy, bool A2h12, bool A2PM) {
// Sets the alarm-2 date and time on the DS3231, using A2* information
byte temp_buffer;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x0b); // A1 starts at 0bh
// Send A2 Minute and A2M2
Wire.write(decToBcd(A2Minute) | ((Alarm2Bits & 0b00010000) << 3));
// Figure out A2 hour
if (A2h12) {
// Start by converting existing time to h12 if it was given in 24h.
if (A2Hour > 12) {
// well, then, this obviously isn't a h12 time, is it?
A2Hour = A2Hour - 12;
A2PM = true;
}
if (A2PM) {
// Afternoon
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A2Hour) | 0b01100000;
} else {
// Morning
// Convert the hour to BCD and add appropriate flags.
temp_buffer = decToBcd(A2Hour) | 0b01000000;
}
} else {
// Now for 24h
temp_buffer = decToBcd(A2Hour);
}
// add in A2M3 bit
temp_buffer = temp_buffer | ((Alarm2Bits & 0b00100000)<<2);
// A2 hour is figured out, send it
Wire.write(temp_buffer);
// Figure out A2 day/date and A2M4
temp_buffer = ((Alarm2Bits & 0b01000000)<<1) | decToBcd(A2Day);
if (A2Dy) {
// Set A2 Day/Date flag (Otherwise it's zero)
temp_buffer = temp_buffer | 0b01000000;
}
Wire.write(temp_buffer);
// All done!
Wire.endTransmission();
}

Ideas anyone?  I really need to get this second alarm working for my project.
Logged

Temple, Texas
Offline Offline
Sr. Member
****
Karma: 14
Posts: 360
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What happens if you try to use only the alarm2? something like
  setA2Time(...)
  getA2Time(...)

Do the AlarmBits still come back as 0?

Also are the other values coming back ok? (day, hour, min, ...)

John
« Last Edit: January 27, 2013, 09:31:54 am by johncc » Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What happens if you try to use only the alarm2? something like
  setA2Time(...)
  getA2Time(...)

Do the AlarmBits still come back as 0?
Yep.

Also are the other values coming back ok? (day, hour, min, ...)
Those are fine.  It correctly sets the time of the alarm.  It just doesn't seem to set the alarm bits which determines when that alarm goes off.
Logged

Offline Offline
Edison Member
*
Karma: 43
Posts: 1557
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the library, the Alarmbits hold the values for BOTH alarms and are ordered like this:
0 A2.2 A2.1 A2.0 A1.3 A1.2 A1.1 A1.0

So if you want to set alarm 1 to zero and alarm 2 to 111 you would set Alarmbits to 0B01110000

Pete
Logged

Where are the Nick Gammons of yesteryear?

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, now we're getting somewhere.  I was under the impression I only needed to pass the bits relevant to each alarm, as opposed to everything together.   So this appears to be working now.  I need to rewrite my sketch now to account for that.

Thanks!
« Last Edit: January 27, 2013, 06:47:53 pm by KirAsh4 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The AlarmBits are sent to the DS3231 correctly, but there is a bug in reading back.
The problem is that AlarmBits in getA1Time and getA2Time were not initialized to 0x00.
AlarmBits is ORd with the correct bit each time, but any random bits will remain.
Fix as follows:
Change DS3231.cpp line 275 (first time AlarmBits is used in getA1Time) from
AlarmBits   = AlarmBits | (temp_buffer & 0b10000000)>>7;   
to
AlarmBits   = (temp_buffer & 0b10000000)>>7;

Similarly, also fix the bug in getA2Time, line 318
AlarmBits   = AlarmBits | (temp_buffer & 0b10000000)>>3;   
to
AlarmBits   = (temp_buffer & 0b10000000)>>3;

Then it works 100%.
pvz

Logged

Pages: [1]   Go Up
Jump to: