direcs-avrsim – mein direcs Atmel-Simulator

 In der Vergangenheit gab es bekanntermaßen diverse Probleme mit der seriellen Schnittstelle. Um hier beim debuggen nicht immer auf den angeschlossenen Roboter angewiesen zu sein, fiel der Entschluss einen direcs1-Roboter-Simulator zu entwickeln. Ziel sollte es sein eine Software zu haben, die auf dem seriellen Port wie die Software auf dem Atmel Microcontroller Befehle entgegennimmt und genauso "antwortet", also regiert.Gesagt, getan, hier das Zwischenergebnis. Als Name des Simulators wurde direcs-avrsim gewählt. 

Vorher noch eine Erklärung, wie das ganze hardwaretechnisch gelöst wurde, denn es müssen ja dann im Betrieb die Daten zwischen zwei seriellen Ports miteinander ausgetauscht werden; also zwischen der direcs-Software und direcs-avrsim. Ganz einfach, man verbindet einfach zwei serielle Ports mit einem seriellen crossover cable, auch Nullmodem-Kabel genannt. Und wenn am Gerät keine seriellen Ports vorhanden sind, jeweils noch über zwei USB-Seriell-Wandler. Und so sieht das Ganze dann aus:

Von Vorteil ist es, wenn USB-Seriell-Wandler mit einem unterschiedlichen Chip verwendet, dann haben die seriellen Ports unterschiedlichere Namen, wie z.B. hier diese drei:

~/develop/direcs% ls /dev/tty*

crw-rw-rw-  1 root    wheel    2,   0 17 Jun 19:38 /dev/tty
crw-rw-rw-  1 root    wheel   11,  46 19 Jun 16:01 /dev/tty.PL2303-003014FA
crw-rw-rw-  1 root    wheel   11,  44 19 Jun 16:02 /dev/tty.SLAB_USBtoUART
crw-rw-rw-  1 root    wheel   11,  40 14 Jun 21:29 /dev/tty.USA19Hfa141P1.1

Um die grundsätzliche Funktionalität der Adapter und des Kabels sicherzustellen, bietet es sich an diese mit zwei Terminal-Programmen zu testen. Z.B. auf dem Mac mit goSerial oder in der Shell (Konsole) mit minicom:

Bei jedem Programm muss dann jeweils der passende serielle Port gewählt werden und jeden Befehl, den man auf "der einen Seite" dann eintippt, sollte "auf der anderen Seite" genauso erscheinen.

Hier die nun sehr einfache GUI von direcs-avrsim direkt nach dem Start:

Das abgebildete Relais, das Flashlight und die GUI-LEDs entsprechen Aufbauten auf dem realen Roboter. Als Code der hier zur Verwendung kommt, dient dabei natürlich zu 99% der, der ansonsten auf dem Atmel läuft (main.c). Dieser kann – da es ja Standard-C ist – weiterverwendet werden. Die Atmel-spezifischen Anweisungen (Setzen von Registern, Watchdog etc.) sind natürlich nicht implementiert.

Die GUI wartet nun auf die Entgegennahme von Befehlen auf dem seriellen Port – eben genau so, wie sonst der reale Roboter. Hier sieht man den Status nach Erhalt der ersten Befehle (*re# = Reset, Roboter antwortet mit *ok#):

Hier sieht man unter anderem wie das Flashlight eingeschaltet wurde (Befehl *f0on#, Roboter antwortet ebenfalls mit *f0on#):

 

Ebenfalls erkennbar ist die Abfrage zweier Sensoren (*s7# und *s8#). Hier antwortet die GUI zurzeit noch mit immer den gleichen Werten. Sie entsprechen den Werten des AD-Wandlers und ergeben umgerechnet dier 12 und 24. Dieses entspricht der Akku-Überwachung mit 12Volt und 24Volt-Akkus.

Unterbodenbeleuchtung

 Unterbodenbeleuchtung…? fragt sich sicher der ein oder andere. Inspiriert durch iRobots AVA Roboter fiel die Entscheidung, zwischendurch (um mal was zu bauen, was funktioniert ;-) ) eine RGB-Beleuchtung für den Roboter direcs1 zu entwickeln.


Quelle: http://www.botjunkie.com

Die Idee die dahintersteckt ist, verschiedene Zustände leicht signalisieren zu können; z.B. "rot=Hindernis" oder "grün=freie Fahrt". Zum Ansteuern von den ausgewählten RGB-LED-Streifen wurden sechs Optokoppler (4N33 813) auf die vorhandene Steuerplatine gelötet – gar nicht so einfach bei der Verkabelung:

  

Die Optokoppler sind erforderlich um die LEDs zu schalten, die direkt an 12V angeschlossen werden können:

   

Nun galt es, die flexiblen LED-Streifen – die übrigens bei Pollin bestellt wurden – auf der Unterseite des Roboters zu montieren. Durch die Klebestreifen, die an den Streifen bereits dran sind, ist dieses sehr simpel. Auch kann die Meterware ca. alle 10 cm einfach mit der Schere geteilt werden. Praktisch. Hier die Fotos dazu:

    

Nicht ganz so einfach gestaltete sich das Verlegen der Anschlusskabel für die LED-Streifen am Bot. Aber lösbar:

     

Nun noch das Ganze für den zweiten Streifen:

 

Und so sieht der erste Test aus:

        

Wie man sieht, sind hier alle Farbkombinationen möglich, wenngleich erst einmal nur die offensichtlisten genutzt werden sollen wie "grün=freie Fahrt" oder "rot=Hindernis". Praktisch dabei: Es wurden die PWM-Anschlüsse des Atmel-Boards genutzt, so dass hier auch verschiedene Helligkeiten möglich sind. An diesen Portbits waren früher einmal Servos angeschlosssen. Darum existiert auch noch jeglicher Code in der Software zur Ansteuerung, nur dass eben sich nicht Servos drehen, sondern LEDs heller oder dunkler werden.

Und so sieht das Ganze dann im Betrieb aus (hier leider nur Fotos, bei denen nur eine Seite beleuchtet ist):

      

Motor Fehlersuche Finale

Wie es aussieht, weisen die Motorcontrol-Boards einen Defekt auf. Hier wurde nun eines der Boards bereits gegen ein neues ausgetauscht. Und *tusch* hier das Ergebnis:

 

Motor Fehlersuche Teil 4 und 5

Im letzten Video zeigte sich, dass anscheinend immer 12 Volt bei den Motoren ankommen, zumindest per Messgerät gemessen. Nun erfolgt der gleiche Test erneut, also mit Betrachtung der Portbits über die 7-Segement-Anzeige (die offenbar immer okay sind). mit angeschlossenen Messgeräten aber zusätzlich mit angeschlossenen Motoren. Hier das Ergebnis:

Ofenbar verhält sich das Motorboard anders, wenn die Motoren anschlossen sind und schaltet die 12 Volt nicht immer / nicht mehr korrekt. Um nun noch als letzte Fehlerursache die Motoren auszuschließen, wurde als nächstes das Ganze noch einmal mit einem Motor im Austausch getestet – mit dem Scheibenwischermotor im Vordergrund:

Das Finale ist nah…

PS.: Leider war es im Video etwas dunkel und man erkennt die Spannungen auf den Messgeräten nicht wirklich. Sorry.

 

Motor Fehlersuche Teil 3

Als nächstes galt es festzustellen, ob vielleicht die 12 Volt nicht durch die Motorcontrol-Boards nicht korrekt „geschaltet“ werden. Dazu wurden nun je Motor ein Messgerät angeschlossen und parallel die Ports über die 7-Segement-Anzeige beobachtet. Aber seht selbst:

Das Ergebnis ist noch nicht wirklich erklärbar. Anscheinend funktionieren die Motorcontrol-Boards korrekt. Die Motoren an sich waren aber okay. Fortsetzung folgt…

Motor Fehlersuche Teil 2

Bei der weiteren Analyse wurde nun die 7-Segement-Anzeige zu Signalisierung der Portbits parallel zum Motorboard it den Motoren angeschlossen. Wie man sieht, werden die Bits korrekt gesetzt, aber trotzdem bleibt gelegentlich ein Motor stehen:

Fortsetzung folgt…

Meanwhile: Motor Fehlersuche 1

Wie bisher berichtet, trat in der Zwischenzeit immer noch das Problem auf, dass bei gleichzeitiger Ansteuerung aller vier Motoren (was natürlich immer der Fall ist, das es ja ein Allrad-Roboter ist) immer mal wieder eines der Räder sich nicht dreht. Das Phänomen stellte sich mit allen Motoren reproduzierbar aber immer an verschiedenen Rädern / Motoren und immer zu unterschiedlichen Zeitpunkten auf.

Um herauszufinden, ob die Bits auch richtig vom Microcontroller gesetzt werden, wurden kurzerhand zwei Sieben-Segement-Anzeigen „missbraucht“ um die verschiedenen Stati anzuzeigen. Dargestellt werden hier die vier PWM-Bits (oben und unten) sowie die zwei Bits pro Motor, also acht Segmente. Hier das Video zur Dokumentation dazu:

Wie man sieht, ist hier als erstes ein Fehler aufgezeigt, der bei der Umstellung auf die neuen seriellen Befehle kopiert wurde: Beim „vorwärts“ fahren, werden die gleichen Bits gesetzt wie beim „links“ fahren. Das wurde natürlich als erstes nach diesem Video beseitigt – zeigt aber auch wie praktisch eine einfache Analyse mit direkter Anzeigt mit einfachen LEDs hier schnell Ergebnisse bringt.

Hier noch mal die 7-Segment-Anzeige und die Bedeutung der Segmente im Detail:

 

Fortsetzung hier…

coding, coding, coding…

Nachdem es in der Vergangenheit öfter Probleme mit der seriellen Übertragung gab, fiel der Entschluss, alle Übertragungen zwischen dem Atmelboard und dem Computer nicht mehr in Binärform sondern in reinem ASCII zu senden. Dazu wurde im git Repository ein neuer Branch namens AtmelSerialClearText angelegt und seit Mitte August immer mal wieder daran gearbeitet. Nun ist es endlich soweit, nahezu alle Funktionen sind komplett auf die neue Übertragungsmethode umgestellt – sowohl auf Computer, als auch auf Atmel-Seite. Wie man sieht, waren dazu doch einige Änderungen nötig:

Merge made by recursive.

 direcs-avr/adconv.c         |   33 ++

 direcs-avr/adconv.h         |    6 +

 direcs-avr/main.c           | 1040 +++++++++++++++++++++++++++++————–

 direcs-avr/main.h           |   13 +-

 direcs-avr/micromag.c       |    4 +

 direcs-avr/usart.c          |  174 ++++++–

 direcs-avr/usart.h          |   38 ++-

 direcs/direcs.tag           |  193 ++++++–

 direcs/src/circuit.cpp      |  112 ++++-

 direcs/src/circuit.h        |   39 ++-

 direcs/src/direcs.cpp       |  127 +++++-

 direcs/src/direcs.h         |   19 +-

 direcs/src/direcsSerial.cpp |   65 ++–

 direcs/src/direcsSerial.h   |    2 +-

 direcs/src/gui.cpp          |   79 ++++-

 direcs/src/gui.h            |   37 ++-

 direcs/src/interfaceAvr.cpp |   98 ++++

 direcs/src/interfaceAvr.h   |   58 ++-

 direcs/src/mainWindow.ui    |   86 +++-

 direcs/src/motor.cpp        |  792 +++++++++++++++++++++———–

 direcs/src/motor.h          |   46 +-

 direcs/src/plotThread.cpp   |   47 ++-

 direcs/src/plotThread.h     |   14 +-

 direcs/src/sensorThread.cpp |  495 +++++++++++———-

 direcs/src/sensorThread.h   |   27 +-

 25 files changed, 2540 insertions(+), 1104 deletions(-)

Zusätzlich wurde das serielle Verfahren auf dem Atmel ebenfalls vollständig neu geschrieben und arbeitet nun – anstatt in einer Endlosschleife auf den Empfang eines Zeichens zu warten – vollständig interruptbasiert.

Wie aber weiß nun der Atmel, wann eine Übertragung für ihn anfängt oder abgeschlossen ist? ganz einfach: Jede Übertragung muss mit einem ‚*‘ starten und mit einem ‚#‘ enden. Alle anderen Zeichenketten werden ignoriert. Eine Signalisierung über LEDs auf der Platine findet ebenfalls statt: Bei jedem empfangenen Zeichen blinkt die rote LED abwechselnd und sobald das Ende eines Befehls mit # erkannt wurde (und zuvor auch mit * startete!) wird dieses über eine grüne LED angezeigt.

Diese Art der Übertragung hat den Vorteil, dass man sie per Terminalprogramm gut debuggen kann, denn es werden nur ASCII-Zeichen verwendet. Zusätzlich antwortet der Atmel auch immer mit der empfangenen Zeichenkette, die wiederum vom Computer als Antwort überprüft wird. Eine neue Sicherheitsfunktion, die zuvor fehlte. Auch kann man dem Atmel so selbst mit einem Terminalprogramm Befehle senden und „sieht“ was er antwortet. Fragt man einen Wert vom Atmel ab, so antwortet er nur mit diesem Wert und dem Starter und Terminator, also z.B. mit *42#.

Und das sind die derzeitigen Befehle:

re = reset

s1 = get value from sensor 1

s8 = get value from sensor 8

s16 = get value from sensor 16

cc = check if compass module is connected. ‚ok‘ or ‚er‘

cx = get value from compass axis x

cy = get value from compass axis y

cz = get value from compass axis z

ms1 = get value from motor sensor 1

ms4 = get value from motor sensor 4

dd1 = get driven distance 1

..

dd4 = get driven distance 4

id1 = init distance 1

id4 = init distance 4

mp1of = motor power 1 off

mp4of = motor power 4 off

md1cw = motor direction 1 clockwise

md4cw = motor direction 4 clockwise

md1cc = motor direction 1 counterclockwise

md4cc = motor direction 4 counterclockwise

mv1nnn = set motor velocity 1 to nnn (0-255)

mv4nnn = set motor velocity 4 to nnn (0-255)

mv0nnn = set motor velocity for all motors to nnn (0-255)

bdf = bot drive forward

bdb = bot drive backward

bdl = bot drive left

bdr = bot drive right

btl = bot turn left

btr = bot turn right

bgo = bot go

bst = bot stop

bwa = bot wait

Schematischer Aufbau direcs1

Auf dieser Seite ist der aktuelle schematische Aufbau des Roboters direcs1 dargestellt:

Stand: 04.04.2011

 

3D-Kompass-Modul-Verbindung wird geprüft und in GUI angezeigt

Beim Testen des Atmelboards außerhalb des Roboter fiel auf, dass es manchmal bei der seriellen Übertragung nach einiger Zeit timeouts gab. Die Ursache lag im Atmelcode für den Micromag 3D-Kompass. Dieser initialisiert beim ersten Start des Atmels das SPI / I²C Protokoll. Danach fragt das direcs-Hauptprogramm den Atmel nach den Kompassdaten. Ist das Kompassmodul aber nun gar nicht mit dem Atmelboard verbunden, so kommt es zu den timeouts, da im SPI-Code auf bestimmte Bitzustände gewartet wird.

Um dieses zu verhindern und hiermit auch eine weitere Sicherheit einzubauen, wird nun beim Abfragen der Kompasswerte jedesmal geprüft, ob ein bestimmtes Portbit gesetzt ist. Dieses Portbit ist durch einen 100k-Widerstand am Atmelboard standardmäßig auf Masse gezogen. Wird das Kompassmodul nun per Falchbandkabel angesteckt, wird diese Leitung vom Kompassmodul aus auf 5V "hoch gezogen". 

Bei der Initialisierung des Atmelboards bzw. der Prüfung ob der Roboter eingeschaltet ist im direcs-Hauptprogramm, wird nun auch zusätzlich abgefragt, ob das Kompassmodul verbunden ist. Dieses wird auch in der GUI grafisch mit einer weiteren LED (rechts oben im Bild) angezeigt.

Atmel-Board gar nicht verbunden (Kompass damit natürlich auch nicht):

Atmel-Board verbunden, Kompassmodul nicht angeschlossen:

Atmel-Board verbunden, Kompassmodul ebenfalls angeschlossen: