Hello,
I am working on a kitchen timer for my mother. It involves having one uC keeping track of 4 independent set timers and passing them via I2C to the second one to display. It is supposed to run on batteries, so I wanted to implement the power-down function in the counting uC (I2C slave), which before going to sleep would disable power for the master uC. It works to some extent - it correctly powers down and wakes up several times, but, usually around 8th power-down, it does not wake up. Whenever I pull the WAKEUP pin (connected to empty ISR) low, current consumption rises to around 4 mA, but the Atmega never comes back to full functionality (unless I manually reset it). Microcontroller I'm using is, as mentioned in the title, Atmega 328p and my code is below. Thanks for your help!
#define BUZZER 13
#define INTERVAL 1000
#define PAUSE 50
#define SHUTUP 2
#define WAKEUP 3
#define MASTERPOWER 8
#include <Wire.h>
#include <LowPower.h>
unsigned int timers[] = {0, 0, 0, 0};
unsigned int zeros[] = {0, 0, 0, 0};
bool ringing [] = {false, false, false, false};
bool currentlyIdle = true;
bool nothingToDo = false;
unsigned int lastAction = 0;
void setup() {
// put your setup code here, to run once:
TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS12);
TIMSK1 |= (1 << TOIE1);
TCNT1 = 34286; //setup timer 1 to generate interrupt every one second
Wire.begin(9);
digitalWrite(SDA, 0);
digitalWrite(SCL, 0); //get rid of pullups on i2c lines
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent); //setup i2c
pinMode(SHUTUP, INPUT_PULLUP); //setup interrupt stopping beeping
attachInterrupt(digitalPinToInterrupt(SHUTUP), buzzeroff, FALLING);
pinMode(WAKEUP, INPUT_PULLUP); //setup pin used for waking up
pinMode(MASTERPOWER, OUTPUT);
digitalWrite(MASTERPOWER, HIGH); //provide power for the master
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
for (int i = 0; i < 4; i++) {
if (ringing[i]) {
for (int j = 0; j < (i + 1); j++) {
digitalWrite(BUZZER, HIGH);
delay((INTERVAL - (i * PAUSE)) / (i + 1));
digitalWrite(BUZZER, LOW); //generate beeps according to what timer is over
delay(PAUSE);
}
delay(INTERVAL);
}
}
nothingToDo = memcmp(timers, zeros, 4) == 0;
if (nothingToDo and !currentlyIdle) {
currentlyIdle = true;
}
if (!nothingToDo) {
currentlyIdle = false;
lastAction = millis();
}
if (currentlyIdle and millis() - lastAction > 20000L) { // go to sleep after 20 seconds since last action
digitalWrite(MASTERPOWER, LOW); //turn master device off
attachInterrupt(digitalPinToInterrupt(WAKEUP), wakeUpISR, LOW);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
currentlyIdle = false;
lastAction = millis();
digitalWrite(MASTERPOWER, HIGH); //turn master back on
detachInterrupt(digitalPinToInterrupt(WAKEUP));
}
}
ISR(TIMER1_OVF_vect) { //isr used for decrementing timers' values
TCNT1 = 34286;
for (int i = 0; i < 4; i++) {
if (timers[i] != 0) {
timers[i]--;
if (timers[i] == 0) ringing[i] = true;
else ringing[i] = false;
}
}
}
void requestEvent() {
byte buf[8];
buf[0] = timers[0] >> 8;
buf[1] = timers[0] & 0xff;
buf[2] = timers[1] >> 8;
buf[3] = timers[1] & 0xff;
buf[4] = timers[2] >> 8;
buf[5] = timers[2] & 0xff;
buf[6] = timers[3] >> 8;
buf[7] = timers[3] & 0xff;
Wire.write(buf, 8);
}
void receiveEvent(int howMany) {
byte index = Wire.read();
unsigned int value = Wire.read() << 8 | Wire.read();
timers[index] = value;
}
void buzzeroff() {
for (int i = 0; i < 4; i++) ringing[i] = false;
}
void wakeUpISR() {
}
