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ß.

Kommentare

Beliebte Posts aus diesem Blog

Arduino Control (Teil 5) - PWM Signal einlesen

RC Fahrtenregler für Lego Kettenfahrzeug

Angular auf dem Raspberry Pi