Mittwoch, 27. Juni 2012

Beschleunigungssensor auslesen mit einem Netduino Plus

WP_000262
Arduino Plus, BMA020 und mein Sensor Shield Prototype
Vielleicht hätte ich diesen Post früher veröffentlicht, wenn mich nicht andere Einflüsse behindert hätten. Dennoch habe ich es geschafft: statt mit dem Arduino Nano 3.0 (zum Post) habe ich den selben Sensor diesmal mit dem Netduino ausgelesen. Der Sinn dürfte klar sein, dass C und C# einfach sehr unterschiedlich sind. Das Prinzip ist allerdings das gleiche. Wobei es mit der mitgelieferten Bibliothek beim Arduino wesentlich kürzer erscheint, als beim Netduino und dem .Net Micro Framework. Anscheinend kommt man im C# nicht aus, ohne eine weitere Klasse zu schreiben, um an die Sensordaten heran zukommen. Bestimmt gibt es eine Lösung dafür, aber bei größeren Projekten macht es keinen Sinn.
image
Zusammengesteckt und Verbindungen hergestellt
Etwas lange habe ich nach einem Beispiel gesucht, wie man über den I²C Bus ein Modul erreicht und auch Daten bekommt. Die ersten Versuche zeigten sich mit Abstürzen und Abbruch des Programmcodes. Kein schöner Gedanke, weil der Sensor ein wichtiger Teil für die Kontrolle des Quadrocopters ist. Letzten Endes habe ich es dann verstanden und frage mich mal wieder, warum ich nicht vorher darauf gekommen bin.
Beschreibung zu den Verbindungen:
  • Netduino Analog Pin 5 (SCL) kommt an den BMA020 Sensor Pin SCK
  • Netduino Analog Pin 4 (SCA) kommt an den BMA020 Sensor Pin SDI
  • BMA020 Sensor Pins UIN, UPullup und CSB werden an +5V angelegt
  • BMA020 Sensor Pins GND und SD0 werden an 0V (GND) angelegt
Nun zum Programmcode, den ich aus dem Netduino Forum habe (gekürzte Fassung). Wichtig ist hier zunächst die Funktion zu bekommen.

Die angepasste Klasse

using Microsoft.SPOT.Hardware;
using System;
namespace IIC_ReaderExample
{
    public class I2CExample
    {
        private I2CDevice.Configuration _Config;
        private I2CDevice _Device;
        /// <summary>
        /// Initialisiert die Klasse
        /// Konfiguration wird angelegt und
        /// die entsprechende Klasse I2CDevice wird initialisiert
        /// </summary>
        /// <param name="address">Adresse zur Hardware</param>
        public I2CExample(byte address)
        {
            // Adresse und Taktfrequenz übergeben
            _Config = new I2CDevice.Configuration(address, 400);
            _Device = new I2CDevice(_Config);
        }
        /// <summary>
        /// Sendet den Inhalt des Byte Array zur Hardware
        /// </summary>
        /// <param name="writeBuffer">Byte Array</param>
        public void Write(byte[] writeBuffer)
        {
            // Byte Array übergeben für das ertellen einer Transaction
            I2CDevice.I2CTransaction[] writeTransaction = new I2CDevice.I2CTransaction[]
            { 
                I2CDevice.CreateWriteTransaction(writeBuffer) 
            };
            // Sende die Daten an die Hardware. TimeOut bei 1 Sekunde
            int written = this._Device.Execute(writeTransaction, 1000);
            
            // Prüfe ob alle daten gesendet wurden, ansonsten Exception ausführen      
            if (written != writeBuffer.Length)
            {
                throw new Exception("Es konnten keine Daten an das Modul gesendet werden.");
            }
        }
        /// <summary>
        /// Ruft mit den Adressen im Buffer die Werte ab
        /// </summary>
        /// <param name="readBuffer">Byte Array mit Adressen für den Abruf entsprechender Daten</param>
        public void Read(byte[] readBuffer)
        {
            // Erstelle ein Transaction zum Lesen mit übergabe des Byte Array        
            I2CDevice.I2CTransaction[] readTransaction = new I2CDevice.I2CTransaction[]
            {            
                I2CDevice.CreateReadTransaction(readBuffer)        
            };
            // Lese die Daten von der Hardware. TimeOut von einer Sekunde     
            int read = this._Device.Execute(readTransaction, 1000);
            // Prüfe, ob die Daten gesendt wurden      
            if (read != readBuffer.Length)
            {
                throw new Exception("Es konnte nicht vom Modul gelesen werden.");
            }
        }
    }
}
Das wesentliche habe ich in die Kommentare geschrieben, und dürfte fürs erste reichen. Nun kommen wir zum Auslesen der Daten aus dem Sensor:
Die Program-Klasse in dem die static Main() ausgeführt wird

using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
namespace IIC_ReaderExample
{
    public class Program
    {
        public static void Main()
        {
            // write your code here
            Debug.Print("Starte Thread");
            new Thread(LedState).Start();
            // 5 Sekunden warten
            Thread.Sleep(5000);
            I2CExample i2cExample = new I2CExample(0x38);
            
            Debug.Print("Starte Schleife");
            while (true)
            {
                // X
                byte[] buffer = new byte[2];
                buffer[0] = 0x02;
                buffer[1] = 0x03;
                i2cExample.Write(buffer);
                i2cExample.Read(buffer);
                int xdValue = buffer[1];
                // Y
                buffer = new byte[2];
                buffer[0] = 0x04;
                buffer[1] = 0x05;
                i2cExample.Write(buffer);
                i2cExample.Read(buffer);
                int ydValue = buffer[1];
                // Z
                buffer = new byte[2];
                buffer[0] = 0x06;
                buffer[1] = 0x07;
                i2cExample.Write(buffer);
                i2cExample.Read(buffer);
                int zdValue = buffer[1];
                Debug.Print("X:" + xdValue.ToString() + " " +
                    "Y:" + ydValue.ToString() + " " +
                    "Z:" + zdValue.ToString());
                Thread.Sleep(20);
            }
        }
        /// <summary>
        /// Dient nur zur Aktivität des Micro Controllers.
        /// </summary>
        public static void LedState()
        {
            OutputPort port = new OutputPort(Pins.ONBOARD_LED, false);
            while (true)
            {
                port.Write(true);
                Thread.Sleep(500);
                port.Write(false);
                Thread.Sleep(500);
            }
        }
    }
}
Am Anfang ist zu sehen, dass ich ein “Thread.Sleep(5000)” eingesetzt habe. Wenn der Zugriff auf den I²C Bus beim Senden steht, dann bleibt das Programm stehen. Schwierigkeiten treten dann auf, beim erneuten Debuggen. In meinen ersten Anläufen blieb mir sogar nichts anderes übrig, als den Netduino Plus vollständig zurück zu setzen. Das bedeutet, dass auch die Firmware weg ist und erst mit einem Tool von Atmel und einer Firmware Datei der Netduino wieder auf Werkseinstellung gesetzt wird. Also wenn etwas sein sollte und der Controller steht, dann ist es möglich, innerhalb von 5 Sekunden den Controller nach einem Reset neu zu beschreiben.
Ich hoffe ich kann mit diesem Post dem einen oder anderen Hobbybastler weiterhelfen und wünsche viel Spaß.

Sonntag, 24. Juni 2012

Neu Verkabeln

Kabel und Stecker

Zugegeben war ich unzufrieden, wie die Verkabelung auf meinem Quadrocopter aussah. Der Missbrauch  Steckersysteme zu verwenden, die Normalerweise im PC selbst zu finden sind, sah nicht schön aus. Daher besorgte ich im Conrad Shop entsprechendes Kabel und passende Stecker, die für den Modellbau geeignet sind.

 Stecker anlöten

Mit meinem anschlagenden Lötstation war das kein leichtes, alle Kabel so vernünftig wie möglich anzulöten. Schwierig waren die Stellen, wo zwei Kabel aneinander gelötet werden.

Schrumpfschlauch herum, nur nicht zu lange mit dem Feuerzeug behandeln

Ich hatte fast immer die passenden Schrumpfschläuche da. Ein wenig bunt wirkt es jedoch schon, da ich nicht immer die entsprechende Farbe wählen konnte.

Fertig ist der Verteiler

Das löten erwies sich als sehr langwierig, dafür ist es nun ordentlicher geworden. Jedoch stellte ich fest, dass mir meine Kabelbinder ausgegangen sind. Dies ist zwar nicht kritisch, da es gerade noch reichte die Regler festzuspannen, dennoch könnten es doch ein paar mehr sein. Wie dem auch sei...

Stat mit dem "wie das andere hieß", sind die Regler mit Kabelbinder festgezogen

Wo schon bereits der Rumpf, die Verkabelung und Elektronik bereits platz gefunden haben, fehlt es immer noch am Programmcode. Es zieht sich hin, das auf Grund verschiedener Einwirkungen mich daran hindern damit zügig fertig zu werden.
Bei einigen Sachen wie zum Beispiel mit dem Stabilisieren könnte ich sicherlich etwas fertiges im Internet finden, aber dann wäre dies nur halb so herausfordernd.

Sonntag, 17. Juni 2012

Brushless Motoren montieren

WP_000208 WP_000211
Brushless Motor und entsprechende Teile
WP_000210
Motor mit Propeller und Fahrtenregler
Nach über einem Monat habe ich endlich die Motoren zu meinem Projekt “Quadrocopter” erhalten. Ärgerlich war, dass das Paket beim Zollamt abgeholt werden musste, weil die entsprechende Rechnung am Paket nicht vorhanden war. Somit hat sich die Montage um eine Woche verzögert.
Quadrocopter_08 Quadrocopter_10
Motor am Rumpf montiert und verkabelt
Nachdem ich wieder die Stellen markiert, gekörnt, angebohrt und gebohrt habe, konnte ich die Motoren montieren. Anschließend kam die Verkabelung dran. Da mir die entsprechenden Y-Verbindungen für die Fahrtenregler fehlten, lötete ich einige Stecker zusammen. Folgend kam die Verkabelung und die Verbindungen auf dem Rumpf. Leider finde ich die Verkabelung noch nicht ganz gelungen, und ich denke, das mache ich am nächsten Wochenende nochmal.
Quadrocopter_09
Mit dem Arduino Nano 3.0 wurde durch geprüft
Nachdem ich alles mehr oder wenig provisorisch verkabelt hatte, schrieb ich für den Arduino ein kleines Programm zum regulieren des PWM Signals. Mit einem Potentiometer konnte ich die Ansteuerung des Fahrtenreglers vornehmen. Zuerst habe ich ein kleines Netzteil verwendet, das sich aber nach dem Anschluss des zweiten Fahrtenreglers als zu schwach herausstellte, und nahm daher den Akku. Mit Vorsicht drehte ich langsam am Potentiometer und staunte, dass ich bereits bei ca. 20% erst einmal anhalten musste, da mir sonst auf dem Tisch weggeflogen wäre. Gemessen an einem Rotor, könnte man schon meinen, dass einer  reichen würde, den ganzen Rumpf hochzuziehen. Später habe ich dann auf dem Boden im Wohnzimmer weiter getestet und drehte auf ca. 50%. Es flatterten schon die Gardinen und meiner Freundin wurde kalt, durch den starken Wind von den Rotoren.
Quadrocopter_11
Passt gerade so auf dem Schreibtisch
Inzwischen hat mein Projekt eine gewisse Größe erreicht. Auf dem Bild zu sehen: mein Quadrocopter auf meinem Schreibtisch.
Nun bleibt noch die Programmierung der Steuerung übrig.

Sonntag, 10. Juni 2012

Landestützen und Halterung für den Akku

Quadrocopter_07
Akku-Halter, Access Point und Mikrocontroller
Allmählich nimmt mein Quadrocopter Gestalt an. Leider sind meine Motoren noch nicht eingetroffen, habe jedoch erfahren, dass ich sie vom Zoll abholen darf. Da hat wohl der Versender versäumt, erforderliche Rechnungen an das Paket zu kleben. Wie dem auch sei, habe ich zunächst weiter am Rumpf gearbeitet. Diesmal überlegte ich, wo ich eigentlich alles platzieren soll. Also Akku, Mikrocontroller und Access Point. Nach einigem Überlegen sägte, schleifte und bohrte ich an einer Halterung für den Akku. Anschließend kümmerte ich mich um ein fehlendes Teil, dass für die Landestütze notwendig war.
WP_000201
Provisorische Ladestation für den Akku von meiner Bohrmaschine
Etwas geplagt hat mich mein Akku für die Bohrmaschine, bis ich darauf kam einfach den Lipo Akku zu verwenden. Jetzt ist die stufenlose Kontrolle weg, dafür habe ich viel Power an der Bohrspitze.
WP_000200
Lipo Akku an meiner Bohrmaschine. Nicht zum Nachammen geeignet
Nachdem ich eine etwas umständliche Lösung hatte, konnte ich mit den fehlenden Teilen fortfahren. Hier ein Loch, dort noch eins und die Landestützen waren fertig. Nun kam das Licht, damit ich in der Luft erkenne, wo rechts und links ist. Als ich nach den passenden LEDs suchte, stellte ich fest, dass ich keine entsprechenden Farben habe. Über 100 LEDs sind in meiner Kiste und man sollte meinen, alles zu haben, was man braucht.
WP_000206
Lichttest
Nun stehe ich noch vor der Steuerung, die ich noch nicht fertig programmiert habe. Mit der App für das Handy kann man derzeitig nur eine LED ein- und ausschalten, und die Anwendung zum kalibrieren steht auch noch nicht.

Sonntag, 3. Juni 2012

Beschleunigungssensor auslesen mit einem Arduino Nano 3.0



image
Arduino Nano 3.0 und Modul mit einem Beschleunigungssensor
Zugegeben habe ich etwas lange gebraucht, um zu verstehen, wie ich diesen Sensor auslesen kann. Das liegt einerseits daran, dass ich bisher noch nichts mit I²C oder SPI gemacht habe. Nachdem ich die Anleitung gelesen hatte, habe ich erst mal nur Bahnhof verstanden. Das änderte sich, als ich es hinbekam, die gemessenen Daten auszulesen.
Da frage ich mich manchmal, warum ich das nicht gleich verstanden habe. Zum Glück gibt es ja google, das mich hin und wieder auf die richtige Seite bringt. Allerdings enthielten die Erklärungen teilweise große Lücken im Verlauf. Vielleicht schaffe ich es hier in meinem Blog dies näher und leichter zu erläutern. Und wenn nicht, kann hier entsprechend auch einen Kommentar abgeben werden für Verbesserungen. Dafür bin ich immer offen.
Zunächst haben wir hier den Sensor von Bosch Sensortec, den BMA020. Auf den 2 Bildern ist das Modul zu sehen, auf den der Sensor gelötet ist. Im Grunde ist es der kleine schwarze SMD Chip, der die Beschleunigung ausliest. Das Modul selbst besteht aus verschiedenen Schaltungen, um z.B. eine stabile Spannungsversorgung zu gewährleisten. Bestellt habe ich mir das Modul bei Amazon, wobei hier anzumerken ist, das der eigentliche Händler ELV ist. Für die Montage selbst müssen die Steckleisten verlötet werden.
imageimage
Unterseite mit den bestückten SMD KomponentenOberseite mit den Beschriftungen und Ausrichtungen des Sensors
Als zweites habe ich den Arduino Nano 3.0, der mit einem ATMega 328 bestückt ist und für seine Baugröße zahlreiche Ein- und Ausgänge bereit stellt. Für das Auslesen, brauchen wir Pin A4 und Pin A5 für die I²C Verbindung zum Sensor Modul.
image
Arduino Nano 3.0
Jetzt müssen die beiden nur richtig verbunden werden. Hierzu sind nur wenige Kabelverbindungen notwendig, wie bereits hier im Schaltbild zu sehen ist.
image
Links der Beschleunigungssensor, rechts der Arduino Nano 3.0
Als weiteres benötigen wir in C geschriebenes Programm. Hierfür habe ich in verschiedenen Foren gesucht und wurde auch fündig. Am Ende ist dieser Code  herausgekommen.
#include <Wire.h>
#define AccelerometerAddress 0x38
#define Axis_X_Out1 0x02
#define Axis_X_Out2 0x03
#define Axis_Y_Out1 0x04
#define Axis_Y_Out2 0x05
#define Axis_Z_Out1 0x06
#define Axis_Z_Out2 0x07

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  Serial.println();
  Serial.print("X1:");
  Serial.print(readAcceleration(Axis_X_Out1), BIN);
  Serial.print("SX2:");
  Serial.print(readAcceleration(Axis_X_Out2), BIN);
  Serial.print("@Y1:");
  Serial.print(readAcceleration(Axis_Y_Out1), BIN);
  Serial.print("SY2:");
  Serial.print(readAcceleration(Axis_Y_Out2), BIN);
  Serial.print("@Z1:");
  Serial.print(readAcceleration(Axis_Z_Out1), BIN);
  Serial.print("SZ2:");
  Serial.print(readAcceleration(Axis_Z_Out2), BIN);
 
  delay(500);
}

byte readAcceleration(byte address)
{
  byte val = 0x00;
  Wire.beginTransmission(AccelerometerAddress);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(AccelerometerAddress, 1);
  val = Wire.read();
  return val;
}
Die Ausgabe kann über die Serielle Verbindung gelesen werden.
Um eine gewisse Übersicht zu behalten, habe ich darauf geachtet, dass der Code auch wirklich kurz gehalten ist und keine unnötigen weiteren Funktionen hat.
Mit #include wird die Library eingebunden, die für die I²C Verbindung erforderlich ist. Die darauf folgenden #define sind Adressen für das auslesen des Sensors. Die erste davon ist die Adresse vom Sensor selbst, da an dem I²C Bus auch mehrere Geräte oder Module Angeschlossen werden können. Mit “Axis_X_Out1” werden die ersten zwei Bits gelesen. Um die eine Achse von ihren Werten vollständig zu erhalten, ist anschließend die Abfrage mit der Adresse “Axis_X_Out2” erforderlich. Zusammengesetzt sind es dann 10 Bits. Die ersten 2 Bits sagen aus, mit wie viel G einwirkt. Die weiteren 8 Bits geben dann den eigentlichen Wert wieder. Das gleiche gilt auch für die weiteren 2 Achsen.
Nun zur Methode “byte readAcceleration(byte address)”. Sie erledigt die eigentliche Aufgabe, die gewünschten Daten aus dem Sensor zu bekommen. Mit “Wire.beginTransmisson” und der Übergabe der Adresse zum Sensor stellen wir eine Verbindung her. Anschließend mit “Wire.write” übergeben wir nun die Adresse für eine der Achsen und mit “Wire.endTransmission” geben wir hier ebenfalls die Adresse des Sensors, um die Verbindung zu beenden. Im folgenden muss noch die Methode “Wire.requestFrom” mit der Adresse des Sensors und ein weiterer Wert für die Anzahl zu erwartenden Bytes.
So, das war die Beschreibung zum Code, der auf dem Arduino ausgeführt wird. Nun will man ja auch das ganze auf dem Bildschirm sehen.
image
Alle Werte der 3 Achsen, allerdings noch in Binär. Das ist für die meisten schlecht zu lesen.
Zur Not kann auch der Serial Monitor vom Arduino Programm verwendet werden, oder man schreibt sich eine Desktop Anwendung, die das auch visualisiert.
image
Desktop Anwendung für die Visualisierung der gemessenen Daten aus dem Sensor.
Da die Beschreibung der Anwendung meinen Rahmen für einen Blog Eintrag sprengen würde, belasse ich es hierbei. Als Hinweis gebe ich jedoch, wer hier mit dem .Net Framework arbeitet, benutzt am besten die Klasse “SerialPort”. Die kann alles, was man für das Auslesen zu einer seriellen Verbindung benötigt.

Gelötet, Löcher gebohrt und zusammengeschraubt

Das Wetter draußen zeichnete sich mehr mit Regen als Sonnenschein, was mich dazu bewegte, mich weiter mit meinem Sommerprojekt zu beschäftigen.
Diese Woche stellte ich fest, dass ich keine richtigen Kabelverbindung für den Netduino habe. So konnte ich nur beschränkt auf dem Arduino mit den Sensoren und Servos entwickeln. Daher dachte ich, dass ich einen eigenen Shield für den Netduino löte. Nach hin und her überlegen, was ich gebrauchen könnte an Steckaufsätzen und wie ich später die Sensoren miteinander verbinde, habe ich es geschafft, etwas passendes zu entwickeln.
Quadrocopter_02
Shield für den Netduino
Eigentlich habe ich relativ lange daran gelötet, dennoch denke ich, dass es ich gelohnt hat. Endlich mal wieder was tun, was nicht am Computer erledigt werden kann!
Quadrocopter_03
Netduino mit meinem Shield. Passt prima, jetzt erst mal testen
Erst wollte ich den Beschleunigungssensor extra auf dem Rumpf montieren. Später entschied ich mich, den Sensor mit auf den Shield anzubringen.
Quadrocopter_04
Der von Bosch BMA 020 Beschleunigungssensor
Und zu guter Letzt schaffte ich es, am Sonntag alle erforderlichen Löcher zu bohren und könnte endlich meinen Rumpf zusammen schrauben. Jetzt fehlen im Grunde nur noch die Löcher für die Motoren. Ich hoffe die kommen nun bald an.
Quadrocopter_05
Der Rumpf für den Quadrocopter

Ameisen Simulation und andere Dinge

Wer lange sich schon mit C# beschäftig, hat sicherlich schon mal was von AntMe gelesen oder gehört. Diese Idee hatte ich aufgegriffen und mi...