// For: https://forum.arduino.cc/t/timer-has-random-error/1037211/
//
// This Wokwi project: https://wokwi.com/projects/344260957282763346
//
// "DS3231" libary from the Library Manager in the Arduino IDE.
// (that is this library: https://github.com/NorthernWidget/DS3231)
//
// Changed #include "DS3231.h" with #include <DS3231.h>
//
// 1 Oct 2022
// Started with my own version with millis:
// https://wokwi.com/projects/344339167081136722
//
#include <LiquidCrystal.h>
#include <Wire.h>
#include <DS3231.h>
#include <Keypad.h>
RTClib RTC;
DS3231 Clock;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
#define Red A1
#define Green A0
#define button 3
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {A2, A3, 0, 1}; /* connect to the row pinouts of the keypad */
byte colPins[COLS] = {4, 7, 6, 5}; //connect to the column pinouts of the keypad
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
char customKey, sign[10];
byte num, a = 0;
bool Key_Status = false, button_press = false, Complete = false, Key_Enter = false;
unsigned int split[10][3], split1[10][3], error = 0;
unsigned long int ms, milli[10];
long int pulse = 0;
unsigned long int b;
void setup() {
pinMode(Red, OUTPUT);
pinMode(Green, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(button, INPUT_PULLUP);
digitalWrite(Red, LOW);
digitalWrite(Green, LOW);
lcd.begin(20, 4);
lcd.clear();
lcd.print("Welcome");
delay(1500);
lcd.setCursor(0, 0);
lcd.print("Enter Split Number");
lcd.setCursor(0, 1);
Split_Number();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Split Times");
Split_Time();
lcd.clear();
customKey = ':';
int j = 0;
int p = (num - 1) / 4 + 1;
int Prev_s = 100;
while (customKey != 'D') {
customKey = customKeypad.getKey();
if (customKey && customKey == 'A')
j = (j + 1) % p;
if (customKey && customKey == 'B')
j = (j - 1 + p) % p;
if (Prev_s != j) {
Prev_s = j;
int i = 0;
lcd.clear();
while (i < 4 && (4 * j + i) < num) {
lcd.setCursor(0, i % 4);
lcd.print(4 * j + i + 1);
lcd.print(". ");
lcd_check(split[4 * j + i][0], 3);
lcd.print(split[4 * j + i][0]); lcd.print("'");
lcd_check(split[4 * j + i][1], 2);
lcd.print(split[4 * j + i][1]); lcd.print("''");
lcd_check(split[4 * j + i][2], 3);
lcd.print(split[4 * j + i][2]); lcd.print("'''");
i ++;
}
}
}
Wire.begin();
lcd.clear();
lcd.setCursor(4, 1);
lcd.print("Press Button");
lcd.setCursor(3, 2);
lcd.print("To Start Race");
}
void squr() {
if (pulse == -1)
error = millis() - error;
pulse += 1;
b = millis();
}
void loop() {
if (digitalRead(button) == 0) {
delay(20);
if (digitalRead(button) == 0) {
if (a == 0) {
b = millis();
error = b;
Clock.enableOscillator(true, false, 0);
pulse = -1;
attachInterrupt(digitalPinToInterrupt(2), squr, FALLING);
}
else {
ms = millis() - b;
if (ms >= 1000)
ms = random(996, 1000);
if (pulse < 0){
pulse = 0;
}
milli[a - 1] = pulse * 1000 + ms + error;
}
a++;
button_press = true;
}
}
if (button_press && a <= (num + 1))
sub();
int i = num - 1;
int prev = num;
int s = 0;
while (Complete) {
customKey = customKeypad.getKey();
if (customKey && customKey == 'A')
i = (i + 1) % num;
if (customKey && customKey == 'B')
i = (i - 1 + num) % num;
if (i != prev) {
prev = i;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(i + 1);
lcd.print(". ");
lcd_check(split[i][0], 3);
lcd.print(split[i][0]);
lcd.print("'");
lcd_check(split[i][1], 2);
lcd.print(split[i][1]);
lcd.print("''");
lcd_check(split[i][2], 3);
lcd.print(split[i][2]);
lcd.print("'''");
lcd.setCursor(0, 2);
lcd.print(i + 1);
lcd.print(". ");
s = milli[i] / 60000;
lcd_check(s, 3);
lcd.print(s);
lcd.print("'");
s = (milli[i] / 1000) % 60;
lcd_check(s, 2);
lcd.print(s);
lcd.print("''");
s = milli[i] % 1000;
lcd_check(s, 3);
lcd.print(s);
lcd.print("'''");
lcd.setCursor(0, 3);
lcd.print(i + 1);
lcd.print(". ");
if (sign[i] == '+') {
digitalWrite(Green, LOW);
digitalWrite(Red, HIGH);
}
else {
digitalWrite(Green, HIGH);
digitalWrite(Red, LOW);
}
lcd.print(sign[i]);
lcd_check(split1[i][0], 3);
lcd.print(split1[i][0]);
lcd.print("'");
lcd_check(split1[i][1], 2);
lcd.print(split1[i][1]);
lcd.print("''");
lcd_check(split1[i][2], 3);
lcd.print(split1[i][2]);
lcd.print("'''");
}
}
}
void lcd_check(int m, int p) {
if (p == 2 && m / 10 == 0) {
lcd.print("0");
return 0;
}
if (p == 3 && m / 10 == 0) {
lcd.print("00");
return 0;
}
if (p == 3 && m / 100 == 0) {
lcd.print("0");
return 0;
}
}
void sub() {
if ((a - 1) < num) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Present Time: ");
lcd.setCursor(0, 1);
lcd.print(a);
lcd.print(". ");
lcd_check(split[a - 1][0], 3);
lcd.print(split[a - 1][0]);
lcd.print("'");
lcd_check(split[a - 1][1], 2);
lcd.print(split[a - 1][1]);
lcd.print("''");
lcd_check(split[a - 1][2], 3);
lcd.print(split[a - 1][2]);
lcd.print("'''");
}
if (a > 1) {
unsigned long int d;
d = split[a - 2][0] * 60000 + split[a - 2][1] * 1000 + split[a - 2][2];
lcd.setCursor(0, 2);
lcd.print("Previous Result: ");
lcd.setCursor(0, 3);
lcd.print(a - 1);
lcd.print(". ");
if (milli[a - 2] > d) {
split1[a - 2][0] = (milli[a - 2] - d) / 60000;
split1[a - 2][1] = ((milli[a - 2] - d) / 1000) % 60;
split1[a - 2][2] = (milli[a - 2] - d) % 1000;
sign[a - 2] = '+';
lcd.print("+");
digitalWrite(Green, LOW);
digitalWrite(Red, HIGH);
}
else {
split1[a - 2][0] = (d - milli[a - 2]) / 60000;
split1[a - 2][1] = ((d - milli[a - 2]) / 1000) % 60;
split1[a - 2][2] = (d - milli[a - 2]) % 1000;
sign[a - 2] = '-';
lcd.print("-");
digitalWrite(Green, HIGH);
digitalWrite(Red, LOW);
}
lcd_check(split1[a - 2][0], 3);
lcd.print(split1[a - 2][0]);
lcd.print("'");
lcd_check(split1[a - 2][1], 2);
lcd.print(split1[a - 2][1]);
lcd.print("''");
lcd_check(split1[a - 2][2], 3);
lcd.print(split1[a - 2][2]);
lcd.print("'''");
}
button_press = false;
if (a == (num + 1)) {
detachInterrupt(digitalPinToInterrupt(2));
Complete = true;
}
while (digitalRead(button) == 0);
delay(10);
}
void Split_Number()
{
while (1)
{
customKey = customKeypad.getKey();
delay(100);
if (customKey <= 57 && customKey != '*' && customKey != '#' && customKey)
{
num = num * 10 + customKey - 48;
lcd.print(customKey);
Key_Enter = true;
}
if (customKey == 'C' || num > 10)
{
num = 0;
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
Key_Enter = false;
}
if (customKey == 'D' && customKey && num != 0 && Key_Enter)
break;
}
}
void Split_Time() {
int k = 1;
for (int i = 0; i < num; i++) {
int j = 0;
lcd.setCursor(0, k);
lcd.print(i + 1);
lcd.print(". ");
Key_Enter = false;
while (1) {
customKey = customKeypad.getKey();
if (customKey <= 57 && customKey >= 48 && customKey && j < 3) {
split[i][j] = split[i][j] * 10 + customKey - 48;
if (split[i][1] >= 60) {
split[i][1] = 0;
lcd.setCursor(3, k);
lcd.print(" ");
lcd.setCursor(3, k);
lcd.print(split[i][0]);
lcd.print("'");
Key_Enter = false;
}
else if (split[i][2] >= 1000) {
split[i][2] = 0;
lcd.setCursor(3, k);
lcd.print(" ");
lcd.setCursor(3, k);
lcd.print(split[i][0]);
lcd.print("'");
lcd.print(split[i][1]);
lcd.print("''");
Key_Enter = false;
}
else {
lcd.print(customKey);
Key_Enter = true;
}
}
if (customKey == 'C') {
j = 0;
split[i][0] = 0;
split[i][1] = 0;
split[i][2] = 0;
lcd.setCursor(3, k);
lcd.print(" ");
lcd.setCursor(3, k);
Key_Enter = false;
}
if (customKey == '*' && j < 3 && Key_Enter) {
j++;
for (int l = 0; l < j; l++)
lcd.print("'");
Key_Enter = false;
}
if (i > 0 && ((split[i][0] < split[i - 1][0] && j == 1) || (split[i][0] == split[i - 1][0] && split[i][1] < split[i - 1][1] && j == 2) || (split[i][0] == split[i - 1][0] && split[i][1] == split[i - 1][1] && split[i][2] < split[i - 1][2] && j == 3))) {
j = 0;
j = 0;
split[i][0] = 0;
split[i][1] = 0;
split[i][2] = 0;
lcd.setCursor(3, k);
lcd.print(" ");
lcd.setCursor(3, k);
Key_Enter = false;
}
if (customKey == 'D' && customKey && j == 3) {
if (k == 3) {
for (k = 1; k <= 3; k++) {
lcd.setCursor(0, k);
lcd.print(" ");
}
k = 0;
}
k++;
break;
}
}
}
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
lcd1:VSS
lcd1:VDD
lcd1:V0
lcd1:RS
lcd1:RW
lcd1:E
lcd1:D0
lcd1:D1
lcd1:D2
lcd1:D3
lcd1:D4
lcd1:D5
lcd1:D6
lcd1:D7
lcd1:A
lcd1:K
r1:1
r1:2
r2:1
r2:2
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
rgb1:R
rgb1:COM
rgb1:G
rgb1:B
r3:1
r3:2
r4:1
r4:2
r5:1
r5:2
rtc1:GND
rtc1:5V
rtc1:SDA
rtc1:SCL
rtc1:SQW
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4