/*
Four digit Countdown Timer
Written for common cathode
In a real circuit the digit pins should have transistor drivers.
TODO: implement increment / decrement
*/
const int START_TIME = 15; // default seconds to countdown from
const int NUM_BTNS = 3;
const int NUM_DIGITS = 4;
const int BTN_PINS[] = {A3, A2, A1};
const int BUZZ_PIN = A4;
const int COLON_PIN = A0;
const int DIG_PINS[] = {2, 3, 4, 5};
const int SEG_PINS[] = {11, 13, 7, 9, 10, 12, 6, 8};
const bool DIGITS[][8] = {
// A B C D E F G DP
{1, 1, 1, 1, 1, 1, 0, 0}, // 0
{0, 1, 1, 0, 0, 0, 0, 0}, // 1
{1, 1, 0, 1, 1, 0, 1, 0}, // 2
{1, 1, 1, 1, 0, 0, 1, 0}, // 3
{0, 1, 1, 0, 0, 1, 1, 0}, // 4
{1, 0, 1, 1, 0, 1, 1, 0}, // 5
{1, 0, 1, 1, 1, 1, 1, 0}, // 6
{1, 1, 1, 0, 0, 0, 0, 0}, // 7
{1, 1, 1, 1, 1, 1, 1, 0}, // 8
{1, 1, 1, 1, 0, 1, 1, 0}, // 9
{0, 0, 0, 0, 0, 0, 0, 0} // blank
};
const unsigned long ONE_SEC = 1000;
// function returns which button was pressed, or 0 if none
int checkButtons() {
static int btnState[NUM_BTNS];
static int oldBtnState[NUM_BTNS];
int btnPressed = 0;
for (int i = 0; i < NUM_BTNS; i++) {
btnState[i] = digitalRead(BTN_PINS[i]); // check each button
if (btnState[i] != oldBtnState[i]) { // if it changed
oldBtnState[i] = btnState[i]; // remember state for next time
if (btnState[i] == 0) { // was just pressed
btnPressed = i + 1;
}
delay(20); // debounce
}
}
return btnPressed;
}
void writeDigit(int digit, int value) {
for (int seg = 0; seg < 8; seg++) {
digitalWrite(SEG_PINS[seg], DIGITS[value][seg]); // !DIGITS for common anode
}
digitalWrite(DIG_PINS[digit], LOW); // invert for common anode
digitalWrite(DIG_PINS[digit], HIGH); // invert for common anode
}
void updateDisplay(int value) {
int minutes = value / 60;
int seconds = value % 60;
writeDigit(0, (minutes / 10) ? (minutes / 10) : 10);
writeDigit(1, minutes % 10);
writeDigit(2, seconds / 10);
writeDigit(3, seconds % 10);
}
void setup() {
Serial.begin(115200);
for (int button = 0; button < NUM_BTNS; button++) {
pinMode(BTN_PINS[button], INPUT_PULLUP);
}
pinMode(BUZZ_PIN, OUTPUT);
pinMode(COLON_PIN, OUTPUT);
for (int digit = 0; digit < NUM_DIGITS; digit++) {
pinMode(DIG_PINS[digit], OUTPUT);
}
for (int segment = 0; segment < 8; segment++) {
pinMode(SEG_PINS[segment], OUTPUT);
}
digitalWrite(COLON_PIN, HIGH);
}
void loop() {
static bool isDone = true;
static bool isRunning = false;
static int count = START_TIME;
static unsigned long prevTime = 0;
// check buttons
int wasPressed = checkButtons();
if (wasPressed == 1) {
if (isDone) { // start / restart counter
isDone = false;
isRunning = true;
Serial.println("Running");
count = START_TIME;
} else { // pause / unpause counter
isRunning = !isRunning;
Serial.println(isRunning ? "Running" : "Paused");
}
prevTime = millis();
} else if (wasPressed == 2) {
Serial.println("Inc");
} else if (wasPressed == 3) {
Serial.println("Dec");
}
// every ONE_SEC if running
if (millis() - prevTime >= ONE_SEC && isRunning) {
count--;
if (count <= 0) { // time's up
isDone = true;
isRunning = false;
Serial.println("Time's up!");
tone(BUZZ_PIN, 440, 1000);
}
prevTime = millis();
}
// refresh the display frequently
updateDisplay(count);
}
Start /
Pause
Inc
Dec