/* Chronometer gemäss Aufgabe 3:
* Start und Stop-Taste für Zeitmessung. Die gestoppte Zeit
* wird laufend und bei Betätigung der Stop-Taste angezeigt.
* Zusätzlich werden die besten fünf gemessenen Zeiten inkl. deren Rang angezeigt.
* Per Next-Taste kann durch die Zeiten "geblättert" werden.
* Die Zeiten bleiben bei ausgeschaltetem Arduino erhalten (im EEPROM gespeichert).
* Nur wenn die Reset-Taste betätigt wird, werden alle Zeiten zurückgesetzt.
*/
#include <EEPROM.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// create object of class LiquidCrytal_I22 and define parametes:
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// Konstanten festlegen (für bessere Lesbarkeit des Codes):
#define startPin 5
#define stopPin 4
#define resetPin 3
#define nextPin 2
#define debounce 150 // Wartezeit zur "Entprellung" der Tasten (Millisekunden)
// Folgende Variable speichert den Status der Zeitmessung
bool timeRunning;
// Folgende Variablen speichern die Zeiten in Millisekunden:
unsigned long startTime;
unsigned long currentTime;
unsigned long stoppedTime;
unsigned long bestTimes[5]; // Array mit den besten fünf Zeiten
unsigned long tempTime; // Zwischenspeicher für den Wertetausch bei der Sortierung
// Folgende Variablen dienen der Anzeige im Format MM:SS:HH:
unsigned int minutes;
unsigned int seconds;
unsigned int hundreds;
char timeString[] = "00:00:00";
// Variable für den anzuzeigenden Rang:
uint8_t rank;
// Array für EEPROM-Adressen:
int addresses[5] = {0,3,6,9,12};
void setup() {
/*Für Debugging:
pinMode(13, OUTPUT);
Serial.begin(9600);*/
// Eingänge definieren:
pinMode(startPin, INPUT_PULLUP);
pinMode(stopPin, INPUT_PULLUP);
pinMode(resetPin, INPUT_PULLUP);
pinMode(nextPin, INPUT_PULLUP);
// Variablen definieren bzw. auf Initial-Werte setzen:
timeRunning = 0;
startTime = 0;
currentTime = 0;
stoppedTime = 0;
rank = 0;
// Beste fünf Zeiten aus EEPROM lesen:
readTimesEEP();
// Anzeige vorbereiten:
lcd.begin(16,2); // initialize the lcd
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Jetzt:");
lcd.setCursor(0, 1);
lcd.print("Rang :");
updateTimes();
}
void loop() {
if(timeRunning == 1){
currentTime = millis() - startTime;
lcd.setCursor(8, 0);
showTime(currentTime);
}
if (digitalRead(startPin) == LOW) {
delay(debounce);
startTime = millis();
stoppedTime = 0;
currentTime = 0;
timeRunning = 1;
}
if (digitalRead(stopPin) == LOW) {
delay(debounce);
stoppedTime = millis() - startTime;
// Falls gestoppte Zeit kleiner als fünft-beste Zeit ODER falls diese = 0:
if(stoppedTime < bestTimes[4] || bestTimes[4] == 0){
bestTimes[4] = stoppedTime;
sortTimes();
storeTimesEEP();
}
updateTimes();
timeRunning = 0;
}
if(digitalRead(resetPin) == LOW) {
delay(debounce);
stoppedTime = 0;
for(uint8_t i=0;i<5;i++){
bestTimes[i] = 0;
}
updateTimes();
storeTimesEEP();
timeRunning = 0;
}
if(digitalRead(nextPin) == LOW){
delay(debounce);
if(rank == 4){
rank = 0;
}
else{
rank +=1;
}
updateTimes();
}
}
void sortTimes(){
// Nullen im Array temporär durch hohe Zahlen ersetzen:
for(uint8_t i = 0; i<5;i++){
if(bestTimes[i] == 0){
bestTimes[i] = 4000000; // max. Wert zu stoppen = 3'599'999
}
}
// Bubblesort:
for(uint8_t n = 4; n>0; n--){
for(uint8_t i = 0; i<n;i++){
// Falls linker Wert höher als rechter ODER linker Wert = 0
if(bestTimes[i]>bestTimes[i+1]){
// ...beide Werte tauschen:
tempTime = bestTimes[i];
bestTimes[i] = bestTimes[i+1];
bestTimes[i+1] = tempTime;
}
}
}
// Hohe Zahlen im Array wieder durch Nullen ersetzen:
for(uint8_t i = 0; i<5;i++){
if(bestTimes[i] == 4000000){
bestTimes[i] = 0; // max. Wert zu stoppen = 3'599'999
}
}
}
void updateTimes(){
lcd.setCursor(8, 0);
showTime(stoppedTime);
lcd.setCursor(5,1);
lcd.print(rank+1);
lcd.setCursor(8, 1);
showTime(bestTimes[rank]);
}
void showTime(unsigned long timeMS){
// Minuten, Sekunden und Hundertstel berechnen:
minutes = timeMS/60000;
seconds = (timeMS-minutes*60000)/1000;
hundreds = (timeMS-minutes*60000-seconds*1000)/10;
// Werte im gewünschten Format in Array timeString schreiben:
sprintf(timeString,"%02d:%02d:%02d", minutes, seconds, hundreds);
// ...und ans LCD ausgeben:
lcd.print(timeString);
}
void storeTimesEEP(){
byte byte0; // byte0 = 0...255
byte byte1; // byte1 = 256...65'535
byte byte2; // byte2 = 65'536...16'777'215
for(uint8_t i=0;i<5;i++){
byte0 = (bestTimes[i] & 0x0000FF);
byte1 = (bestTimes[i] & 0x00FF00) >> 8;
byte2 = (bestTimes[i] & 0xFF0000) >> 16;
EEPROM.write(addresses[i],byte0);
EEPROM.write(addresses[i]+1,byte1);
EEPROM.write(addresses[i]+2,byte2);
}
}
void readTimesEEP(){
byte byte0; // byte0 = 0...255
byte byte1; // byte1 = 256...65'535
byte byte2; // byte2 = 65'536...16'777'215
for(uint8_t i=0;i<5;i++){
byte0 = EEPROM.read(addresses[i]);
byte1 = EEPROM.read(addresses[i]+1);
byte2 = EEPROM.read(addresses[i]+2);
bestTimes[i] = byte0 + (byte1 << 8) + (byte2 << 16);
}
}