mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit dem BMA180 Beschleunigungssensor


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe hier einen BMA180 von Bosch. Das ganze wird über I2C an einem 
Atmega328(Arduino) angesteuert. Mein Problem ist, das er bei der 
Initialisierung abbricht und nicht weiter macht. Verkabelt ist alles wie 
im Datenblatt vorgesehen. Einziger Unterschied ist, dass ich den INT-Pin 
freigelassen habe.
Datenblatt: http://www.spezial.cz/pdf/BST-BMA180-DS000-03.pdf

Sieht jemand meinen Fehler? Normalerweise sehen mehrere Augen mehr als 
zwei ;)

Das hier ist mein Code:
#include <Wire.h>

//#define address 0x40
int address = 64;

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

void loop()
{
  Wire.beginTransmission(address);
  Serial.println("Beginne zu Addresse: " + address);
  Wire.send(0);
  Serial.println("Sende eine 0");
  Wire.endTransmission();
  Serial.println("Beende Transmission");
  Wire.requestFrom(address, 1);
  Serial.println("Frage nach einem Byte von der Adresse");
  while(Wire.available() == 0);
  Serial.println("While Schleife übersprungen - lesen der Daten");
  int c = Wire.receive();
  Serial.println("Ausgabe");
  Serial.println("-----------------");
  Serial.println(c);
  delay(500);
}
  
void readId()
{
  int temp, result;

  Wire.beginTransmission(address);
  Wire.send(0x00);
  Wire.requestFrom(address, 1);
  while(Wire.available())
  {
    temp = Wire.receive();
  }
  Serial.print("Id = ");
  Serial.println(temp);
  result = Wire.endTransmission();
  Serial.println("Result: " + result);
  delay(10);
} 

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist noch kurz mein Schaltplan (beachtet da einfach nur die 
Analog-Pins):
http://centralnexus.com/seismograph/bma180-wiring.png

Im Datenblatt steht, dass I2C von Anfang an aktiviert ist. Unter 7.12.3 
steht irgendwas von der ID und auf Seite 54 (was mir sinnvoller 
erscheint). Liegt da vielleicht mein Fehler? Habe ich die falsche ID 
benutzt?

Der Code oben ist in echt natürlich etwas länger, aber ich habe als Test 
einfach nur die ID auslesen wollen.

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ein main mit Endlosschleife wäre die Grundvoraussetzung, damit 
überhaupts irgendwas funktioniert ...

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ein C Dialekt. Eben in dieser Arduino Sprache. Er gibt mir auch 
was aus, aber er bleibt halt bei "Sende eine 0" stehen.

Autor: Tipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meiner Erfahrung nach ist CS für eine Kommunikation mit dem BMA180 
unverzichbar. Im Schaltplan ist er ja mit VCC verbunden.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie bindet man den CS-Pin in den Code ein? Die Arduino Library geht 
ja nur von SDA und SCL aus. Das einzige was mir logisch erscheinen würde 
wäre wenn man bei Wire.beginn(CS-Pin) einsetzen würde.

Autor: Juergen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Martin,
in Deinem Schaltbild dast Du keine Pullup-Widerstände eingezeichnet.
Die werden auf jeden Fall benötigt, sonst wird es nicht funktionieren.

Du musst auch noch das RW-bit in der Slave-Adresse auf 1 setzen, sonst
mein der Chip Du möchstest schreiben. Steht im Datenblatt unter 8.3.5.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meinst du, dass bei Wire.send(0x00) --> Wire.send(0x01) hin muss? Ich 
glaub ich versteh nicht ganz genau was im Datenblatt steht.
Wenn man die Verbindung aufgebaut hat, soll man ein Byte schicken, dass 
entweder 1 oder 0 ist. Dann kann man entweder lesen oder schreiben. Nur 
wieso funktioniert dann mein Code nicht?

PullUp Widerstände habe ich jetzt eingebaut. Allerdings hinter dem 
Pegelwandler (also zum Arduino hin. Nicht auf der "Sensorseite"). Sind 
beides 10k Ohm.
#include <Wire.h>

int temp;
int result;

#define address 0x40

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

void loop()
{
  Wire.beginTransmission(address);
  Serial.println("Beginne zu Addresse");
  Wire.send(0x01);
  Serial.println("Sende eine 1 in Bytes");
  Wire.requestFrom(address, 1);
  Serial.println("Verbingund nicht abgebrochen und Probebyte abgefragt");
  while(Wire.available())
  {
    temp = Wire.receive();
    Serial.println("Temp gelesen");
  }
  Serial.print("Id = ");
  Serial.println(temp);
  result = Wire.endTransmission();
  Serial.println("Result: " + result);
  delay(10);
}

void readID(){
  Wire.beginTransmission(address);
  Serial.println("Beginne zu Addresse");
  Wire.send(0);
  Serial.println("Sende eine 0");
  Wire.endTransmission();
  Serial.println("Beende Transmission");
  Wire.requestFrom(address, 1);
  Serial.println("Frage nach einem Byte von der Adresse");
  while(Wire.available() == 0);
  Serial.println("While Schleife übersprungen - lesen der Daten");
  int c = Wire.receive();
  Serial.println("Ausgabe");
  Serial.println("-----------------");
  Serial.println(c);
  delay(10);
}

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In diesem Forum (http://arduino.cc/forum/index.php/topic,55373.15.html) 
habe ich einen I2C Scanner gefunden. Interessant ist, dass ich ohne das 
Protoshield mit dem Sensor darauf nur die Meldung bekomme, dass er jetzt 
scannt, dann aber nichts weiteres mehr. Ohne Shield geht er einmal alle 
Addressen durch und gibt mir am Ende auch das "done" aus. Habt ihr dafür 
eine Erklärung?
/**
 * I2CScanner.pde -- I2C bus scanner for Arduino
 *
 * 2009, Tod E. Kurt, http://todbot.com/blog/
 *
 */

#include "Wire.h"
extern "C" { 
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}

// Scan the I2C bus between addresses from_addr and to_addr.
// On each address, call the callback function with the address and result.
// If result==0, address was found, otherwise, address wasn't found
// (can use result to potentially get other status on the I2C bus, see twi.c)
// Assumes Wire.begin() has already been called

void scanI2CBus(byte from_addr, byte to_addr, 
                void(*callback)(byte address, byte result) ) 
{
  byte rc;
  byte data = 0; // not used, just an address to feed to twi_writeTo()
  
  for( byte addr = from_addr; addr <= to_addr; addr++ ) {
    rc = twi_writeTo(addr, &data, 0, 1);
    callback( addr, rc );
  }
}

// Called when address is found in scanI2CBus()
// Feel free to change this as needed
// (like adding I2C comm code to figure out what kind of I2C device is there)
void scanFunc( byte addr, byte result ) {
  Serial.print("addr: ");
  Serial.print(addr,HEX);
  Serial.print( (result==0) ? " found!":"       ");
  Serial.print( (addr%4) ? "\t":"\n");
}


byte start_address = 01;
byte end_address = 127;

// standard Arduino setup()
void setup()
{
    Wire.begin();

    Serial.begin(19200);
    Serial.println("\nI2CScanner ready!");

    Serial.print("starting scanning of I2C bus from ");
    Serial.print(start_address,HEX);
    Serial.print(" to ");
    Serial.print(end_address,HEX);
    Serial.println("...");

    // start the scan, will call "scanFunc()" on result from each address
    scanI2CBus( start_address, end_address, scanFunc );

    Serial.println("\ndone");
}

// standard Arduino loop()
void loop() 
{
    // Nothing to do here, so we'll just blink the built-in LED
    digitalWrite(13,HIGH);
    delay(300);
    digitalWrite(13,LOW);
    delay(300);
}

Autor: Juergen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Martin,
das mit dem RW-Bit macht wohl die wire Bibliothek ganz automatisch. Ich 
verwende hier die SPI-Schnittstelle zur Kommunikation mit einem BMA180, 
da ist das dann wichtig.

Zur Hardware:
Der BMA180 hat im I2C-Modus open drain Ausgänge, soll heissen die 
Ausgänge können vom Chip nur auf Masse gezogen werden. Genauso macht es 
auch der Arduino auf der anderen Seite. Deshalb benötigtst Du die 
Pullup-Widerstände.
Die Kommunikation ist bidirektional. Wo hast Du da einen Pegelwandler 
drin ?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

In der SCL und SDA Leitung ist der Wandler drin (Nach diesem Thread: 
http://arduino.cc/forum/index.php/topic,22309.0.html). Der BMA180 läuft 
ja mit 3,3V und da kommt das mit den 5V Pegeln nicht so gut.

Kannst du mir mal ein Bild von deiner Schaltung schicken? Würde notfalls 
das ganze auch mit SPI ansprechen.

Autor: Juergen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also,
ich hab mal die Schaltung nach Deinem Link genommen:
http://codeyoung.blogspot.com/2009/11/adxl345-acce...

Siehe auch angehängtes Bild. Als Programm hab ich Deinen etwas 
abgespeckten Code genommen:
#include <Wire.h>

//#define address 0x40
int address = 64;

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

void loop()
{
  int temp, result;

  Wire.beginTransmission(address);
  Wire.send(0x00);
  Wire.requestFrom(address, 1);
  while(Wire.available())
  {
    temp = Wire.receive();
  }
  Serial.print("Id = ");
  Serial.println(temp);
  result = Wire.endTransmission();
  Serial.println("Result: " + result);
  delay(1000);
}

Damit funkioniert es problemlos:
  Id = 3
  Result: 

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ja komisch. Mir wurde immer gesagt, dass man einen Pegelwandler 
zwischen schalten muss. Hast du noch irgendwelche "Einstellungen" 
vorgenommen um den Pegel runter zu bringen, oder ist das gar nicht 
nötig?

Autor: Martin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal schnell von meinem Aufbau ein Foto gemacht..

Autor: Juergen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim I2C-Bus ist die Datenkommunikation bidirektional, also müssen
sowohl der BMA180 als auch der Arduino auf der gleichen Leitung Daten 
senden können. Damit es keinen elektrischen Kurzschluß gibt sind die 
Ausgänge als open drain ausgeführt, d.h. sie können von den Chips nur 
auf Masse gezogen werden. Das High-Signal wird über die 
Pullup-Widerstände erzeugt, wenn kein Chip die Leitung auf Masse zieht.

Da der BMA180 und der Arduino unterschiedliche Betriebsspannungen 
verwenden kann es zwei Probleme geben:
1. Du programmierst den Arduino falsch und er gibt +5V auf die Pins. 
Passiert nur wenn Du explizit die Pins als Ausgang programmierst.
2. Der Arduino erkennt die 3.3V nicht als High-Pegel. Laut Datenblatt 
benötigt er mindestens 0.6*VCC = 3V am Eingang. Passt also.

Wenn Du ganz auf Nummer sicher gehen willst dann kannst Du den 
Pegelwandler und SPI verwenden.
Das geht dann so etwa (Codefragment):
/*
 Arduino       BMA 180
 D11 (MOSI) -> SDI
 D12 (MISO) <- SDO
 D13 (SCK)  -> SCK
 D9         -> CS
 */
#include <SPI.h>

int u2s(int u) {
  if ( u > 0x1fff)
    return -((~u & 0x1fff)+1);
  else
    return u;  
} 

void setup() {
  pinMode (CSPin, OUTPUT);
  SPI.setDataMode(3);
  SPI.setBitOrder(MSBFIRST);
  SPI.begin();
}

void loop() {
  int rc, acc_x, acc_y, acc_z; 

  digitalWrite(CSPin,LOW); 
  SPI.transfer(0x82);
  rc = SPI.transfer(0x00); 
  acc_x = (rc & 0xfc) >> 2;
  rc = SPI.transfer(0x00);  
  acc_x = acc_x | ( (rc & 0xff) << 6);
  acc_x = u2s(acc_x);
  digitalWrite(CSPin,HIGH); 
}

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ok. Wusst ich noch nicht, aber man lernt ja dazu.

Auch ohne Pegelwandler kann ich nichts auslesen. Er bleibt immer noch 
bei "Sende eine 1" hängen. Egal welchen Code ich einsetze, ich bekomme 
keine Rückgabe. Kann es sein, dass der Chip kaputt ist?

Autor: Juergen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist noch keiner kaputt gegangen.
Hast Du den BMA180 richtig angeschlossen ?

Arduino  BMA180
A5    <-> SCK + Pullup 10K auf 3V3
A4    <-> SDI + Pullup 10K auf 3V3
3V3   <-> VIO
3V3   <-> VDD
3V3   <-> CS
GND   <-> SDO
GND   <-> GND

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau so. Hab auch nochmal alles auf Wackelkontakte überprüft. Nix. 
Irgendwie ist das ja schon etwas komisch..

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einen Fehler habe ich jetzt schon gefunden. Am GND Pin war eine kalte 
Lötstelle. Hab jetzt schnell noch alle Pins nachgelötet und ich denke, 
dass jetzt die Hardware fehlerlos ist.

Autor: Bruno Hoegger (bruno_h83)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Möchte einen BMA180 Beschleunigungssensor (Sparkfun breakout board)  mit 
einem Arduino Uno betreiben! Da ich gerne mehr über das Messen mit dem 
BMA180 Beschleunigungssensor wissen möchte ... die Test- Sketches die in 
diesem Forum erschienen sind laufen bei mir mit dem I2C-Interface ... 
zur Zeit ohne Pegelwandler ... nach Angaben von Jürgen ... ohne Problem 
! Kann mir jemand ein Arduino Sketch geben, womit ich alle drei Achsen 
mit dem Arduino Uno auslesen kann  ... und mit dem genannten ACC-Sensor 
etwas üben kann ... vielen Dank zum voraus ... !

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.