GCC mit C++14 Unterstützung für Ubuntu/Mint installieren

Die aktuelle GCC Version aus dem Ubuntu Repository bietet keine Unterstützung für C++14. Damit der Standard verwendet werden kann, muss die GCC aktualisiert werden. Das kann einfach erledigt werden, indem die Ubuntu Toolchain PPA als Repository aufgenommen wird. Die folgenden Befehlen tragen das Repositoy ein und installieren die g++-4.9 compiler, welcher C++14 unterstützt:

Danach kann getestet werden, ob der Compiler richtig installiert wurde:

Der Standard-Compiler wird durch die Installation nicht angepasst, so zeigt g++ noch auf die alte Version. Dies kann man leicht überprüfen:

Um nun den neuen Compiler als Standard zu konfigurieren, kann man den symlink einfach auf die richtige Version zeigen lassen:

Jetzt kann getestet werden, ob die richtige Version durch den Link aufgerufen wird. Als Ausgabe sollte nun eine Version 4.9.X angezeigt werden:

Das war es schon. Nun kann der Quellcode mit dem C++14 Standard kompiliert werden:

Veröffentlicht unter Linux | 3 Kommentare

TSL2561 Lichtsensor mit dem STM32F4

Der TSL2561 ist ein Sensor, der die Lichtintensität messen und in einen 16-bit aufgelösten, digitalen Wert transformieren kann. Auf dem Sensor sind zwei Fotodioden enthalten, die das Lichtspektrum messen und in einen digitalen 16-Bit Wert transformieren. Die erste Fotodiode misst das Lichtspektrum inklusive dem infraroten Anteil. Die zweite Diode misst lediglich die infraroten Lichtbereich. Die synchron aufgezeichneten Messwerte werden über eigene Kanälen in Datenregister transferiert (channel0 und channel1). Die Idee dabei ist, dass beide Werte dazu verwendet werden, den infraroten Lichtanteil durch eine Subtraktion zu herauszurechnen. Das resultierende Lichtspektrum entspricht somit dem, welches das menschliche Auge erfassen kann.
Die Messwerte können über den I2C oder den SMBus ausgelesen werden. In diesem Artikel wird eine Kommunikation über den I2C-Bus eingesetzt, um Daten zwischen dem STM32F4 und dem TSL2561 auszutauschen.

Den Sensor anschließen

Der TSL2561 arbeitet mit einer Spannung von 3.8V, verwenden Sie nicht den 5V Pin des STM32F4, sonst laufen Sie Gefahr, den Sensor zu zerstören. Es gibt zwei Anschlüssen für die I2C-Kommunikation (SDA und SCL). Der SDA Pin ist für den Datenaustausch mit dem Sensor, währen SCL für den Bustakt verwendet wird. Der ADDR Pin ermöglicht es, den Sensor mit einer I2C Adresse zu konfigurieren. Solange die Standardadresse auf dem Bus nicht für ein anderes Gerät verwendet wird, kann diese problemlos verwendet werden. Die Standardadresse für den Sensor lautet 0x39, diese kann aber auf die Adressen 0x29 bzw. 0x49 angepasst werden. Außerdem kann der Sensor einen Interrupt auslösen, sodass es nicht notwendig ist, diesen zu pollen. In dieser Beispielimplementierung wird allerdings auf die Verwendung eines Sensorinterrupts verzichtet.

TSL2561 Lichtsensor

Die Software

Der STM32F4 Controller verfügt über mehrere I2C Schnittstellen. In diesem Beispiel wird I2C1 verwendet, welcher an den IOs GPIO6 (SCL) und GPIO7 (SDA) angeschlossen ist. Die Konfiguration ist übrigens in einer Konfigurationsdatei gekapselt, sodass diese leicht angepasst werden kann. Die Software kann aus dem Repository (Projektname TSL2561_example) runtergeladen werden. Die Taktfrequenz für die I2C Kommunikation liegt bei 400 kHz, diese ist, wie auch die IOs, in der Konfigurationsdatei hinterlegt. Die init_lightsensor(void) Methode konfiguriert alle benötigten IOs und die Peripherie für die I2C Kommunikation mittels initLightSensorI2C(void).
Die Messwerte werden in insgesamt vier Registern hinterlegt (zwei für jeden Kanal), welche ausgelesen werden können. Diese Register enthalten die Messwerte als 8 Bit low bzw high bytes.

Beschreibung Adresse
0x00 control register
0x8C low byte (channel0)
0x8D high byte (channel0)
0x8E low byte (channel1)
0x8F high byte (channel1)

Um Bytes aus den Registern des Moduls zu lesen, wird vorab die Registeradresse an das Control Register (0x00) des Moduls geschickt. Außerdem muss das sogenannte Command Bit gesetzt werden, damit das Modul korrekt auf die Anfragen reagiert.

Die empfangenen Daten können in die SI-Einheit LUX umgerechnet werden. Diese Berechnung ist bereits in dem Beispielprogramm enthalten. Die read_lightness_value() Methode empfängt die Datenbytes und führt die Transformation durch.

Anhang

Veröffentlicht unter ARM, Eingebettete Systeme, Sensoren, STM32F4 | Verschlagwortet mit , , , | Hinterlasse einen Kommentar

STM32F4 mit ERIKA Enterprise RTOS OSEK

Erika Enterprise ist ein open source OSEK konformes Echtzeitbetriebssystem (RTOS), das den STM32F4-Discovery Controller unterstützt. Außerdem gibt es eine eclipse Integration, sodass es möglich ist, Software direkt in der IDE zu entwickeln. In Kombination mit dem GNU ARM Eclipse Plugin und dem stlink Debugger/Programmer, sowie den GNU Tools for ARM Embedded Processors, wird eclipse zu einer Entwicklungsumgebung, die neben der eigentlichen Entwicklung des Codes, auch das Flashen und Debuggen auf der Hardware (in-circuit-debugging) von ERIKA RTOS basierten Anwendugen für den STM32F4-Discovery Controller ermöglicht. ERIKA kann auf der Projektseite runtergeladen werden. Um weitere Informationen zu der Installation bzw. Einrichtung der Plugins oder ERIKA zu erhalten, schauen Sie bitte in die entsprechenden Wikis und Foren auf den verlinkten Seiten.ERIKA wird über ein oil-File konfiguriert, welches die Parameter für den Kernel enthält. In dieser Datei gibt es verschiedene Einstellungsmöglichkeiten, die das Verhalten des Kernels beeinflussen. Neben diesen werden aber auch Abhängigkeiten zu externen Bibliotheken, wie beispielsweise dem Microcontroller Software Interface Standard (CMSIS), festgelegt.
Der Kernel unterstützt verschiedene Klassen von tasks (basic und extended tasks). Im Vergleich zu den basic tasks, unterstützen die extended tasks eine eventgesteuerte Synchronisation. Mehr Informationen zu den Klassen gibt es in der offiziellen Dokumentation, an dieser Stelle soll nicht weiter auf die Unterschiede eingegangen werden.

Der folgende Abschnitt beschreibt die Verwendung von ERIKA Enterprise mit extended tasks, also einem eventgesteuerten Scheduling auf dem STM32F4 Controller. Um diese Kernelkonfiguration einzusetzten, gibt es ein paar Parameter, die in der Konfigrationsdatei (*.oil) gesetzt werden müssen. Eine entsprechende Konfiguration sieht wie folgt aus:

Der STM32F4-discovery verfügt über einen ARM Cortex-M4 Prozessor, welcher mit 168 MHz getaktet wird. Der genaue Takt hängt von dem verwendeten Modell ab, in diesem  Beispiel wurde ein STM32F407VG verwendet. Der APP_SRC Paramter listet die *.c Dateien auf, die mit dem Kernel kompiliert werden sollen. Um mehrere Dateien anzugeben, dann der Parameter einfach wiederholt werden. Die Entwicklung basiert auf dem GNU ARM Compiler und Debugger, deshalb wird der Parameter COMPILER_TYPE für die GNU toolchain konfiguriert. Um extended tasks zu verwenden, muss ein sogenannter MULTI_STACK mit einer statischen Größe konfiguriert werden. Der letzte Block in dem Ausschnitt der Konfigurationsdatei setzt den Controller.

Die Konfigurationsdatei wird außerdem dazu verwendet externe Bibliotheken, wie beispielsweise den ARM spezifischen CMSIS, einzubinden. Der folgende Ausschnitt zeigt, wie diese Bibliotheken eingebunden werden:

Die Parameter sind spezifisch für den STM32F4 Controller. Als nächstes wird das Scheduling des ERIKA Kernels konfiguriert. Der Kernel unterstützt insgesamt vier Klassen, die das Scheduling beieinflussen, sogenannte conformance classes (ECC1, ECC2, BCC1, BCC2). Die BCC Klassen unterstützen basic tasks, während die ECC Klassen die extended tasks unterstützen. Extended tasks erweitern die basic tasks um die Eigenschaft, durch events aktiviert zu werden. Für weitere Informationen zu diesen Klassen, schauen Sie bitte in das ERIKA reference manual. Um in der Konfigurationsdatei eine conformance class zu definieren, wird der folgende Paramter gesetzt:

Als nächstes werden events und tasks definiert. In diesem Beispiel wird ein task definiert, der über ein event aktiviert werden kann. Dieser Task wird setPwmTask heißen und auf ein pwmEvent reagieren. Generell können tasks auf mehrere events reagieren. Diese müssen nur entsprechend in der Konfigurationsdatei festgelegt werden. Eine entsprechende Konfiguration eines tasks mit einem event sieht wie folgt aus:

Anschließend werden der task und das event in der Implementierung deklariert, damit der task durch die Software aktiviert werden kann:

Der letzte Schritt ist die Initialisierung des Kernels. Wurde diese durchgeführt, kann das eventbasierte Scheduling verwendet werden. Der folgende Codeausschnitt zeigt wie die Initialisierung des Kernels und die periodische Aktivierung des setPwmTask durch das pwmEvent durchgeführt werden kann:

Mit ERIKA Enterprise bekommt man ein sehr schönes open source Echtzeitbetriebssystem, welche direkt in die eclipse IDE integriert werden kann. Die STM32F4 Unterstützung bietet einem alle netten features eines RTOS auf diesem Controller.

Veröffentlicht unter ARM, Eingebettete Systeme, Mikroprozessoren, RTOS, STM32F4 | Verschlagwortet mit , , , , , , | Hinterlasse einen Kommentar

SRF02 Ultraschallsensoren am STM32F4-Discovery

Der SRF02 Ultrasonic range finder ist ein Ultraschallsensor, der über nur eine Membran verfügt aber trotzdem als Tranceiver funktioniert. Dadurch ist der Sensor praktischerweise von seiner Bauart her sehr kompakt und eignet sich besonders für Einsatzbereiche, in denen es aus die Größe des Sensors ankommt. Der Sensor detektiert Hindernisse in einem Bereich von 16 – 6000 cm. Die benötigte Spannungsversorgung von 5 V erlaubt es, dass des Sensor an einer Vielzahl von  Mikroprozessoren direkt angeschlossen werden kann.
Der Sensor kann per serieller Leitung (UART) oder per i²c Bus (oder aus I2C Bus genannt) angesteuert und ausgelesen werden. Im Folgenden wird die Ansteuerung per I2C beschrieben, da dies den charmanten Vorteil hat, dass lediglich zwei Leitungen (SDA und SCL) auf dem Controller (auch bei der Verwendung mehrerer Sensoren) zur Kommunikation benötigt werden. SDA ist dabei die Datenleitung und SCL die Taktleitung. Komponenten am i²c Bus werden über eine eindeutige Adresse identifiziert. Im folgenden zeige ich beispielhaft den Einsatz von insgesamt vier SRF02 Ultraschallsensoren an einem i²c Bus, inklusive der vorhergehenden Konfiguration der eindeutigen Adressen. Als Mastercontroller wird ein ARM basierter STM32F4-Discovery (STM32F407VG) eingesetzt.

Frontansicht SRF02

Rückansicht SRF02

Seitenansicht SRF02

 Grundlagen zum SRF02 Sensor

Der SRF02 Sensor kann Distanzen mittels Ultraschall messen. Dafür sendet der Sensor einen kurzen Ultraschallimpuls über die Membran aus und detektiert im Anschluss die Reflexion der Schallwellen. Außerdem misst der Sensor die Zeit zwischen dem Aussenden des Impulses und der Detektion der Reflexion. Da die Geschwindigkeit des Schalls konstant ist, kann mit der ermittelten Zeit, die Distanz berechnet werden. Dieses Verfahren nennt sich time-of-flight Messung.

Der SRF02 muss nicht explizit kalibriert werden, dies wurde durch den Hersteller durchgeführt, sodass diese Arbeit erspart bleibt. Der Sensor kann für die Distanzen verschiedenen Messwerte liefert. So kann die Distanz in cm, in inch oder aber die Zeit zwischen dem Aussenden und Detektieren eines Schallimpulses von dem Sensor übertragen werden. Die Messwerte, die der Sensor liefert, können konfiguriert werden. Die Register des Sensors sind wie folgt aufgebaut:

Adresse Funktion
0x50 Messwerte in inch
0x51 Messwerte in cm
0x52 Messwerte in Mikrosekunden
0x56 Fake Range Modus (inch)
0x57 Fake Range Modus (cm)
0x58 Fake Range Modus (Mikrosekunden)
0xA0 1. Sequenz zum Setzen der I2C Adresse
0xA5 2. Sequenz zum Setzen der I2C Adresse
0xAA 3. Sequenz zum Setzen der I2C Adresse

Setzten einer eindeutigen I2C Adresse

Die Adressen der Sensoren werden als Bytes hexadezimal übertragen. Initial hat jeder Sensor die Adresse 0xE0. Wird nur ein Sensor eingesetzt, ist es nicht notwendig, diese Adresse zu ändern, sollen aber mehrere Sensoren an einem Bus eingesetzt werden, muss die Adresse auf dem Bus eindeutig sein. Dafür wird die neue Adresse an das Command Register (0x00) des Sensors übertragen. Damit der Sensor in den Modus wechselt, in dem er die neue Adresse empfängt und übernimmt, müssen die Steuerbytes (1. – 3. Sequenz) zum Setzen der Adresse zuvor übertragen werden. Die neue Adresse bleibt auf dem Sensor gespeichert, sodass diese auch dann gesetzt ist, wenn den Sensor abschaltet wird.

Die konfigurierte Adresse eines Sensors kann man anhand des Blinkverhaltens der LED beim Einschaltvorgang erkennen. Der Sensor teilt seine Adresse durch kurze Lichtpulse der LED mit. Beim Einschalten des Sensors leuchtet die LED einmal lange auf. Danach blinkt die LED in Abhängigkeit von der gesetzten Adresse. So würde diese bei der Adresse 0xE0 kein mal blinken, während sie bei der 0xF0 8 mal aufblinken würde. Die Zuordnung zwischen den Adressen und den Lichtpulsen zeigt die folgende Tabelle:

Adresse Lichtpulse
0xE0 0
0xE2 1
0xE4 2
0xE6 3
0xE8 4
0xEA 5
0xEC 6
0xEE 7
0xF0 8
0xF2 9
0xF4 10
0xF6 11
0xF8 12
0xFA 13
0xFC 14
0xFE 15

Die Implementierung im Repository (Projekt: SRF02_example) beinhaltet eine Funktion zum Setzen einer I2C Adresse für die Sensoren. Da diese initial alle eine identische Adresse haben, müssen diese nacheinander Konfiguriert werden. Will man die Adresse eines Sensors ändern, kann das einfach mit der Funktion setSensorI2CAddress() durchgeführt werden. Die Funktion erwartet als Parameter die aktuelle und die neue Adresse des Sensors. Eine Implementierung könnte wie folgt aussehen:

STM32F4 Anbindung

Der Beispielcode im Repository zeigt die Anbindung und Konfiguration von insgesamt vier Sensoren an einem STM32F4 Controller. Das Projekt ist in dem Verzeichnis SRF02_example zu finden. Damit die Sensoren verwendet werden können, wird zuerst der I2C Bus in der Funktion  initSRF02() konfiguriert. Anschließend wird der einzelne Sensor mittels initUltrasonicSensorI2C() initialisiert. Die Funktion erwartet die I2C Adresse des Sensors. Außerdem wird an dieser Stelle die Messeinheit konfiguriert. Danach kann die gemessene Distanz des Sensors mit Hilfe der Funktion readDistance() abgefragt werden. Eine Implementierung zum Auslesen eines Sensors sieht wie folgt aus:

 

Anhang

Datenblatt
Bezugsquelle: exp-tech
Veröffentlicht unter Sensoren | Verschlagwortet mit , , , | 3 Kommentare

Xbox360 Controller C Integration

Heute habe ich ein Stück Code geschrieben, der es einfach ermöglicht, einen Xbox360 Controller  in ein C Programm zu integrieren. Der Code liest die Werte der Achsen und Knöpfe des Controllers aus und gibt diese Informationen auf dem Bildschirm aus. Das folgende Bild zeigt die Ausgabe dieser Informationen:

XBox360 Controller Signale

In diesem Fall wurden die Tasten „A“ and „TL“, welche die „top left“ Taste ist, gedrückt. Das Projekt trägt den Namen xboxControllerClient und kann in meinem Repository unter https://code.google.com/p/scholtyssek-blogspot/ untergeladen werden.

Die Konfiguration des Controllers befindet sich in der Headerdatei xboxController.h. Darin ist außerdem das Mapping der Tasten und Achsen implementiert. Die gemessenen Daten werden in einer Struktur von Typ xboxCtrl gespeichert, welche sich ebenfalls in der Headerdatei befindet. Das folgende Beispiel zeigt, wie der Code verwendet werden kann:

Die Methode initXboxContoller(XBOX_DEVICE) öffnet eine Verbindung zu dem Device  /dev/input/js0. Dieses ist als Standarddevice eingetragen, um ein anderes Device zu verwenden, kann einfach der Wert von XBOX_DEVICE verändert werden. Anschließend wird mit dem Aufruf von getXboxDataStruct() ein Pointer auf die Datenstruktur xboxCtrl geholt. Darin sind die Messdaten gespeichert. Die Werte können mit einem Aufruf von  readXboxData(xbox) periodisch aktualisiert werden. Mit einem Aufruf von printXboxCtrlValues(xbox) können die Messwerte dann auf in der Konsole ausgegeben werden. Das war’s schon, viele Freude damit 🙂

Veröffentlicht unter Eingebettete Systeme, Linux | Verschlagwortet mit , , | Hinterlasse einen Kommentar

Rigol DS1052D und Open Logic Sniffer

Heute habe ich den Logic Analyzer des Rigol DS1052D ausprobiert und festgestellt, dass dieser die aufgezeichneten Signale nicht auswertet. Da es sich bei dem Oszilloskop um ein Gerät im unteren Preissegment handelt, ist das auch in Ordnung. Die gemessenen Signale können allerdings leicht exportiert und auf einem PC mit dem Open Source Tool Open Logic Sniffer ausgewertet werden. Damit das funktioniert, müssen diese im CSV Format exportiert und im Anschluss konvertiert werden. Die folgenden Schritte zeigen, dass es tatsächlich sehr einfach ist.

Rigol DS1052D oscilloscope

1. Daten speichern und exportieren

Wenn man mit dem Logic Anlyzer Flanken miss, kann man die Messung mit dem Button „RUN/STOP“ einfrieren. Nun können die Messwerte mit dem Button „Storage“ gespeichert werden. Dazu wählt man im Untermenü von „Storage“ den Punkt External. Dieser ist nur aktiv, wenn man einen USB-Stick an dem Oszilloskop angeschlossen hat. Jetzt einfach nur noch das Datenformat CSV einstellen und einen Dateinamen vergeben (z. B. Messwerte.csv). Nun kann man die Datei speichern.

2. Daten konvertieren

Die Messwerte können nun auf einen PC kopiert und konvertiert werden. Die Konvertierung kann mit einem Befehl durchgeführt werden:

Dieser Befehl erstellt eine neue Datei „Messwerte.ols“, welche nun noch angepasst werden muss. Dafür öffnet man die Datei und entfernt die ersten beiden Zeilen. Anschließend fügt man die beiden Parameter Rate und Channels an den Beginn der Datei an. Rate definiert die Bandbreite des Oszilloskops (hier 50MHz) und Channels gibt die Anzahl der verwendeten Kanäle an (1-16). Die Datei sollte in etwa so aussehen:

3. Daten in OLS importieren

Jetzt kann man den Open Logic Sniffer starten und die Daten mittels „File -> Open“ importieren. Wenn alles funktioniert hat, sollten die Signale nun im Open Logic Sniffer zu sehen sein:

Importierte Messdaten

Veröffentlicht unter Linux, Oszilloskop | Verschlagwortet mit , , | Hinterlasse einen Kommentar

STM32F4 basierter Mecanum Roboter mit Odometrie

In den vergangenen Monaten habe ich mich in den STM32F4-Controller eingearbeitet, um ein (Roboter-)Projekt damit umzusetzen. Genauer gesagt, handelt es sich um einen Roboter, der über Mecanum-Räder (oder auch swedish-wheels) verfügt. Diese Räder zeichnen sich deshalb besonders aus, weil auf dem Außenring der Felge, Gummiwalzen im 45° Winkel angeordnet sind, welche sich passiv über den Untergrund abrollen. Dadurch verfügt der Roboter über einen weiteren Freiheitsgrad. Das bedeutet, dass der Roboter – trotz fehlender Lenkachse – alle Richtungen (X, Y und Θ) auf der Ebene erreichen kann und deshalb die maximale Bewegungsfreiheit hat. X und Y entspricht dabei Bewegungen in die die entsprechenden Richtungen und Θ bezeichnet die Drehbewegung des Roboters.

Der Roboter

Bei dem Roboter handelt es  sich um den Nexus 4WD. Dieser verfügt über vier Faulhaber Motoren, welche direkt mit Inkrementalgebern ausgestattet sind, (Ultraschall-)Distanzsensoren und einem Arduino Controller, auf dem auch direkt passende Motortreiber vorhanden sind. Die 12 V Gleichstrommotoren, wie aus die restliche Hardware werden über einen Akku versorgt, der mit einem gewöhnlichen Tamiya Stecker angeschlossen wird.

Da ich mich für den STM32F4 entschieden habe, wurden einige Modifikationen an dem Roboter durchgeführt. Insbesondere der Arduino-Controller wurde durch den STM32F4 ausgetauscht, was aber zur Folge hatte, dass die Motortreiber, welche fest auf der Platine des Arduinos verbaut waren, ebenfalls aus dem Roboter entfernt wurden. Deshalb musste eine neue Motorsteuerung mit entsprechenden Treiber (H-Brücken) entwickelt werden, damit die Motoren richtig angesteuert werden können. Zusätzlich zu den vorhandenen Sensoren und Aktoren, wurde der Roboter mit einem Gyroskop ausgestattet, damit die Orientierung, also die Drehbewegungen des Roboters, im Rahmen der Odometrie gemessen werden kann.

Die Abbildung1 und Abbildung2 zeigen den Roboter mit geöffnetem Chassis. Man kann die vier Mecanum-Räder erkennen, welche an den Wellen der Motoren befestigt sind. Außerdem sieht man – trotz der vielen Leitungen – die Hardwarekomponenten und den Akku. Abbildung2 stellt den Roboter noch einmal in der Vogelperspektive dar und Abbildung3 hebt die individuell nachgerüstete Hardware besonders hervor.

Abbildung1: Nexus 4WD (Heckansicht)

Abbildung2: Nexus 4WD (Vogelperspektive)

 

Abbildung3: Nexus 4WD mit hervorgehobener Hardware

Die Bewegungsrichtung des omnidirektionalen Roboters ist davon abhängig, wie die Räder angeordnet sind und wie diese sich drehen. Bei diesem Roboter sind die Mecanumräder so angeordnet, dass die Walzen bei der Sicht von oben, in die Fahrzeugmitte zeigen. Dadurch sind die Bewegungsrichtungen fest durch die Radbewegungen definiert. Abbildung4 zeigt drei Szenarien, die verdeutlichen sollen, wie sich die Drehrichtungen der Räder auf die Bewegung des Roboters auswirken. So sieht man in Beispiel (a), dass alle Räder sich nach vorne drehen. Die resultierende Bewegung des Roboters ist somit eine Vorwärtsbewegung. In Beispiel (b) drehen sich die Räder in unterschiedliche Richtungen. Die auf der linken Seite des Roboters drehen sich nach Innen, während die Räder auf der Rechten Seite sich nach außen drehen. Die resultierende Bewegung ist eine Bewegung in Richtung Y auf der Ebene. Bei dem dritten Beispiel drehen sich die Räder der linken Seite nach hinten, während die auf der rechten Seite sich nach vorne drehen. Daraus resultiert eine Linksdrehung des Roboters.

Abbildung4: Roboterbewegungen in Abhängigkeit der Drehrichtung der Mecanumräder

 

Motorsteuerung

Die Motortreiber des Roboters wurden wie oben bereits erwähnt, mit dem Arduino aus dem Roboter entfernt. Deshalb wurde eine Platine entwickelt, auf der sich zwei Motortreiber vom Typ TB6612FNG von Toshiba befinden. Die Treiber können jeweils zwei Motoren steuern, deshalb wurden insgesamt zwei Stück eingesetzt. Diese Motortreiber sind ein wenig unterdimensioniert, denn die Motoren sind im Datenblatt mit einem maximalen Strom von 1,4A angegeben. Da die Motortreiber allerdings nur einen maximalen Strom von 1,2A aushalten, wurde die Motorleistung in der Software auf maximal 80% begrenzt. In der Software wird (durch den STM32F4) ein PWM-Signal generiert, durch das die Treiber eine entsprechende Spannung an die Motoren anlegen. Dadurch kann die Leistung der Motoren beeinflusst werden.

Inkrementalgeber

Inkrementalgeber sind Sensoren, die eine Rotation messen. Damit kann die Winkelgeschwindigkeit einer Rotation mit Hilfe einer Zeitmessung bestimmt werden. Durch Integration kann aus dieser Winkelgeschwindigkeit, der zurückgelegte Winkel ermittelt werden. Da der Durchmesser bzw. der Radius der Räder fix ist, dann durch eine Multiplikation des Winkels mit dem Radradius, die zurückgelegte Distanz berechnet werden.
Der Nexus-Roboter verfügt über photoelektrische Inkrementalgeber, welche insgesamt 12 Impulse pro Umdrehung generieren. Photoelektrische Inkrementalgeber emittieren ein Lichtimpuls durch eine rotierende Messscheibe. Dadurch werden periodische Signale generiert, die einen Schluss auf die Geschwindigkeit und Richtung des Rades ermöglichen. Dieses Signal wird von den Encodern des STM32F4-Controller ausgewertet und in der Software verarbeitet. Die Motoren sind mit einem Getriebe im Verhältnis 64:1 übersetzt. Dadurch erhöht sich die Anzahl der Impulse um den Faktor 64 auf insgesamt 768 Schritte pro Umdrehung. Durch eine sogenannte Vierfachauswertung, werden die Impulse noch einmal um den Faktor vier, auf insgesamt 3072 Impulse pro Umdrehung, erhöht. Daraus ergibt sich eine Auflösung der Inkrementalgeber von ungefähr 0,117°.

Das folgende Beispiel zeigt die Initialisierung eines Encoders mit Vierfachauswertung:

Die gezählten Impulse können anschließend über den Timer ausgelesen werden:

Gyroskop

Das Gyroskop wird dazu eingesetzt, die relative Winkeländerung des Roboters zu messen. Auf dem Roboter wurde ein GyroClick-Modul der Firma MikroElektronika verbaut, welches mit dem L3GD20-Drehratensensor ausgestattet ist (siehe Abbildung5). Da der Roboter holonomen Zwangsbedingungen unterliegt (dieser sich nur auf der Ebene bewegen kann), ist die Auswertung der Gierrate ausreichend. Es werden also nur Drehungen um die Z-Achse ausgewertet, weil diese relativen Orientierung des Roboter entsprechen. Das Gyroskop misst die Geschwindigkeiten einer Drehung, welche durch Integration über die Zeit auf den relativen Winkel schließen lässt. Für die Kommunikation mit dem STM32F4 wurde ein SPI Bus eingesetzt und so konfiguriert, dass das Gyroskop mit einer Abtastrate von 760Hz ausgelesen wird.

Abbildung5: GyroClick Drehratensensor

Da das Gyroskop sehr stark driftet, wurde eine Kalibrierung in zwei Schritten durchgeführt. Als erstes wurde der Bias durch mehrere Referenzmessungen in der Nulllage, während der Initialisierungsphase, durch das arithmetische Mittel (Mittelwert) bestimmt. Dieser kann bei den Messungen als Offset aus dem Ergebnis rausgerechnet werden. Abbildung6 zeigt eine aufgezeichnete Referenzmessung, aus der ersichtlich ist, wie die Messwerte des Gyroskopes in der Nullage verschoben sind (Offset). Bei dieser Messung lag der Bias bei ungefähr -56, was bei der (Gyro-)Auflösung von 8,75 °/s, einem Offset von ca. -0,49 °/s entspricht.

Abbildung6: Nulllagenmessung zur Bestimmung des Bias

Die zweite Methode zur Unterdrückung des Driftverhalten ist der Einsatz einer Schranke. In der Software wurde eine Untergrenze definiert, welche die minimale Winkelgeschwindigkeit beschreibt, die gemessen werden muss, damit die Software diese Winkeländerung aus auswertet. Dadurch können sehr kleine Winkeländerungen zwar nicht mehr genau gemessen werden, jedoch reduziert sich das Driftverhalten erheblich, sodass diese in Kauf genommen wurde.

Das Gyroskop misst die Winkeländerungen pro Zeit. Um den relativen Winkel der Drehbewegung zu erhalten, wird die gemessene Winkeländerung über die Zeit integriert. In der Software wurde für die Implementierung das Trapezverfahren eingesetzt. Die Berechnung des Offsets wird mit Hilfe des arithmetischen Mittels von 2000 Messungen durchgeführt:

Für das Rauschen wird eine Grenze definiert, welche die gemessene Winkelgeschwindigkeit überschreiten muss, damit diese als Winkeländerung detektiert wird. Die Berechnung dieser Grenze wird wie folgt durchgeführt:

Mit diesen Werten kann nun der relative Winkel durch Integration mit dem Trapezverfahren ermittelt werden. Der Winkel ist auf das Intervall [0°,360°] abgebildet:

Odometrie

Odometrie ist ein Verfahren, mit dem die relative Position von bodengebundenen Fahrzeugen, durch die Bewegung der Räder (oder Schritte bei humanoiden Roboter) bestimmt werden kann. Da viele Roboter über die Möglichkeit verfügen, Radbewegungen zu messen, wird die Odometrie besonders gerne zur Lokalisierung eingesetzt, weil die notwendige Sensorik schon im Rahmen von anderen Anforderungen vorhanden ist. Das Verfahren basiert dabei auf der Tatsache, dass die Drehungen der Räder auf Distanzen umgerechnet und aufsummiert werden. Dadurch kann die Bewegung des Roboters nachvollzogen werden.
Da die Abtastrate in der Software bei 5ms liegt werden viele Daten im Rahmen der Odometrie generiert. Diese werden mit Hilfe eines DMA-Bausteins und der Bibliothek FatFs per SPI auf einer microSD-Karte gespeichert und stehen einer späteren Auswertung somit zur Verfügung. Abbildung7 zeigt die aufgezeichneten Odometriedaten einer Testfahrt des Roboters.
Die Messung wurde über eine Distanz von 6280mm durchgeführt und der Roboter dabei kontinuierlich lokalisiert. Man sieht, dass der Roboter einen Versatz bei der Geradeausfahrt hat. Dies ist darauf zurückzuführen, dass bisher keine Drehzahlregelung implementiert wurde.

Abbildung7: Odometriedaten einer Testfahrt

Veröffentlicht unter Eingebettete Systeme, Mecanum, Odometrie, Roboter, STM32F4 | Verschlagwortet mit , , , , , , , , , , | Hinterlasse einen Kommentar

Yakindu Statechart Tools Arduino Integration

Die Yakindu Statechart Tools sind dafür prädestiniert, Systemverhalten als Statemachine zu beschreiben, um anschließend Quellcode aus dieser Beschreibung zu generieren. Der Code kann in Java, C oder C++ generiert werden. Wir wollten den Codegenerator dazu einsetzen, Quellcode für eingebettete Systeme zu generieren, deshalb haben wir und für den Arduino Uno als Plattform entschieden. Dafür haben wir das TrafficLight Beispiel modifiziert und etwas simplen glue code (also Verbindungscode zwischen der Hardware und dem Generat) geschrieben, um die timer und die I/Os des Controllers zu mappen. Außerdem haben wir eine Ampel mit LEDs auf einer kleinen Platine entworfen, welche die Signale des Arduinos repräsentiert. Im Anhang befindet sich ein eagle-Schaltplan, sodass diese Platine leicht nachgebaut werden kann.
Das Beispiel wurde direkt für den AVR ATMEGA328P-PU Prozessor entwickelt, da dieser sich auf dem Arduino Uno befinden. Es ist ebenfalls möglich, die Programmierbibliothek für den Arduino zu verwenden, um die Ampelsteuerung zu integrieren, allerdings haben wir uns bewusst dagegen entschieden, da wir zeigen wollen, dass wir eine ganze Prozessorfamilie unterstützen können, weil die eigentliche Implementierung losgelöst von dem Generat ist. Aus diesem Grund benutzt die Implementierung die AVR-Bibliothek direkt (avr-libc).

Um das Beispiel zu ergründen, sind ein paar Schritte notwendig, die im Folgenden beschrieben werden:

1. Entwicklungsumgebung

  • Zu Beginn installiert man die Eclipse IDE mit dem integrierten Yakindu SCT. Alternativ können die Statechart Tools auch über den Eclipse Update Manager installiert werden. Beides findet man auf der Seite der SCT (http://statecharts.org/download.html)
  • Unter (debian basierten) Linuxdistributionen installiert man nun die AVR Umgebung mit dem folgenden Befehl:
    sudo apt-get install avrdude binutils-avr gcc-avr avr-libc gdb-avr.
  • Als nächstes lädt man die Arduino Bibliothek von der Seite http://arduino.cc/en/Main/Software und um die libArduinoCore.a Bibliothek zu erstellen. Unter http://playground.arduino.cc/Code/Eclipse#Arduino_core_library ist die Vorgehensweise genau beschrieben, sodass an dieser Stelle auf diese Beschreibung verwiesen wird. Sobald man die libArduinoCore.a erstellt hat, kopiert man diese in einen „lib“ Ordner (ggf. muss dieser erstellt werden) im Projektverzeichnis und setzt den include path für das Projekt im Eclipse wie folgt:

  • Danach sollte man das ArduinoTrafficLight-Projekt direkt aus dem Git-Repository auszuchecken. Das Projekt ist unter https://github.com/Yakindu/statecharts/tree/master/ im Unterverzeichnis archive zu finden. Nach dem Import sollten noch einmal die include paths überprüft werden und ggf. an die eigene Umgebung angepasst werden.
  • Damit das Beispiel ausprobiert werden kann, sollte die Platine gelötet und an den Arduino angeschlossen werden. Der Schaltplan befindet sich im Anhang.
  • Nun kann der C++ Code mit der TrafficLight.sgen generiert werden. Dazu klickt man einfach mit der rechten Maustaste auf diese Datei und wählt den Menüpunkt „generate artifacts“ aus. Ein kleiner Hinweis dazu:
    Aktuell generieren die SCT Datentypen, die nicht für die Hardware angepasst sind, sodass hier ein manueller Eingriff erfolgen muss. In der Datei sind die Datentypen definiert. Der Datentyp sc_integer muss  in dieser Datei src-gen/sc_types.h von int32_t auf uint32_t verändert werden. Das war’s schon. Jetzt kann das Projekt kompiliert werden, dazu klickt man einfach auf das Hammersymbol im Eclipse.
  • Nachdem der Code nun kompiliert wurde, kann dieser durch einen Klick auf das AVR-Symbol, auf den Prozessor geflasht werden.

Jetzt führt der AVR-Prozessor den generierten Code aus. Wenn die Hardware korrekt gelötet und an den Arduino angeschlossen ist, kann man das beschriebene Verhalten aus dem Statechart direkt testen. Das Modell kann nach Belieben angepasst werden, um das Verhalten direkt auf der Hardware auszuprobieren.

2. Ein paar Worte zum Beispielcode

 Es gibt insgesamt drei Dinge, die als gluecode implementiert werden müssen, damit der generierte Code mit dem Arduino arbeitet:

2.1 CycleRunner

Der CycleRunnter prüft periodisch, ob sich der Zustand des Modells verändert hat. Für den periodischen Aufruf wird ein (Hardware-) Timer verwendet (timer0), welcher diese Überprüfung durch einen Interrupt antriggert. Die Prüfung auf Zustandsänderungen im Statechart werden durch Aufruf der Funktion trafficlight_runCycle(handle) ausgeführt. Die Implementierung in dem Beispiel sieht wie folgt aus:

2.2 Timer und TimeEvent

Die Klasse Timer repräsentiert die Timer des Prozessors und ist dafür zuständig, diese zu initialisieren und TimeEvents auszulösen. In dem TrafficLight Beispiel verwenden wir timer1 um diesen Trigger zu implementieren. Ein TimeEvent wird aufgelöst, wenn beispielsweise dann ausgelöst, wenn die Zeit für einen Zustandsübergang erreicht ist. In manchen Situationen laufen mehrere Timer parallel, deshalb ist es in diesen Fällen notwendig, die TimeEvents in einem Array zu speichern (vgl. das Event-Array in der Datei Main.cpp). Der Timer prüft periodisch (alle 10ms), ob eine Zeitgrenze erreicht wurde und löst bei Bedarf ein Event aus. Das folgende Beispiel verdeutlicht das beschriebene Verhalten:

2.3 IO port mapping

An dieser Stelle müssen die IOs der Hardware durch den Programmierer mit dem Statechart verbunden werden. In dem Beispiel werden die Pins des Arduinos als Ausgänge konfiguriert, sowie eine Funktion für das Setzen eines entsprechenden Signals angeboten. Ein beispielhaftes Mapping für die rote LED sieht wie folgt aus:
Das Signal der LED kann nun mit Hilfe der Funktion aus dem Statemachine-Interface gesetzt werden: 

3. Anhang

Das Video zeigt die Ampelsteuerung mit dem definierten Verhalten aus dem Modell. Das Modell, welches das hier verwendeten Verhalten beschreibt, wird in der anschließenden Grafik dargestellt.

Yakindu trafficlight Statechart

Schaltplan für die Ampelsteuerung

Veröffentlicht unter AVR, Eingebettete Systeme, itemis, Mikroprozessoren, Yakindu | Verschlagwortet mit , , , , , , | Hinterlasse einen Kommentar