Posts mit dem Label Bosch Sensortec werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Bosch Sensortec werden angezeigt. Alle Posts anzeigen

Samstag, 14. September 2013

Tippe die Lampe an

HitLamp01

Letztes Jahr habe ich zu dem Sensor BMA020 bereits ein Code Beispiel für den Arduino gepostet. Nun dachte ich, da der so rum liegt, kann man den vielleicht auch mal für etwas verwenden. Also kam mir die Idee eine Lampe einzuschalten, in dem man gegen sie tippt oder leicht schlägt.

Schaltung_HitLamp_bearbeitet-1
Im späteren Verlauf stellte ich fest, dass einige Widerstände zu groß berechnet wurden. Die Abweichungen kommen durch die LED, die eigentlich für 12V ausgelegt sind und ich sie aber mit 9V betreibe. (Für den ATMega fehlt auf dem Bild der Quarz, PIN9 und PIN10)

Zunächst skizzierte ich mir meine Schaltung und berechnete anhand des Schaltbildes die Widerstände. Dann sammelte ich meine benötigten Komponenten zusammen und steckte sie auf meinem Breadboard, um zu sehen ob meine Überlegung richtig ist.

image
Versuchsaufbau der Schaltung

Natürlich funktioniert die Schaltung nicht ohne einen Programmcode und daher musste ich mir zunächst etwas überlegen. Zum Beispiel wie ich aus den drei Achsen einen Wert berechne und wie hoch die Abweichung sein muss, um eine Bewegung als Tippen wahrzunehmen. Die Formel für den Gravitationsvektor half nicht sonderlich weiter. Am Ende kam ich auf ein simples Zusammenrechnen, wie es im Programmcode zu sehen ist.

gravitySum = axisX / 3 + axisY / 3 + axisZ / 3;

Dies habe ich mir auf den Serial Monitor ausgeben lassen und tippte solange gegen meinen Arduino mit dem Sensor, bis ich einen passenden Wert ermittelt hatte.

image
Nach dem gegentippen bekam ich einen Wert von mehr als 9000 (echt Zwinkerndes Smiley)

Dann übernahm ich den Wert in die Bedingung für das Einschalten oder Ausschalten. Nun musste das Ganze noch auf eine Platine gelötet werden und das möglichst im kleinsten Raum und mit den LEDs, die ich dafür verwenden möchte. Als Hülle habe ich einen Teil von einer Plastikflasche verwendet.

image
Die LED Fläche zerlegt. Diese LED Lampe kommt aus einem IKEA Lampen Set.
image
Hier schneide ich den Flaschenhals auseinander. Mit einer Halterung brachte ich den Teil des Flaschenhalses in Rotation und bekam durch diese Methode einen sauberen Schnitt mit dem Cutter Messer.
image
Anschließend noch in einer stylischen Farbe lackieren…
image
Die fertige Schaltung einsetzen und die LED Flächen ankleben.

Am Ende noch den fertigen Programmcode auf den ATMega326 bringen.

#include <Wire.h>

// I²C Adresse vom Beschleunigungssensor
#define AccelerometerAddress 0x38

// Byte Array in dem die Ergebnisse gespeichert werden
byte data[6];
// Ruft die XYZ Achsen Beschleunigung ab oder legt sie fest.
int axisX;
int axisY;
int axisZ;

// Beim Einschalten muss der Sensor Kalibriert werden.
// Der Sensor sollte sich in dem Moment nicht bewegen.

int axisX_offset;
int axisY_offset;
int axisZ_offset;

// Wird nach dem Kalibrieren auf False gesetzt.
boolean isFirstTime = true;

// Die Beschleunigung wird zusammengerechnet,
// durch 3 geteilt und dieser Variable gespeichert.
double gravitySum;

// Zeigt den maximalen berechneten Wert aus 'gravitySum'
int maxValue = 0;

// Ruft ab, ob die Lampen eingeschaltet
// oder ausgeschaltet werden.
boolean isHitting = false;

// An welchem Pin soll die LED
// ein oder ausgeschaltet werden.

int ledPin = 12;

void setup()
{
  // Die serielle Verbindung wird nur zum Ermitteln
  // des 'gravitySum' benötigt.
  Serial.begin(57600);
  // LED Pin zuweisen
  pinMode(ledPin, OUTPUT);
  // I²C Verbindung starten
  Wire.begin();
  // LED Pin zunächst ausschalten.
  digitalWrite(ledPin, LOW);
}

void loop()
{
  // Liest die Sensor Beschleunigungsdaten ein.
  readAcceleration();
 
  // per Byte Shifting den 10Bit Wert zusammenfügen
  axisX = (data[0] >> 1) | data[1] << 8;
  axisY = (data[2] >> 1) | data[3] << 8;
  axisZ = (data[4] >> 1) | data[5] << 8;
 
  // Wenn dies der erste Durchlauf ist
  // dann wird das Offset gesetzt.

  if(isFirstTime)
  {
    axisX_offset = axisX;
    axisY_offset = axisY;
    axisZ_offset = axisZ;
    isFirstTime = false;
  }
  else
  {
    // Abweichung runterrechnen
    axisX = axisX - axisX_offset;
    axisY = axisY - axisY_offset;
    axisZ = axisZ - axisZ_offset;
  }
 
  // Keine Gravitationsberechnung, nur einfaches
  // Zusammenrechnen, um einen Wert später zu erhalten
  // der nur bei Bewegung gemessen wurde.

  if(axisX < 0){ axisX = axisX * -1; }
  if(axisY < 0){ axisY = axisY * -1; }
  if(axisZ < 0){ axisZ = axisZ * -1; }

  gravitySum = axisX / 3 + axisY / 3 + axisZ / 3;
 
  // Ergebnisse ausgeben
  Serial.print("Axis X: ");
  Serial.print(axisX, DEC);
  Serial.print("\tAxis Y: ");
  Serial.print(axisY, DEC);
  Serial.print("\tAxis Z: ");
  Serial.print(axisZ, DEC);
 
  Serial.print("\tGravity: ");
  Serial.print((int)gravitySum, DEC);
 
 
// Der 'maxValue' zeigt den höchsten
  // berechneten Wert aus 'gravitySum'

  if(gravitySum > maxValue)
  {
    maxValue = gravitySum;
  }
 
 
// Maximalen Wert wiedergeben,
  // der später als Schwellwert verwendet werden kann
  Serial.print("\tMax Value: ");
  Serial.println(maxValue, DEC);
 
 
// Wenn der maxValue ermittelt wurde
  // kann der Wert zum Vergleich eingesetzt werden.
  // So soll erst ein Schaltvorgang gesetzt werden,
  // wenn der Schwellwert (hier 9000) erreicht wurde.
  if(gravitySum > 9000)
  {
    // Zustand ändern
    isHitting = !isHitting;
   
   // Einschalten, wenn die Lampe aus ist
    if(isHitting)
    {
      digitalWrite(ledPin, HIGH);
      Serial.println("AN");
    }
   
else
    {
      digitalWrite(ledPin, LOW);
      Serial.println("AUS");
    }
   
   
// Verzögerung zum Ausschwingen,
    // damit nicht gleich die Lampe
    // wieder ausgeschaltet wird.
    delay(1500);
  }
 
  delay(100);
}

// Liest den Beschleunigungssensor ein und schreibt das Ergebnis in ein Byte Array.
void readAcceleration()
{
  Wire.beginTransmission(AccelerometerAddress);
  Wire.write(0x02);
  Wire.endTransmission();
  Wire.requestFrom(AccelerometerAddress, 6);

  for(int i = 0; i < 6; i++)
  {
    data[i] = Wire.read();
  }
}

Mit einem 9V Block Akku lässt sich dies leider nicht lange betreiben, da die LEDs zusammen 1W Leistung verbrauchen. Ein 9V Block ist spätestens nach einer halben Stunde leer. Besser eignet sich hier ein Netzteil (oder eine Batterie mit mehr Kapazität). Hier noch ein kurzer Zusammenschnitt als Video.

Was vielleicht von Interesse sein könnte, sind die verwendeten Bauteile. Alternativ kann nach Bedarf das Aussehen bestimmt werden. Zwinkerndes Smiley

Materialliste:

  • 1 x Arduino Duemilanove (Geht auch mit anderen)
  • 1 x Beschleunigungssensor BMA020
  • 1 x Spannungsregler LM317
  • 1 x Quarz 16Mhz
  • Widerstände: 1 x 47 Ohm, 1 x 4,7kOhm, 1 x 10Ohm, 2 x 2,2kOhm
  • Transistoren: 1 x BC177A (PNP), 3 x BC547B (NPN)
  • 1x Potentiometer 500Ohm
  • 1x Streifenplatine
  • 1 x DIODER (Name des IKEA Produktes mit den LED Flächen)
  • 1 x Breadboard
  • 1 x Platine
  • 1 x 9V Block
  • eine Menge Kabel
  • 1 x Kunststoff Flasche

Donnerstag, 30. Mai 2013

Beschleunigungswerte aus dem Sensor umrechnen

Quadrocopter_47
Die Sensoren MPU6050 und BMA020

Es gibt zwei Varianten, wie der Winkel errechnet werden kann. Als erstes Beispiel nehmen wir für einen Winkel von 90° einen imaginären Messbereich von 0 bis 100, der die Y Achse darstellt.

image_thumb[2]
Visuelle Darstellung der Achsenausrichtung.

Dann könnte die Formel “(MaxWert / 90°) x Messwert = Winkel” lauten. Die Umsetzung ist relativ naheliegend und kann schnell im Programmcode geschrieben werden.

// Variable mit dem Messwert
int reading = 0;
// Ergebnis = (Maximaler Wert / 90°) * Messwert
double result = (100 / 90) * reading;

Messbereich von 0 bis 100

Je nach Sensor ergeben sich andere maximale Wert. Beim MPU6050 geht der Messbereich von 0 bis 65535 und in Abhängigkeit, welche Einstellung gesetzt wurde, ergibt sich der “MaxWert”. Wenn z.B. der Sensor auf 8G initialisiert wurde, dann muss der Wert durch 8 geteilt werden und erhält somit den MaxWert = 8192. Dieser Wert wird erreicht, wenn die Achse 1G misst.

// Variable mit dem Messwert
int reading = 0;
// Ergebnis = (Maximaler Wert / 90°) * Messwert
double result = (8192 / 90) * reading;

Messbereich von 0 bis 8192

Hier bildet sich allerdings ein konstanter Nachteil. Der “MaxWert” muss immer für verschiedene Messbereiche neu gesetzt werden.

Eine geschicktere Lösung sind die Formellösungen für die Berechnung eines Dreiecks. Da jeder in der Schule im Matheunterricht Geometrie hatte, erspare ich die Erklärung, wie ich zu dieser Formelaufstellung gekommen bin.

image
Verwendete Formel

Das sieht etwas wild aus und benötigt auch im Programmcode einige Zeilen mehr. Im vorigen Beispiel habe ich die restlichen 270° ausgelassen, da eine weitere Erläuterung nicht weiter sinnvoll erschien.

private static int GetAngle(int a, int b)
{
    if (a != 0 & b != 0)
    {
       
// Angewendete Formel zur berechnung des Winkels
        // Winkel = ArkusSin((a² + c² - b² / 2ac) * (360 / Pi))

        double qA = System.Math.Pow(a, 2);
        double qB = System.Math.Pow(b, 2);
        double qC = qA + qB;

        // Das Ergebnis das unter dem Bruch entsteht, führte zu einem Fehler,
        // wenn ich dies alles in ein Zeile geschrieben habe.

       double divided = (2 * a * System.Math.Sqrt(qC));
       double result = (System.Math.Acos((qA + qC - qB) / divided) * (180.0 / System.Math.PI));

       if (a > 0 & b < 0)
        {
    
// Wenn Z nach unten ausgerichtet ist und Y(X) nach links(oder rechts) gekippt ist
            //   |
            // -- --
            // x |
            // -90 bis -180

            return (90 - ((int)result)) * -1;
        }
        else if (a > 0 & b > 0)
        {
    
// Wenn Z nach unten ausgerichtet ist und Y(X) nach rechts(oder links) gekippt ist
            //   |
            // -- --
            //   | x
            // 0 bis -90

            return ((int)result) - 90;
        }
        else if (a < 0 & b < 0)
        {
    
// Wenn Z nach oben ausgerichtet ist und Y(X) nach links(oder rechts) gekippt ist
            // x |
            // -- --
            //   |
            // 90 bis 180

            return ((int)result) - 180;
        }
   
// Wenn Z nach oben ausgerichtet ist und Y(X) nach rechts(oder links) gekippt ist
        //   | x
        // -- --
        //   |
        // 0 bis 90

       return 180 - (int)result;
    }
    else if (a == 0 & b != 0)
    {
        if (b < 0)
        {
            return -90;
        }
       else
        {
           return 90;
        }
    }
    else if (a != 0 & b == 0)
    {
       
// Wenn jedoch Y 0 ist und Z mehr als 1
       if (a > 0)
        {
            return -90;
        }
    }
    return 0;
}

Methode um aus Z und X (oder Y) den Winkel Y (oder X) zu berechnen.

Die Methode nimmt zwei Werte an. Für den Integer ‘a’ wird der Wert von der Beschleunigungssensorachse Z übergeben, der Integer für ‘b’ benötigt den Wert von der Achse X oder Y. Z und X ergeben den Winkel Y. Für Z und Y kommt der Winkel X heraus. Bevor jedoch die Messwerte durch die Methode geschickt werden, muss festgestellt werden, dass ein negativer Wert abgebildet wird. Daher ist es sinnvoll, den Sensor Wert mit der Hälfte des Maximalen Wertes zu verschieben.

private static int GetShiftValue(int value)
{
    if (value > 32768 && value < 65536)
    {
        value = 65536 - value;
    }
    else
    {
        value = 0 - value;
    }
    return value;
}

Mit der Methode wird aus 0 bis 65535, ein Bereich von –32767 bis +32767

Naja, hier muss dann doch am Ende der Maximale Wert gesetzt werden, dabei ist die Einstellung des Sensors wiederum egal. Bei dem Windows Phone 8 ist diese Methode nicht erforderlich.

Quadrocopter_46
Test auf dem Windows Phone 8 (Lumia 820)

Mit dieser Methode können die Daten von verschiedenen Sensoren genutzt werden, ohne dass jedes mal vorher ein Maximal Wert ermittelt und gesetzt werden muss.

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

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