Rundenzähler für Slotracer
von Wolfram Herzog
ELO 2010
Das Mitzählen der gefahrenen Runden beim Slotrace ist eine mühselige
und fehlerträchtige Angelegenheit. Daher wurde auf der Basis des BASCOM
Lernpaketes ein Rundenzähler für Slot-Racer-Bahnen umgesetzt. Dieser
zählt nicht nur die Runden und ermittelt den Sieger sondern gibt auch
ein akustisches Startsignal.
Erfassen der gefahrenen Runden
Um die gefahrenen Runden zu ermitteln, wurden Reedkontakte in die
Fahrbahn eingesetzt. Diese haben den Vorteil der einfachen Montage. Sie
werden einfach mit Heißkleber unter die Fahrbahn geklebt und die
Anschlüsse über einen Stecker nach Außen geführt. Der hier verwendete
Steckverbinder ist ein vierpoliger Stecker (Stromversorgung eines 3,5“
Diskettenlaufwerks) von einem alten PC-Netzteil.
Es empfiehlt sich, zum Schluss ein Klebeband zur Isolierung darüber zu kleben.
Der Hardwareaufbau
Die Hardware für den Rundenzähler besteht aus der Experimentierplatine
des BASCOM Lernpaketes und einem daran angeschlossenen LCD-Display. So
kann die Experimentierplatine auch ohne PC benutzt werden. Als
Stromversorgung dient im Rennbetrieb ein Steckernetzteil eines MP3
Players mit USB-Buchse, in die das mitgelieferte USB-Kabel eingesteckt
wird. Der Mini-USB Stecker wird wie gewohnt mit der
Experimentierplatine verbunden.
Näheres zum Anschluß eines LCD Displays an die Experimentierplatine finden Sie in dem Beitrag „LCD Display für BASCOM Lernpaket“
Weiterhin wird an der Experimentierplatine ein Piezo-Piepser
angeschlossen. Da es beim Slotrace schon mal ein wenig laut hergehen
kann wurde hier ein Murata-Piepser angeschlossen, der aus einem alten
Siemens Telefon stammt. Natürlich kann auch das Piezoelement aus dem
Lernpakte verwendet werden, es ist nur nicht so laut.
Alle Bauteile wurden auf ein Sperrholzbrett geschraubt, um die
Handhabung zu vereinfachen. Die Verbindung zum Slotcar-Fahrbahn erfolgt
über ein dreipoliges Kabel und eine vierpolige 2,54mm Stiftleiste. Die
Anschlüsse der Experimentierplatine sind nun wie folgt belegt:
PB0 RS Pin des LCD Display
PB1 DB4 Pin des LCD Display
PB2 DB5 Pin des LCD Display
PB3 DB6 Pin des LCD Display
PB4 DB7 Pin des LCD Display
PB5 ENABLE Pin des LCD Display
PD6 Reedkontakt Spur1
PD7 Reedkontakt Spur 2
ADC0 Anschluß rot Piezo
GND Anschluß schwarz Piezo
GND Anschluß Reedkontakt Spur1
GND Anschluß Reedkontakt Spur2
Da die internen Pull-Up Widerstände des MEGA88 von PD6 un dPD7
aktiviert sind, ist eigentlich ein Draht vom Port zum Reedkontakt und
dann an GND ausreichend. Wir hatten allerdings hin und wieder
merkwürdige Störungen und daher einen externen 2,2K Pull-up-Widerstand
von PD6 und PD7 nach Vcc hinzugefügt. Danach waren die Probleme
beseitigt.
Die Software
Das Programm ist in der üblichen Art und Weise aufgebaut. Es werden
zuerst die Anschlüsse für das LCD Display definiert, anschließend die
verwendeten Ports konfiguriert.
Um die Lesbarkeit des Programms zu verbessern werden mit dem Befehl
ALIAS den verschiedenen Ports verständliche Namen zugewiesen, so wird
z.B. der PortC.0 an den der Piezo-Piepser angeschlossen wird mit dem
Name „Buzzer“ versehen.
Die Software benutzt zwei der drei Timer des MEGA88 – es sind die
beiden 8-Bit Timer Timer0 und Timer2. Der 16Bit Timer1 bleibt frei und
könnte für künftige Programmerweiterungen – z.B. eine Zeitmessung der
Rundenzeiten – genutzt werden.
Es werden drei Interrupts genutzt, die dann entsprechende
Interruptroutinen aufrufen. Zum einen der flankengetriggerte PCINT0,
der bei einer fallenden Flanke am Port ausgelöst wird. Damit wird das
Schließen der Reedschalter durch das darüberfahrende Slotcar erkannt.
Zum anderen die beiden Timer-Overflow-Interrupts für die Timer0 und
Timer2, mit denen ein Entprellen der Reedkontakte erfolgt. Da manche
Slotcar-Autos nicht nur einen sondern auch zwei oder drei Magnete an
der Unterseite haben, muss neben dem Entprellen der Reedkontakte auch
die Mehrfachauslösung durch die verschiedenen Magnete ausgewertet
'*****************************************
' Rundenzähler für Slotcar-Racing
' Wolfram Herzog 13.1.2010
'
' für Franzis BASCOM Lernpaket mit MEGA88
' erstellt mit BASCOM 1.11.9.5
'
' Taster INT0 und INT1 als Eingabe
' Reedkontakte an PD6 und 7
'
' Timer0 und 2 wird als Entpreller auf fallende Flanke benutzt
'
' Version 1.1.11
'******************************************
$regfile = "m88def.dat"
$crystal = 8000000
$baud = 19200
$hwstack =
32
' default use 32 for the hardware stack
$swstack =
10
' default use 10 for the SW stack
$framesize =
40
' default use 40 for the frame space
Config Lcd = 16 * 2
Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.5 , Db4 = Portb.1 , Db5 = Portb.2 , Db6 = Portb.3 , Db7 = Portb.4
Config Pind.2 =
Input
' Taster auf dem Board
Config Pind.3 = Input
Config Pind.6 =
Input
' Reedkontakte
Config Pind.7 = Input
Config Portb.7 =
Output
' LED zu Kontrollzwecken
Config Portb.6 = Output
Config Timer0 = Timer , Prescale =
1024
'8-64-256-1024
Config Timer2 = Timer , Prescale =
1024
'8-32-64-128-256-1024
Portd.2 =
1
' Interne Pull-ups aktivieren
Portd.3 = 1
Portd.6 = 1
Portd.7 = 1
Taster0 Alias
Pind.2
'Für bessere Lesbarkeit des Programmes
Taster1 Alias Pind.3
Kontakt1 Alias Pind.6
Kontakt2 Alias Pind.7
Buzzer Alias
Portc.0
'Piezo Summer
Enable
Interrupts
'enable global ints
Enable
Pcint0
'we enable pcint0 as this has pcint0-pcint7
On Pcint0
Isr_pcint0
'we jump to this label when one of the pins is changed
Pcmsk0 =
&B11001100
'enable pcint6-pcint7 (portb.0-portb.3)
Enable
Timer0
' Timer freigeben
Enable Timer2
On Timer0
Isr_timer0
' Timer Interrupt freigeben
On Timer2
Isr_timer2
' für Timer0 und Timer2
Config Debounce =
30
' Wartezeit in ms für taster
Dim S1 As
Byte
'Flag ob steigende Flanke erkannt
Dim S2 As Byte
Dim Z1aehler As
Byte
'Gefahrene Runden
Dim Z2aehler As Byte
Dim Fz1 As
Byte
'Debounce Zähler
Dim Fz2 As Byte
Dim Runden As
Byte
' Anzahl der Runden
Dim Fertig As
Byte
' Flag ob Rundenzahl erreicht
Dim Erunden As Eram
Byte
'Rundenzahl im EEPROM gespeichert
Sstart:
Cls
' Begrüßungsbildschirm
Cursor Off
Upperline
Lcd "SLOTRACE V1.1.11"
Lowerline
Lcd "1=Rennen 2=Setup"
Tastenwart:
' Verzweigung Setup
Debounce Taster1 , 0 ,
Pstarten
'int1 Taste gedrückt
Debounce Taster0 , 0 , Setuprunden ,
Sub
'INT0 Taste gedrückt
Goto Tastenwart
Pstarten:
'Beginn des Hauptteils
S1 =
0
' Alle Variablen initialisieren
S2 = 0
Fertig = 0
Z1aehler = 0
Z2aehler = 0
Runden =
Erunden
' Anzahl der zu fahrenden Runden aus EEPROM holen
Stop
Timer0
' Timer erst anhalten sonst stimmt der Zähler nicht
Stop Timer2
Cls
' Startbildschirm
Cursor Off
Upperline
Lcd "START " ; Runden ; " Runden"
Lowerline
Lcd "* Taste druecken"
Tast2wart:
Debounce Taster1 , 0 ,
Losgehts
'int1 Taste gedrückt
Debounce Taster0 , 0 ,
Sstart
'INT0 Taste gedrückt
Goto Tast2wart
Losgehts:
'Akustisches Startsignal
Sound Buzzer , 400 , 450
Waitms 600
Sound Buzzer , 400 , 450
Waitms 600
Sound Buzzer , 400 , 450
Waitms 600
Sound Buzzer , 800 , 350
Cls
'----------- Zählschleife --------------------
Do
Upperline
Lcd "Spur1: " ; Z1aehler
Lowerline
Lcd "Spur2: " ; Z2aehler
Debounce Taster1 , 0 ,
Zfertig
' Taste für Abbruch gedrückt
Loop Until Fertig = 1
' ---------- Platzierung ----------------------
Sieger:
'Anzeige der Platzierung
Cls
Lcd "Erster "
Gosub Winner
If Z1aehler >= Runden Then
Lcd " Spur1 " ; Z1aehler
Locate 2 , 1
Lcd "Zweiter Spur2 " ; Z2aehler
End If
If Z2aehler >= Runden Then
Lcd " Spur2 " ; Z2aehler
Locate 2 , 1
Lcd "Zweiter Spur1 " ; Z1aehler
End If
Gosub Winner
Gosub
Wtaste
'Auf Taste warten
Goto
Pstarten
'Nächstes Rennen
End
'end program
' -- Vorzeitiger Abbruch -------------------------
Zfertig:
Sound Buzzer , 400 , 450
Cls
Lcd "### Abbruch! ###"
Lowerline
Lcd "Spur1 " ; Z1aehler ; " Spur2 " ; Z2aehler
Gosub Wtaste
Goto
Pstarten
'Nächstes Rennen
' --------------- Unterprogramme -----------------
' -----------Flanke am Zähleingang ---------------
Isr_pcint0:
If Pind.6 = 0
Then
'Fallende Flanke erkannt
If S1 = 0
Then
'Prüfung ob erste Flanke
S1 =
1
'Timerflag setzen
Fz1 =
0
'Flankenzähler auf Null
Start
Timer0
'Timer starten
End If
End If
If Pind.7 = 0 Then
If S2 = 0 Then
S2 = 1
Fz2 = 0
Start Timer2
End If
End If
Return
'----------- Timer 0 abgelaufen -----------------
Isr_timer0:
' Toggle Portb.6
If Pind.6 = 1
Then
' Ist Pin wieder high?
Incr
Fz1
'Flankenzähler plus 1
If Fz1 = 20
Then
'ca. 30ms Vergangen
Incr
Z1aehler
'Runde zählen
S1 =
0
'Flankenerkennung auf Null
Stop
Timer0
'Timer anhalten
Toggle
Portb.6
' Kontroll LED umschalten
End If
End If
If Z1aehler = Runden Then Fertig =
1
' maximale Runden erreicht
Return
'----------- Timer 2 angelaufen ------------------
Isr_timer2:
' Toggle Portb.7
If Pind.7 = 1 Then
Incr Fz2
If Fz2 = 20 Then
Incr Z2aehler
S2 = 0
Stop Timer2
Toggle
Portb.7
' Kontroll LED schalten
End If
End If
If Z2aehler = Runden Then Fertig =
1
' maximale Runden erreicht
Return
'--- INT1 Taster abfragen zum Warten ----
Wtaste:
Debounce Taster1 , 0 ,
Wfertig
'Warten bis INT1 Taster gedrückt
Goto Wtaste
Wfertig:
Return
'----- Setup Rundenzahl ----
Setuprunden:
Runden =
Erunden
' Wert aus EEPROM Holen
Cls
Lcd "Runden: " ; Runden
Lowerline
Lcd "Neuer Wert:"
Cursor On Blink
Fz1 = 1
Setuploop:
Locate 2 , 12
Lcd Fz1
Shiftcursor Left
Do
Debounce Taster0 , 0 ,
Splus
'Warten bis INT1 Taster gedrückt
Debounce Taster1 , 0 ,
Setupfertig
'Warten bis INT1 Taster gedrückt
Loop
Splus:
Incr
Fz1
'Rundenzahl erhöhen
Goto Setuploop
Setupfertig:
Erunden =
Fz1
'Neuer Wert ins EEPROM schreiben
Cursor Off
Return
'---- Sound für Renn-Ende ----------
Winner:
Sound Buzzer , 500 , 450
Waitms 400
Sound Buzzer , 800 , 350
Waitms 300
Sound Buzzer , 500 , 450
Waitms 200
Sound Buzzer , 800 , 350
Return
' Ende des Listings