How to auto reset

Hi,

I have utilised a programme using an Uno, for a countdown timer. I have tried to contact the original designer but without success. The coding is open source so I believe its ok to list this below. If someone could advise what additional code is required to enable this timer to auto reset 1-2 seconds from reaching 00:00 I would be very grateful. Thanking you in advance.

Original code

//-----------------------------------------------------

// Kitchen Timer with TM1637 Display

// by: mircemk

// License: GNU GPl 3.0

// Created: April 2025

//-----------------------------------------------------

#include <TM1637Display.h>

// Pin definitions

#define CLK 2

#define DIO 3

#define POT_PIN A0

#define START_BUTTON 4

#define RESET_BUTTON 5

#define BUZZER_PIN 6

#define RANGE_BUTTON 7

// Constants

#define QUANTIZE_INTERVAL 10

#define POT_SMOOTHING 30

#define POT_READ_DELAY 50

#define ALARM_FREQ 500

#define ALARM_ON_TIME 200

#define ALARM_OFF_TIME 200

#define COLON_ON_TIME 500

#define COLON_OFF_TIME 500

#define RANGE_DISPLAY_TIME 1000

#define BUTTON_DEBOUNCE_TIME 300

// Timer ranges in seconds

const int TIMER_RANGES[] = {300}; // 30min

const int NUM_RANGES = 1;

// Display instance

TM1637Display display(CLK, DIO);

// Variables

unsigned long previousMillis = 0;

const long interval = 1000;

bool timerRunning = false;

int remainingTime = 0;

bool colonState = true;

unsigned long lastBuzzTime = 0;

unsigned long lastColonToggle = 0;

bool alarmOn = false;

bool displayOn = true;

int lastDisplayedTime = -1;

unsigned long lastPotRead = 0;

unsigned long lastDisplayFlash = 0;

int currentRangeIndex = 2; // Start with 60min range (index 2)

unsigned long rangeDisplayStartTime = 0;

bool showingRange = false;

unsigned long lastRangeButtonPress = 0;

// State enumeration

enum TimerState {

IDLE,

SHOWING_RANGE,

RUNNING,

ALARMING

};

TimerState currentState = IDLE;

void setup() {

pinMode(START_BUTTON, INPUT_PULLUP);

pinMode(RESET_BUTTON, INPUT_PULLUP);

pinMode(RANGE_BUTTON, INPUT_PULLUP);

pinMode(BUZZER_PIN, OUTPUT);

display.setBrightness(0x0a);

updateDisplay(quantizeTime(readSmoothedPot()));

}

void loop() {

unsigned long currentMillis = millis();

switch(currentState) {

case SHOWING_RANGE:

  // Stay in range display mode until time elapsed

  if (currentMillis - rangeDisplayStartTime >= RANGE_DISPLAY_TIME) {

    currentState = IDLE;

    lastDisplayedTime = -1;  // Force pot reading update

  } else {

    // Keep showing range

    displayRange(TIMER_RANGES\[currentRangeIndex\]);

    return;  // Skip all other processing while showing range

  }

  break;

  

case IDLE:

  // Handle range button

  if (digitalRead(RANGE_BUTTON) == LOW) {

    if (currentMillis - lastRangeButtonPress >= BUTTON_DEBOUNCE_TIME) {

      currentRangeIndex = (currentRangeIndex + 1) % NUM_RANGES;

      rangeDisplayStartTime = currentMillis;

      lastRangeButtonPress = currentMillis;

      currentState = SHOWING_RANGE;

      displayRange(TIMER_RANGES\[currentRangeIndex\]);

      return;  // Exit loop immediately after changing to range display

    }

  }

  

  // Handle potentiometer input

  if (currentMillis - lastPotRead > POT_READ_DELAY) {

    lastPotRead = currentMillis;

    int potTime = quantizeTime(readSmoothedPot());

    if (potTime != lastDisplayedTime) {

      colonState = true;

      updateDisplay(potTime);

      lastDisplayedTime = potTime;

    }

  }

  

  // Handle start button

  if (digitalRead(START_BUTTON) == LOW) {

    delay(50);

    if (digitalRead(START_BUTTON) == LOW) {

      remainingTime = quantizeTime(readSmoothedPot());

      currentState = RUNNING;

      previousMillis = currentMillis;

      lastDisplayedTime = -1;

      colonState = true;

      lastColonToggle = currentMillis;

    }

  }

  break;

  

case RUNNING:

  // Handle colon blinking

  if (colonState && (currentMillis - lastColonToggle >= COLON_ON_TIME)) {

    colonState = false;

    lastColonToggle = currentMillis;

    updateDisplay(remainingTime);

  }

  else if (!colonState && (currentMillis - lastColonToggle >= COLON_OFF_TIME)) {

    colonState = true;

    lastColonToggle = currentMillis;

    updateDisplay(remainingTime);

  }

  

  // Update timer

  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    if (remainingTime > 0) {

      remainingTime--;

      updateDisplay(remainingTime);

    }

    if (remainingTime == 0) {

      currentState = ALARMING;

    }

  }

  

  // Check reset button

  if (digitalRead(RESET_BUTTON) == LOW) {

    delay(50);

    if (digitalRead(RESET_BUTTON) == LOW) {

      resetTimer();

    }

  }

  break;

  

case ALARMING:

  handleAlarm();

  if (digitalRead(RESET_BUTTON) == LOW) {

    delay(50);

    if (digitalRead(RESET_BUTTON) == LOW) {

      resetTimer();

    }

  }

  break;

}

}

void displayRange(int rangeInSeconds) {

int minutes = rangeInSeconds / 60;

uint8_t segments[4];

segments[0] = display.encodeDigit(minutes / 10);

segments[1] = display.encodeDigit(minutes % 10) | 0x80; // Force colon on

segments[2] = display.encodeDigit(0);

segments[3] = display.encodeDigit(0);

display.setSegments(segments);

}

int readSmoothedPot() {

long total = 0;

for (int i = 0; i < POT_SMOOTHING; i++) {

total += analogRead(POT_PIN);

delay(1);

}

int average = total / POT_SMOOTHING;

return map(average, 0, 1023, 0, TIMER_RANGES[currentRangeIndex]);

}

int quantizeTime(int seconds) {

int quantized = (seconds / QUANTIZE_INTERVAL) * QUANTIZE_INTERVAL;

return constrain(quantized, 0, TIMER_RANGES[currentRangeIndex]);

}

void updateDisplay(int timeInSeconds) {

if (currentState == ALARMING && !displayOn) {

display.clear();

return;

}

int minutes = timeInSeconds / 60;

int seconds = timeInSeconds % 60;

uint8_t segments[4];

segments[0] = display.encodeDigit(minutes / 10);

segments[1] = display.encodeDigit(minutes % 10);

segments[2] = display.encodeDigit(seconds / 10);

segments[3] = display.encodeDigit(seconds % 10);

if (colonState) {

segments\[1\] |= 0x80;

}

display.setSegments(segments);

lastDisplayedTime = timeInSeconds;

}

void handleAlarm() {

unsigned long currentMillis = millis();

// Handle display flashing

if (currentMillis - lastDisplayFlash >= 500) {

lastDisplayFlash = currentMillis;

displayOn = !displayOn;

updateDisplay(0);

}

// Handle intermittent alarm sound

if (currentMillis - lastBuzzTime >= (alarmOn ? ALARM_ON_TIME : ALARM_OFF_TIME)) {

lastBuzzTime = currentMillis;

alarmOn = !alarmOn;



if (alarmOn) {

  tone(BUZZER_PIN, ALARM_FREQ);

} else {

  noTone(BUZZER_PIN);

}

}

}

void resetTimer() {

currentState = IDLE;

timerRunning = false;

noTone(BUZZER_PIN);

alarmOn = false;

displayOn = true;

colonState = true;

lastDisplayedTime = -1;

updateDisplay(quantizeTime(readSmoothedPot()));

}

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

Please post your full sketch, using code tags when you do

Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

It is also helpful to post error messages in code tags as it makes it easier to scroll through them and copy them for examination

Your topic has nothing to do with the Website and Forum category of the forum and therefore has been moved.

Please use code tags when posting code; see https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum/679966#posting-code

It would be better to recognize the author and post a link to his work and have indeed the code here with code tags.


You can probably make the timer auto-reset 2 seconds before it hits 0 by checking if remainingTime is 2 in the RUNNING state and calling resetTimer() at that point

That seems like a totally useless funcion for a kitchen timer.
Why would you want to do that?

1 Like

Because I have made a gym timer (work and rest) I have successfully done this by utilising two cascade timers but its a bit of a waste of circuitry and effort when it could be done by simple code - of which is beyond me.

Why don’t you express the actual needs to chatGPT (if you don’t want to learn ) - you are likely to get a relevant answer

So how did you determine that modifying the code you posted (incorrectly) would do what you want?