I paid someone to help me create a stopwatch type timer for split times like used by track coaches. The timer works as planned however it has an error when compared to a stopwatch. The error is always less than one second. The timer reads millis at the start of the race and then at each split time (which was input prior to start) it records millis and subtracts from the expected split time input before the race and displaying the difference. What ever the error as compared to a stopwatch is at the first split time it will be the same for every split time in that session. It seems to be rounding the initial millis reading at the start of the race. The error is different for each test but always consistent for all split times during the test. I made attempts to make changes where it records the initial millis and calls it "error" but no positive results. My skill level is from what I can find posted as tutorials.
Sketch is attached and a schematic of the PCB. I used EasyEDA to open the schematic. The oscillator is a YXC 16.0SDF.
I am no longer able to contact the individual who made this for me and attempting to correct it myself. I would be happy to pay someone to help me work through this.
Ds3231 (5).zip (73.5 KB)
[code]
#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;
}
}
}
}
[/code]