mediakasper:
wäre nett wenn du mir da nochmal Hilfestellung leisten könntest.
Ich bin dann mal so nett.
Das mit der Interruptprogrammierung geht natürlich weit über "Anfängerprogrammierung" hinaus. Aber ohne die Nutzung von Interrupts ist es für Deinen Anwendungsfall kaum sinnvoll zu realisieren, wenn man nicht "verschluckte" Runden riskieren möchte. Mit typischer Anfängerprogrammierung ist Dein Anwendungsfall leider nicht perfekt in Software umsetzbar, sondern nur mit fortgeschrittenen Programmiertechniken und Nutzung der Hardware-Interrupts.
Als Goodies außerhalb Deiner Spezifikation habe ich gleich nochmal einen "Rundenzähler" eingebaut und eine Anzeige, die im Zweisekundentakt wechselt zwischen "Anzeige der Rundenzeiten" und "Anzeige der Rundenanzahl".
Vollständig unter Echtbedingungen testen kann ich natürlich nicht, da ich weder die Rennbahn noch die Reedkontakte habe.
Das Timing selbst ist bis hin zur Verarbeitung übrigens auf tausendstel Sekunden genau und erst beim Anzeigen der Zeiten wird auf hundertsel Sekunden gerundet.
Probier's aus, ob Du was damit anfangen kannst!
Damit Du ggf. selbst Änderungen vornehmen kannst, habe ich einige Kommentarzeilen dazugeschrieben und mich bemüht, sprechende Variablennamen zu vergeben, die von selbst erklären, was darin gespeichert ist.
Außerdem habe ich das Programm gleich so angelegt, daß man es mit möglichst geringem Aufwand auf bis zu sechs Slot-Zeitmessungen erweitern könnte, falls man es auf ein MEGA Board (mit 6 Interrupts) umschreiben und erweitern möchte.
/*
Slotcar timing by "jurs" for German Arduino forum
Hardware required: Arduino UNO, LCD keypad shield, 2 reed contacts
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Sainsmart keypad LCD
#define LEDPIN 13
#define SLOTS 2
// Mindestrundenzeit in Millisekunden, alles darunter als Kontaktprellen interpretieren
#define MINROUNDTIME 500
// Pins zum Anschluss der Reedkontakte (D2, D3)
byte reedPins[]={2,3};
// Interrupt-Nummern zu diesen Pins
byte pinInterrupts[]={0,1};
// Interrupt-Behandlungsroutinen
void (*isrFunctions[])() = { timing1, timing2 };
// Start der letzten Runde in Millisekunden, volatile weil Zugriff auch aus ISR!
volatile long rundenAnfang[]={0,0};
// Rundenzeit der letzten Runde in Millisekunden
long rundenZeit[]={99990,99990};
// Rundenzeit der schnellsten Runde in Millisekunden
long rundenZeitRekord[]={99990,99990};
// Rundenzähler
int rundenAnzahl[]={0,0};
void setup() {
// LCD Anzeige mit Spalten und Zeilen initialisieren
lcd.begin(16, 2);
// Anzeige LED-13 auf dem Board initialisieren
pinMode(LEDPIN,OUTPUT);
// Reedkontakte und ISR Routinen initialisieren
for (int i=0;i<SLOTS;i++)
{
pinMode(reedPins[i],INPUT_PULLUP);
attachInterrupt(pinInterrupts[i], isrFunctions[i], FALLING);
}
}
void timing1()
{
if (millis()-rundenAnfang[0]>MINROUNDTIME)
rundenAnfang[0]=millis();
}
void timing2()
{
if (millis()-rundenAnfang[1]>MINROUNDTIME)
rundenAnfang[1]=millis();
}
void RundenzeitenVerarbeiten()
{
// Start der vorletzten Runde in Millisekunden
static long rundenAnfangVerarbeitet[]={0,0};
long curMillis;
// Aktuellen Stand der millis() Funktion merken
curMillis=millis();
// Alle Slots auf Veränderungen der Rundenstartzeit abklappern
for (int i=0;i<SLOTS;i++)
{
if (rundenAnfangVerarbeitet[i]!=rundenAnfang[i])
{ // Neue Runde seit dem letzten Loopdurchlauf
rundenAnzahl[i]++; // Rundenzähler hochzählen
// Rundenzeit ermitteln
rundenZeit[i]=rundenAnfang[i]-rundenAnfangVerarbeitet[i];
// Feststellen ob es eine schnellste Runde war
if (rundenZeit[i]<rundenZeitRekord[i])
rundenZeitRekord[i]=rundenZeit[i];
// Am Ende diese Rundenzeit als verarbeitet merken
rundenAnfangVerarbeitet[i]=rundenAnfang[i];
}
}
}
void RundenanzahlAnzeigen()
{ static long lastUpdate;
char lcdline[17];
// Anzeige nur alle 500 ms aktualisieren
if (millis()/500==lastUpdate) return;
lastUpdate=millis()/500;
for (int i=0;i<SLOTS;i++)
{
snprintf(lcdline,sizeof(lcdline),"%d %5d Runden ",i+1,rundenAnzahl[i]);
lcd.setCursor(0,i);
lcd.print(lcdline);
}
}
void RundenzeitenAnzeigen()
{ static long lastUpdate;
long dieseRunde, dieserRekord;
char lcdline[17];
int zeit[4];
// Anzeige nur alle 500 ms aktualisieren
if (millis()/500==lastUpdate) return;
lastUpdate=millis()/500;
for (int i=0;i<SLOTS;i++)
{
// Rundenzeit und schnellste Zeit auf Zeitangabe in hundertstel runden
dieseRunde=(rundenZeit[i]+5)/10;
dieserRekord=(rundenZeitRekord[i]+5)/10;
zeit[0]=dieseRunde/100; // ganze Sekunden
zeit[1]=dieseRunde%100; // hundertstel Sekunden
zeit[2]=dieserRekord/100; // ganze Sekunden
zeit[3]=dieserRekord%100; // hundertstel Sekunden
snprintf(lcdline,sizeof(lcdline),"%d%3d:%02d SR%3d:%02d",i+1,zeit[0],zeit[1],zeit[2],zeit[3]);
lcd.setCursor(0,i);
lcd.print(lcdline);
}
}
void loop()
{
RundenzeitenVerarbeiten();
if ((millis()/2000)%2==1)
RundenzeitenAnzeigen();
else
RundenanzahlAnzeigen();
// Nun noch die Pin-13 LED ein wenig blinken lassen, wenn man möchte
if (millis()-rundenAnfang[0]<200 || millis()-rundenAnfang[1]<200)
digitalWrite(LEDPIN,HIGH);
else
digitalWrite(LEDPIN,LOW);
}