Sparrow-Speed2Flash           

von Ralf Beesner                      
      
Elektronik-Labor  Projekte  AVR  Sparrow  Contest          




Ich zog vor vielen Jahren in eine Wohnung in einer ruhigen Seitenstraße, die sich jedoch im Laufe der Zeit zu einem beliebten Schleichweg entwickelt hat. Die "Obrigkeit" hat zwar, um die Anwohner ruhigzustellen, Tempo-30-Schilder aufgestellt und ein paar den Verkehrsweg einengende Schikanen, an denen die Leute nun per Hupe um die Vorfahrt streiten ;-) , aber zur morgendlichen und abendlichen Rush Hour, wenn die Hauptwege verstopft sind, wälzt sich die Blechlawine durch die Straße, und auch zu den Nebenzeiten wird der Schleichweg stetig beliebter, da man so ein paar Ampeln ausweichen kann.

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).

 
Download: sparrow-speed2flash-soft.zip
Direkt laden: http://tiny.systems/categorie/cheepit/GeschwindigkeitsmesserEasy.html
Direkt laden (Morse-Version) : http://tiny.systems/categorie/cheepit/Geschwindigkeitsmesser.html
' 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






Elektronik-Labor  Projekte  AVR  Sparrow Contest