Natürlich hält sich kaum jemand an die 30 km/h, aber das ist per Blick aus dem
Küchenfenster, unter dem die Lawine durchrollt, nur gefühlt und nicht gemessen.
Seit Jahren reizt mich das zu einem Bastelprojekt, aber die technischen
Schwierigkeiten bzw. der Aufwand haben mich bislang abgeschreckt. Ich habe (da
ich im ersten Geschoß wohne) zwar einen guten Blick auf die Strecke, aber für
Infrarot-Lichtschranken und Reflektoren ist der Blickwinkel zu steil, und
Radar, Messung des akustischen Dopplereffekts der Fahrzeuggeräusche oder gar
Videoauswertung dürften recht kompliziert werden.
So bin ich auf eine Low-Tech-Lösung verfallen, die zwar menschliche Interaktion
erfordert, aber dafür simpel ist, mit einem ATtiny 13 auskommt und nach
Anpassung der Portbelegung sogar für den Sparrow-Wettbewerb taugt.
An der Straße vor meinem Küchenfenster stehen einige knorrige Alleebäume, und
zwei von denen nutze ich als Wegmarken für eine Zeitmessung. Wenn ein Fahrzeug
auf Höhe mit der ersten Wegmarke ist, wird der rechte Taster des Sparrow
gedrückt, bei Erreichen der zweiten Wegmarke wird der Taster wieder
losgelassen. In Kenntnis der Streckenlänge (die sich ja sehr einfach ausmessen
lässt) errechnet der Sparrow aus der Zeitdauer die Geschwindigkeit und gibt sie
zweistellig per Blinkcode und optional über einen an PortB.4 angeschlossenen
Piezolautsprecher (Buzzer) aus.
Z.B. bei 35 km/h blinkt die linke rote LED dreimal, anschließend die rechte
fünfmal. Parallel dazu gibt der Piezolautsprecher drei höhere Töne und
anschließend fünf tiefere Töne aus. Eine "Null" wird durch einen
langen Blinkimpuls (und einen langen Ton) signalisiert. Das akustische Signal
ist einfacher aufzunehmen als das optische, aber der Piezo verletzt ja die
Sparrow-Wettbewerbsbedingungen....
Bevor das Programm genutzt werden kann, muss jedoch dem Mikrocontroller die
Entfernung zwischen den Wegmarken mitgeteilt werden. Hierzu ist als erstes der
linke Taster und dann zusätzlich der rechte Taster des Sparrow zu drücken. Die
beiden LEDs beginnen zu blinken. Jedes Blinken steht für 0,5 m. Nach Erreichen
der erforderlichen Anzahl (z.B. 33 Blitze für 16,5m) läßt man die beiden Taster
los.
Wer morsen kann, ist klar im Vorteil - ein zweites Programm gibt die
Geschwindigkeit zweistellig in Morsezeichen aus. Die optische Decodierung über
die beiden LEDs ist etwas anstrengend, aber die
akustische Decodierung mit dem optionalen Buzzer ist sehr komfortabel,
und bei guten Morsekenntnissen kann man das Morsetempo noch ordentlich
"tunen".
Die Programme nutzen "Pin Change Interupts". Der Controller wartet im
Tiefschlaf auf einen Tastendruck des rechten Tasters (Taster2/PinB2), der ihn
aufweckt. Das Programm verharrt dann in einer Schleife, solange der Taster
gedrückt bleibt; in der Schleife wird die Variable "Zeit" in
10ms-Schritten erhöht. Danach wird der Wert ausgegeben und der Controller geht
wieder in den Tiefschlaf. Eine Batterie müsste jahrelang halten, da im
Tiefschlaf nur 20 µA (also 180 mAh pro Jahr) verbraucht werden. Ist der
Brownout des Controllers deaktiviert, sind es sogar nur 1 µA.
Wichtig für einen niedrigen Stromverbrauch ist, dass die Programmierschaltung,
die etwa 1,2 mA "frisst", nicht mit Spannung versorgt wird. Die
Batteriespannung darf also nur an den mit "U" gekennzeichneten Pin
und an "-" angelegt werden.
Verwendet man nicht den Sparrow, sondern baut sich eine eigene Schaltung, kann
man die LEDs und alle Widerstände weglassen und sich auf die akustische Ausgabe
beschränken. Dann sind nur 5 Teile erforderlich: ATtiny13, Abblockkondensator,
Buzzer und zwei Taster.
Die ersten Ergebnisse waren übrigens seltsam niedrig, "gefühlte" 50
km/h stellten sich als ca. 35 km/h heraus; da jedoch auch schnelle Radfahrer
kaum über 20 km/h kamen, habe ich noch mal die Strecke ausgemessen und
festgestellt, dass ich mich um 5m vermessen hatte. Das korrekte Ausmessen der
Strecke ist doch nicht so einfach wie oben behauptet, wenn man kein 25m-Bandmaß
hat.
Nach Eingabe des korrekten Abstands decken sich Messungen und Gefühl nun doch
halbwegs, die meisten fahren etwa 45 km/h. Addiert man die Fehlanzeige der
Auto-Tachos dazu, fahren die Leute also überwiegend mit "Tacho-50"
durch die Tempo-30-Strecke (von den üblichen Verdächtigen in sportlichen
Roadstern, rollenden Wummer-Musikboxen
oder auf Motorrädern mal abgesehen; da sind es dann eher 60 km/h).
' Programm dient zum Stoppen der Zeit, die ein Fahrzeug zwischen zwei Markierungen
' zurücklegt. Die Zeit wird in Geschwindigkeit umgerechnet und zweistellig per Blinkcode
' ausgegeben.
' Die Zeitaufnahme erfolgt durch Taster2 - solange der Taster gedrückt ist, wird die Zeit
' gemessen und bei Loslassen des Tasters über beide LEDs und einen optionalen Buzzer an
' Portb.4 ausgegeben
' Die Zehnerstelle wird durch Blinken von Led2 angezeigt, die Einerstelle durch Led1.
' Also bei 35 km/h blinkt Led2 (rot) dreimal, dann Led 1 (grün) fünfmal.
' Ausserdem wird das Ergebnis durch Piepstöne an PortB.4 ausgegeben, wenn man dort einen
' Piezoschwinger anschliesst. Zuerst erfolgt die Ausgabe der Zehnerstelle in hoher Tonlage,
' dann die der Einerstelle in tieferer Tonlage.
' Nullen werden durch einen langen Blinkimpuls bzw.einen langen Ton angezeigt.
' Umrechnung der Zeit in Geschwindigkeit:
' Speed [m/s] = Distanz [m] / T [sec]
' Speed [km/h] = 3,6 * Distanz [m] / T [sec]
' = 3,6 * Distanz [dm] * 0,1 / T [10 msec] * 0,01
' = 36 * Distanz [dm] / T [10ms]
' = Faktor / T [10ms]
' Um Fliesskommazahlen zu vermeiden, rechnen wir in Dezimetern und 10 ms-Intervallen
' Zu Beginn ist die Eingabe der Entfernung zwischen den Wegmarkierungen erforderlich. Sie
' erfolgt in 0,5m- Schritten. Erst wird Taster1 und dann zusätzlich Taster2 gedrückt und
' gehalten. Beide LEDs beginnen zu blinken, Jedes Blinken steht für 0,5m. Nach Erreichen der
' erforderlichen Anzahl läßt man die beiden Tasten los.
' Verwendeter Compiler: BASCOM 2.0.5 DEMO
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$regfile = "ATtiny13.dat"
$crystal = 1200000 ' Taktfrequenz: 1,2MHz
$hwstack = 8 ' nur max 4 geschachtelte Unterprogramme; spart SRAM
$swstack = 0 ' nicht benötigt; spart SRAM
$framesize = 0 ' dito
'---- vom Nutzer anzupassen
Const Kurz = 50 ' daraus ergibt sich die Blinkgeschwindigkeit
Const Pause = 450
Const Tonhoehe = 150 ' Tonhöhen
Const Tonhoehe2 = 180
'----
Const Lang = Kurz * 10
Buzzer Alias Portb.4
Led1 Alias Portb.1 ' grün, rechts
Led2 Alias Portb.3 ' rot, links
Taster1 Alias Pinb.0 ' links
Taster2 Alias Pinb.2 ' rechts
Dim I As Byte
Dim N As Byte
Dim Zeit As Word
Dim Speed As Word
Dim Distanz As Word
Dim Faktor As Word
Dim Zehner As Word ' Zehnerstelle des umgerechneten Analogwertes
Dim Einer As Word ' Einerstelle des umgerechneten Analogwertes
Clkpr = 128
Clkpr = 3 ' Takt herabsetzen, falls der ATtiny mit 9,6 MHz Takt läuft
Clkpr = 3
Acsr.acd = 1 ' Analog-Komparator ausschalten, spart etwas Strom
Gimsk.5 = 1 ' Pin Change Interrupt Enable
Sreg.7 = 1 ' Global Interrupt Enable
Pcmsk.2 = 1 ' Pin Change Interrupt PB2 aktivieren
Ddrb = &B00011010 ' PortB.1 und Portb.3 Ausgang
Portb = &B00000101 ' PullUp-Widerstände an Pinb.0 und Pinb.2
Didr0 = &B00011010 ' nicht benoetigte Digital- Eingänge abschalten
'
'-------------------------------------------------------------------------------
' Hauptprogramm:
Do
If Taster2 = 1 Then ' unterdrückt die Ausgabe "00" unmittelbar nach Anlegen der Batteriespannung
Goto Schlafen
End If
If Taster1 = 0 Then ' Wirkungsweise: PCINT2 (Taster2) weckt den Controller auf. Nur wenn
Gosub Einstellen ' er Taster1 bereits gedrückt vorfindet, wird nach "Einstellen" gesprungen ' wird in die Einstell-Routine verzweigt
Goto Schlafen
End If
Gimsk.5 = 0 ' Pin Change Interrupt ausschalten
Zeit = 0
Do
Incr Zeit
Waitms 10
Loop Until Taster2 = 1
Faktor = Distanz * 36
Speed = Faktor / Zeit
If Speed > 99 Then ' Überlauf abfangen
Speed = 99
End If
Zehner = Speed / 10 ' Zerlegung in Einzelzahlen
Einer = Speed Mod 10
Wait 1
N = Zehner ' Zehnerstelle des Messwerts
Gosub Beepandblink_z ' wir senden die Zehnerstelle
Wait 1
N = Einer ' Einerstelle des Messwerts
Gosub Beepandblink_e ' wir senden die Einerstelle
Schlafen:
Gimsk.5 = 1 ' Pin Change Interrupt wieder einschalten
Powerdown
Loop
Beepandblink_z:
If N = 0 Then
Led2 = 1
Sound Buzzer , Lang , Tonhoehe
Led2 = 0
End If
For I = 1 To N
Led2 = 1
Sound Buzzer , Kurz , Tonhoehe
Led2 = 0
Waitms Pause
Next
Return
Beepandblink_e:
If N = 0 Then
Led1 = 1
Sound Buzzer , Lang , Tonhoehe2
Led1 = 0
End If
For I = 1 To N
Led1 = 1
Sound Buzzer , Kurz , Tonhoehe2
Led1 = 0
Waitms Pause
Next
Return
Einstellen:
Distanz = 0
Do
Distanz = Distanz + 5 ' 0,5m-Schritte
Led1 = 1
Led2 = 1
Waitms 100
Led1 = 0
Led2 = 0
Waitms 400
Loop Until Taster1 = 1 And Taster2 = 1
Return
End
Morse-Version:
' Programm dient zum Stoppen der Zeit, die ein Fahrzeug zwischen zwei Markierungen
' zurücklegt. Die Zeit wird in Geschwindigkeit umgerechnet und zweistellig per Morsezeichen
' ausgegeben.
' Die Zeitaufnahme erfolgt durch Taster2 - solange der Taster gedrückt ist, wird die Zeit
' gemessen und bei Loslassen des Tasters das Ergebnis in Morse ausgegeben. Die Ausgabe
' erfolgt über beide LEDs und einen optionalen Buzzer an Portb.4
' Umrechnung der Zeit in Geschwindigkeit:
' Speed [m/s] =/ Distanz [m] / T [sec]
' Speed [km/h] = 3,6 * Distanz [m] / T [sec]
' = 3,6 * Distanz [dm] * 0,1 / T [10 msec] * 0,01
' = 36 * Distanz [dm] / T [10ms]
' = Faktor / T [10ms]
' Um Fliesskommazahlen zu vermeiden, rechnen wir in Dezimetern und 10 ms-Intervallen
' Zu Beginn ist die Eingabe der Entfernung zwischen den Wegmarkierungen erforderlich. Sie
' erfolgt in 0,5m- Schritten. Erst wird Taster1 und dann zusätzlich Taster2 gedrückt und
' gehalten. Beide LEDs beginnen zu blinken, Jedes Blinken steht für 0,5m. Nach Erreichen der
' erforderlichen Anzahl läßt man die beiden Tasten los.
' Erläuterungen zum Morseteil:
'
' Codierung der Morsezeichen: 1 Byte pro Zeichen, niederwertiges Bit zuerst.
' Ist der Bit-Wert 0: Morsepunkt (dit)
' Ist der Bit-Wert 1: Moersestrich (dah)
' Da Morsezeichen unterschiedlich lang sind, ist das Ende-Zeichen ebenfalls ein 1-Bit.
'
' Beispiel Morsezeichen "a" (dit dah): &B00000110
' Beispiel Morsezeichen "9" (dah dah dah dah dit): &B00101111
' Auslesen der codierten Zeichen:
' niederwertigstes Bit auslesen, Byte um 1 Stelle nach rechts schieben, niederwertigstes Bit
' auslesen. Ist der Gesamtwert des Bytes nur noch 1, ist das Zeichen komplett.
' Verwendeter Compiler: BASCOM 2.0.5 DEMO
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$regfile = "ATtiny13.dat"
$crystal = 1200000 ' Taktfrequenz: 1,2MHz
$hwstack = 8 ' nur max 4 geschachtelte Unterprogramme; spart SRAM
$swstack = 0 ' nicht benötigt; spart SRAM
$framesize = 0 ' dito
'---- vom Nutzer anzupassen
Const Dit = 120 ' Länge eines Punkts, daraus ergibt sich die Morsegeschwindigkeit
Const Tonhoehe = 150 ' Tonhöhe
'----
Const Msg_laenge = 11 ' Anzahl der DataBytes; maximal 47
Const Dah = Dit * 3 ' Länge eines Strichs
Const Dit_pause = Dit
Const Dah_pause = Dit_pause * 5
Buzzer Alias Portb.4
Led1 Alias Portb.1 ' grün, rechts
Led2 Alias Portb.3 ' rot, links
Taster1 Alias Pinb.0 ' links
Taster2 Alias Pinb.2 ' rechts
Dim I As Byte ' wird in Zählschleife verwendet
Dim N As Byte ' Aktueller Morsebuchstabe
Dim M As Word ' wird fürs Auslesen der Morsebits verwendet
Dim L As Byte ' niederwertigstes Bit von M verwendet
Dim Zeit As Word '
Dim Distanz As Word
Dim Faktor As Word
Dim Speed As Word
Dim Zehner As Word ' Zehnerstelle des umgerechneten Analogwertes
Dim Einer As Word ' Einerstelle des umgerechneten Analogwertes
Dim Msg(msg_laenge) As Byte ' Feld für die 10 Morse-Ziffern
Clkpr = 128
Clkpr = 3 ' Takt herabsetzen, falls der ATtiny mit 9,6 MHz Takt läuft
Clkpr = 3
Acsr.acd = 1 ' Analog-Komparator ausschalten, spart etwas Strom
Gimsk.5 = 1 ' Pin Change Interrupt Enable
Sreg.7 = 1 ' Global Interrupt Enable
Pcmsk.2 = 1 ' Pin Change Interrupt PB2 Enable
Ddrb = &B00011010 ' Portb.1, Portb.3, Portb.4 Ausgang
Portb = &B00000101 ' PullUp-Widerstände an Pinb.0 und Pinb.2
Didr0 = &B00011010 ' nicht benoetigte Digital- Eingänge abschalten
Restore Message ' Feld einlesen
For I = 1 To Msg_laenge
Read Msg(i)
Next
'
'-------------------------------------------------------------------------------
' Hauptprogramm:
Do
If Taster2 = 1 Then ' unterdrückt die Ausgabe "00" unmittelbar nach Anlegen der Batteriespannung
Goto Schlafen
End If
If Taster1 = 0 Then ' Wirkungsweise: PCINT2 (Taster2)weckt den Controller auf. Nur wenn
Gosub Einstellen ' er Taster1 bereits gedrückt vorfindet, wird nach "Einstellen" gesprungen ' wird in die Einstell-Routine verzweigt
Goto Schlafen
End If
Gimsk.5 = 0 ' Pin Change Interrupt ausschalten
Zeit = 0
Do
Incr Zeit
Waitms 10
Loop Until Taster2 = 1
Faktor = Distanz * 36
Speed = Faktor / Zeit
If Speed > 99 Then ' Überlauf abfangen
Speed = 99
End If
Zehner = Speed / 10 ' Zerlegung in Einzelzahlen
Einer = Speed Mod 10
Wait 1
N = Zehner + 1 ' Zehnerstelle des Messwerts
Gosub Morse ' wir senden die Zehnerstelle
Waitms Dah_pause
N = Einer + 1 ' Einerstelle des Messwerts
Gosub Morse ' wir senden die Einerstelle
Schlafen:
Gimsk.5 = 1 ' Pin Change Interrupt wieder einschalten
Powerdown
Loop
' Morsezeichenerzeugung:
Morse:
M = Msg(n) ' aktuelles Zeichen aus Kette rauspicken
For I = 1 To 8
If M = 1 Then ' Das Byte hat nur noch den Wert 1; Zeichenende!
Goto Sign_end
End If
Led1 = 1
Led2 = 1
If M.0 = 1 Then ' ist Bit.0 = 1 -> dah
Sound Buzzer , Dah , Tonhoehe
Else
Sound Buzzer , Dit , Tonhoehe ' ist das Bit 0 -> dit
End If
Led1 = 0
Led2 = 0
Waitms Dit_pause ' Pause innerhalb des Morsezeichens
Shift M , Right , 1 ' Bits um eine Stelle nach rechts shiften
Next I
Sign_end:
Return
Einstellen:
Distanz = 0
Do
Distanz = Distanz + 5 ' 0,5m-Schritte
Led1 = 1
Led2 = 1
Waitms 100
Led1 = 0
Led2 = 0
Waitms 400
Loop Until Taster1 = 1 And Taster2 = 1
Return
End
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
' Codierung der Morsezeichen. Bei einem Prozessor mit viel SRAM würde man die Zeichentabelle
' in ein Array einlesen, den in Morse zu codierenden Text in einen String packen und diesen
' String zeichenweise abarbeiten.
'
' Da der Attiny13 nur wenig SRAM hat, ist der Weg hier anders: Der zu codierende Text ist ein
' Array mit 10 Elementen, in dem die auszusendenden Zeichen stehen, allerdings in einer leicht
' lesbaren Schreibweise.
' Die Übersetzungstabelle ist mit Konstanten realisiert. Nur die wirklich benötigten Zeichen werden
' (beim kompilieren des Programmes) umgewandelt.
Const #0 = &B00111111
Const #1 = &B00111110
Const #2 = &B00111100
Const #3 = &B00111000
Const #4 = &B00110000
Const #5 = &B00100000
Const #6 = &B00100001
Const #7 = &B00100011
Const #8 = &B00100111
Const #9 = &B00101111
Message:
Data #0 , #1 , #2 , #3 , #4 , #5 , #6 , #7 , #8 , #9