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)
Das 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:
- Der Verkäuferlink zu dem Arduino Beispielcode führte leider ins Leere.
- Eine Dokumentation bietet der Anbieter auch auf Anfrage nicht an.
- 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. Weiterhin 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.
- 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
- ———————————————-
- 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:
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
@arduino_h Viel Erfolg! Und danke für die gute Produktbewertung 🙂
Danke für den Kommentar 🙂
Gibt es neue interessante Sensoren von Bosch Sensortec, können wir gern einmal einen Blick drauf werfen.
RT @arduino_h: Mein Paket… … ein 3-Achsen Beschleunigungssensor BMA 180 Bosch Sensortec: Heute, kam mein Paket…
http://t.co/TtdnfE7Wpd
bei mir wird nur einmal gemessen und dann ist ruhe im protokoll
Hallo morob65,
der Sketch hat ein Memory-Leck :
statt byte result[5]
muss es byte result[6]
heissen
vielleicht ist das die Ursache für den Hänger.
Hubbie
Danke für den Hinweis. Am Wochenende werde ich den Testaufbau nochmals aufbauen und das prüfen.
Olaf
joo das wars
Auch mit verschiedenen Boards wie Uno und Duemilanove funtioniert der im obigen Beitrag erwähnte Sketch bei mir. Wie dem aber auch sei, mit Hubbies Support gibt es nun ein Update des Sketches. Einfach den Arduino Link im Kommentar des Updates anclicken. Läuft dann nun hoffentlich in jeder Umgebung.
Hallo,
Habe mir ebenfalls den bma180 besorgt, seinen Nachfolger bma280 finde ich leider nicht bereits auf einem Board verlötet.
Meine Eindrücke sind ähnlich wie hier geschildert, der Artikel half mir teilweise, allein kann ich selbst bei „low noise“, egal bei welchen Datenrate auch fest Eingespannt ohne Bewegung immer Werte zwischen +5 bis -3 mg ablesen.
Ist das wohl ein Fehler meines Chips, oder habt ihr ähnliche Erfahrungen (laut Datenblatt 150üg/hz^(1/2))?
Die Wire.beginTransmission() und Wire.endTransmission() sollten nur mit Wire.write() verwendet werden. Sie werden nicht für Wire.requestFrom() benötigt.