/*
Wokwi | questions
Help my project
Sensei_Markus - Wednesday, April 1, 2026 10:55 AM
Can someone help me with my project?
A 60 second countdown timer with Start/Stop and Reset buttons.
Randomly selects a "basket" as the target.
A ball going into the correct target increments the score.
Written for common cathode displays.
In a real circuit the grey common pins should drive transistors
*/
const uint8_t MAX_DIGITS = 4;
const uint8_t NUM_BTNS = 7;
const uint8_t BTN_PINS[] = {12, 10, 8, 6, 4, 14, 15};
const uint8_t LED_PINS[] = {11, 9, 7, 5, 3};
const uint8_t DIG_PINS[] = {45, 43, 41, 39};
const uint8_t SEG_PINS[] = {23, 25, 27, 29, 31, 33, 35, 37}; // a - g, dp
// lookup table, which segments are on for each value
const uint8_t DIG_BITS[] = {
0xFC, // 0
0x60, // 1
0xDA, // 2
0xF2, // 3
0x66, // 4
0xB6, // 5
0xBE, // 6
0xE0, // 7
0xFE, // 8
0xF6, // 9
0x00 // blank
};
const unsigned long INTERVAL = 1000;
const int COUNT_START = 20;
bool isRunning = false;
bool ledStates[] = {0, 0, 0, 0, 0};
int timeCount = COUNT_START;
int score = 0;
int targetLed = 0;
int btnState[NUM_BTNS];
int oldBtnState[NUM_BTNS];
unsigned long previousTime = 0;
// function returns which button was pressed, or 0 if none
int checkButtons() {
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 updateDisplay(uint32_t value, uint8_t dpPos) {
uint8_t digitVal;
uint8_t powOfTen = MAX_DIGITS - 1;
//uint8_t powOfTen = MAX_DIGITS;
uint32_t op1 = 1, op2 = 1;
for (uint8_t digit = 0; digit < powOfTen + 1; digit++) {
for (uint8_t p = powOfTen - digit; p >= 1; p--) {
op1 = op1 * 10;
}
op2 = op1 * 10;
// with leading zero blanking (10 is a blank char)
//digitVal = value < op1 ? 10 : (value % op2) / op1;
digitVal = (value % op2) / op1;
writeDigitSegs(digit, digitVal, ((dpPos - 1) == digit) ? true : false);
op1 = 1; op2 = 1;
}
// last digit is never blanked
//writeDigitSegs(powOfTen, value % 10, ((dpPos - 1) == powOfTen) ? true : false);
}
// sets proper segments for "value"
void writeDigitSegs(uint8_t digit, uint8_t number, bool dp) {
byte segments = DIG_BITS[number];
for (uint8_t segment = 0; segment < 8; segment++) {
digitalWrite(SEG_PINS[segment], bitRead(segments, 7 - segment) ? HIGH : LOW);
if (segment == 7 && dp) digitalWrite(SEG_PINS[segment], HIGH); // sets DP
}
digitalWrite(DIG_PINS[digit], LOW);
digitalWrite(DIG_PINS[digit], HIGH);
}
// for hardware test only
void testDisplay() {
writeDigitSegs(0, 1, false);
writeDigitSegs(1, 2, true);
writeDigitSegs(2, 3, false);
writeDigitSegs(3, 4, false);
}
void setup() {
Serial.begin(115200);
for (int i = 0; i < 8; i++) {
pinMode(SEG_PINS[i], OUTPUT);
}
for (int i = 0; i < 5; i++) {
pinMode(LED_PINS[i], OUTPUT);
}
for (int i = 0; i < MAX_DIGITS; i++) {
pinMode(DIG_PINS[i], OUTPUT);
digitalWrite(DIG_PINS[i], HIGH);
}
for (int i = 0; i < NUM_BTNS; i++) {
pinMode(BTN_PINS[i], INPUT_PULLUP);
}
randomSeed(analogRead(A0));
}
void loop() {
int btnNumber = checkButtons();
if (btnNumber) {
if ((btnNumber >= 1 && btnNumber <= 5) && isRunning) {
//ledStates[btnNumber - 1] = !ledStates[btnNumber - 1];
//digitalWrite(LED_PINS[btnNumber - 1], ledStates[btnNumber - 1]);
targetLed = random(5);
digitalWrite(LED_PINS[targetLed], HIGH);
score++;
} else if (btnNumber == 6) {
Serial.println("Start/Stop");
isRunning = !isRunning;
if (isRunning) targetLed = random(5);
//Serial.println(targetLed);
digitalWrite(LED_PINS[targetLed], HIGH);
} else if (btnNumber == 7) {
Serial.println("Reset");
timeCount = COUNT_START;
score = 0;
isRunning = false;
}
}
if (millis() - previousTime >= INTERVAL && isRunning) {
previousTime = millis();
timeCount--;
if (timeCount <= 0) isRunning = false;
//for (int i = 0; i < 5; i++) {
//digitalWrite(LED_PINS[i], LOW);
//}
}
updateDisplay((timeCount * 100) + score, 0);
//testDisplay();
}
TIME
SCORE
Start
Reset