Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Alarm on DS3231 #94

Closed
Untitled86 opened this issue Jun 23, 2018 · 8 comments
Closed

Add support for Alarm on DS3231 #94

Untitled86 opened this issue Jun 23, 2018 · 8 comments

Comments

@Untitled86
Copy link

I’ve added support for the alarm feature on the DS3231. I’m using that an NPN transistor and a few resistors to run the Huzzah Feather in “deeper sleep” on just 20 microamps (as opposed to 6.5milliamps with the Huzzah using the ESP’s deepsleep).

How can I share this enhancement?

@Untitled86
Copy link
Author

Nobody responded so I'm dumping this here...

Example usage...
`
// flags define what calendar component to be checked against the current time in order
// to trigger the alarm - see datasheet
// A1M1 (seconds) (0 to enable, 1 to disable)
// A1M2 (minutes) (0 to enable, 1 to disable)
// A1M3 (hour) (0 to enable, 1 to disable)
// A1M4 (day) (0 to enable, 1 to disable)
// DY/DT (dayofweek == 1/dayofmonth == 0)
uint8_t flags[5] = { 0, 0, 0, 1, 0 };

DateTime wakeTime = DateTime(rtc.now().unixtime() + (duration / 1e6L));

rtc.clearAlarm();
rtc.setAlarm((uint8_t)wakeTime.second(), (uint8_t)wakeTime.minute(), (uint8_t)wakeTime.hour(), 0, flags);
`

Coded added to RTCLib.cpp

`

// Taken from: https://github.com/rodan/ds3231/blob/master/ds3231.cpp
// Many thanks to Rodan!
void DS3231_set_addr(const uint8_t addr, const uint8_t val)
{
Wire.beginTransmission(DS3231_I2C_ADDR);
Wire.write(addr);
Wire.write(val);
Wire.endTransmission();
}

// control register
void DS3231_set_creg(const uint8_t val)
{
DS3231_set_addr(DS3231_CONTROL_ADDR, val);
}

// Taken from: https://github.com/rodan/ds3231/blob/master/ds3231.cpp
// Many thanks to Rodan!
uint8_t DS3231_get_addr(const uint8_t addr)
{
uint8_t rv;

Wire.beginTransmission(DS3231_I2C_ADDR);
Wire.write(addr);
Wire.endTransmission();

Wire.requestFrom(DS3231_I2C_ADDR, 1);
rv = Wire.read();

return rv;

}

// Taken from: https://github.com/rodan/ds3231/blob/master/ds3231.cpp
// Many thanks to Rodan!
uint8_t DS3231_get_sreg(void)
{
uint8_t rv;
rv = DS3231_get_addr(DS3231_STATUS_ADDR);
return rv;
}

/* control register 0Eh/8Eh
bit7 EOSC Enable Oscillator (1 if oscillator must be stopped when on battery)
bit6 BBSQW Battery Backed Square Wave
bit5 CONV Convert temperature (1 forces a conversion NOW)
bit4 RS2 Rate select - frequency of square wave output
bit3 RS1 Rate select
bit2 INTCN Interrupt control (1 for use of the alarms and to disable square wave)
bit1 A2IE Alarm2 interrupt enable (1 to enable)
bit0 A1IE Alarm1 interrupt enable (1 to enable)
*/
void DS3231_init(const uint8_t ctrl_reg)
{
DS3231_set_creg(ctrl_reg);
}

// Taken from: https://github.com/rodan/ds3231/blob/master/ds3231.cpp
// Many thanks to Rodan!
/*
bit7 OSF Oscillator Stop Flag (if 1 then oscillator has stopped and date might be innacurate)
bit3 EN32kHz Enable 32kHz output (1 if needed)
bit2 BSY Busy with TCXO functions
bit1 A2F Alarm 2 Flag - (1 if alarm2 was triggered)
bit0 A1F Alarm 1 Flag - (1 if alarm1 was triggered)
*/
void DS3231_set_sreg(const uint8_t val)
{
DS3231_set_addr(DS3231_STATUS_ADDR, val);
}

// Taken from: https://github.com/rodan/ds3231/blob/master/ds3231.cpp
// Many thanks to Rodan!
uint8_t dectobcd(const uint8_t val)
{
return ((val / 10 * 16) + (val % 10));
}

// Taken from: https://github.com/rodan/ds3231/blob/master/ds3231.cpp
// Many thanks to Rodan!
//
// flags are: A1M1 (seconds), A1M2 (minutes), A1M3 (hour),
// A1M4 (day) 0 to enable, 1 to disable, DY/DT (dayofweek == 1/dayofmonth == 0)
void RTC_DS3231::setAlarm(const uint8_t s, const uint8_t mi, const uint8_t h, const uint8_t d, const uint8_t * flags)
{

uint8_t t[4] = { s, mi, h, d };
uint8_t i;

Wire.beginTransmission(DS3231_ADDRESS);
Wire.write(DS3231_ALARM1_ADDR);

for (i = 0; i <= 3; i++)
{
    if (i == 3)
    {
        Wire.write(dectobcd(t[3]) | (flags[3] << 7) | (flags[4] << 6));
    }
    else
    {
        Wire.write(dectobcd(t[i]) | (flags[i] << 7));
	}
}

Wire.endTransmission();

DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);

}

void RTC_DS3231::clearAlarm(void)
{
uint8_t reg_val;

reg_val = DS3231_get_sreg() & ~DS3231_A1F;
DS3231_set_sreg(reg_val);

}

boolean RTC_DS3231::begin(void) {
Wire.begin();
DS3231_init(DS3231_INTCN);
return true;
}
`

Code added to RTCLib.h

`
#define DS3231_ALARM1_ADDR 0x07
#define DS3231_STATUS_ADDR 0x0F
#define DS3231_I2C_ADDR 0x68
#define DS3231_CONTROL_ADDR 0x0E
#define DS3231_INTCN 0x4
#define DS3231_A1IE 0x1
#define DS3231_A1F 0x1

class RTC_DS3231 {
public:
boolean begin(void);
static void adjust(const DateTime& dt);
static void clearAlarm();
static void setAlarm(const uint8_t s, const uint8_t mi, const uint8_t h, const uint8_t d, const uint8_t * flags);
bool lostPower(void);
static DateTime now();
static Ds3231SqwPinMode readSqwPinMode();
static void writeSqwPinMode(Ds3231SqwPinMode mode);
};
`

@Untitled86
Copy link
Author

I'm ready to push my changes if someone gives me access. Otherwise, there's the code.

@NuclearPhoenixx
Copy link

Thanks for your code, that's neat, I don't know why Adafruit didn't add this to the functions. By the way, you might also be interested in this lib right here https://github.com/JChristensen/DS3232RTC; they created something similar

@edgar-bonet
Copy link
Contributor

@Untitled86: Have you considered making a proper pull request?

@Untitled86
Copy link
Author

@edgar-bonet - Thanks, I'll do that next time.

@ClydeBarron
Copy link

Hello,
like you Untitled86 I need to leverage the DS3231 alarms to wake my circuit up to conserve power.

I've moddified my RTClib.h file with your additions above. Seems simple enough.

Though in RTClib.cpp I'm not sure where to copy over code. I'm assuming your RTClib.cpp is in addition to the existing code i.e. drop it in after
,
write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
,
Which is the end of the // RTC_DS3231 implementation section

OR
Do I replace existing code in RTC_DS3231 implementation section

Please advise

@ripper121
Copy link

push

@drak7
Copy link
Contributor

drak7 commented Oct 9, 2019

Please submit this as a PR and we'll merge it!

@drak7 drak7 closed this as completed Oct 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants