Setting up a reset timer
Using a button input to reset a countdown timer mid-count
[Solved] Help with START and RESET counterdown timer
timer with reset
Videos
You can do an almost immediate full reset with watchdog by activating it 'on place'.
wdt_enable(WDTO_15MS); // resets the MCU after 15 milliseconds
while (true);
You can use millis() for timing the reset as any other timed function.
You can use the watchdog timer, but you have to change the way you measure the elapsed time. Try this code:
#include <avr/wdt.h>
unsigned long myTime; // Millis() function time value
unsigned long elapsedTime;
unsigned long timeExpected = 5000; // I want to reset it in every 5 secs for testing.
const int RESET_PIN = 2; // Reset pin's connection
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
myTime = millis();
Serial.println("INIT");
wdt_enable(WDTO_2S); //Enable wdt every two seconds
}
void loop() {
//************RESET HANDLER********************//
elapsedTime = millis() - myTime;
if (elapsedTime > timeExpected) {
Serial.print("RESET");
while (1); //Intentionally halt the program, so the watchdog performs the reset
}
//**********************************************
//****************REST OF THE PROGRAM***********
wdt_reset(); //Ensure one call to this function at least one time in two seconds or less
digitalWrite(LED_BUILTIN, HIGH);
Serial.println(elapsedTime); // prints time since program started
delay(1000);
}
Please note that if you have multiple delays in your program, you have to ensure the call to wdt_reset() in order to prevent unwanted resets. Personally I try not to use delays and would recommend avoid delays as much as possible. You may check out this tutorial if you want to see how to avoid delays. If you achieve avoiding delays you can call wdt_reset() just one time at the begining of the loop.
So I'm getting excited and frustrated as I near the completion of my first complete arduino project.
Right now I'm trying to add a stopwatch (simple count up, reset at button press), and it's driving me a bit loony.
I didn't use the stopwatch code found on the Arduino sight because I wanted to learn and attempt it myself (because I didn't completely understand the code as well).
So I ask for some help here. Right now, when I press my Reset Button and the display correctly shows 00:00. But only for one second, and then it reverts back to the time it was last at.
I have an inkling as to the problem but am not sure how to approach it, thanks for any help.
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
int ledPin = 3;
int buttonPin = 2;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
lcd.begin(20, 4);
lcd.print("Initilizing."); delay(400);
lcd.print(".."); delay(200);
lcd.print("...."); delay(200);
lcd.clear();
}
void loop() {
int buttonState = digitalRead(buttonPin);
static unsigned long timerA = 0;
int refreshRate = 100;
int seconds = millis()/1000;
int minutes = millis()/60000;
if (buttonState == HIGH){
seconds = 0;
minutes = 0;
digitalWrite(ledPin,HIGH); delay(50);
digitalWrite(ledPin,LOW); delay(50);
digitalWrite(ledPin,HIGH); delay(50);
digitalWrite(ledPin,LOW); delay(50);
}
if (millis() - timerA >= refreshRate){
timerA = millis();
lcd.setCursor(0, 3);
lcd.print("Stopwatch: ");
if (seconds > 59) {seconds = seconds - (60 * minutes);}
if (minutes < 10) {lcd.print("0");}
lcd.print(minutes);
lcd.print(":");
if (seconds < 10) {lcd.print("0");}
lcd.print(seconds);
}
}a few things:
avoid timerA as a variable name. There are hardware timers, and this could affect them (though probably not).
Second, I'd suggest breaking out the time display function so you pass it a single parameter and it handles all the formatting and everything. This will make the code considerably cleaner.
Third, Arduino is terrible with this, but if your pins aren't changing during execution, it's better from a code size and execution time standpoint to use #define BUTTONPIN 2 instead of int buttonPin=2; the #define is replaced at compile time, and the pin assignment is stored in program memory and you have one less variable.
Lastly, why it doesn't work is because millis() only resets when the board is reset (or it overflows). you can think of it as time since the board started running (or last overflowed). All you're doing to reset the time is to temporarily set seconds and minutes to 0. Then when you go back into the loop, you set them to millis() again. What you'll need to do is to have a base time (let's call it baseTime). Then do this:
void loop(){
currTime = millis() - baseTime;
if(digitalRead(buttonPin)){
baseTime = millis();
}
dispTime(time);
delay(10); //don't need to update much faster than this
}
that's really all you need for your loop(). Then you have dispTime do a little math and formatting, and you're all set.
You sent them to 0 then when the loop starts again you reset them to millis()/1000 & millis()/60000. Don't reset them at the beginning of the loop.
The following 555 circuit will produce a 170 ms low-going pulse every 24.2 hours. You can adjust the values of the components using this calculator if you want different timing parameters.

Since the reset line of a microcontroller is configured for open-drain (meaning you can connect several inputs to it, which is a good thing since we are taking advantage of that), we need to drive it with a open-drain output. That is what the buffer on the bottom of the circuit is for, to convert the push-pull output of the 555 to open-drain. A typical buffer is one section of a 7407.
Here is the circuit I use which depends on a heartbeat from the arduino and resets the arduino if 8 pulses are missed and also enables the arduino code to know that an external watchdog reset occured

and the Arduino code which can be incorporated into your sketch
//Watchdog
#define ResetDetect 8 // watchdog detect pin, HIGH if a watchdog reset has occured
#define heartbeat 9 // heartbeat pin
int pulseState = LOW; // pulseState used to set the heartbeat pin
long lastbeat = 0; // will store last time the heartbeat pin was updated
long HeartBeatFreq = 500; // interval at which to blink (milliseconds)
boolean ResetHappened; // Set to true if a watchdog reset has occurred
void setup(){
pinMode(ResetDetect, INPUT); // set Watchdog Reset sensing pin as input
digitalWrite(ResetDetect, HIGH);// and turn on pullup
pinMode(heartbeat, OUTPUT); // set the heartbeat pin as output:
// Check if Restarting after Watchdog Reset
// NB must come before heartbeat resets external counter
int ResetSet = digitalRead(ResetDetect);
if (ResetSet == HIGH){
ResetHappened = true;
}
else {
ResetHappened = false;
}
}
void loop(){
// Heartbeat resets external watchdog when pin goes high
if ((long)( millis() - (lastbeat + HeartBeatFreq)) >= 0) {
lastbeat = millis();
// if the LED is off turn it on and vice-versa:
if (pulseState == LOW)
pulseState = HIGH;
else
pulseState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(heartbeat, pulseState);
}
}
If there are long running sections of code the 'heartbeat' could be put into a function and that function called in the appropriate places to avoid unintended timeouts/resets