Often when I’m playing a solo set, I lose track of the time. I’ve tried a small app on the laptop screen, but it covers part of the screen and I tend not to notice it(!) Rather than invest in some kind of clock, I thought I’d put together a solution using an arduino nano and a display I had lying around. The hardware side was straight-forward, though I had to cobble together the various code elements I wanted and so it’s far from well structured!

You switch it on and after a short welcome message(!) use the momentary switch to select the required time and flick the SPST switch to start the count down. The case is something my son made some years ago when he launched a short-lived pedal company. Code & fritzing below.

// stopwatch with 5 minute intervals oct 23
#include <Arduino.h>
#include <TM1637Display.h>
#define CLK_PIN 11
#define DIO_PIN 10
TM1637Display display(CLK_PIN, DIO_PIN);
#define bounceDelay 20    //Minimum delay before regarding a button as being pressed and debounced
#define minButtonPress 3  //Number of times the button has to be detected as pressed before the press is considered to be valid

uint8_t arse[] = {
  SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,  // A
  SEG_E | SEG_G,                                  // r
  SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,          // s
  SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,          // e
};

unsigned long startTime;  // countdown time
unsigned long currentTime;
unsigned long elapsedTime;
const int goButt = 2;  // SPST for alternating betwen set time & start countdown
int currentState = 0;  // checking SPST
int lastState = 0;     // checking SPST
int goState = 0;       // checking SPST
int CLS = 0;           // clear screen

const int timeButt = 3;   // momentary for set time buootn
uint32_t previousMillis;  // Timers to time out bounce duration for each button
uint8_t pressCount;       // Counts the number of times the button is detected as pressed, when count reaches minButtonPress button is regared as debounced
int countdownTime = 10;    // initial interval, incremented once per button press

void setup() {

  display.setBrightness(3);  // Set the brightness of the display (0-7)
  display.setSegments(arse); // say hello
  delay(3000); // wait a bit
  display.clear();  // Clear the display
  pinMode(goButt, INPUT);
  pinMode(timeButt, INPUT);
  digitalWrite(goButt, HIGH);
  digitalWrite(timeButt, HIGH);
}

void loop() {
  if (goState != currentState && currentState == HIGH) {  // set time - how do I clear the display without it looping?
    if (CLS == 0) {                                       //  clear screen
      display.clear();
      CLS = 1;  // rest clear screen
    }
    display.showNumberDecEx(countdownTime, true, 2, 2);
    debounce();
    goState = LOW;
    startTime = millis();  // Record the starting time

  } else {  // if switch thrown, start countdown

    currentTime = millis();                          // Get the current time
    elapsedTime = (currentTime - startTime) / 1000;  // Calculate elapsed time in seconds
    if (elapsedTime <= (countdownTime * 60)) {       // multiply time to seconds
      unsigned long remainingTime = (countdownTime * 60) - elapsedTime;
      unsigned int minutes = remainingTime / 60;
      unsigned int seconds = remainingTime % 60;
      display.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true);  // Display remaining time in Minutes:Seconds format
      CLS = 0;                                                             // reset clear screen
      if (remainingTime == 0) {                                            // when countdown reaches 00:00
        buttonWait(goButt);
      }           // end remainingTime == 0
    }             // end elapsed time
    delay(1000);  // Wait for 1 second
  }
  currentState = digitalRead(goButt);
}  // end loop

void debounce() {
  uint8_t i;
  uint32_t currentMillis = millis();
  if (digitalRead(timeButt)) {       //Input is high, button not pressed or in the middle of bouncing and happens to be high
    previousMillis = currentMillis;  //Set previousMillis to millis to reset timeout
    pressCount = 0;                  //Set the number of times the button has been detected as pressed to 0
  } else {
    if (currentMillis - previousMillis > bounceDelay) {
      previousMillis = currentMillis;  //Set previousMillis to millis to reset timeout
      ++pressCount;
      if (pressCount == minButtonPress) {
        doStuff();  //Button has been debounced. Call function to do whatever you want done.
      }
    }
  }  // end else
}

void doStuff() {
  countdownTime += 5;  // add 5 minutes
  display.clear();     // Clear the display
  display.showNumberDecEx(countdownTime, true, 2, 2);
  if (countdownTime == 65) { countdownTime = 5; }  // reset after maximum
}

void buttonWait(int buttonPin) {
  int buttonState = 0;
  int k;  // loop display count
  while (1) {
    buttonState = digitalRead(buttonPin);
    for (k = 0; k < 7; k++) {
      display.setBrightness(k);
      display.setSegments(arse);
      delay(50);
    }
    display.setBrightness(3);
    if (buttonState == HIGH) {
      return;
    }
  }
}