hallo,
in die wo wird der wert des sensors in var "wert "gespeichert" ?
hallo,
in die wo wird der wert des sensors in var "wert "gespeichert" ?
Hallo an alle,
hier mal ein Programmschnippsel für die Neugierigen, die wissen wollen wie es geht: (Und es geht gut!)
Um z.B. das Status-Register 14 (Hex) auszulesen macht man folgendes:Code:/*---------------------------------------------------------------------------- Defines: Adresse vom BMA020-3D-Beschleunigungssensor */ #define I2C_BMA_W 0x70 #define I2C_BMA_R 0x71 int16_t x, y, z; uint8_t ret; /* Lesen von 6 Registern ab Register 0x02. X, Y, Z-Koordinate */ ret = StartI2C (I2C_BMA_W); ret = WriteI2C (0x02); StopI2C (); ret = StartI2C (I2C_BMA_R); ret = ReadI2C (ACK); x = (int16_t)ret; ret = ReadI2C (ACK); x = x | ((int16_t)ret << 8); x /= 64; ret = ReadI2C (ACK); y = (int16_t)ret; ret = ReadI2C (ACK); y = y | ((int16_t)ret << 8); y /= 64; ret = ReadI2C (ACK); z = (int16_t)ret; ret = ReadI2C (NAK); z = z | ((int16_t)ret << 8); z /= 64; StopI2C ();
Code:/*---------------------------------------------------------------------------- Defines: Adresse vom BMA020-3D-Beschleunigungssensor */ #define I2C_BMA_W 0x70 #define I2C_BMA_R 0x71 /* Lesen des Status-Registers 0x14 : reserviert:7:5 range:4:3 bandwidth:2:0 */ uint8_t ret, r14; uint8_t range; ret = StartI2C (I2C_BMA_W); ret = WriteI2C (0x14); StopI2C (); ret = StartI2C (I2C_BMA_R); r14 = ReadI2C (NAK); StopI2C (); range = (r14 & 0b00011000) >> 3;
Und bei mir betrug die Lieferzeit nur ca. 10 Tage. Jippie
Gruß
Sternthaler
[edit 11.10.2010]
Auf Wunsch eine kleine Erklärung für die Berechnung der x-, y-, z-Werte.
Für X steht im oberen Code-Block folgendes:
Zeile 1) ret = ReadI2C (ACK); x = (int16_t)ret;
Zeile 2) ret = ReadI2C (ACK); x = x | ((int16_t)ret << 8 ); x /= 64;
In Zeile 1) wird beim ersten ReadI2C der Wert vom Register 0x02 aus dem Chip gelesen. Darin sind nur die beiden obersten Bit relevant für das X-Ergebnis. Es sind die beiden untersten Bits vom gesamten 10-Bit-Messwert.
Trotzdem wird diese Byte nun als 16-Bitwert in der Variablen x gespeichert.
In Zeile 2) wird mit dem nächsten ReadI2C das Register 0x03 aus dem Chip gelesen. (Die Adresse wird automatisch vom Chip hochgezählt.)
Dahinter wird nun das in Zeile 1) gelesene BIT-Muster mit |-Zeichen und dem in Zeile 2) gelesenen und mit dem <<8 um 8 BIT nach links geschobenem Registerwert aus 0x03 'verbunden'.
=> 0000 0000 ??-- ----: Die 2 Bits aus Zeile 1) in der 16-Bit-Variablen x
Bit-ODER-Verknüpft (|-Zeichen) mit dem um 8 Bit nach links geschobenem Wert aus Zeile 2)
=> ???? ???? 0000 0000: Die oberen 8 Bit vom Messwert. Ergibt:
----------------------------
=> ???? ???? ??-- ----
Die ? sind also nun die 10 Bit Messergebnis
Die - sind Bits, die auch gelesen wurden, aber hier nicht interessieren.
Die 0 sind Bits, die wir bewusst gesetzt hatten.
Jetzt noch in Zeile 2) mit dem x /= 64 diese Ergebnis einfach um 6 Bit nach rechts schieben. (Man kann auch schreiben x = x / 64
Man hätte auch x = ( x | ((int16_t)ret << 8 ) ) >> 6; schreiben können. Das macht der Compiler sowiso daraus.
Also ist das Ergebnis nun:
=> 0000 00?? ???? ????
Und damit haben wir die 10 Bit X-Messwert 'greifbar'.
ACHTUNG: Das höchste ?-Bit ist ein Vorzeichen.
Die Zählweise für den Betrag des Wertes kann man am besten in der Doku nachlesen.
Datenblatt: BMA020
Die Register sind auf Seite 9 beschreiben.
Die Zählweise vom Ergebnis ist auf Seite 21.
Viel Spaß beim Lesen wünscht
Sternthaler
Lieber Asuro programieren als arbeiten gehen.
@wtp
Hallo, 3 Dinge sind mir aufgefallen in deinem Programm.
Aber erst mal muss ich gleich sagen, dass ich noch nie mit diesem Basic was gemacht habe und, dass ich die I2C-Schnittstelle hier zum ersten mal benutze. Allerdings in C und es funktioniert bei mir.
Nun zu deinem Programm.
1) Nach dem I2C-Init setzt du noch einen Parameter mit config. Das würde ich tauschen.
2) Vor dem schreiben der Adresse 71 (Leseaufforderung) hast du ein I2C-Start. Ich habe vor dem Start noch einen Stop-Befehl. Eventuell hilft das schon.
3) Du liest Register 02 aus. Das sind nur die beiden untersten Bits von X-Beschleunigungswert. Versuche mal Register 03 zu lesen. Oder las das setzen vom Shadow_dis-Bit und lese dann Register 02 und sofort auch Register 03 und nutze nur 03.
Viel Erfolg
Gruß Sternthaler
Lieber Asuro programieren als arbeiten gehen.
Was kann man denn mit so ein teil tolles machen? ^^
Geschwindigkeit? Zurückgelegte strecke?
LG Raz
Hallo,
hat jemand schon Erfahrungen mit diesem Gyro gemacht?
Mich Interessiert vorallem die Bascom kompabilität, die tauglichkeit für ausbalancierte Fluggeräte (Tri-Quadrocoper), und die zuverlässigkeit.
Kann jemand zu einem der Punkte schon etwas sagen?
Es grüßt,
Basteltisch
- Lesen -
...hat nix mit Gyro zu tun !
Falls es am Datenblatt mangelt - das hab ich noch
Ich hab vor ca. einem Jahr bei Bosch Sensortec angerufen und da wurde mir gesagt, daß der BMA020 nicht mehr hergestellt wird.
Ich programmiere mit AVRCo
Moin Leute,
ich versuche auch Daten aus dem Sensor mit einem ATMega644 zu lesen (via SPI). Leider gibt mein Display für die 8 höchsten Bits der z-Beschleunigung eine 0 aus.
Ich hab das Programm gut kommentiert, sollte leicht verständlich sein.
Sieht jemand von Euch einen Fehler darin? Meines Erachtens habe ich alles beachtet.
Code:#include <avr/io.h> #include <util/delay.h> #include "m50530.h" #include <stdlib.h> #define DDR_SPI DDRB #define PORT_SPI PORTB #define PIN_SPI PINB #define DD_BMA020_CS PB4 #define DD_MOSI PB5 #define DD_MISO PB6 #define DD_SCK PB7 #define P_BMA020_CS PB4 #define P_MOSI PB5 #define P_MISO PB6 #define P_SCK PB7 #define acc_z 7 #define read 7 void SPI_MasterInit(void) { // Set MOSI and SCK output, all others input DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK); // BMA020 ChipSelect is output (low active) DDR_SPI |= (1<<DD_BMA020_CS); // Deselect BMA020 PORT_SPI |= (1<<P_BMA020_CS); // Enable SPI, Master, set clock rate fck/16, SPI Mode 3 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL)|(1<<CPHA); } void SPI_MasterTransmit(char cData) { /* Start transmission */ SPDR = cData; /* Wait for transmission complete */ while(!(SPSR & (1<<SPIF))) ; } char getZ(void) { // Select BMA020 PORT_SPI &=~ (1<<P_BMA020_CS); // Send command: Read z_acceleration SPI_MasterTransmit((1<<read)|(acc_z)); // Send dummy byte SPI_MasterTransmit(0); // Deselect BMA020 PORT_SPI |= (1<<P_BMA020_CS); // Return z acceleration return SPDR; } int main(void) { uint16_t z=0; char string[20]; // Wait 2 ms for the BMA020 _delay_ms(2); // Initialize LCD and SPI LCDInit(); SPI_MasterInit(); while(1) { // Read z-axis via SPI z=getZ(); // Convert z To String itoa(z, string, 10); // Print z on LCD LCDWrite(string); // Set CoursorPosition to [0,0] LCDSetCursorPos(0,0); } return 0; }
Vielen Dank schonmal und Grüße aus Hamburch
Hallo,
falls es noch für jemanden von Interesse ist: ich habe die I2C-Kommunikation mit dem Sensormodul mal in Bascom implementiert. Hier ist ein Beispielcode:
Ich habe auf meiner Homepage noch ein paar zusätzliche Informationen zu dem Programm hinterlegt. Hier kann man nachlesen, wenn man mag: http://www.mtahlers.de/index.php?opt...d=32&Itemid=69Code:' kleines beispielprogramm zum auslesen des bma020 ' malte ahlers 2010 ' weitere infos auf malteahlers.de ' ' ' compiler steuerung $regfile = "m8def.dat" $crystal = 1000000 $framesize = 64 $swstack = 64 $hwstack = 64 $baud = 9600 $lib "i2c_twi.lbx" ' ' hardware konfigurieren ' - taster Config Pinb.6 = Input Portb.6 = 1 Config Pinb.7 = Input Portb.7 = 1 Config Pind.5 = Input Portd.5 = 1 Taster1 Alias Pinb.6 Taster2 Alias Pinb.7 Taster3 Alias Pind.5 ' - leds Config Portd.7 = Output Config Portd.6 = Output Config Portb.0 = Output Led_gl Alias Portd.7 Led_rt Alias Portd.6 Led_gr Alias Portb.0 ' - I2C Config Scl = Portc.5 Config Sda = Portc.4 ' ' variablen dimensionieren Dim V(6) As Byte Dim Ax As Integer At V(1) Overlay Dim Ay As Integer At V(3) Overlay Dim Az As Integer At V(5) Overlay Dim Acc_cntr As Byte Dim I As Byte Dim Acc_range As Byte Dim D2g As Single Dim S As Single ' ' konstanten Const Acc_w = &H70 Const Acc_r = &H71 ' ' subs Declare Sub Set_acc_range(byval Range As Byte) ' ' hauptprogramm Print "acc test!" Wait 1 ' I2cinit ' Call Set_acc_range(0) ' messbereich: ' Set_acc_range(0) -> +/- 2g (default) ' Set_acc_range(1) -> +/- 4g ' Set_acc_range(2) -> +/- 8g ' Do I2cstart ' ' sensor adressieren I2cwbyte Acc_w ' ' acc datenregister adressieren I2cwbyte &H02 ' I2cstop ' I2cstart ' ' daten lesen I2cwbyte Acc_r ' For I = 1 To 5 I2crbyte V(i) , Ack Next I I2crbyte V(6) , Nack ' I2cstop ' ' format konvertieren Ax = Ax / 64 Ay = Ay / 64 Az = Az / 64 ' ' in beschleunigungen umrechnen & ausgeben S = Ax * D2g Print "a(x)= " ; S ; S = Ay * D2g Print " a(y)= " ; S ; S = Az * D2g Print " a(z)= " ; S ' Toggle Led_rt Waitms 10 ' Loop ' End ' Sub Set_acc_range(byval Range As Byte) I2cstart ' ' sensor adressieren I2cwbyte Acc_w ' ' kontrollregister adressieren I2cwbyte &H14 ' I2cstop ' I2cstart ' kontrollregister lesen I2cwbyte Acc_r I2crbyte Acc_cntr , Nack ' I2cstop ' ' kontrollregister manipulieren Acc_cntr.3 = Range.0 Acc_cntr.4 = Range.1 ' I2cstart ' ' kontrollregister zurückschreiben I2cwbyte Acc_w I2cwbyte &H14 I2cwbyte Acc_cntr ' I2cstop ' ' umrechnungsfaktor neu berechnen D2g = 2 ^ Range D2g = D2g * 2 D2g = D2g / 512 ' End Sub
Gruß
Malte
hallo malthy,
hallo Sternthaler,
Danke für die Code-Beispiele.
Der Basic-Code sieht aus meiner Sicht sehr gut aus und ist gut dokumentiert. Einzig in der Leseschleife wird bei V() ein kleines i verwandt, aber da ist Basic vielleicht gnädig ?
Beim C-Code wäre mir ein wenig Doku hilfreich.
Auch wäre in der ASURO-Umgebung interessant, wie man die Sensordaten
auf dem LCD-Display, das ja auch an I2C hängt, ausgeben kann.
SCL könnte bleiben (MY_I2C_SCL --> PC3/Pin26) aber SDA müsste man wohl umswitchen von PC2/PIN25 für LCD auf z.B. PC4/Pin27 für BMA020.
Werd aber wohl mit dem C-Code testen, da ich von BASIC wenig Ahnung habe.
Gruss mausi_mick
Lesezeichen