Ok
Here they are, 1st original code for uno and lcd
2nd adaptation for oled
#include <LiquidCrystal.h>
#include <EEPROM.h>
int SensorPin = 2;
int lap = 0; // numéro du tour en cours
int Nlaps = 0;
int NbestLap = 0;
int Ntops = 0;
int count = 0; // comptage des boucles
int chrono_stat = 0;
byte incomingByte;
int ChronoManu_stat = 0;
int ResetTime = 0;
int ChronoManu_count = 0;
int exit_loop = 0;
// variables de sélection des menus
int main_menu_index;
long address = 0;
long address_temp = 0;
unsigned long BestTime;
unsigned long LapTime;
unsigned long heures;
unsigned long minutes;
unsigned long secondes;
unsigned long millisecs;
unsigned long a0;
unsigned long a1;
unsigned long interm[] = {0, 0};
unsigned long TManu;
int inter;
int temp_lap;
unsigned long Time = 0;
unsigned long Time1 = 0;
const String MainMenuEntries[] = {" LAP TIMER", " RETRIEVE LAPS", " RETR. LAPS AUTO", " NBR of INTERM.", " RETRIEVE on PC", " CHRONOMETER", " ERASE EEPROM"};
// organisation des données dans l'EEPROM
//
// addresse | type de donnée | donnée |
// 0 | int | Nbre de partiels |
// 1 | int | Nbre de tours |
// 2 | unsigned long | Best Lap Time |
// 6 | unsigned long | partiel#1 |
// 10 | unsigned long | Partiel#2 |
// 15 | int | N meilleur tour |
// 16->19 | N/A | espace vacant |
// 20 | unsigned long | Lap#1 |
// 24 | unsigned long | Lap#2 |
// ......
//
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
#define debounceTime 200
#define NLapsMax 83
#define StopTime 600000
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0);
if (adc_key_in > 1000) return btnNONE;
delay(200);
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE;
}
// ****************************** initialisation ******************************
void setup()
{
pinMode(SensorPin, INPUT);
digitalWrite(SensorPin, HIGH);
lcd.begin(16, 2); // start the library
WelcomScreen();
MainMenu();
}
// ****************************** écran d'accueil ******************************
void WelcomScreen() {
lcd.setCursor(0, 0);
lcd.print("Moiry Racing 58 ");
lcd.setCursor(0, 1);
lcd.print("Lap Timer v1.0 ");
delay(3000);
}
// ****************************** boucle ******************************
void loop() {
}
// ****************************** adressage de l'EEPROM ******************************
long address_lap(int lap, int inter) {
return lap * 12 + 4 * inter + 20;
}
// ****************************** Menu principal ******************************
void MainMenu() {
// initialisation des variables principales
Ntops = EEPROM.read(0); // lecture du nombre de boucles magnétiques
Nlaps = EEPROM.read(1); // No du dernier tour couvert
NbestLap = EEPROM.read(15); // No du meilleur tour
address = (Nlaps) * 4 + 20; // calcul de l'adresse de départ en fonction du nombre de tours
BestTime = EEPROMReadlong(2); // meilleur tour
LapTime = EEPROMReadlong(address);// dernier tour chronométre
count = 0; // remise Ă jour du comptage des boucles
main_menu_index = 0;
a0 = 0;
a1 = 0;
chrono_stat = 0;
updateMain();
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
break;
}
case btnLEFT:
{
break;
}
case btnUP:
{
if (main_menu_index == 0) {
main_menu_index = 6;
} else {
main_menu_index = main_menu_index - 1;
}
updateMain();
break;
}
case btnDOWN:
{
if (main_menu_index == 6) {
main_menu_index = 0;
} else {
main_menu_index = main_menu_index + 1;
}
updateMain();
break;
}
case btnSELECT:
{
ModeSelect();
break;
}
case btnNONE:
{
break;
}
}
} while (1);
}
// ****************************** Mise Ă jour de l'affichage du menu principal ******************************
void updateMain() {
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print("Select Mode:");
lcd.setCursor(13, 0);
lcd.print(main_menu_index + 1);
lcd.setCursor(14, 0);
lcd.print("/7");
lcd.setCursor(0, 1);
lcd.print(MainMenuEntries[main_menu_index]);
}
// ****************************** sélection du mode ******************************
void ModeSelect() {
switch (main_menu_index)
{
case 0:
{
RunMode();
break;
}
case 1:
{
if (Nlaps > 0) {
RetrDash();
} else {
NoData();
}
break;
}
case 2:
{
if (Nlaps > 0) {
RetrDashAuto();
} else {
NoData();
}
break;
}
case 3:
{
SetTops();
break;
}
case 4:
{
RetrPC();
break;
}
case 5:
{
ChronoManu();
break;
}
case 6:
{
EraseEEPROM();
break;
}
}
}
// ****************************** mode RUN ******************************
void RunMode() {
updateRUN();
attachInterrupt(digitalPinToInterrupt(SensorPin), chrono, RISING);
exit_loop = 0;
do {
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT:
{
chrono();
break;
}
case btnSELECT:
{
detachInterrupt(digitalPinToInterrupt(SensorPin));
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
// arrĂȘt du chrono au delĂ de 10 minutes
if ((millis() - a1) > StopTime) {
chrono_stat = 0;
}
} while (exit_loop == 0);
}
// ****************************** update affichage RUN ******************************
void updateRUN() {
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print("LP:");
if (Nlaps < 10) {
lcd.setCursor(4, 0);
} else {
lcd.setCursor(3, 0);
}
lcd.print(Nlaps);
lcd.setCursor(0, 1);
lcd.print("BL:");
if (NbestLap < 10) {
lcd.setCursor(4, 1);
} else {
lcd.setCursor(3, 1);
}
lcd.print(NbestLap);
BestTime = EEPROMReadlong(2);
PrintTime(BestTime, 1, 6);
LapTime = EEPROMReadlong(address_lap(Nlaps, 0));
PrintTime(LapTime, 0, 6);
}
// ****************************** No data ******************************
void NoData() {
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print(" NO DATA ");
delay(1000);
MainMenu();
}
// ****************************** mode retrieve dash ******************************
void RetrDash() {
temp_lap = Nlaps;
inter = 1;
updateRetrDash();
exit_loop = 0;
do {
lcd_key = read_LCD_buttons();
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnDOWN:
{
if (temp_lap > 1) {
temp_lap--;
} else {
temp_lap = Nlaps;
}
updateRetrDash();
break;
}
case btnUP:
{
if (temp_lap > Nlaps - 1) {
temp_lap = 1;
} else {
temp_lap++;
}
updateRetrDash();
break;
}
case btnLEFT:
{
inter = 1;
updateRetrDash();
break;
}
case btnRIGHT:
{
inter = 2;
updateRetrDash();
break;
}
case btnSELECT:
{
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** affichage de RetrDash ******************************
void updateRetrDash() {
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print("LP:");
lcd.setCursor(3, 0);
lcd.print(temp_lap);
address_temp = address_lap(temp_lap, 0);
LapTime = EEPROMReadlong(address_temp);
PrintTime(LapTime, 0, 6);
lcd.setCursor(0, 1);
lcd.print("P#");
lcd.setCursor(2, 1);
lcd.print(inter);
address_temp = address_lap(temp_lap, inter);
LapTime = EEPROMReadlong(address_temp);
PrintTime(LapTime, 1, 6);
}
// ****************************** mode retrieve dash AUTO ******************************
void RetrDashAuto() {
temp_lap = Nlaps;
inter = 1;
updateRetrDash();
exit_loop = 0;
a1 = millis();
do {
if (millis() - a1 > 1000) {
if (inter == 1) {
inter = 2;
updateRetrDash();
}
}
if (millis() - a1 > 2000) {
temp_lap = temp_lap - 1;
if (temp_lap == 0) temp_lap = Nlaps;
inter = 1;
updateRetrDash();
a1 = millis();
}
lcd_key = read_LCD_buttons();
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnSELECT:
{
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** mode réglage du nombre de boucles ******************************
void SetTops() {
updateTops();
exit_loop = 0;
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
if (Ntops < 3) Ntops++;
updateTops();
break;
}
case btnLEFT:
{
if (Ntops > 1) Ntops--;
updateTops();
break;
}
case btnSELECT:
{
EEPROM.write(0, Ntops);
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** Mise Ă jour de l'affichage du nombre de boucles ******************************
void updateTops() {
EraseDisplay();
lcd.setCursor(1, 0);
lcd.print("NBRE OF INTERM.:");
lcd.setCursor(7, 1);
lcd.print(Ntops - 1);
lcd.setCursor(5, 1);
lcd.print("<");
lcd.setCursor(9, 1);
lcd.print(">");
}
// ****************************** mode retrieve PC ******************************
void RetrPC() {
EraseDisplay();
exit_loop = 0;
lcd.setCursor(0, 0);
lcd.print(" READY TO SEND ");
Serial.begin(9600);
do
{
incomingByte = Serial.read();
// incoming "S"
if (incomingByte == 83) {
SendToPC();
}
// incoming "E"
if (incomingByte == 69) {
EraseEEPROM();
}
// incoming "Q"
if (incomingByte == 81) {
Serial.end();
MainMenu();
}
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnSELECT:
{
Serial.end();
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** envoi des data PC ******************************
void SendToPC() {
int temp_lap;
Serial.println("START");
for (temp_lap = 1; temp_lap < Nlaps + 1 ; temp_lap++) {
// liste des temps au tour
address_temp = address_lap(temp_lap, 0);
Time = EEPROMReadlong(address_temp);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print("Lap:");
Serial.print(temp_lap);
Serial.print(" - ");
Serial.print(minutes);
Serial.print(":");
if (secondes < 10) {
Serial.print("0");
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(".");
Serial.print(millisecs);
// intermediate#1
address_temp = address_lap(temp_lap, 1);
Time = EEPROMReadlong(address_temp);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(" - inter#1: ");
Serial.print(minutes);
Serial.print(":");
if (secondes < 10) {
Serial.print("0");
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(".");
Serial.print(millisecs);
// intermediate#2
address_temp = address_lap(temp_lap, 2);
Time = EEPROMReadlong(address_temp);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(" - inter#2: ");
Serial.print(minutes);
Serial.print(":");
if (secondes < 10) {
Serial.print("0");
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(".");
Serial.println(millisecs);
}
// meilleur temps
Time = EEPROMReadlong(2);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.println("----------");
Serial.print("Best lap: ");
Serial.print(NbestLap);
Serial.print(" - ");
Serial.print(minutes);
Serial.print(":");
if (secondes < 10) {
Serial.print("0");
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(".");
Serial.print(millisecs);
// inter#1
Time = EEPROMReadlong(6);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(" - inter#1: ");
Serial.print(minutes);
Serial.print(":");
if (secondes < 10) {
Serial.print("0");
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(".");
Serial.print(millisecs);
// inter#2
Time = EEPROMReadlong(10);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(" -inter#2: ");
Serial.print(minutes);
Serial.print(":");
if (secondes < 10) {
Serial.print("0");
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(".");
Serial.println(millisecs);
Serial.println("----------");
Serial.println("END");
}
// ****************************** chronometre ******************************
void ChronoManu() {
exit_loop = 0;
ChronoManu_stat = 0;
ResetTime = 1;
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print("TIME: ");
PrintTime(0, 0, 6);
ChronoManu_count = 0;
a0 = 0UL;
a1 = 0UL;
Time = 0UL;
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
if (ChronoManu_stat == 0) {
ChronoManu_stat = 1;
if (ResetTime == 1) {
a1 = millis();
a0 = millis();
ChronoManu_count = 0;
ResetTime = 0;
}
} else {
PrintTime(Time, 0, 6);
ChronoManu_stat = 0;
}
break;
}
case btnLEFT:
{
ResetTime = 1;
a1 = millis();
a0 = millis();
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print("TIME: ");
PrintTime(0, 0, 6);
break;
}
case btnDOWN:
{
if (ChronoManu_stat == 1) {
ChronoManu_count = ChronoManu_count + 1;
lcd.setCursor(0, 1);
lcd.print("LAP# ");
lcd.setCursor(4, 1);
lcd.print(ChronoManu_count);
PrintTime(Time1, 1, 6);
a0 = millis();
}
break;
}
case btnSELECT:
{
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
if (ChronoManu_stat == 1) {
lcd.setCursor(0, 0);
lcd.print("TIME:");
Time = millis() - a1;
Time1 = millis() - a0;
PrintTime(Time, 0, 6);
} else {
a1 = millis() - Time;
}
} while (exit_loop == 0);
}
void test() {
}
// ****************************** mode erase EEPROM ******************************
void EraseEEPROM() {
EraseDisplay();
lcd.setCursor(0, 0);
lcd.print(" ERASE DATA? ");
lcd.setCursor(0, 1);
lcd.print(" NO<-- -->YES ");
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
for (Nlaps = 0; Nlaps < NLapsMax; Nlaps++) {
address = address_lap(Nlaps, 0);
EEPROMWritelong(address, 0UL);
address = address_lap(Nlaps, 1);
EEPROMWritelong(address, 0UL);
address = address_lap(Nlaps, 2);
EEPROMWritelong(address, 0UL);
lcd.setCursor(0, 0);
lcd.print(" ERASING... ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(7, 1);
lcd.print(Nlaps);
}
EEPROM.write(0, 1);
EEPROM.write(1, 0);
EEPROMWritelong(2, 3599999UL);
EEPROMWritelong(6, 3599999UL);
EEPROMWritelong(10, 3599999UL);
EEPROMWritelong(15, 0);
setup();
break;
}
case btnLEFT:
{
MainMenu();
break;
}
case btnNONE:
{
break;
}
}
} while (1);
}
// ****************************** Affiche un chrono à l'écran ******************************
void PrintTime(unsigned long Time, int y, int x)
{
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
if (minutes < 10) {
lcd.setCursor(x, y);
lcd.print(" ");
lcd.setCursor(x + 1, y);
lcd.print(minutes);
} else {
lcd.setCursor(x, y);
lcd.print(minutes);
}
lcd.setCursor(x + 2, y);
lcd.print(":");
if (secondes < 10) {
lcd.setCursor(x + 3, y);
lcd.print("0");
lcd.setCursor(x + 4, y);
lcd.print(secondes);
} else {
lcd.setCursor(x + 3, y);
lcd.print(secondes);
}
lcd.setCursor(x + 5, y);
lcd.print(".");
lcd.setCursor(x + 6, y);
lcd.print(millisecs);
}
// ****************************** Efface l'affichage ******************************
void EraseDisplay() {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
}
// ****************************** controle du chrono ******************************
void chrono() {
Serial.println(millis() - a0);
if (millis() - a0 > debounceTime) {
if (chrono_stat == 1) {
if (count > Ntops - 2) {
LapTime = millis() - a1;
a1 = millis();
if (LapTime < BestTime) {
BestTime = LapTime;
NbestLap = Nlaps + 1;
EEPROMWritelong(2, BestTime);
EEPROMWritelong(6, interm[0]);
EEPROMWritelong(10, interm[1]);
EEPROM.write(15, NbestLap);
lcd.setCursor(5, 0);
lcd.print(">");
lcd.setCursor(16, 0);
lcd.print("<");
}
Nlaps = Nlaps + 1;
EEPROM.write(1, Nlaps);
address = address_lap(Nlaps, 0);
EEPROMWritelong(address, LapTime);
address = address_lap(Nlaps, 1);
EEPROMWritelong(address, interm[0]);
address = address_lap(Nlaps, 2);
EEPROMWritelong(address, interm[1]);
updateRUN();
count = 0;
if (Nlaps > NLapsMax) Nlaps = 0;
} else {
interm[count] = millis() - a1;
count = count + 1;
}
} else {
a1 = millis();
chrono_stat = 1;
count = 1;
}
}
a0 = millis();
}
// ****************************** routine d'écriture d'un long dans l'EEPROM ******************************
void EEPROMWritelong(int address, long value)
{
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}
// ****************************** routine de lecture d'un long dans l'EEPROM ******************************
long EEPROMReadlong(long address)
{
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
I#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
int SensorPin = 2;
int lap = 0; // numéro du tour en cours
int Nlaps = 0;
int NbestLap = 0;
int Ntops = 2;
int count = 0; // comptage des boucles
int chrono_stat = 0;
byte incomingByte;
int ChronoManu_stat = 0;
int ResetTime = 0;
int ChronoManu_count = 0;
int exit_loop = 0;
int testint=0;
// variables de sélection des menus
int main_menu_index;
long address = 0;
long address_temp = 0;
unsigned long BestTime;
unsigned long LapTime;
unsigned long heures;
unsigned long minutes;
unsigned long secondes;
unsigned long millisecs;
unsigned long a0;
unsigned long a1;
unsigned long interm[] = {0, 0};
unsigned long TManu;
int inter;
int temp_lap;
unsigned long Time = 0;
unsigned long Time1 = 0;
const String MainMenuEntries[] = {" LAP TIMER", " RETRIEVE LAPS", " RETR. LAPS AUTO", " NBR of INTERM.", " RETRIEVE on PC", " CHRONOMETER", " ERASE EEPROM"};
// organisation des données dans l'EEPROM
//
// addresse | type de donnée | donnée |
// 0 | int | Nbre de partiels |
// 1 | int | Nbre de tours |
// 2 | unsigned long | Best Lap Time |
// 6 | unsigned long | partiel#1 |
// 10 | unsigned long | Partiel#2 |
// 15 | int | N meilleur tour |
// 16->19 | N/A | espace vacant |
// 20 | unsigned long | Lap#1 |
// 24 | unsigned long | Lap#2 |
// ......
//
// select the pins used on the LCD panel
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
#define debounceTime 200
#define NLapsMax 83
#define StopTime 600000
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0);
if (adc_key_in > 1000) return btnNONE;
delay(200);
if (adc_key_in < 75) return btnUP;
if (adc_key_in < 260) return btnSELECT;
if (adc_key_in < 440) return btnDOWN;
if (adc_key_in < 620) return btnRIGHT;
if (adc_key_in < 800) return btnLEFT;
if (adc_key_in < 950) return btnNONE;
return btnNONE;
}
// ****************************** initialisation ******************************
void setup()
{
Serial.begin(9600);
pinMode(SensorPin, INPUT);
digitalWrite(SensorPin, HIGH);
display.begin(SSD1306_SWITCHCAPVCC,0x3C);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
WelcomScreen();
MainMenu();
}
// ****************************** écran d'accueil ******************************
void WelcomScreen() {
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F("Lap Timer V2"));
display.display();
}
// ****************************** boucle ******************************
void loop() {
}
// ****************************** adressage de l'EEPROM ******************************
long address_lap(int lap, int inter) {
return lap * 12 + 4 * inter + 20;
}
// ****************************** Menu principal ******************************
void MainMenu() {
// initialisation des variables principales
Ntops = EEPROM.read(0); // lecture du nombre de boucles magnétiques
Nlaps = EEPROM.read(1); // No du dernier tour couvert
NbestLap = EEPROM.read(15); // No du meilleur tour
address = (Nlaps) * 4 + 20; // calcul de l'adresse de départ en fonction du nombre de tours
BestTime = EEPROMReadlong(2); // meilleur tour
LapTime = EEPROMReadlong(address);// dernier tour chronométre
count = 0; // remise Ă jour du comptage des boucles
main_menu_index = 0;
a0 = 0;
a1 = 0;
chrono_stat = 0;
updateMain();
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
break;
}
case btnLEFT:
{
break;
}
case btnDOWN:
{
if (main_menu_index == 0) {
main_menu_index = 6;
} else {
main_menu_index = main_menu_index - 1;
}
updateMain();
break;
}
case btnUP:
{
if (main_menu_index == 6) {
main_menu_index = 0;
} else {
main_menu_index = main_menu_index + 1;
}
updateMain();
break;
}
case btnSELECT:
{
ModeSelect();
break;
}
case btnNONE:
{
break;
}
}
} while (1);
}
// ****************************** Mise Ă jour de l'affichage du menu principal ******************************
void updateMain() {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F("Select Mode:"));
display.print(main_menu_index + 1);
display.println(F("/7"));
display.print(MainMenuEntries[main_menu_index]);
display.display();
}
// ****************************** sélection du mode ******************************
void ModeSelect() {
switch (main_menu_index)
{
case 0:
{
RunMode();
break;
}
case 1:
{
if (Nlaps > 0) {
RetrDash();
} else {
NoData();
}
break;
}
case 2:
{
if (Nlaps > 0) {
RetrDashAuto();
} else {
NoData();
}
break;
}
case 3:
{
SetTops();
break;
}
case 4:
{
RetrPC();
break;
}
case 5:
{
ChronoManu();
break;
}
case 6:
{
EraseEEPROM();
break;
}
}
}
// ****************************** mode RUN ******************************
void RunMode() {
updateRUN();
attachInterrupt(digitalPinToInterrupt(SensorPin), chrono, RISING);
exit_loop = 0;
do {
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT:
{
chrono();
break;
}
case btnSELECT:
{
detachInterrupt(digitalPinToInterrupt(SensorPin));
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
// arrĂȘt du chrono au delĂ de 10 minutes
if ((millis() - a1) > StopTime) {
chrono_stat = 0;
}
} while (exit_loop == 0);
}
// ****************************** update affichage RUN ******************************
void updateRUN() {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F("LP: "));
LapTime = EEPROMReadlong(address_lap(Nlaps, 0));
PrintTime(LapTime);
display.print(F("BL: "));
BestTime = EEPROMReadlong(2);
PrintTime(BestTime);
}
// ****************************** No data ******************************
void NoData() {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F(" NO DATA "));
display.display();
delay(1000);
MainMenu();
}
// ****************************** mode retrieve dash ******************************
void RetrDash() {
temp_lap = Nlaps;
inter = 1;
updateRetrDash();
exit_loop = 0;
do {
lcd_key = read_LCD_buttons();
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnDOWN:
{
if (temp_lap > 1) {
temp_lap--;
} else {
temp_lap = Nlaps;
}
updateRetrDash();
break;
}
case btnUP:
{
if (temp_lap > Nlaps - 1) {
temp_lap = 1;
} else {
temp_lap++;
}
updateRetrDash();
break;
}
case btnLEFT:
{
inter = 1;
updateRetrDash();
break;
}
case btnRIGHT:
{
inter = 2;
updateRetrDash();
break;
}
case btnSELECT:
{
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** affichage de RetrDash ******************************
void updateRetrDash() {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F("LP: "));
display.print(temp_lap);
address_temp = address_lap(temp_lap, 0);
LapTime = EEPROMReadlong(address_temp);
PrintTime(LapTime);
display.setCursor(0, 1);
display.print(F("P#"));
display.setCursor(2, 1);
display.print(inter);
address_temp = address_lap(temp_lap, inter);
LapTime = EEPROMReadlong(address_temp);
PrintTime(LapTime);
display.display();
}
// ****************************** mode retrieve dash AUTO ******************************
void RetrDashAuto() {
temp_lap = Nlaps;
inter = 1;
updateRetrDash();
exit_loop = 0;
a1 = millis();
do {
if (millis() - a1 > 1000) {
if (inter == 1) {
inter = 2;
updateRetrDash();
}
}
if (millis() - a1 > 2000) {
temp_lap = temp_lap - 1;
if (temp_lap == 0) temp_lap = Nlaps;
inter = 1;
updateRetrDash();
a1 = millis();
}
lcd_key = read_LCD_buttons();
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnSELECT:
{
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** mode réglage du nombre de boucles ******************************
void SetTops() {
updateTops();
exit_loop = 0;
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
if (Ntops < 3) Ntops++;
updateTops();
break;
}
case btnLEFT:
{
if (Ntops > 1) Ntops--;
updateTops();
break;
}
case btnSELECT:
{
EEPROM.write(0, Ntops);
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** Mise Ă jour de l'affichage du nombre de boucles ******************************
void updateTops() {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F("NBRE OF INTERM.:"));
display.print(F(" <"));
display.print(Ntops - 1);
display.println(F(">"));
display.display();
}
// ****************************** mode retrieve PC ******************************
void RetrPC() {
display.clearDisplay();
exit_loop = 0;
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F(" READY TO SEND "));
display.display();
Serial.begin(9600);
do
{
incomingByte = Serial.read();
// incoming "S"
if (incomingByte == 83) {
SendToPC();
}
// incoming "E"
if (incomingByte == 69) {
EraseEEPROM();
}
// incoming "Q"
if (incomingByte == 81) {
Serial.end();
MainMenu();
}
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnSELECT:
{
Serial.end();
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
} while (exit_loop == 0);
}
// ****************************** envoi des data PC ******************************
void SendToPC() {
int temp_lap;
Serial.println("START");
for (temp_lap = 1; temp_lap < Nlaps + 1 ; temp_lap++) {
// liste des temps au tour
address_temp = address_lap(temp_lap, 0);
Time = EEPROMReadlong(address_temp);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(F("Lap:"));
Serial.print(temp_lap);
Serial.print(F(" - "));
Serial.print(minutes);
Serial.print(F(":"));
if (secondes < 10) {
Serial.print(F("0"));
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(F("."));
Serial.print(millisecs);
// intermediate#1
address_temp = address_lap(temp_lap, 1);
Time = EEPROMReadlong(address_temp);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(F(" - inter#1: "));
Serial.print(minutes);
Serial.print(F(":"));
if (secondes < 10) {
Serial.print(F("0"));
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(F("."));
Serial.print(millisecs);
// intermediate#2
address_temp = address_lap(temp_lap, 2);
Time = EEPROMReadlong(address_temp);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(F(" - inter#2: "));
Serial.print(minutes);
Serial.print(F(":"));
if (secondes < 10) {
Serial.print(F("0"));
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(F("."));
Serial.println(millisecs);
}
// meilleur temps
Time = EEPROMReadlong(2);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.println(F("----------"));
Serial.print(F("Best lap: "));
Serial.print(NbestLap);
Serial.print(F(" - "));
Serial.print(minutes);
Serial.print(F(":"));
if (secondes < 10) {
Serial.print(F("0"));
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(F("."));
Serial.print(millisecs);
// inter#1
Time = EEPROMReadlong(6);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(F(" - inter#1: "));
Serial.print(minutes);
Serial.print(F(":"));
if (secondes < 10) {
Serial.print(F("0"));
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(F("."));
Serial.print(millisecs);
// inter#2
Time = EEPROMReadlong(10);
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
Serial.print(F(" -inter#2: "));
Serial.print(minutes);
Serial.print(F(":"));
if (secondes < 10) {
Serial.print(F("0"));
Serial.print(secondes);
} else {
Serial.print(secondes);
}
Serial.print(F("."));
Serial.println(millisecs);
Serial.println(F("----------"));
Serial.println(F("END"));
}
// ****************************** chronometre ******************************
void ChronoManu() {
exit_loop = 0;
ChronoManu_stat = 0;
ResetTime = 1;
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F("TIME: "));
PrintTime(0);
display.display();
ChronoManu_count = 0;
a0 = 0UL;
a1 = 0UL;
Time = 0UL;
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
if (ChronoManu_stat == 0) {
ChronoManu_stat = 1;
if (ResetTime == 1) {
a1 = millis();
a0 = millis();
ChronoManu_count = 0;
ResetTime = 0;
}
} else {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F("TIME: "));
PrintTime(Time);
display.display();
ChronoManu_stat = 0;
}
break;
}
case btnLEFT:
{
ResetTime = 1;
a1 = millis();
a0 = millis();
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F("TIME: "));
PrintTime(0);
display.display();
break;
}
case btnDOWN:
{
if (ChronoManu_stat == 1) {
ChronoManu_count = ChronoManu_count + 1;
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(F("TIME: "));
PrintTime(Time);
display.print(F("LAP #"));
display.print(ChronoManu_count);
display.print(" ");
PrintTime(Time1);
display.display();
a0 = millis();
}
break;
}
case btnSELECT:
{
exit_loop = 1;
updateMain();
break;
}
case btnNONE:
{
break;
}
}
if (ChronoManu_stat == 1) {
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.fillRect(0, 0, 127, 6, BLACK);
display.print(F("TIME: "));
Time = millis() - a1;
Time1 = millis() - a0;
PrintTime(Time);
display.display();
} else {
a1 = millis() - Time;
}
} while (exit_loop == 0);
}
// ****************************** mode erase EEPROM ******************************
void EraseEEPROM() {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F(" ERASE DATA? "));
display.print(F(" NO<-- -->YES "));
display.display();
do {
lcd_key = read_LCD_buttons();
switch (lcd_key)
{
case btnRIGHT:
{
for (Nlaps = 0; Nlaps < NLapsMax; Nlaps++) {
address = address_lap(Nlaps, 0);
EEPROMWritelong(address, 0UL);
address = address_lap(Nlaps, 1);
EEPROMWritelong(address, 0UL);
address = address_lap(Nlaps, 2);
EEPROMWritelong(address, 0UL);
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(F(" ERASING... "));
display.print(F(" "));
display.print(Nlaps);
display.display();
}
EEPROM.write(0, 1);
EEPROM.write(1, 0);
EEPROMWritelong(2, 3599999UL);
EEPROMWritelong(6, 3599999UL);
EEPROMWritelong(10, 3599999UL);
EEPROMWritelong(15, 0);
setup();
break;
}
case btnLEFT:
{
MainMenu();
break;
}
case btnNONE:
{
break;
}
}
} while (1);
}
// ****************************** Affiche un chrono à l'écran ******************************
void PrintTime(unsigned long Time)//, int y, int x)
{
heures = Time / 3600000;
minutes = (Time - heures * 3600000) / 60000;
secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
display.print(minutes);
display.print(F("'"));
display.print(secondes);
display.print(F("."));
display.println(millisecs);
display.display();
}
// ****************************** controle du chrono ******************************
void chrono() {
Serial.println(millis() - a0);
if (millis() - a0 > debounceTime) {
if (chrono_stat == 1) {
if (count > Ntops - 2) {
LapTime = millis() - a1;
a1 = millis();
if (LapTime < BestTime) {
BestTime = LapTime;
NbestLap = Nlaps + 1;
EEPROMWritelong(2, BestTime);
EEPROMWritelong(6, interm[0]);
EEPROMWritelong(10, interm[1]);
EEPROM.write(15, NbestLap);
}
Nlaps = Nlaps + 1;
EEPROM.write(1, Nlaps);
address = address_lap(Nlaps, 0);
EEPROMWritelong(address, LapTime);
address = address_lap(Nlaps, 1);
EEPROMWritelong(address, interm[0]);
address = address_lap(Nlaps, 2);
EEPROMWritelong(address, interm[1]);
updateRUN();
count = 0;
if (Nlaps > NLapsMax) Nlaps = 0;
}
else {
interm[count] = millis() - a1;
count = count + 1;
}
} else {
a1 = millis();
chrono_stat = 1;
count = 1;
}
}
a0 = millis();
}
// ****************************** routine d'écriture d'un long dans l'EEPROM ******************************
void EEPROMWritelong(int address, long value)
{
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}
// ****************************** routine de lecture d'un long dans l'EEPROM ******************************
long EEPROMReadlong(long address)
{
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}