Hello!
What I want to do: increase minutes displayed on my gLCD, with the push button (hours will be implemented after I make it work).
What I did: I set arduino in SLEEP_MODE_PWR_DOWN, with the "wake up" every 60 seconds, together with possible interrupt from button connected to INT4 on pin 7. Interrupt works correctly.
So I set a flag inside it, and put an if-statement in the loop() which (at least I think it should) checks the flag and accordingly increments the tm.Minute part of the tm structure.
What is wrong: Minutes are increased, BUT clock increments 8(!) minutes every 1 minute, and what is even more important the whole function responsible for correct time display somehow DOES allow minutes to exceed 60 After overflow -> hours are NOT incremented
Jugding by that magic 8 value, I discovered that is the exact number of my loop() entering sleep mode (because I wanted to have longer sleep than 8 seconds).
However, I have no idea how to discern the difference for the program, something like:
"when entering watchdog interrupt do not change the flag, instead make an additional interrupt ONLY for button press, where the flag should be changed".
Then I guess everything should be fine.
Does anybody know how to write such a interrupt routine only for button, without changing the sleep&wake operation?
Or maybe there is an easier way to do that?
Code:
#include "U8glib.h"
#include <Wire.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
tmElements_t tm;
volatile boolean flag;
const int indicatorLed = 13;
U8GLIB_DOGM128 u8g(11, 10, U8G_PIN_NONE); //U8GLIB_DOGM128(cs, a0 [, reset])
void setup()
{
digitalWrite (7, HIGH);
// We start the I2C on the Arduino for communication with the RTC.
Wire.begin();
}
void loop()
{
pinMode(indicatorLed, OUTPUT);
digitalWrite(indicatorLed, LOW);
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
myWatchdogEnable (0b100001);
myWatchdogEnable (0b100001);
myWatchdogEnable (0b100001);
myWatchdogEnable (0b100001);
myWatchdogEnable (0b100001);
myWatchdogEnable (0b100001);//48s
myWatchdogEnable (0b100000);//+4s
myWatchdogEnable (0b000110);//+1s
myWatchdogEnable (0b000101);//+0.5s
myWatchdogEnable (0b000011);//+0.125s
myWatchdogEnable (0b000010);//+0.0625s
}
void draw(void) {
// graphic commands for drawing including drawgraph()
u8g.setFont(u8g_font_6x12);
//tmElements_t tm;
//RTC.read(tm);
myTime(flag);
u8g.setPrintPos(10, 128);
print2digits(tm.Hour);
u8g.write(':');
print2digits(tm.Minute);
u8g.write(':');
print2digits(tm.Second);
}
//credit to Nick Gammon
void myWatchdogEnable(const byte interval) {
MCUSR = 0; // reset various flags
WDTCSR |= 0b00011000; // see docs, set WDCE, WDE
WDTCSR = 0b01000000 | interval; // set WDIE, and appropriate delay
wdt_reset();
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
attachInterrupt (4, wake, LOW); // allow grounding pin 2 to wake us
sleep_mode(); // now goes to Sleep and waits for the interrupt
detachInterrupt (4);
}
void print2digits(int number) {
if (number >= 0 && number < 10) {
u8g.write('0');
}
u8g.print(number);
}
void drawgraph(void){
//draws a chart
}
ISR(WDT_vect) {
wake(); // disable watchdog
}
// interrupt service routine for when button pressed
void wake ()
{
flag = true;
wdt_disable(); // disable watchdog
} // end of wake
void addMin(tmElements_t &tm){
tm.Minute++;
}
void myTime(bool flag){
if (flag){
RTC.read(tm);
addMin(tm);
RTC.write(tm);
flag = false;
}
}
EDIT: I wanted to add
ISR(INT6_vect){
flag = true;
wdt_disable();
}
but unfortunately it doesn't compile with the error:
Arduino: 1.0.6 (Windows 7), Board: "Arduino Leonardo"
core.a(WInterrupts.c.o): In function__vector_7': D:\ARDUINO\hardware\arduino\cores\arduino/WInterrupts.c:260: multiple definition of
__vector_7'
wszystko.cpp.o:D:\ARDUINO/wszystko.ino:193: first defined here