Mein Paket… …ein 3-Achsen Beschleunigungssensor BMA 180 Bosch Sensortec

Heute, kam mein Paket…

…mit einem 3-Achsen Beschleunigungssensor auf einem Breakout Board an. Dieses hatte ich über einen ebay-Shop bestellt.

(BMA180 Triple Axis Acceleration Sensor (SKU 00100-124) für 12,58 € inkl. Versand)

CIMG3507Das Breakout Board enthält einen 3-Achsen Beschleunigungssensor BMA 180 von Bosch Sensortec mit digitalem Ausgang. Es gibt auch ähnliche Sensoren von Freescale wie z. B. den MMA7260 oder auch von Analog Devices aus der ADXL3xx Familie. Diese sind allerdings zum Teil deutlich teurer, während der BMA180 inzwischen relativ preiswert in diversen Shops zu erhalten ist. Hintergrund ist vermutlich, dass Bosch Sensortec den Chip bereits in 2011 abgekündigt hat und noch große Restmengen am Markt verfügbar sind.

Da die Versorgungsspannung des BMA180 Sensorchips nur max. 3,6V beträgt, ist es recht praktisch, dass sich auf diesem Board auch gleich noch ein Spannungsregler und Levelshifter befinden. So soll das Board gefahrlos an 3,3V und 5V betrieben werden können. Die Kommunikation des ICs kann grundsätzlich per SPI oder I2C-Protokoll erfolgen. Auf diesem Breakout Board hier wird allerdings nur I2C unterstützt. Die auf dem Board herausgeführten I2C Pins werden intern übrigens sowohl für den SPI wie auch den I2C Mode geteilt. Ist der CSB-Pin des Chips LOW, so wird er im SPI-Mode angesprochen, bei HIGH im I2C-Mode! Durch die entsprechende Vorverdrahtung auf diesem Breakout Board lässt sich hier allerdings nur der I2C-Mode verwenden.

  • SPI-Mode                  I2C-Mode
  • —————————————————
  • SDI  Input                  SDA Bidirectional
  • SDO Output              ADDR Address Bit/Input
  • SCK Input                  SCL Input
  • CSB Chip Select       I2C Mode Select/Input (HIGH)

Wahlweise muss nun entweder noch die beigelegte Stiftleiste eingelötet werden oder man lötet hier die Anschlussdrähte vom Host direkt an. Ich habe mich für die Stiftleiste entschieden, da ich das Modul so erst einmal besser auf einem Steckbrett in Augenschein nehmen kann. Es gibt allerdings erst noch einige Hürden zu nehmen:

  1. Der Verkäuferlink zu dem Arduino Beispielcode führte leider ins Leere.
  2. Eine Dokumentation bietet der Anbieter auch auf Anfrage nicht an.
  3. Der qualitativ extrem schlechte Aufdruck lässt eine Zuordnung der herausgeführten Anschlüsse leider auch nicht zu.

Nachfolgend die von mir recherchierte Pinbelegung bei Blick von oben auf die Bestückungsseite mit nach Nord ausgerichteter Stiftleiste. Zählweise ist von links nach rechts.

Pinbelegung der Stiftleiste

INT | VCC-3,3V | SDA | SCLK (SCK) | GND | VCC-5,0V

Die Vorteile des Sensors

Mit einem digitalen Butterworth Tiefpassfilter 2. Ordnung, bereits direkt unterstützt durch den Mikroelektromechanischen MEMS-Chip BMA180, kann hier das Signal im Bereich von 10Hz bis 1200Hz in Schritten von10Hz, 20Hz, 40Hz, 75Hz, 150Hz, 300Hz, 600Hz und 1200Hz gleich recht elegant vorkonditioniert werden. ButterworthfilterWeiterhin stehen ein Hochpassfilter mit einer Grenzfrequenz von 1Hz sowie ein Bandpassfilter zwischen 0,2Hz bis 300Hz zur Verfügung. MEMS sind übrigens kleine elektronische Elemente, die sowohl Logikelemente als auch mikromechanische Strukturen in einem Chip vereinen. So können sie mechanische und elektrische Informationen verarbeiten.

Umfangreiche optionale Mess- und Kalibrieroptionen sowie programmierbare Interrupts und verschiedene Power Modi runden das Ganze ab. Damit können sowohl rein statische als auch dynamische Beschleunigungen mit dem Board erfasst werden.

Die technischen Daten des Breakout Boards in Kurzform:

  • Vcc:                            3,0V – 5,0V
  • Low Power:                Der BMA180 Chip ist mit 650uA angegeben
  • Betriebstemperatur:   -40°C – + 85°C Chip, der Rest vermutlich nur 0°C – + 70°C
  • Messbereiche:           ±1g, 1.5g, 2g, 3g, 4g, 8g und 16g
  • Anschlussbelegung:  INT, VCC 3,3V, SDA, SCLK (SCK), GND, VCC 5,0V
  • Interface:                    I2C 2 Adressen wählbar, hier 0x40
  • Auflösung:                  0,5mg
  • Ausgangssignal:        12 oder 14 bit
  • Speicher:                   256 bit EEPROM für Kalibrierungs- und Anwenderdaten
  • Schnittstelle:              0.1 Zoll, 2.54mm, 6-polig einreihig
  • Modulgröße:               18 mm × 17mm
  • Gewicht:                    ca. 1,6gr

Der BMA180 Chip:

Ein ausführliches Datenblatt kann hier bei Bedarf heruntergeladen werden.

BMA180PinningPin    Name      Funktion

  • 1      DNC        Frei lassen
  • 2      VDD        Analog UB
  • 3      VSS        Masse
  • 4      INT          Interrupt
  • 5      CSB        SPI Chip Select
  • 6      DNC        Frei lassen
  • 7      SCK        Serial Clock
  • 8      SDO       Serial Data Out
  • 9      SDI         Serial Data In
  • 10     VDDIO   Digital UB
  • 11+12 DNC    Frei lassen

Sicht von oben – DNC bedeutet: Do Not Connect (internally connected to VSS)

Der Schaltungsaufbau mit I2C Ansteuerung

CIMG3512Arduino Pin              BMA180 Breakout

  • ———————————————-
  • GND        <->          GND
  • 5V            <->          5V
  • A5            <->          SCK
  • A4            <->         SDI (SDA)

Die sonst üblichen I2C Pullup Widerstände an A4 und A5 sind nicht erforderlich. Soweit ich verstanden habe, werden die internen „Weak Pullup Widerstände des Arduino Boards“ durch die Wire Bibliothek eingeschaltet. Dieser Versuchsaufbau funktioniert sowohl mit vom Arduino gespeisten 3,3V als auch mit 5V.

Das Testprogramm

Im Internet habe ich einen gut strukturierten Beispielsketch für die Arduino 1.0x IDE gefunden, der keine spezielle Bibliothek benötigt. Mit diesem Testprogramm lassen sich Daten aus dem Beschleunigungssensor einwandfrei auslesen. Auf Basis des obigen Sketches habe ich mir nach Studium des Datenblattes den Code für meine Zwecke noch etwas angepasst und versucht diesen nochmals etwas präziser zu dokumentieren. Auf Seite 22 der Bosch Sensortec Dokumentation ist eine Übersicht aller vorhandenen Register zu finden. Beim hantieren damit ist jedoch Vorsicht geboten, da es auch möglich ist die Kalibrierungsdaten des Sensors versehentlich zu überschreiben. Nachfolgend sind einige der interessanten Funktionen aufgelistet:

Einstellung des Messbereiches RANGE über Register 0x35 mit Bits 3..1

Messbereich
RANGE
Max. Beschleunigung
(+/-g)
ADC Auflösung (mg/LSB)
000 1 0,13
001 1,5 0,19
010 2 0,25
011 3 0,38
100 4 0,50
101 8 0,99
110 16 1,98
111 Nicht erlaubt Nicht erlaubt

Einstellung der Filterbandbreite über das Register 0x20 mit den Bits 7..4

Bandbreite BW Bandbreite in Hz
0000 10
0001 20
0010 40
0011 75
0100 150
0101 300
0110 600
0111 1200
1000 Hochpass 1Hz
1001 Bandpass 0,2Hz..300Hz
1010..1111 Nicht erlaubt

Auslesen der Temperatur über das Register 0x08 mit den Bits 7..0

Die Auflösung beträgt 0,5°/LSB. -40°C werden als 0x80 ausgegeben. Der typische Wert bei 25°C sind binär 00000010 im 2er-Komplement.

Hier nun der derzeitige Stand des Testsketches:

/**********************************************************************************************************/
/* BMA180 triple axis accelerometer I2C test code 
 * Displays x, y, z acceleration in 2g mode
 * 
 * Origin Author:        www.geeetech.com
 * Modified by:          Olaf Meier
 *                       http://Arduino-Hannover.de
 *                       http://electronicfreakblog.wordpress.com/
 *
 *
 * Hardware connection:  A4 to SDI   I2C Data
 *                       A5 to SCK   I2C Clock
 *                       
 * 
 * ToDo:                 Calculate temperature in °C
 *                       Spent some time for sensor autocalibration during setup
 * 
 */
/**********************************************************************************************************/
/*
 Example of output:     x=0.01g,y=-0.01g,z=1.01g
 *                                 x=0.01g,y=0.00g,z=1.00g
 *                                 x=0.02g,y=-0.00g,z=1.00g
 *
 *
 */
/**********************************************************************************************************/
/**********************************************************************************************************/
/***  Declaration of global constants and initialization of variables. Add includes.  ***/
/**********************************************************************************************************/
/***  Software release and date  ***/
const char* author                =  "Olaf Meier";
const char* revision              =  "R.0.6";
const char* date                  =  "2013/09/11";

#if ARDUINO < 100                                  // Include libraries IDE version depending
#include <WProgram.h>                              // Add other libraries on demand as requested
#else
#include <Arduino.h>                               // Needed when working with libraries
#endif
#include <Wire.h>                                  // Include I2C library

/***  Declare constants and variables for the serial monitor  ***/
int debug                              =  1;       // DEBUG counter; if set to 1, will write values back via serial
const unsigned int baudRate            =  9600;    // Baud rate for the serial monitor

/***  Declare constants and variables for the BMA180 test code  ***/
const byte BMA180                      =  0x40;    // Address of the BMA180 device
/***  All registers are 8 bit. Bit MSB 7..0 LSB  ***/
const byte RESET                       =  0x10;    // Register for soft reset. Value 0xB6
const byte PWR                         =  0x0D;    // Register for power mode. Wake up. 
const byte BW                          =  0X20;    // Register for bandwidth, 4 bits for bw 7..4, tcs 3..0
const byte RANGE                       =  0X35;    // Register for range. Bits 3..1
const byte DATA                        =  0x02;    // Register for updated x, y, z data
const byte CHIP_ID                     =  0x00;    // Register for the chip ID. 3 bits 2..0
byte chipID[1];                                    // Value of register
const byte VERSION                     =  0x01;    // Register for version. 4 bit 3..0
byte chipVersion[1];                               // Value of register
const byte CHIPTEMPREGISTER            =  0x08;    // Temperature register, value is 2's complement
byte chipTemp[1];                                  // Temperature is 8-bit value. 

/***  Manual calibration values  ***/
const int offx = 31;                               // Offset x-achsis
const int offy = 47;                               // Offset y-achsis   
const int offz = -23;                              // Offset z-achsis 
/**********************************************************************************************************/
/**********************************************************************************************************/
void setup() {                                     // Function Setup
  /***  Optional Debug routine via serial monitor  ***/
  if (debug) {                                     // If we want to see some values for debugging in general...
    /***  Start class Serial with function/method begin(9600)  ***/
    /***  Instance variable .dot operator. method  ***/
    Serial.begin(baudRate);                        // ...set up the serial monitor
    Serial.println("Debugging activated");
  }                                                // End of debug loop
  /***  Show software release  ***/
  Serial.println();
  Serial.print(author);
  Serial.print("\t");
  Serial.print(revision);                         
  Serial.print("\t");
  Serial.println(date);  
  Serial.println();
  /**********************************************************************************************************/
  Wire.begin();                                    // Start class wire with method begin()
  Serial.println("Initializing BMA180 sensor");
  Serial.println(); 
  accelerometerInit();                             // Function to init sensor BMA180
  Serial.println("BMA180 sensor has been initialized");  
  Serial.println();
  readFrom(BMA180, CHIP_ID, 1, chipID);            // Read the chip id             
  readFrom(BMA180, VERSION, 1, chipVersion);       // Read the version number
  readFrom(BMA180, CHIPTEMPREGISTER, 1, chipTemp); // Read the register value for temperature

  Serial.print("Chip ID: ");
  Serial.print(chipID[0]);
  Serial.print("\t");                              // Insert a tab for better readability
  Serial.print("Version: ");
  Serial.println(chipVersion[0]);
  Serial.println();
  Serial.print("2'S binary value of temperature register: ");
  Serial.println(chipTemp[0], BIN);
  Serial.println();
}                                                  // End of void setup() loop
/**********************************************************************************************************/
/**********************************************************************************************************/
void loop() {                                      // Function Loop

  /***  Optional Debug routine via serial monitor  ***/
  if (debug) {                                     // If TRUE 
    debug += 1;                                    // Increment the debug counter
    if (debug > 100)                               // Print every 1... loops
    {
      debug = 1;                                   // Reset the counter
      /***  Display the debug values  **/
      /*
      Serial.print("abc ");
       Serial.println(variable);                   // Put in here your debug values
       */
    }                                              // End of if debug() > x

  }                                                // End of if debug()
  /***  End of optional Debug routine via serial monitor  ***/

  accelerometerRead();                             // Function to read data
  delay(1000);                                     // Slow down output to serial monitor
}                                                  // End of void loop()
/**********************************************************************************************************/
/**********************************************************************************************************/
/***  Function to initialize accelerometer sensor  ***/
void accelerometerInit()                           // Function to initialize the sensor
{ 
  byte temp[1];
  byte temp1;
  writeTo(BMA180, RESET, 0xB6);                    // Soft reset with binary value b10110110
  writeTo(BMA180, PWR, 0x10);                      // Wake up mode with binary value b00010000

  readFrom(BMA180, BW,1,temp);                     // 
  temp1 = temp[0] & 0x0F;                          // Mask bit 3..0: 0b00001111 
  temp1 = temp1 | 0b0001;                          // Default 0b1000 OR 0b0001 = 0b1001 = band pass 0,2Hz - 300Hz
  writeTo(BMA180, BW, temp1);   

  readFrom(BMA180, RANGE, 1 ,temp);                // Range +/- 2g (Default range, is calibrated ex works)
  temp1 = (temp[0] & 0xF1) | 0x04;
  writeTo(BMA180, RANGE, temp1);
}
/**********************************************************************************************************/
/***   Function to read data of the 3 axis, each one is 14 bits. Display data to serial monitor  ***/ 
void accelerometerRead() 
{ 
  int n = 6;                                       // Loop value n to read 6 registers 
  byte result[5];
  readFrom(BMA180, DATA, n , result);

  int x = (( result[0] | result[1] << 8) >>2 )+offx ;
  float x1 = x / 4096.0;
  Serial.print("x=");
  Serial.print(x1);
  Serial.print("g"); 

  int y = (( result[2] | result[3] << 8) >> 2)+offy;
  float y1 = y / 4096.0;
  Serial.print(", y=");
  Serial.print(y1);
  Serial.print("g"); 

  int z = (( result[4] | result[5] << 8) >> 2)+offz;
  float z1 = z / 4096.0;
  Serial.print(", z=");
  Serial.print(z1);
  Serial.println("g"); 
}
/**********************************************************************************************************/
/***  Function to write values to address register of the BMA180 accelerometer sensor  ***/
void writeTo(int DEVICE, byte address, byte val) 
{
  Wire.beginTransmission(DEVICE);                  // Start transmission to the sensor
  Wire.write(address);                             // Send register address
  Wire.write(val);                                 // Send value to write
  Wire.endTransmission();                          // End transmisson
}
/**********************************************************************************************************/
/***  Function to read num bytes starting from address register into buffer array  ***/
void readFrom(int DEVICE, byte address, int num, byte buff[])
{
  Wire.beginTransmission(DEVICE);                  // Start transmission to the sensor
  Wire.write(address);                             // Send register address
  Wire.endTransmission();                          // End transmission

  Wire.beginTransmission(DEVICE);                  // Start transmission to sensor
  Wire.requestFrom(DEVICE,num);                    // Request 6 bits from sensor

  int i = 0;
  while(Wire.available())                          // Sensor may be abnormal
  {
    buff[i] = Wire.read();                         // Receive a byte
    i++;
  }
  Wire.endTransmission();                          // End transmission
}
/**********************************************************************************************************/
/**********************************************************************************************************/

Update 2013_09_27

Obiger Sketch sollte sowohl mit einem Arduino Uno wie auch mit einem Duemilanove funktionieren. Mit Hubbies Unterstützung nun noch ein Update des Sketches, das hoffentlich überall funktioniert. Der Download kann von hier erfolgen:arduino-icon

Meine Zusammenfassung :

Bauteil:             BMA180 Triple Axis Acceleration Sensor
(SKU 00100-124)
Lieferant :          ebay: http://www.ebay.de/itm/170846446797
Verkäufer:          monkeyemerald
Preis:                12,58 €
Lieferzeit:          etwa 3 Wochen
Versandkosten: inklusive
Sonstiges:         der Verkäufer akzeptiert sogar die Rückgabe des Artikels innerhalb von 14 Tagen nach Erhalt. Der Käufer trägt allerdings die Versandkosten!

Agenda zur Bewertung:

*=Ganz Mies      **=Mies      ***=Akzeptabel      ****=Gut      *****=Sehr Gut

Verkäufer:                                         ****

Produkt:                                           *****

Nach Klärung der offenen Fragen zum Sensor via Internet und eigener Versuche, ist das Produkt absolut empfehlenswert. In dem Preissegment dürfte es derzeit nicht viele Sensoren mit ähnlich guten technischen Daten geben. Daher 5 von 5 Sternen für das Produkt. Dem Verkäufer gebe ich nur 4 von 5 Sternen, da er die notwendigen Informationen zur Erstinbetriebnahme in seinem Shop nicht zur Verfügung gestellt hat und auch auf Anfrage keine Reaktion gezeigt hat. Die Kaufabwicklung war jedoch völlig reibungslos.

Olaf Meier

Arduino Hannover       http://Arduino-Hannover.de

*Info: In diesem Beitrag verweisen orangefarbende Links auf Affiliates.