I'm attempting to use a hardware interrupt to reset the seconds value of a DS1307 Real Time Clock breakout board kit. The RTC.adjust() function works perfectly in other parts of the program (thanks to your previous help). But when I include it in an interrupt function it immediately stops the program.
#include "RTClib.h"
RTC_DS1307 RTC;
void setup() {
...
attachInterrupt(0, Seconds_Reset, RISING); // Interrupt '0' goes to pin D2
if (! RTC.isrunning()) {
RTC.adjust(DateTime(__DATE__, __TIME__));
...
}
void Seconds_Reset()
{
DateTime now = RTC.now();
RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), 0));
}
etc...
The above will compile and run until I trigger the interrupt, which stops the program. If I leave out the "DateTime now = RTC.now();" statement the program will not compile, giving the error message "'now' was not declared in this scope". I believe that the interrupt logic itself works since if I replace the two RTC statements with a simple serial print statement, the program will print the message in response to the trigger and continue to run as expected.
After trying a number of combinations, it seems to me that no form of the RTC function can be used inside of an interrupt function. Maybe because it uses an interrupt of its own like the delay() function? If so, is there a workaround that will reset the RTC seconds value in response to an external asynchronous trigger?
Using RTC.adjust() in a hardware interrupt
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88091
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using RTC.adjust() in a hardware interrupt
Interrupts are disabled on entry to the interrupt service routine. You can re-enable them, but there is some risk involved in that. If you don't need microsecond accuracy (the RTC only has one second resolution), set a flag in the interrupt service routine and catch it on your next pass through the loop.
- dnorbury
- Posts: 25
- Joined: Sat Aug 17, 2013 12:19 pm
Re: Using RTC.adjust() in a hardware interrupt
Bill,
I followed your suggestion:
void Seconds_Reset()
{
interrupts();
DateTime now = RTC.now();
RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute() + 1, 0));
noInterrupts();
}
and, so far, it seems to work. I say "seems" to work because the project still has a few bugs. But I think that at least this one is fixed. Thanks!
I really appreciate your help and Adafruit's willingness to support its users. The answers are solid and really quick. I generally try to buy everything in this area from Adafruit for this reason.
Thanks again (and I'm sure you'll hear from me again...),
Dave
I followed your suggestion:
void Seconds_Reset()
{
interrupts();
DateTime now = RTC.now();
RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute() + 1, 0));
noInterrupts();
}
and, so far, it seems to work. I say "seems" to work because the project still has a few bugs. But I think that at least this one is fixed. Thanks!
I really appreciate your help and Adafruit's willingness to support its users. The answers are solid and really quick. I generally try to buy everything in this area from Adafruit for this reason.
Thanks again (and I'm sure you'll hear from me again...),
Dave
- adafruit_support_bill
- Posts: 88091
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using RTC.adjust() in a hardware interrupt
That looks like it should work. The noInterrupts() at the end is not really necessary. They will be re-enabled on exit from the ISR anyhow.
Please be positive and constructive with your questions and comments.