Seid gegrüßt,
nachdem ich seit längerem nun schon mit der MultiWii rumspiele habe ich mir jetzt erstmal ein nacktes Arduino Mega 2560 geholt.
Nun hatte ich hier auch noch einen BMA020 von ELV rumfliegen.
CSB + UIN + Pullup = VCC
SDO + GND = GND
SCK = I2C SCL
SDI = I2C SDA
So, habe mir dieses dann erstmal mit Breadboardkabeln versehen.
VCC geht auf 3.3V am Arduino Mega.
Als Programmcode nutze ich folgenden:
#include <Wire.h>
#define BMA020_ADDR 0x38
byte data[6]; //Byte field for incoming i2c data
int bma020_x; //Current G on X direction
int bma020_y; //Current G on Y direction
int bma020_z; //Current G on Z direction
boolean bma020_x_new; //True = Last X value was new
boolean bma020_y_new; //True = Last Y value was new
boolean bma020_z_new; //True = Last Z value was new
void setup() {
Wire.begin();
Serial.begin(19200);
Serial.println("Init start...");
initBMA020();
Serial.println("Init done!");
}
void loop() {
//Read new Data from BMA
readBMA020(BMA020_ADDR);
//Show output
Serial.print("X: ");
Serial.print(bma020_x);
Serial.print(" Y: ");
Serial.print(bma020_y);
Serial.print(" Z: ");
Serial.print(bma020_z);
Serial.print(" Betrag: ");
Serial.print(norm3dim(bma020_x, bma020_y, bma020_z));
Serial.println();
delay(200);
}
void initBMA020() {
byte control;
//Set SPI 4 Wire mode
writeRegister(0x38, 0x15, 0x80);
//Range Settings
// Range to 2g --> 255 in datafield is ~1g
// Range to 4g --> 127 in datafield is ~1g
// Range to 8g --> 63 in datafield is ~1g
//Set Range + Bandwidth
control = readRegister(0x38,0x14);
control = control & 0xE0; // save bits 7,6,5
control = control | (0x02 << 3); // Range to 8g (10)
control = control | 0x00; // Bandwidth 25 Hz 000
writeRegister(0x38, 0x14, control);
Serial.println(readRegister(0x38,0x15));
delay(50);
Serial.println(readRegister(0x38,0x14));
delay(50);
}
byte readRegister(byte addr, byte reg){
byte val = 0x00;
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(addr, (byte)1);
return Wire.read();
}
void writeRegister(byte addr, byte reg, byte value){
byte val = 0x00;
Wire.beginTransmission(BMA020_ADDR);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
void readBMA020(byte addr) {
int i;
for (i = 0; i < 6; i++) {
data[i] = readRegister(addr, 0x02+i);
}
//Parse data information
bma020_x = ( (int)data[1] << 8) + (int)data[0];
bma020_y = ( (int)data[3] << 8) + (int)data[2];
bma020_z = ( (int)data[5] << 8) + (int)data[4];
//Extract "new data Bits"
bma020_x_new = bma020_x & 0x0001;
bma020_y_new = bma020_y & 0x0001;
bma020_z_new = bma020_z & 0x0001;
bma020_x = bma020_x >> (6);
bma020_y = bma020_y >> (6);
bma020_z = bma020_z >> (6);
}
int norm3dim (int a, int b, int c) {
double total;
total = sq((double)bma020_x) + sq((double)bma020_y) + sq((double)bma020_z);
//return total;
return (int)(sqrt(total));
}
Ich bin soweit auch ganz zufrieden, weil es so halbwegs klappt. Aber jetzt kommen wir zu meinen Problem.
Zum einen bin ich noch sehr "ungeübt" in i2c kommunikation. Leider ist auch für mich die Dokumentation der I2C Funktionen in der Wire.h "dürftig".
Mir fehlt einfach die Analogie zum normalen Mikrocontroller I2C.
Anbei das Datenblatt zum BMA020:
--> Seite 34/35: I2C Kommunikation
--> Seite 9: Registerbeschreibung
--> Seite 21: Format der X, Y und Z-Register
Meine erste Frage: Ist das readRegister() + writeRegister() bezogen auf den BMA020 richtig implementiert? Oder sind diese Funktionen eher "glückstreffer"?
Nun zum eigentlichen Problem:
Ich lasse mir über die Konsole die gemessenen Werte ausgeben. Meine X, Y und Z Register für die aktuelle beschleunigung ist lt. Datenblatt 10 Bit groß. 10 Bit ==> von -512 bis +511
Der BMA020 habe ich auf 8g gestellt. d.h. 8g ~ 511, das bedeutet 1g ~ 63.
Und das klappt auch soweit. Setze ich den BMA auf 4g ist 1g ~ 127. Auf 2g ist 1g ~ 255
Lege ich den Sensor mit 8g vor mir flach hin erhalte ich folgende Ausgabe:
Flach hingelegt bekomme ich folgende Ausgabe:
X: 4 Y: -4 Z: 62 Betrag: 62
Der Betrag hier sieht auch ganz plausibel aus. (Ich gehe davon aus meine Betragsrechnung korrekt angesetzt ist)
Drehe ich den Sensor komplett auf den Kopf erhalte ich:
X: 4 Y: -1 Z: -63 Betrag: 63
Auch hier bin ich noch vollkommen zufrieden.
Neige ich nun die Y-Achse des Sensors richung "Anziehungskraft" erhalte ich (Schrott?!)
X: 3 Y: 58 Z: -4 Betrag: 58
Ist diese "Toleranz" zwischen den einzelnen Achsen "normal"?
Oder Versemmel ich es irgendwie mit der Umrechnung der Werte?
Habe den Sensor in Schrumpfschlauch "Verschweißt". Ist das evtl. eine Störquelle für diesen Effekt?
Mit freundlichen Grüßen
Chris2go