Der Flugrekorder arbeitet auf 400Hz!

Es ist einige Arbeit nötig gewesen, um den zuvor vorgestellten Flugrekorder schneller zu machen, aber nun arbeitet er mit einer meiner Meinung nach zufrieden stellenden Datenrate. Das grundsätzliche Funktionsprinzip des Programms ist folgendes:

  • Von einem Timerinterrupt gesteuert wird in einem festen Intervall der Beschleunigungssensor per I²C ausgelesen. Bei jedem zweiten Aufruf wird das Magnetometer ebenfalls ausgelesen. Dieses arbeitet also mit 200 Messungen pro Sekunde.
  • Die Werte werden gespeichert in einem Ringpuffer, der konstant neue Werte aufnehmen kann, auch wenn die SD Karte wieder Schluckauf hat und über 100ms Latenz bis zum Wegschreiben braucht. Der Puffer ist im Wesentlichen ein Array, das sich bewusst ist, in welchem Bereich Werte geschrieben wurden.
  • In der main loop, also immer dann, wenn die Ausleseroutine gerade nichts tut, wird der Inhalt des Ringpuffers in CSV formatiert und auf die SD Karte geschrieben.

Die Datenrate beim Auslesen beträgt etwa 6,6 KB/s die Schreibrate etwa 20KB/s. Der Unterschied erklärt sich mit der Formatierung in CSV, die es möglich macht die gewonnenen Daten direkt mit OpenOffice Calc oder MATLAB zu importieren. Letzte Nacht habe ich den Logger mal durchlaufen gelassen. Das Resultat waren 400MB Logdaten!

Windows Explorer Scrrenshot

Ich finde, das sind doch ganz erstaunliche Ergebnisse und bin sehr zufrieden mit dem Fortschritt bisher, auch wenn ich bisher nicht auf die maximale Sanplingrate des Beschleunigungssensors von 1 kHz komme. Im GitHub Repository ist als Beispiel ein Logfile zu finden.

Möglich ist das vor allem durch die SdFat Bibliothek von Bill und William Greiman. Zusätzlich benutze ich auch noch den Buffered Writer und TimerTwo von den beiden. Und auch noch die I2C Bibliothek von Wayne Truchsess. Alleine hätte ich das alles niemals hinbekommen. In diesem Sinne ein großer Dank an die Autoren! Im Wesentlichen habe ich nur viel Kleber zwischen die genannten libraries und die vorliegende Hardware geschrieben.

Screenshot einer CSV Datei aus dem Flugrekorder

Das Format ist folgendes: Spalte A: Aufnahmezeit in Mikrosekunden, Spalte B-D: Beschleunigungswerte, Spalte: E-G: Magnetometerwerte, Spalte H: Anzahl der Überläufe

Der Weg bis dahin war trotzdem recht lang. Man muss erstmal die richtigen Konzepte finden und das Debugging ist gerade bei Problemen mit dem Schreiben auf SD auch ziemlich aufwändig: FTDI Breakout an den Computer und den Arduino stecken, Kompilieren und Hochladen, laufen lassen, SD Karte rausziehen, in Adapter stecken, in den Computer, Dateien angucken, rumrätseln, Code umschreiben, alles von vorn!

Ein wichtiger Faktor ist noch die Notwendigkeit, das Schreiben auf SD auch tatsächlich zu erzwingen, was Zeit kostet. Bei der derzeitigen Messrate ist das jede Sekunde möglich, ohne einen überfüllten Puffer zu riskieren.  Abschließend sollte die Datei geschlossen werden. Wird ein Jumper auf zwei Pins gesetzt, so schlägt ein Interrupt an und beendet das Programm. Ich nenne den Jumper Flight Recording Termination System (FTS) – eine typische RBF Komponente.

Foto vom Flugrekorder beim Loggen

Bei seiner Lieblingsbeschäftigung erwischt: Datenlogger auf 400 Hz

Was ich noch vorhabe: Nach Fehlern neu starten, Einbau in die Rakete.

Und dann habe ich noch etwas anderes vor: Aus dem Programm eine eigene Library bauen, die ich der Arduino Community zur Verfügung stelle. Der Anwendungsfall wäre folgender: Nutzer sucht sich beliebige I²C Sensoren aus, trägt Anzahl der auszulesenden Werte und Messrate ein, definiert Ausleseregister und schreibt Konfigurationscode => und schon läuft sein Logger mit über 600 Hz bei einem Arduino pro mini @ 8 MHz und 3 Achsen mit 16 bit Genauigkeit. Aus diesem Grund trägt der hochgeladene Code schon eine Menge englischer Kommentare.

Und hier ist das Programm zu finden: GitHub

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

Flugrekorder

20131118-233613.jpg

Ich möchte den Flug einer kleinen Modellrakete aufnehmen. Die Einheit besteht aus einem Arduino pro mini 3.3V, einem Beschleunigungssensor, einem Magnetometer, einer SD Karte, einer AAA Akkuzelle und einem Step Up Wandler.
Das Gewicht dürfte zur Hälfte Kabel sein, aber 28 Gramm sind immer noch voll im Rahmen.
Auf zur Programmierung!

Positiver Nebeneffekt vom Bloggen: Ich hab mal wieder meine Waage geputzt!

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.