I have a 1940s Westminster clock that chimes 4 times per hour and strikes the hours, we recently moved it and now it disturbs our sleep so I decided to disable the chime and strike trains during the night using an Arduino.
After testing with an UNO r3 I built a Veroboard with an Atmega328p running on the internal clock at 8MHz. It's powered from a 2000mah 5v lithium power bank, the battery was lasting a few days so I added a regulator to drop the voltage to 3.3v this improved the battery life to about 6 days (I wind the clock every 7 days and so would prefer to change the battery at the same time)
I didn't want to add a real time clock so I'm counting the strikes using a microswitch on the star wheel of the clock, this microswitch was connected to digital pin 5. It's been running fine for several weeks but I decided to make it sleep to improve the battery life.
My programming knowledge is limited so I decided to use a library (Sleep_n0m1.h) I initially tested it on a breadboard with a momentary button instead of the microswitch. To make it wake when it strikes I connected the microswitch to an external interrupt pin digital pin 2 (int0).
Once tested I moved it to the clock and found it was not always disabling or enabling the chimes, so I did some more testing and found with or without the sleep code running it was not reading all the strikes, I tried the microswitch connected to digital pin 2 (int0) and digital pin 3 (int1) but it was the same, when I moved it back to digital pin 5 it worked consistently without any issues.
See code and a circuit diagram I have only included the code and components needed to reproduce the issue, I get the same issue using an UNO r3, it seems to be a combination of using the external interrupt pins and the microswitch on the clock star wheel but I have no clue why and hope that it makes sense to someone so they can point me in the right direction, thanks.
#include <Sleep_n0m1.h>
Sleep sleep;
// this constant won't change:
const int switchPin = 2;
const int ledPin = 8;
const long delayforCheck = 30000;
const long delayforClear = 60000;
// Variables will change:
int strikeCounter = 0; // counter for the number of strikes
int switchState = 0; // current state of the switch
int lastswitchState = 0; // previous state of the switch
unsigned long previousMillis = 0;
unsigned long previousMillis1 = 0;
void setup() {
pinMode(switchPin, INPUT);
pinMode(ledPin, OUTPUT);
// Serial.begin(9600);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
}
void loop() {
// read the pushswitch input pin:
unsigned long currentMillis = millis();
unsigned long currentMillis1 = millis();
switchState = digitalRead(switchPin);
// compare the switchState to its previous state
if (switchState != lastswitchState) {
// if the state has changed, increment the counter
if (switchState == HIGH) {
previousMillis = currentMillis;
previousMillis1 = currentMillis1;
// if the current state is HIGH then the switch went from off to on:
strikeCounter++;
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
// Serial.println(strikeCounter);
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastswitchState = switchState;
// After 60 seconds clear strikeCounter
if (currentMillis - previousMillis >= delayforClear) {
strikeCounter = 0;
}
// After 30 seconds do something then clear strikeCounter
if (currentMillis1 - previousMillis1 >= delayforCheck) {
strikeCounter = 0;
}
previousMillis1 = currentMillis1;
if (strikeCounter == 0) {
// Serial.println("Sleep");
delay(500);
sleep.pwrDownMode(); //set sleep mode
//Sleep till interrupt pin equals a particular state.
//In this case "low" is state 0.
sleep.sleepPinInterrupt(switchPin, HIGH); //(interrupt Pin Number, interrupt State)
// Serial.println("Wake");
}
}