Forum: Mikrocontroller und Digitale Elektronik Problem mit dem BMA180 Beschleunigungssensor


von Martin (Gast)


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:
1
#include <Wire.h>
2
3
//#define address 0x40
4
int address = 64;
5
6
void setup()
7
{
8
  Wire.begin();
9
  Serial.begin(9600);
10
  delay(2000);
11
}
12
13
void loop()
14
{
15
  Wire.beginTransmission(address);
16
  Serial.println("Beginne zu Addresse: " + address);
17
  Wire.send(0);
18
  Serial.println("Sende eine 0");
19
  Wire.endTransmission();
20
  Serial.println("Beende Transmission");
21
  Wire.requestFrom(address, 1);
22
  Serial.println("Frage nach einem Byte von der Adresse");
23
  while(Wire.available() == 0);
24
  Serial.println("While Schleife übersprungen - lesen der Daten");
25
  int c = Wire.receive();
26
  Serial.println("Ausgabe");
27
  Serial.println("-----------------");
28
  Serial.println(c);
29
  delay(500);
30
}
31
  
32
void readId()
33
{
34
  int temp, result;
35
36
  Wire.beginTransmission(address);
37
  Wire.send(0x00);
38
  Wire.requestFrom(address, 1);
39
  while(Wire.available())
40
  {
41
    temp = Wire.receive();
42
  }
43
  Serial.print("Id = ");
44
  Serial.println(temp);
45
  result = Wire.endTransmission();
46
  Serial.println("Result: " + result);
47
  delay(10);
48
}

von Martin (Gast)


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.

von Lehrmann M. (ubimbo)


Lesenswert?

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

von Martin (Gast)


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.

von Tipp (Gast)


Lesenswert?

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

von Martin (Gast)


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.

von Juergen (Gast)


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.

von Martin (Gast)


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.
1
#include <Wire.h>
2
3
int temp;
4
int result;
5
6
#define address 0x40
7
8
void setup()
9
{
10
  Wire.begin();
11
  Serial.begin(9600);
12
  delay(2000);
13
}
14
15
void loop()
16
{
17
  Wire.beginTransmission(address);
18
  Serial.println("Beginne zu Addresse");
19
  Wire.send(0x01);
20
  Serial.println("Sende eine 1 in Bytes");
21
  Wire.requestFrom(address, 1);
22
  Serial.println("Verbingund nicht abgebrochen und Probebyte abgefragt");
23
  while(Wire.available())
24
  {
25
    temp = Wire.receive();
26
    Serial.println("Temp gelesen");
27
  }
28
  Serial.print("Id = ");
29
  Serial.println(temp);
30
  result = Wire.endTransmission();
31
  Serial.println("Result: " + result);
32
  delay(10);
33
}
34
35
void readID(){
36
  Wire.beginTransmission(address);
37
  Serial.println("Beginne zu Addresse");
38
  Wire.send(0);
39
  Serial.println("Sende eine 0");
40
  Wire.endTransmission();
41
  Serial.println("Beende Transmission");
42
  Wire.requestFrom(address, 1);
43
  Serial.println("Frage nach einem Byte von der Adresse");
44
  while(Wire.available() == 0);
45
  Serial.println("While Schleife übersprungen - lesen der Daten");
46
  int c = Wire.receive();
47
  Serial.println("Ausgabe");
48
  Serial.println("-----------------");
49
  Serial.println(c);
50
  delay(10);
51
}

von Martin (Gast)


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?
1
/**
2
 * I2CScanner.pde -- I2C bus scanner for Arduino
3
 *
4
 * 2009, Tod E. Kurt, http://todbot.com/blog/
5
 *
6
 */
7
8
#include "Wire.h"
9
extern "C" { 
10
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
11
}
12
13
// Scan the I2C bus between addresses from_addr and to_addr.
14
// On each address, call the callback function with the address and result.
15
// If result==0, address was found, otherwise, address wasn't found
16
// (can use result to potentially get other status on the I2C bus, see twi.c)
17
// Assumes Wire.begin() has already been called
18
19
void scanI2CBus(byte from_addr, byte to_addr, 
20
                void(*callback)(byte address, byte result) ) 
21
{
22
  byte rc;
23
  byte data = 0; // not used, just an address to feed to twi_writeTo()
24
  
25
  for( byte addr = from_addr; addr <= to_addr; addr++ ) {
26
    rc = twi_writeTo(addr, &data, 0, 1);
27
    callback( addr, rc );
28
  }
29
}
30
31
// Called when address is found in scanI2CBus()
32
// Feel free to change this as needed
33
// (like adding I2C comm code to figure out what kind of I2C device is there)
34
void scanFunc( byte addr, byte result ) {
35
  Serial.print("addr: ");
36
  Serial.print(addr,HEX);
37
  Serial.print( (result==0) ? " found!":"       ");
38
  Serial.print( (addr%4) ? "\t":"\n");
39
}
40
41
42
byte start_address = 01;
43
byte end_address = 127;
44
45
// standard Arduino setup()
46
void setup()
47
{
48
    Wire.begin();
49
50
    Serial.begin(19200);
51
    Serial.println("\nI2CScanner ready!");
52
53
    Serial.print("starting scanning of I2C bus from ");
54
    Serial.print(start_address,HEX);
55
    Serial.print(" to ");
56
    Serial.print(end_address,HEX);
57
    Serial.println("...");
58
59
    // start the scan, will call "scanFunc()" on result from each address
60
    scanI2CBus( start_address, end_address, scanFunc );
61
62
    Serial.println("\ndone");
63
}
64
65
// standard Arduino loop()
66
void loop() 
67
{
68
    // Nothing to do here, so we'll just blink the built-in LED
69
    digitalWrite(13,HIGH);
70
    delay(300);
71
    digitalWrite(13,LOW);
72
    delay(300);
73
}

von Juergen (Gast)


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 ?

von Martin (Gast)


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.

von Juergen (Gast)


Angehängte Dateien:

Lesenswert?

Also,
ich hab mal die Schaltung nach Deinem Link genommen:
http://codeyoung.blogspot.com/2009/11/adxl345-accelerometer-breakout-board.html

Siehe auch angehängtes Bild. Als Programm hab ich Deinen etwas 
abgespeckten Code genommen:
1
#include <Wire.h>
2
3
//#define address 0x40
4
int address = 64;
5
6
void setup()
7
{
8
  Wire.begin();
9
  Serial.begin(9600);
10
  delay(2000);
11
}
12
13
void loop()
14
{
15
  int temp, result;
16
17
  Wire.beginTransmission(address);
18
  Wire.send(0x00);
19
  Wire.requestFrom(address, 1);
20
  while(Wire.available())
21
  {
22
    temp = Wire.receive();
23
  }
24
  Serial.print("Id = ");
25
  Serial.println(temp);
26
  result = Wire.endTransmission();
27
  Serial.println("Result: " + result);
28
  delay(1000);
29
}

Damit funkioniert es problemlos:
1
  Id = 3
2
  Result:

von Martin (Gast)


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?

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab mal schnell von meinem Aufbau ein Foto gemacht..

von Juergen (Gast)


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):
1
/*
2
 Arduino       BMA 180
3
 D11 (MOSI) -> SDI
4
 D12 (MISO) <- SDO
5
 D13 (SCK)  -> SCK
6
 D9         -> CS
7
 */
8
#include <SPI.h>
9
10
int u2s(int u) {
11
  if ( u > 0x1fff)
12
    return -((~u & 0x1fff)+1);
13
  else
14
    return u;  
15
} 
16
17
void setup() {
18
  pinMode (CSPin, OUTPUT);
19
  SPI.setDataMode(3);
20
  SPI.setBitOrder(MSBFIRST);
21
  SPI.begin();
22
}
23
24
void loop() {
25
  int rc, acc_x, acc_y, acc_z; 
26
27
  digitalWrite(CSPin,LOW); 
28
  SPI.transfer(0x82);
29
  rc = SPI.transfer(0x00); 
30
  acc_x = (rc & 0xfc) >> 2;
31
  rc = SPI.transfer(0x00);  
32
  acc_x = acc_x | ( (rc & 0xff) << 6);
33
  acc_x = u2s(acc_x);
34
  digitalWrite(CSPin,HIGH); 
35
}

von Martin (Gast)


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?

von Juergen (Gast)


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

von Martin (Gast)


Lesenswert?

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

von Martin (Gast)


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.

von Bruno H. (bruno_h83)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.