Thymio liest Barcodes
Barcodes sind allgegenwärtig
Wir finden an allen möglichen und unmöglichen Orten Barcodes!
Was sind denn Barcodes eigentlich? Barcodes representieren im Prinzip einfach Zahlen und Texte, welche besonders leicht von Maschinen gelesen werden können.
Auf allen Artikeln im Supermarkt sind zum Beispiel die Artikelnummern als Barcodes angebracht. Diese werden an der Kasse 'gescannt', die Kasse kennt den Preis zu dieser Nummer und der Artikel wird dann direkt aus dem Lagerbestand gelöscht und eventuell sogar noch automatisch nachbestellt.
Ein Barcode für Thymio
Die Barcodes, welche Thymio lesen kann müssen deutlich breitere Striche (=Bars) als dies kommerziell verwendeten haben. Auch können wir nicht ganze Texte kodieren, wir beschränken uns auf die Zahlen von '0' bis '7'. So soll unser Barcode aussehen:
Der Barcode besteht aus vier gleichgrossen Feldern oder Bits, diese sind entweder 'schwarz' oder 'weiss' eingefärbt. Thymio 'liest' nun die Farbe dieser Felder und berechnet daraus den gesuchten Zahlenwert des Barcodes.
Damit Thymio erkennt dass als nächstes ein Barcode kommt ist das erste Feld immer schwarz: Dieses Feld wird Synchronisations-Bit, oder kürzer Sync-Bit genannt. Nach dem Sync-Bit folgen drei sogenannte Daten-Bit, in welchen unsere Zahl kodiert ist:
- Wenn das erste Daten-Bit 'weiss' ist hat es den Wert '1', sonst 'null'.
- Wenn das zweite Daten-Bit 'weiss' ist hat es den Wert '2', sonst 'null'.
- Wenn das dritte Daten-Bit 'weiss' ist hat es den Wert '4', sonst 'null'.
Unsere gesuchte Zahl ist nun die Summe dieser drei Werte. Sind alle Daten-Bits 'schwarz' dann ist die gesuchte Zahl 0+0+0=0, sind alle Daten-Bits 'weiss', dann ist die Zahl 1+2+4=7. Wir können also wie gewünscht alle Zahlen von 0 bis 7 darstellen.
Das folgende Bild zeigt einige Beispiele. (Achtung: Diese Barcodes müssen von 'unten' nach 'oben' gelesen werden, das unterste Bit ist also das Sync-Bit)
Die Barcodes können von der Kopiervorlage ausgeschnitten und mit Filzstiften 'ausgemalt' werden, sie können aber auch, wie im Bild dargestellt, händisch gezeichnet werden. Die Barcodes werden dann auf möglichst geraden Streckenabschnitten in 20 mm Abstand parallel zur Piste befestigt.
Thymio liest Barcodes
Ein Barcode-Leseprogramm sollte drei Fähigkeiten haben:
- Es muss einem Weg mit konstanter Geschwindigkeit folgen. Dabei darf nur ein Bodensensor benutzt werden. Auf der Seite Thymio folgt einer schwarzen Kante wird das Verfolgen einer Linie mit nur einem Bodensensor ausführlich beschrieben.
- Es muss den Barcode lesen. Thymio fährt den Barcode mit konstanter Geschwindigkeit ab und liest mit dem zweiten Bodensensor den Barcode. Dies wird nachfolgend beschrieben.
- Es muss mit dem gelesenen Barcode etwas anfangen, so wie zum Beispiel beim Projekt Lichtmalerei mit Barcodes. Hier wird mit dem gelesenen Code entweder nichts gemacht oder der Code wird einfach angezeigt. Die Idee dahinter ist, dass das Programm als Grundlage für eigene Entwicklungen und Erweiterungen benutzt werden kann.
So geht der Lesevorgang
Die Bodensensoren von Thymio messen in Abständen von 0.1 Sekunden die Helligkeit des Untergrundes. Die Fahrgeschwindigkeit von Thymio wird nun so eingestellt, dass Thymio in 0.1 Sekunden genau 5 mm weit fährt1. Ein Bit ist 25 mm breit, das heisst Thymio braucht 0.5 Sekunden um ein Bit zu durchfahren, dabei macht er 5 jeweils Messungen2.
Im unten stehenden Bild wird jede Messung des Bodensensors als vertikaler Strich dargestellt, pro Bit sind 5 Messungen zu erkennen.
Wenn Thymio zum erstem Mal 'schwarz' entdeckt, hat er das Sync-Bit gefunden und er beginnt die einzelnen Messungen zu zählen. Da die erste 'schwarz'-Messung ganz links vom Sync-Bit ist, beginnt er die Zählung mit dem Wert -2.
Immer wenn der Zähler durch 5 ohne Rest teilbar ist (durch rote Zahlen dargestellt), befindet er sich in der Mitte des Bit und der entsprechende Wert (1, 2 oder 4) dieses Bits wird, falls die Messung an dieser Stelle 'weiss' ergibt, zum Code dazu addiert.
Wenn der Zähler bei 20 angekommen ist, beendet Thymio den Lesevorgang und beginnt wieder nach einen Sync-Bit zu suchen.
Hier ist der beschriebene Algorithmus als Blockly Programm :
Die ersten vier 'Zeilen' dieses Programms dienen zur Verfolgung der Linie, der Rest zum Lesen der Barcodes.
Das Programm ist voll funktionsfähig, die Barcodes werden aber nur gelesen und nicht weiterverarbeitet. Im leeren Unterprogramm use_results können (und sollten) die eigenen Aktionen zu den gelesenen Barcodes eingefügt werden.
Dieser Algorithmus ist nicht auf Barcodes mit drei Datenbits (wordlen=3) beschränkt: Er kann Barcodes mit 0 bis zu 15 Datenbits lesen.
Das gleiche3 Lese-Programm als Text Programm.
Ein vollständiges Beispiel mit automatischer Kalibrierung
Geschwindikeit wählen
Wenn dieses Programm startet, zeigt es auf den Ring-Leds die gewählte Geschwindigkeit an. Bei der Anzeige
- 0 ist die Geschwindigkeit klein. (interval=7)
- 1 ist die Geschwindigkeit mittel. (interval=5)
- 2 ist die Geschwindigkeit hoch. (interval=3)
Mit den Tasten 'Rechts' und 'Links' kann die Geschwindigkeit verändert werden.
Geschwindigkeit kalibrierien
Es ist ausserordentlich wichtig, dass das die Geschwindigkeit genau auf die Länge der Bits angepasst ist. Dies kann, etwas mühsam durch probieren, oder aber auch automatisch geschehen.
Zum Kalibrieren der Geschwindigkeit wird ein spezieller 'Barcode' (Kopiervorlage) benutzt: Dieser Barcode besteht aus acht 'schwarzen' Bits und ist somit genau 20 cm lang.
Thymio wird vor den diesen Barcode gesetzt und dann wird die Taste 'Rückwärts' berührt; Thymio fährt über den spezial Barcode und bleibt wenn er fertig ist wieder stehen.
Wenn eine SD-Karte eingesezt ist, wird die Kalibrierung auf der Karte permanent abgespeichert und bei jeden Neustart automatisch wieder eingelesen.
Barcodes lesen
Mit der 'Vorwärts' wird der Lesevorgang gestartet: Thymio folgt der Bahn und liest alle gefundenden Barcodes. Die Werte der Barcodes (0..7) werden auf den Ring-Leds dargestellt.
Mit der 'Mittel'-Taste kann Thymio wieder gestoppt werden.
Dieses Programm als Text-Programm .aesl oder als Blockly-Programm .aesl zum Download.
Alle Programme und Kopiervorlagen als Zip-Datei.
Herausforderung: Barcodes mit 'Grauwerten'
Die bisher benutzten Barcodes unterscheiden zwei Werte, sie werden daher auch binäre Barcodes genannt. Es ist aber auch möglich, statt einfach nur 'schwarz' und 'weiss' zu verwenden, mit Grauwerten mehr als zwei Ziffern pro Datenfeld zu kodieren.
Um die Barcodes 'druckerfreundlich' zu gestalten, wird kein Fotoraster benutzt, sondern es wird eine Abfolge von weissen und schwarzen 'Balken' verwendet. Der Bodensensor mittelt die Messung auf einem Feld von etwa 6 mm grösse und misst daher den mittleren Grauwert diese Feldes. Hier sind die Ziffern von '0' bis '9' als Raster-Grauwerte dargestellt:
Die Messung muss viel genauer sein als bei binären Barcodes, deshalb wird die Art des Barcodes etwas angepasst: Nach dem Sync-Feld, welches auch zur Kalibrierung des 'Schwarz'-Wertes dient, folgt ein 'Weiss'-Feld zur Kalibierung des 'Weiss'-Wertes. Als Beispiel folgt nun der Barcode mit dem Wert '834' mit den obigen Ziffern:
Das Leseprogramm ist an die vorherige binäre Version angelehnt. Es wurde jedoch um die s/w-Kalibierung und auf die Fähigkeit mehre Werte zu dekodieren ergänzt. Hier der Code:
#onevent startup
interval = 5
system = 4
wordlen = 2
grey=512
call sd.open(1000,status)
if status == 0 then
call sd.read(product,status)
call sd.open(-1,status)
else
product=733 # a guess for product
end
speed=product/interval
sub use_result
# put your action here
emit spy result
sub follow_the_track
p1 = prox.ground.delta[1]
preg = (p1 - grey) / 4
ireg += preg / 3
steer = preg + ireg
motor.left.target = speed + steer
motor.right.target = speed - steer
onevent prox
callsub follow_the_track
p0 = prox.ground.delta[0]
if state == S_WAIT_SYNC then
if p0 < grey then
state = S_READING
counter = -interval / 2
digit = BLACK
digival = 1
code = 0
end
else
counter++
if counter % interval == 0 then
if digit == BLACK then
black = p0
elseif digit == WHITE then
white = p0
diff = white - black
grey= (white + black) / 2
elseif digit < wordlen then
valeur = ((system - 1 ) * (p0 - black) + diff / 2) / diff
code += valeur * digival
digival *= system
else
state = S_WAIT_SYNC
result = code
callsub use_result
end
digit++
end
end
Das vollständige Programm als Download.
Ausblick
Das Drucken und Lesen von Barcodes ist eine grosse Herausforderung. Bis jetzt war es nur möglich Barcodes mit 5 Grauwerten zu lesen. Es braucht sicher noch einige Experimente mit verschieden Rastern und Algorithmen um das hohe Ziel, Barcodes mit zehn Graustufen zu lesen, zu erreichen.
Ein Barcode-Generator
Der Barcode-Generator kann Barcodes mit beliebig vielen Feldern und Anzahl "Ziffern" pro Feld herstellen. So geht's4:
stotz.basil@amxa:~$ ./gen_barcodes.sh
usage: ./gen_barcodes.sh numbase wordlength val_1 val_2 val_3 .... val_N
numbase ist die Anzahl Werte pro Feld (2..~10). wordlength ist die Anzahl der Daten-Felder (0..~8) und val_1, val_2 etc sind die zu kodierenden Zahlen. Das Programm gibt einen LaTeX-Quelltext aus, welcher dann mit pdflatex direkt in ein PDF übersetzt wird. So erzeugt
stotz.basil@amxa:~$ ./gen_barcodes.sh 6 3 192 13 24 101 | pdflatex
zum Beispiel ein PDF mit vier Barcodes für die Werte 192, 13, 24 und 101 zur Basis 6 mit je drei Datenfeldern.
Die erzeugte PDF-Datei heisst texput.pdf und kann direkt ausgedruckt werden.
Das Feld zum klaibireren des 'weiss'-wertes wird bei binären (numbase=2) Barcodes nicht gedruckt.