Mein neuer Lieblingsmikrocontroller

Lieber Arduino, wir haben zusammen viele großartige Jahre miteinander verbracht, doch man entwickelt sich halt weiter und wer bei der Verwendung von ARM-Prozessoren immer noch von seinen Nutzern erwartet, über Serial.print() zu debuggen, der hat wohl einfach den Schuss nicht gehört.

Nun habe ich den Schritt getan und halte ab jetzt die Fahne hoch für einen bösen Megakonzern: STMicroelectronics. Dieser hält im Mikrocontrollermarkt Anteile von um die 50%! Der Verdacht, dass die Mikrocontroller von ST also was taugen, könnte also durchaus berechtigt sein. Es gibt für arme kleine Privatentwickler zwei Reihen von Evaluationsboards, die sehr interessant sind:

STM32F4-Discovery

Neben dem gezeigten Board, das einen Cortex-M4F besitzt, gibt es auch noch weitere Varianten mit anderen Prozessoren oder zusätzlicher Peripherie. Der Prozessor meines Boards trägt die Bezeichnung STM32F407VGT6 und beherbergt 1Megabyte Flash, 192KB RAM, 3 Analog-Digital Wandler, 2 Digital-Analog-Wandler und 14 Timer. Weiterhin sind auf dem Board noch ein Beschleunigungssensor, ein Mikrofon, eine Audioverstärker, vier LEDs und ein Taster, die für eigene Funktionen genutzt werden können, und ein USB on-the-go Anschluss. Das Wichtigste ist das obere Viertel der Platine; hier befindet sich der ST-Link/V2, ein Debugger, mit dem der Mikrocontroller nicht nur programmiert werden kann, sondern mit dem auch der Prozessor angehalten werden kann und alle Register ausgelesen werden können – ganz neue Dimensionen für Leute wie mich, die vorher tatsächlich mit der seriellen Schnittstelle versucht haben, Fehler zu finden 😀

Als Entwicklungsumgebung eignet sich die Coocox IDE sehr gut. Sie bindet die Bibliotheken von ST sowie akzeptable Dokumentation ein und ist komplett kostenlos.

Darüber hinaus gibt es aber noch eine zweite Möglichkeit, für den STM32F407 zu entwickeln, die es ansonsten in dieser Form für kaum einen anderen Mikrocontroller gibt: Mit Simulink! Leider erfordert das eine sündhaft teure Matlab Lizenz. Wäre ich nicht Student an einer Uni, die sechsstellig pro Jahr für eine ‘Total Headcount’-Lizenz löhnt, hätte ich diesen Weg wohl niemals ausprobiert. Das grafische Programmieren ist in ähnlichem Umfang auch mit Labview möglich, welches aber nur mit den eigenen Geräten von National Instruments gut funktioniert. Für Simulink gibt es eine Basisunterstützung vieler Geräte, z.B. für Arduino, Raspberry Pi, Lego NXT, etc. Richtig gute Unterstützung erhält man mit den C2000 DSPs von Texas Instruments, dem Mathworks-eigenen xPC-Target oder der dSpace Hardware.

Oder eben mit dem STM32F4-Discovery. Dafür sorgt das Blockset Waijung. Es scheint für Studenten in Thailand geschrieben zu sein und deckt nahezu jedes Feature des Prozessors ab. I²C, UART, SPI, CAN – alle wichtigen Busse sind da, die Timermodule können nicht nur PWM ausgeben, man kann auch Pulse einlesen und Inkrementalencoder anschließen. Bis zu 6 Encoder lassen sich auslesen! In Hardware!

Hier eine Linkliste zu Ressourcen, die ich noch nicht genannt hatte, die einem aber verdammt gut weiterhelfen beim Einarbeiten in die Materie:

  • mikrocontroller.bplaced.net: Große Sammlung an Libraries, sehr gute Anleitung zur Einrichtung der Coocox IDE
  • tkjelectronics.dk: Review des Discovery Boards mit ausführlichen Demos
  • Waijung: Auf der Seite des Projekts gibt es eine Installationsanleitung, einen Link auf das RapidSTM32-Paket und einen Hinweis auf den Shop, wo Erweiterungsmodule angeboten werden

Und last but definitely not least: Das Ding ist billig. Richtig billig, ST subventioniert das Board, um neue Entwickler an die eigene Plattform heranzuführen.

Kosten: 15€ (farnell, ebay)

 

 

Nucleo

Nucleo F401RE, Bild von STMicroelectronics

Nucleo F401RE, Bild von STMicroelectronics

Nach unten abgerundet wird das Evaluation Board Sortiment von ST durch die Nucleo-Serie. Hier sind schwachbrüstigere Mikrocontroller als bei den Discovery Boards und nochmal niedrigere Preise zu finden. Das Hauptaugenmerk möchte ich hier auf das F401RE, bzw. seinen Nachfolger F411RE legen, welches neben einem Arduino-kompatiblen Pinout auch kompatibel zur Entwicklungsumgebung mbed ist. Hier werden Programme im Browser geschrieben und das Kompilat (Kompilat, hihi :D) auf dem Mikrocontroller gespeichert, welcher sich als USB-Datenträger beim Computer anmeldet. Zusätzlich kann der verbaute ST-Link auch die klassische Debugfunktionalität übernehmen. Ich besitze bisher noch keinen Nucleo, aber das ist nur noch eine Frage der Zeit…

Kosten: ca. 12€ (farnell, ebay)

Advertisements

RFM12 Funkmodule mit Arduino ansprechen

Der Kistenschieber  Elektronikversender Pollin bietet RFM12 Module für gerade mal 5€ an.

Ein Schnäppchen, verglichen mit Xbee oder Bluetooth Modulen. Dummerweise sind die Dinger nicht mehr so ganz taufrisch und die meiste Hilfe im Internet bezieht sich auf den Nachfolger RFM12B.

Die alten RFM12-Module zum Laufen zu bringen ist kein Kunststück – die Schwierigkeit für mich bestand damals eher darin, mich durch die vielen Tutorials und Beispielprogramme zu wühlen. Die meisten sind in normalem C, ich wollte aber etwas, was schön gekapselt in einer Library steckt und sich einfach benutzen lässt.

Die Lösung stellte Jean-Claude Wippler zur Verfügung, ein passionierter Programmierer und Blogger, dessen Daily Weblog jeelabs.org ich euch sehr ans Herz legen möchte. Als ich es gefunden hatte, habe ich begonnen, jeden einzelnen Post zu lesen – jetzt, wo ich damit fertig bin, hat er das Bloggen eingestellt 😥

Sein RF12-driver ist in der Bibliothek JeeLib zu finden, die es hier auf Github herunterzuladen gibt (Ganz rechts findet man den Button ‘Download ZIP’). Alles ist gut dokumentiert und erlaubt einen sehr energiesparenden Betrieb (Bei ihm zuhause läuft ein Mikrocontrollerboard, das seit 3 Jahren mit einer einzigen Akkuladung läuft und jede Minute über das RFM12B-Modul einen Zählerstand ausgibt). Um das alte RFM12-Modul zu verwenden, muss man Folgendes beachten:

  • Das letzte Argument in der Funktion rf12_initialize muss 212 sein
  • Das RFM12 ist explizit 5V-tolerant. Man braucht keine Pegelwandler.

Was für beide Versionen des Funkmoduls gültig ist:

  • Vor dem Senden mittels rf12_sendStart müssen eventuelle Empfangsvorgänge abgeschlossen werden (rf12_recvDone aufrufen) und abgefragt werden, ob das Senden auch begonnen werden kann (rf12_canSend gibt 1 zurück). Bereits der Aufruf von rf12_canSend leitet das Senden ein. Wenn rf12_canSend 1 zurückliefert, muss man auch direkt danach rf12_sendStart aufrufen, ansonsten passiert Blödsinn.
  • Das zweite Argument von rf12_sendStart ist ein Zeiger auf die zu übertragenden Daten. Wenn du eine einzelne Variable übertragen willst, dann schreibe ein & vor ihren Namen; wenn du ein Array versenden willst, reicht dessen Name. Das dritte Argument ist die Länge der Daten in Byte. Bis zu 66 Byte passen in ein Paket.
  • Zum Empfangen sollte möglichst häufig die Funktion rf12_recvDone aufgerufen werden. Wenn diese etwas anderes zurückliefert als 0, so ist gerade ein Paket empfangen worden. Dieses wurde in das Array rf12_data gespeichert und sollte von dort möglichst schnell ausgelesen werden, damit die Daten nicht beim Empfang des nächsten Pakets überschrieben werden.

Beispielprogramme zum Senden und Empfangen sind auf GitHub zu finden. Ich habe hier im Wesentlichen die Programme von oppes kopiert. Man braucht zwei Arduinos und zwei RFM12 Module. Der eine sendet einen konstant ansteigenden Zähler aus. Der andere gibt die empfangenen Daten auf der seriellen Konsole aus. Voilá! – Deine erste Funkstrecke!

Der Anschluss funktioniert folgendermaßen (Macht bitte parallel diese Seite zur Referenz auf):Steckleisten_RFM12

  • SDO an Pin 12 (MISO)
  • nIRQ an Pin 2 (INT0)
  • FSK über einen 10 Kiloohm Widerstand mit der Versorgungsspannung verbinden
  • nSEL an Pin 10 (SS)
  • SCK an Pin 13 (SCK)
  • SDI an Pin 11 (MOSI)
  • GND an Masse
  • VDD an die Versorgungsspannung
  • an ANT ein Stück Draht anlöten, etwa 173mm bei der 433MHz-Version

Bei Instabilitäten noch die Kontakte nRES und nIRQ mit 10K Widerständen hochziehen. Ich habe zurechtgebogene Stiftleisten zur Breadboardmontage angelötet – absolut schrecklich! Schöner gehts mit diesem Adapter oder einer selbstdesignten Platine.

Alles in allem eine sehr schöne Möglichkeit, um geringe Datenmengen zu übertragen. Vielen Dank an JCW für den fantastischen Treiber!

 

 

 

Flugrekorder Teil 2

Ich habe gestern und heute eine erste Programmversion für den Flugrekorder geschrieben, die alle Sensoren ausliest und die Ergebnisse auf eine SD Karte schreibt.

Ein paar Details zu den Sensoren:

1. Beschleunigunssensor (ACC1) LIS331HH: Befindet sich auf der roten Breakoutplatine, wird später in den vordersten Teil der Raketenspitze geschraubt. Per I²C angebunden.

2. Magnetometer (MAG) LSM303DLHC: Befindet sich auf der grünen Platine, enthält zusätzlich noch einen zweiten Beschleunigungssensor ACC2 und ein Thermometer THM. Per I²C angebunden.

Die microSD Karte wird über SPI angeschlossen und mit der FAT Bibliothek von fat16lib angesprochen. Für die mechanische Verbindung habe ich einen microSD-SD Adapter an den Arduino angelötet, in den die microSD Karte eingeschoben wird.

Für die Stromversorgung nutze ich eine AAA NiMH Zelle mit Lötfahnen (700 mAh bei 1,2V), deren Spannung mittels eines Step-Up-Wandlers auf 3,3V erhöht wird.

Der Arduino ist genau genommen ein Wattuino auf 3.3V.

Alles funktioniert nach dem Zusammenlöten ohne Probleme. Vllt werde ich noch externe Pullups für das I²C Interface anlöten, aber das wars dann auch.

Das Programm, das derzeit läuft, liest linear alle Sensordaten aus und schreibt sie in einen Puffer, der dann auf die SD Karte geschrieben wird. Besonders das Schreiben ist sehr langwierig (~30ms). Da muss ich mich noch tiefer einarbeiten, um mit mehreren Puffern alles flüssiger hinzubekommen und Messraten von um die 1000 Hz zu erreichen. Die FAT Library bringt dazu definitiv die richtigen Werkzeuge mit.

Nachdem ich vor einem Jahr schonmal mit dem roten Beschleunigungssensor gearbeitet hatte, war die Konfiguration diesmal ein Kinderspiel. Direkt beim ersten Ausführen des Programms sind Daten ausgelesen worden. Darauf bin ich voll stolz 🙂 Wenn ich dagegen an die endlosen Verbindungsversuche zum Sensor im letzten Jahr denke – da steckt doch ein guter Fortschritt dazwischen.

Seinen ersten Test hat der Rekorder bestanden: Im Rucksack hatte ich ihn beim Einkaufen dabei und hat er tadellos aufgenommen und 5MB Logdaten erzeugt.

Der Quellcode ist auf GitHub zu finden.

Zum Schluss noch ein wunderschönes Bild, auf dem man die Daten der Sensoren sieht, wenn ich den Flugrekorder schüttel:

Daten diverser Sensoren über die Zeit aufgetragen

Aufgenommen mit MegunoLink Pro

Todo:

  • Schneller und gleichmäßiger loggen
  • Hardware gegen Stöße, Kontakte, etc. schützen
  • Umrechnung der Sensordaten in SI Einheiten

Aus einem Arduino einen USB Joystick machen – Teil 1

Nur eine Sammlung von Links und Gedanken – keine Ergebnisse

Heute sind wir auf die Idee gekommen, für diverse Spiele selbst einen Joystick und andere Eingabegeräte zu bauen. Das Bauen mag aufwendig sein, das Auslesen ein Kinderspiel, die Daten rüber auf den PC zu bringen wird aber zur Krux.

Natürlich wollen wir so ein Gerät mit jedem Spiel, das mit handelsüblichen Joysticks arbeitet, benutzen können. Wir müssen also dem Computer glaubhaft machen, dass wir ein solcher Joystick wären. Der Standard Arduino kann das nicht, er hat einen FTDI Chip zur USB-Kommunikation, der sich nur als USB-COM Schnittstelle ausgibt. Der Leonardo mit seinem 32U4 hat einen nativen USB Port, mit dem er Mäuse und Keyboards emuliert. Nicht schlecht, aber noch nicht so ganz das Richtige.

Wir brauchen vollständige Kontrolle über den USB-Port, denn wir müssen dem Computer eine selbst erstellte HID Descriptor Datei unterschieben, die ihm die Funktionalität des Geräts vermittelt. Dann senden wir ihm laufend neue “Reports”, in denen alle Werte der Taster und Sensoren  drin stehen. Folgende Ansätze habe ich bisher gefunden:

  • Mjoy: Ein ATmega ohne nativen USB-Port wird mit Assembler programmiert und kann auf seinen GPIO Pins per “bit banging” USB sprechen. Gestartet von einem Mindaugas Milasauskas, dessen Homepage leider verwaist ist, wurde das Projekt unter anderem von Michael Wolf weiterentwickelt zu einer Variante, die 28 Taster und 8 analoge Achsen auslesen kann. Hier noch eine andere Variante basierend auf dem gleichen Mjoy. Und noch eine.
  • Emulation auf dem PC: Alle Werte über eine simple serielle Schnittstelle in den PC hineinfüttern, dann die Werte auf ein virtuelles Eingabegerät umbiegen. Müsste doch möglich sein, oder? Ich finde leider nichts dazu. Vielleicht kommt man im Umfeld von libusb und HID API weiter?
  • Native Schnittstelle von 8U2, 16U2, 32U4: Die Beschränkung auf Maus und Tastatur lässt sich durch eine geänderte Firmware umgehen.
  • Native USB-Schnittstelle des Due: Hier versucht jemand etwas Ähnliches. Der AT91SAM3X8E auf dem Due dürfte eigentlich alle benötigten Features bereit stellen. Das Datenblatt konzentriert sich allerdings eher auf den host mode.
  • Antiquierten Joystickport emulieren und per Adapter auf USB konvertieren: What could possibly go wrong?

Ich für meinen Teil bin erstaunt, dass es keine einfache Lösung für unseren Fall gibt. Schauen wir hier in die falsche Richtung?

Soweit die ersten Ideen, mal schauen ob es einen Teil 2 geben wird.

Geschwindigkeit von Gelenken auslesen

Die Spannung an einem Potentiometer mit einem Hochpass ableiten und durch einen Operationsverstärker schicken

Motivation: Der Winkel von Gelenken lässt sich sehr günstig und mit mäßiger Genauigkeit durch ein Potentiometer auslesen. Es gibt eine Spannung proportional zum Winkel aus. Für viele Anwendungen ist es zudem wichtig, auch die Winkelgeschwindigkeit, also die Ableitung des Winkels zu kennen, z.B. bei einer Zustandsregelung. Die Geschwindigkeit lässt sich unter anderem mit folgenden Methoden bestimmen:

  • numerische Differentiation: In einem definierten Intervall den Winkel (also die Spannung am Potentiometer) messen und von diesem den Winkel bei der letzten Messung abziehen. Nun diese Winkeländerung durch das Zeitintervall teilen.Vorteile: Kein zusätzlicher analoger Eingang erforderlich, im Prinzip schnell zu implementieren. Nachteile: heftige Sprünge, viel Logik zur Glättung und Filterung notwendig.
  • modellhafte Differentiation mit Luenberger Beobachter: Der Prozessor rechnet sich aus, welche Geschwindigkeit infolge der Steuersignale ungefähr zustande kommen müssten und passt seine Simulation immer wieder an die tatsächlich auftretenden Messwerte an. Rechenaufwendig und anspruchsvoll, gängig in der Regelungstechnik.
  • analoge Differentiation: Die Potentiometerspannung wird im idealen Fall in Reihe mit einem Kondensator an einen analogen Eingang angeschlossen. Zudem wird die Leitung über einen Pulldown-Widerstand Richtung Masse gezogen. Der Fachmann erkennt: ein Hochpass! Und der hat differenzierenden Charakter. Mit üblichen Bauteilgrößen ergibt sich nur ein kleiner Ausgangsspannungsbereich. Den erweitern wir durch einen Operationsverstärker.

Im Folgenden zeige ich den Aufbau eines analogen Differenzierers, der beim Anschluss an einen Mikrocontroller wie z.B. den Arduino einen komfortablen Wertebereich hat.

Foto des Versuchsaufbaus - Breadboard mit 5V Spannungsquelle, Arduino Nano (Klon), Operationsverstärker, Hochpass, Potentiometer

Breadboard mit 5V Spannungsquelle, Arduino Nano (Klon), Operationsverstärker, Hochpass, Potentiometer

Folgende Elemente sind nötig:

  • Bauteil mit analogem Ausgang, z.B. Potentiometer
  • Operationsverstärker – in diesem Fall ein LM358, andere funktionieren ganz ähnlich, haben aber teilweise Spannungsbereiche, die der Ausgang nicht annimmt (z.B. geht der LM741 nicht unter 2V und hat damit einen viel kleineren nutzbaren Bereich)
  • Kondensator für den Hochpass, ich nehme hier 100nF, eine Größenordnung mehr oder weniger schadet auch nicht
  • Strombegrenzungswiderstand in Reihe zum Kondensator. Ich nehme 10 Kiloohm, wieder schadet eine Größenordnung mehr oder weniger nicht. Widerstand und Kondensator in bilden die Verbindung vom Potentiometer zum negativen Eingang des Operationsverstärkers.
  • Spannungsteiler: Zwei Widerstände vom gleichen Wert, zwischen einem Kiloohm und ein paar Dutzend Kiloohm. Damit legen wir die Hälfte der Versorgungsspannung auf den positiven Eingang. Wenn wir die Widerstände ungleich wählen, können wir Einschränkungen des Operationsverstärkers elegant umschiffen.
  • Rückkopplungswiderstand zwischen Ausgang und negativem Eingang des Operationsverstärker, sollte sehr eng sein, ich nehme 1 Megaohm.
  • Arduino oder anderer Mikrocontroller mit analogem Eingang, welcher mit dem Ausgang des Operationsverstärkers verbunden wird. Der Mikrocontroller muss mit derselben Spannung wie der Rest der Schaltung versorgt werden.
  • 5V Netzteil, notfalls reicht auch die Versorgung über USB, dann kommen etwa 4,4V noch an. Falls es der Mikrocontroller erfordert, ist der Betrieb mit 3,3V mit dem exakt gleichen Layout möglich.

Jetzt alles nach folgendem Foto aufbauen.

Erratum: Als Begrenzungswiderstand ist auf dem Foto ein 1K Widerstand (der mit dem roten Ring) statt des empfohlenen 10K Widerstandes (oranger Ring) zu sehen.

Operationsverstärker: oben links ist VCC+, unten sind von links nach rechts: Ausgang, negativer Eingang, negativer Eingang, VCC- Detaillierte Verschaltung: 5V an VCC+, Masse an VCC-, Spannungsteiler aus zwei 15K Widerständen zwischen 5V, positivem Eingang und Masse, 1M Widerstand zwischen Masse und negativem Eingang, 100nF Kondensator und 10K Widerstand in Reihe zwischen Potentiometerausgang und negativem Eingang.

Operationsverstärker: oben links ist VCC+, unten sind von links nach rechts: Ausgang, negativer Eingang, negativer Eingang, VCC-
Detaillierte Verschaltung: 5V an VCC+, Masse an VCC-, Spannungsteiler aus zwei 15K Widerständen zwischen 5V, positivem Eingang und Masse, 1M Widerstand zwischen Masse und negativem Eingang, 100nF Kondensator und 10K Widerstand in Reihe zwischen Potentiometerausgang und negativem Eingang.

Jetzt kann man den Strom einschalten und den Ausgang messen. Bei Stillstand sollte der Ausgang etwa 2,5V annehmen und beim Drehen proportional zur Geschwindigkeit steigen oder fallen.

Zeit um ein paar Messwerte zu sammeln!

Ausgangsspannung aufgetragen über die Zeit, für einen Motor, der sich vor und zurück dreht, ergibt sich ein Rechtecksignal

Screenshot aus dem Programm Megunolink Pro

Ich habe hier nicht von Hand am Poti gedreht, sondern das aus einem gehackten Servo angeschlossen. Der Servo hat sich vor und zurück gedreht (also ein Dreieckssignal). Man erkennt, wie die Spannung an unserem Differenzierer zwischen zwei konstanten Geschwindigkeiten wechselt. Ein Rechtecksignal und damit genau die Ableitung des Dreieckssignals, das wir in den Differenzierer hinein gefüttert haben!

Der Wertebereich 0-1023 des Analog-Digital-Wandlers vom Arduino wird noch nicht voll ausgeschöpft. Wir können höhere Ausschläge erreichen, indem wir den Rückkoppelwiderstand enger(höherer Wert) oder den Strombegrenzungswiderstand weiter(kleinerer Wert) wählen. Jeder Operationsverstärker braucht aber seine Reserve, er geht nicht unbedingt vollständig bis auf VCC+ und VCC-.

Im Vergleich zu einem einfachen numerischen Differenzierer hat das Signal keine riesigen Ausreißer aber ein hohes Rauschen und immer wieder Werte, die nicht vollständig plausibel sind. Dafür sollte man Filterroutinen schreiben.

Aber auch schon so haben wir eine sehr gute Möglichkeit gefunden, ohne großen Rechenaufwand und nahezu latenzfrei die Geschwindigkeit eines beliebigen Signals zu messen.

Zum Schluss noch der Quelltext auf GitHub.