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");
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.
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.
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.
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");
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()
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 ?
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.
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?
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):
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?
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.
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 ... !