/*
Arduino | coding-help
4 digit 7 segment display not printing
ThisIan — January 11, 2025 at 9:37 PM
I'm in the process of making a timer up to 1 hour and as I try
to integrate seconds in my timer the display stops working.
I can confirm this is not a hardware/physical issue. Please feel
free to ask whatever any part of my code does.
NOTE: Digit pins should have transistor drivers!
*/
// constants
const uint8_t MAX_DIGITS = 4;
const uint8_t DP_POSITION = 1; // DP on second digit
const unsigned long INTERVAL = 1000;
const boolean DIGIT_BITS[][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
};
// pin definitions
const uint8_t BUZZ_PIN = 41;
const uint8_t CLK_PIN = 3;
const uint8_t DT_PIN = 2;
const uint8_t SW_PIN = 39;
const uint8_t DIGIT_PINS[MAX_DIGITS] = {5, 6, 7, 4};
const uint8_t SEG_PINS[] = {37, 33, 29, 25, 23, 35, 31, 27}; // a - g, dp
// global variables
// timer
unsigned long previousTime = 0;
unsigned long startTime = 600; // 3599 = 59:59
volatile unsigned long timeCount = startTime;
uint8_t mode = 0;
// encoder
volatile uint8_t counter = 0;
volatile uint8_t currStateCLK;
volatile uint8_t lastStateCLK;
uint8_t oldBtnState = HIGH; // pin idles HIGH
String currentDir = "";
// function returns true if encoder button is pressed
bool checkButton() {
bool isPressed = false;
int btnState = digitalRead(SW_PIN);
if (btnState != oldBtnState) {
oldBtnState = btnState;
if (btnState == LOW) {
isPressed = true;
Serial.println("Switch pressed");
}
delay(20); // debounce
}
return isPressed;
}
void playSound() {
tone(BUZZ_PIN, 880);
delay(250);
tone(BUZZ_PIN, 440);
delay(250);
tone(BUZZ_PIN, 220);
delay(250);
noTone(BUZZ_PIN);
}
// for hardware test only
void testDisplay() {
writeDigitSegs(0, 1);
writeDigitSegs(1, 2);
writeDigitSegs(2, 3);
writeDigitSegs(3, 4);
}
void updateDisplay(int value) {
int minute = (value / 60);
int second = value % 60;
value = (minute * 100) + second;
//Serial.println(value);
// display results here
// with leading zero blanking (10 is a blank char)
int displayValK = value < 1000 ? 10 : (value % 10000) / 1000; // kilo
int displayValH = (value % 1000) / 100; // hecto
int displayValD = (value % 100) / 10; // deka
int displayValU = value % 10; // units
// write values to display
writeDigitSegs(0, displayValK);
writeDigitSegs(1, displayValH);
writeDigitSegs(2, displayValD);
writeDigitSegs(3, displayValU);
}
void updateEncoder() {
// Read the current state of CLK
currStateCLK = digitalRead(CLK_PIN);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currStateCLK != lastStateCLK && currStateCLK == 1) {
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT_PIN) != currStateCLK) {
if (mode == 1) {
if (timeCount > 60) timeCount = timeCount - 60;
//} else {
//if (timeCount > 0) timeCount--;
}
counter --;
currentDir = "CCW";
} else {
// Encoder is rotating CW so increment
if (mode == 2) {
if (timeCount < 3539) timeCount = timeCount + 60;
} else {
if (timeCount < 3599) timeCount++;
}
counter ++;
currentDir = "CW";
}
Serial.print("Direction: ");
Serial.print(currentDir);
Serial.print(" | Counter: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currStateCLK;
}
// sets proper segments for "number"
void writeDigitSegs(uint8_t digit, uint8_t number) {
for (uint8_t segment = 0; segment < 8; segment++) {
digitalWrite(SEG_PINS[segment], DIGIT_BITS[number][segment]);
if (segment == 7 && digit == DP_POSITION) digitalWrite(SEG_PINS[segment], HIGH); // sets DP
}
digitalWrite(DIGIT_PINS[digit], LOW);
digitalWrite(DIGIT_PINS[digit], HIGH);
}
void setup() {
Serial.begin(115200);
for (int i = 0; i < MAX_DIGITS; i++) {
pinMode(DIGIT_PINS[i], OUTPUT);
digitalWrite(DIGIT_PINS[i], HIGH);
}
for (int i = 0; i < 8; i++) {
pinMode(SEG_PINS[i], OUTPUT);
}
pinMode(BUZZ_PIN, OUTPUT);
pinMode(CLK_PIN, INPUT);
pinMode(DT_PIN, INPUT);
pinMode(SW_PIN, INPUT_PULLUP);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK_PIN);
// Call updateEncoder() when any high/low changed seen
// on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(digitalPinToInterrupt(2), updateEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), updateEncoder, CHANGE);
}
void loop() {
if (checkButton()) {
mode++;
if (mode == 3) mode = 0;
Serial.print("Mode: ");
Serial.println(mode);
}
if (mode == 0 && timeCount > 0) {
if (millis() - previousTime >= INTERVAL) {
previousTime = millis();
int minute = (timeCount / 60);
int second = timeCount % 60;
/*
Serial.print("Time count: ");
Serial.print(timeCount);
Serial.print("\t\t");
Serial.print("Display: ");
Serial.print(minute);
Serial.print(":");
if (second < 10) Serial.print("0");
Serial.println(second);
*/
timeCount--;
if (timeCount <= 0) {
playSound();
//timeCount = 0;
}
}
}
//testDisplay();
updateDisplay(timeCount);
}