// Define pin numbers for segments
const int pinA = 11;
const int pinB = 7;
const int pinC = 4;
const int pinD = 2;
const int pinE = 3;
const int pinF = 10;
const int pinG = 5;
const int pinH = 13;
// Define pin numbers for common pins
const int pinD1 = 12;
const int pinD2 = 9;
const int pinD3 = 8;
const int pinD4 = 6;
// Define pin number for a button switch (goal 3 to start and stop the counting process)
#define switch1 A3
// Variables to read the state of the button switch and keep track of its previous state
int buttonReading;
int state = LOW;
int previous = LOW;
// Set suitable refresh rate for display ( 100000 microseconds by default here, 1000 will refresh much faster )
const unsigned long refreshRate = 100000UL;
// Variable to store the timestamp of the last refresh
unsigned long refreshTimestamp;
// Lookup tables for segment and common pins (goal 2 display count from 0000 to 9999)
const byte SegmentsLUT[8] = {pinA, pinB, pinC, pinD, pinE, pinF, pinG, pinH};
const byte CommonsLUT[4] = {pinD1, pinD2, pinD3, pinD4};
// Lookup table for hexadecimal values representing segments to display numbers 0 through 9
const byte NumbersLUT[11] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00};
// Array to store the data for each digit to be displayed on the 7-segment display
byte displayData[4] = {0x00, 0x00, 0x00, 0xFC};
// Variable to keep track of the current digit being displayed
byte digitIndex = 0;
// Variables to store the time values and shift decimal points
// (goal 4, displays time by moving the decimal place right as the count progresse
// I begin in 0.001 milliseconds until it addsup to 9.999 millisecond
// and then decible point shift to right 10.00 and it adds up to 99.99 etc
// after it reaches 9999. it will be reset to 0.001
int tensOfSeconds;
int hundredsOfSeconds;
int thousandofseconds;
int seconds;
bool point1 = true;
bool point2 = true;
bool point3 = true;
bool one = true;
bool two = false;
bool three = false;
bool four = false;
// put your setup code here, to run once:
void setup() {
Serial.begin(9600);
// Set pins number as outputs
pinMode (pinA, OUTPUT);
pinMode (pinB, OUTPUT);
pinMode (pinC, OUTPUT);
pinMode (pinD, OUTPUT);
pinMode (pinE, OUTPUT);
pinMode (pinF, OUTPUT);
pinMode (pinG, OUTPUT);
pinMode (pinH, OUTPUT);
pinMode (pinD1, OUTPUT);
pinMode (pinD2, OUTPUT);
pinMode (pinD3, OUTPUT);
pinMode (pinD4, OUTPUT);
}
// put your main code here, to run repeatedly:
void loop()
{
// Read the state of the switch
buttonReading = digitalRead(switch1);
// Check if the switch state has changed
if (buttonReading == LOW && previous == HIGH)
{
// Add some delay
delay(50);
// Check if the switch state is still LOW after debounce
if (digitalRead(switch1) == LOW)
{
// Toggle the state
state = !state;
}
}
// Update the previous switch state
previous = buttonReading;
// Check if the state is HIGH (indicating the counter is active)
if (state == HIGH)
{
// Increment count every 100 milliseconds by default
if (micros() - refreshTimestamp >= refreshRate)
{
incrementCount();
refreshTimestamp = micros();
}
// For decimal point each of the segment is treated individually, these are
// triggered when the values are met
if (one == true)
{
// Update display with time values
// display data is an array which contain four bytes of digits
// the data from each seven segement display is stored in the
// display data array at specific postions
displayData[0] = NumbersLUT[thousandofseconds];
displayData[1] = NumbersLUT[hundredsOfSeconds];
displayData[2] = NumbersLUT[tensOfSeconds];
displayData[3] = NumbersLUT[seconds] | 0x80;
displayRefresh();
}
if (two == true)
{
// Update display with time values
displayData[0] = NumbersLUT[thousandofseconds] | 0x80;
displayData[1] = NumbersLUT[hundredsOfSeconds];
displayData[2] = NumbersLUT[tensOfSeconds] ;
displayData[3] = NumbersLUT[seconds] ;
displayRefresh();
}
if (three == true)
{
// Update display with time values
displayData[0] = NumbersLUT[thousandofseconds] ;
displayData[1] = NumbersLUT[hundredsOfSeconds] | 0x80 ;
displayData[2] = NumbersLUT[tensOfSeconds] ;
displayData[3] = NumbersLUT[seconds] ;
displayRefresh();
}
if (four == true)
{
// Update display with time values
displayData[0] = NumbersLUT[thousandofseconds] ;
displayData[1] = NumbersLUT[hundredsOfSeconds] ;
displayData[2] = NumbersLUT[tensOfSeconds]| 0x80 ;
displayData[3] = NumbersLUT[seconds] ;
displayRefresh();
}
Serial.println("Record");
Serial.print("one");
Serial.println(one);
}
}
void incrementCount()
{
// Increment tens of seconds
tensOfSeconds++;
// Check if tens of seconds exceeds 9
if (tensOfSeconds > 9)
{
// Reset tens of seconds to 0
tensOfSeconds = 0;
// Increment hundreds of seconds
hundredsOfSeconds++;
// Check if hundreds of seconds exceeds 9
if (hundredsOfSeconds > 9)
{
// Reset hundreds of seconds to 0
hundredsOfSeconds = 0;
// Increment milliseconds
thousandofseconds++;
// Check if milliseconds exceeds 9
if (thousandofseconds > 9)
{
// Reset milliseconds to 0
thousandofseconds = 0;
// Increment seconds
seconds++;
// Check if seconds exceeds 9
// flags are introduced to keep track of decimal point
// this will keep the decimal point at the appropriate place
// avoid conflicting with other decimal points
if (seconds > 9 && point1 == true)
{
one = false;
two = true;
point1 = false;
// Reset seconds to 0
seconds = 1;
}
// point 1 will keep the decimal point 1 from the second place which is
// point 2 and will trigger display value in loop function
if (seconds > 9 && point1 == false && point2 == true)
{
seconds = 1;
thousandofseconds = 0;
hundredsOfSeconds = 0;
point1 = false;
point2= false;
two = false;
three = true;
}
// point 1, point 2 and point 3 is used to keep track of decimal point for
// 3rd place and trigger the display values in loop function
if (seconds > 9 && point1 == false && point2 == false && point3 == true)
{
seconds = 1;
thousandofseconds = 0;
hundredsOfSeconds = 0;
tensOfSeconds = 0;
point1 = false;
point2 =false;
point3 = false;
two = false;
three = false;
four = true;
}
if (seconds > 9 && point1 == false && point2 == false && point3 == false)
{
seconds = 0;
thousandofseconds = 0;
hundredsOfSeconds = 0;
tensOfSeconds = 0;
point1 = true;
four= false;
one = true;
}
}
Serial.print(" Point1= ");
Serial.print(point1);
Serial.print(" Point2= ");
Serial.print(point2);
Serial.print(" Point3= ");
Serial.println(point3);
}
}
Serial.print("thousandofseconds: ");
Serial.print(thousandofseconds);
Serial.print(" Seconds: ");
Serial.print(seconds);
Serial.print(" Hundreds of Seconds: ");
Serial.print(hundredsOfSeconds);
Serial.print(" Tens of Seconds: ");
Serial.print(tensOfSeconds);
Serial.println(" ");
}
// Function to refresh the display
void displayRefresh() {
// Turn off the current digit (common cathode) by setting its common pin LOW
digitalWrite(CommonsLUT[digitIndex], LOW);
// Loop through each segment pin
for (int i = 0; i < 8; i++) {
// Set the segment pin based on the display data and polarity (HIGH for common anode, LOW for common cathode)
digitalWrite(SegmentsLUT[i], ((displayData[digitIndex] & (0x01 << i)) ? LOW : HIGH)); // swap HIGH and LOW for common cathode
}
// Move to the next digit index or reset to the first digit if the last digit was reached
digitIndex = (digitIndex >= 3) ? 0 : (digitIndex + 1);
// Turn on the next digit (common cathode) by setting its common pin HIGH
digitalWrite(CommonsLUT[digitIndex], HIGH); // LOW for common cathode
Serial.print(" digitIndex ");
Serial.println(digitIndex);
}
// Function to display the indiviual number in each segment (optional)
void number(int i) {
switch (i) {
case 0: //display 0
digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
digitalWrite(pinC, LOW);
digitalWrite(pinD, LOW);
digitalWrite(pinE, LOW);
digitalWrite(pinF, LOW);
digitalWrite(pinG, HIGH);
break;
case 1:// display 1
digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
digitalWrite(pinC, LOW);
digitalWrite(pinD, LOW);
digitalWrite(pinE, HIGH);
digitalWrite(pinF, HIGH);
digitalWrite(pinG, LOW);
break;
case 2:
digitalWrite(pinA, HIGH);
digitalWrite(pinB, HIGH);
digitalWrite(pinC, HIGH);
digitalWrite(pinD, HIGH);
digitalWrite(pinE, LOW);
digitalWrite(pinF, LOW);
digitalWrite(pinG, HIGH);
break;
case 3:
digitalWrite(pinA, LOW);
digitalWrite(pinB, HIGH);
digitalWrite(pinC, HIGH);
digitalWrite(pinD, LOW);
digitalWrite(pinE, HIGH);
digitalWrite(pinF, HIGH);
digitalWrite(pinG, LOW);
break;
case 4:
digitalWrite(pinA, HIGH);
digitalWrite(pinB, LOW);
digitalWrite(pinC, LOW);
digitalWrite(pinD, HIGH);
digitalWrite(pinE, HIGH);
digitalWrite(pinF, LOW);
digitalWrite(pinG, LOW);
break;
case 5:
digitalWrite(pinA, LOW);
digitalWrite(pinB, HIGH);
digitalWrite(pinC, LOW);
digitalWrite(pinD, LOW);
digitalWrite(pinE, HIGH);
digitalWrite(pinF, LOW);
digitalWrite(pinG, LOW);
break;
case 6:
digitalWrite(pinA, LOW);
digitalWrite(pinB, HIGH);
digitalWrite(pinC, LOW);
digitalWrite(pinD, LOW);
digitalWrite(pinE, LOW);
digitalWrite(pinF, LOW);
digitalWrite(pinG, LOW);
break;
case 7:
digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
digitalWrite(pinC, LOW);
digitalWrite(pinD, HIGH);
digitalWrite(pinE, HIGH);
digitalWrite(pinF, HIGH);
digitalWrite(pinG, HIGH);
break;
case 8:
digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
digitalWrite(pinC, LOW);
digitalWrite(pinD, LOW);
digitalWrite(pinE, LOW);
digitalWrite(pinF, LOW);
digitalWrite(pinG, LOW);
break;
case 9:
digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
digitalWrite(pinC, LOW);
digitalWrite(pinD, HIGH);
digitalWrite(pinE, HIGH);
digitalWrite(pinF, HIGH);
digitalWrite(pinG, LOW);
break;
}
}