-
Hallo damfino,
Dein Code ist wohl nur ein Ausschnitt. Auf welche Geschwindigkeit ist der I²C eingestellt? Habe eben etwas über die max. Geschwindigkeit und Kabellänge am Sensor gelesen. Solltest 100kHz auf SCL nicht überschreiten. Leider finde ich auf die schnelle das Datenblatt des Sensors nicht (bei ELV ist jedenfalls kein direkter Download ode sowas zu sehen). Ohne Datenblatt kann ich aber die Sequenz nicht nachprüfen...
H.A.R.R.Y.
-
Hallo Kekse,
war lange nicht im Forum und hab Deine Frage erst heute gesehen.
Hab mir das mit der Linearisierung relativ einfach gemacht und das eigentlich
nur auf +-255 normiert.
Wenn der Maximalmesswert bei 90° z.B. bei 280 lag und der Minimalwert z.B. bei -230, hab ich das auf +-255 umgerechnet und dazwischen dann eine Gerade gelegt (bei 0,5% Linearität eigentlich erlaubt).
Dafür hab ich bei meinem Exemplar folgende Parameter benutzt:
double const rad_to_grad = 57.29577951;
double const maxm = 256.00;
// Konstanten zur Eichung der acc-Kennlinie (von Exemplar zu Exemplar unterschiedlich)
double const x_norm = 1.080169; // x : 267 ... - 207 = 474 512/474 = 1.108169;
double const y_norm = 1.028112; // y : 227 ... - 271 = 498 512/498 = 1.102811;
double const z_norm = 1.015873; // z : 259 ... - 245 = 504 512/504 = 1.105873;
double const x_null = -32.405; // x : (267 - 32.405) * x_norm = 256;
double const y_null = 22.619; // y : (227 + 22.619) * y_norm = 256;
double const z_null = -7.11; // z : (259 - 7.11) * z_norm = 256;
Gruss mausi_mick
-
Hallo damfino,
bins nochmal - nachdem ich jetzt das Datenblatt vom Sensor habe, sehe ich einen möglichen Fehler in Deinem Code. Um zu lesen sendest Du ein WR-Befehl (0x70) mit Registeradresse 2. Danach eine RESTART-Sequenz. Im Gegensatz zu den diversen I²C-EEPROMs, die diese Sequenz kennen, kann der Sensor sie offenbar nicht! Im Datenblatt ist ganz eindeutig eine STOP-Sequenz und dann eine neue START-Sequenz, diesmal mit Lesebefehl (0x71), zu sehen. Keine RESTART-Sequenz! [Page 35, Figure 16]
Versuch mal dein Programm entsprechend zu ändern und bitte berichte über Erfolg oder Mißerfolg.
H.A.R.R.Y.
-
Hi,
das hatte ich auch schon probiert als ich hier die Codebeispiele durchging.
Code vom letzten Versuch gestern (im AVR Studio ists schön formatiert aber hier??):
Code:
i2c_start(0x70);
i2c_write(2);
i2c_stop(); _delay_ms(1);
i2c_start(0x70+I2C_READ);
xl = i2c_readAck();
xm = i2c_readAck();
yl = i2c_readAck();
ym = i2c_readAck();
zl = i2c_readAck();
zm = i2c_readNak();
i2c_stop();_delay_ms(1);
Ich habe auch kurze Delays eingebaut falls stop-start zu schnell hintereinander kommt, hat nichts geändert. Im Datenblatt steht vom Sensor eine maximale Busgeschwindigkeit von 3.4Mhz, aber keine Ahnung wie schnell die Pegelwandler von der ELV Platine arbeiten. Der I2C Bus ist auf 100khz eingestellt.
Bei dem obigen Beispiel erhalten ich für alle Bytes den Wert 113, dh hex71.
LG!
-
Das sieht immerhin schon mal so aus wie im Datenblatt dargestellt.
Mich irritiert aber Dein Rücklesewert von 0x71. Das ist ziemlich genau das was Du abschickst, als ob der USI noch gar nichts empfangen hätte. Oder der Sensor einfach nur ein Echo sendet.
Funktioniert genau dieses i2c_readAck() & Co mit dem Balancer oder Kompaß?
Als Referenz würde ich spätestens jetzt einen PCF8574 an den Bus anhängen, 4 LEDs zur Ausgabe und 4 Jumper, Taster, Schalter, Drahtbrücken oder was auch immer zur Eingabe dran. Wenn die Lib den sauber ansteuern kann, dann ist sie wohl auch grundsätzlich I²C-konform.
-
Hab den gleichen Sensor von ELV ich hab ihn versucht mit dem I2C/USB Adapter auch von ELV auszulesen da kommt aber nur Müll raus welchen Bustakt solt ich einstellen bzw wie habt ihr das Makro abgeändert ?
-
Hallo.
Erstmal wollte ich mich bedanken, da ich mit hilfe euer Codes erstmal einigermaßen verstanden habe wie der Sensor anzusprechen ist. Leider ist es mir nach einer Woche noch nicht gelungen die Kommunikation zwischen meinem TI 28016, welcher auf nem Olimex Development Board sitzt, und dem BMA020 auf die Beine zu stellen.
Meine µC-Kenntnis sind eher rudimentär und mit dem TI arbeite ich erst seit 3 Wochen. Deshalb habe ich versucht ein fertiges Snippet anzupassen, geschrieben von Brad Griffis 2008.
Das ist dabei rausgekommen:
Code:
//I2C test
#include "DSP280x_Device.h" // DSP280x Headerfile Include File
#include "DSP280x_Examples.h" // DSP280x Examples Include File
// Prototype statements for functions found within this file.
void I2CA_Init(void);
Uint16 I2C_Write(Uint16 slvaddr, int data, Uint16 length);
Uint16 I2C_Read(Uint16 slvaddr, Uint16* data, Uint16 length);
Uint16 Values[6];
void main(void)
{
InitSysCtrl(); // Step 1. Initialize System Control:
InitI2CGpio(); // Step 2. Initalize GPIO only for I2C functionality
I2CA_Init(); // Step 4. Initialize all the Device Peripherals
for(;;) // Application loop
{
I2C_Write(0x70,0x02,2);
I2C_Read(0x71,Values,6);
} // end of for(;;)
} // end of main
void I2CA_Init(void)
{
// I2caRegs.I2CSAR = 0x38; // Slave address - EEPROM control code
I2caRegs.I2CPSC.all = 6; // Prescaler - need 7-12 Mhz on module clk for 60MHz CPU
I2caRegs.I2CCLKL = 4200; // NOTE: must be non zero
I2caRegs.I2CCLKH = 4200; // NOTE: must be non zero
I2caRegs.I2CIER.all = 0x3E; // Enable SCD,XRDY,RRDY,ARDY,NACK interrupts
// I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset, Stop I2C when suspended
// I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO
// I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT,
return;
}
Uint16 I2C_Write(Uint16 slvaddr, int data, Uint16 length)
{
Uint16 i;
while (( I2caRegs.I2CSTR.bit.BB==1 )); //bus busy?
if (I2caRegs.I2CSTR.bit.BB == 1)
{
return I2C_BUS_BUSY_ERROR;
}
I2caRegs.I2CMDR.all = 0; //disable I2C during config
I2caRegs.I2CCNT = length; //number of bytes to be send
I2caRegs.I2CSAR = slvaddr; //setup receiver addr
// Mode settings
I2caRegs.I2CMDR.bit.IRS=1; //I2C module enable
I2caRegs.I2CMDR.bit.STT=1; //If master -> start condition generated
I2caRegs.I2CMDR.bit.STP=1; //If master -> stop condition generated if data counter=0
I2caRegs.I2CMDR.bit.TRX=1; //Transmitter mode
I2caRegs.I2CMDR.bit.MST=1; //Master mode
I2caRegs.I2CMDR.bit.FREE=1; //I2C module runs free
I2caRegs.I2CMDR.bit.RM=1;
/* Transmission*/
for(i=0;i<length;i++)
{
while(!(I2caRegs.I2CSTR.bit.XRDY|I2caRegs.I2CSTR.bit.ARDY)); //wait for xdry flag before transmit data or ardy if NACK appears
if (I2caRegs.I2CSTR.bit.NACK==1) //if NACK appears -> SCL=low, STP=0
{
I2caRegs.I2CMDR.all=0; //reset I2C -> SCL not held low
}
I2caRegs.I2CDXR = data;
}
}
Uint16 I2C_Read(Uint16 slvaddr, Uint16* data, Uint16 length)
{
Uint16 i;
while (( I2caRegs.I2CSTR.bit.BB==1 )); //bus busy?
if (I2caRegs.I2CSTR.bit.BB == 1)
{
return I2C_BUS_BUSY_ERROR;
}
I2caRegs.I2CMDR.all = 0; //disable I2C during config
I2caRegs.I2CCNT = length; //number of bytes to be send
I2caRegs.I2CSAR = slvaddr; //setup receiver addr
// Mode settings
I2caRegs.I2CMDR.bit.IRS=1; //I2C module enable
I2caRegs.I2CMDR.bit.STT=1; //If master -> start condition generated
I2caRegs.I2CMDR.bit.STP=1; //If master -> stop condition generated if data counter = 0
I2caRegs.I2CMDR.bit.MST=1; //Master mode
I2caRegs.I2CMDR.bit.FREE=1; //I2C module runs free
I2caRegs.I2CMDR.bit.NACKMOD=1;
/* Reception */
for(i=0;i<length;i++)
{
while(!(I2caRegs.I2CSTR.bit.XRDY|I2caRegs.I2CSTR.bit.ARDY)); //wait for xdry flag before transmit data or ardy if NACK appears
if (I2caRegs.I2CSTR.bit.NACK==1) //if NACK appears -> SCL=low, STP=0
{
I2caRegs.I2CMDR.all=0; //reset I2C -> SCL not held low
}
while(I2caRegs.I2CSTR.bit.RRDY==1);
data[i] = I2caRegs.I2CDRR ;
}
}
//EOF
Das Ergebnis hab ich mir mit nem Oszi angeschaut: Nach dem ersten Senden wird SDI auf low gezogen und SCK bleibt high. Wenn ich die
Code:
while (( I2caRegs.I2CSTR.bit.BB==1 ));
in der Schreib- bzw. Lesefunktion auskommentiere kann ich folgendes Bild sehen:
http://img24.imageshack.us/img24/7899/bild0027h.jpg
Meiner laienhaften Meinung nach wird keine Stop Condition erzeugt, weshalb BB immer 1 ist.
Ein Versuch eine I2C-Minimalversion für diese Sache zu schreiben sah so aus:
Code:
//I2C test
#include "DSP280x_Device.h" // DSP280x Headerfile Include File
#include "DSP280x_Examples.h" // DSP280x Examples Include File
// Prototype statements for functions found within this file.
void I2CA_Init(void);
Uint16 Values[6],i;
void main(void)
{
InitSysCtrl(); // Step 1. Initialize System Control:
InitI2CGpio(); // Step 2. Initalize GPIO only for I2C functionality
I2CA_Init(); // Step 4. Initialize all the Device Peripherals:
for(;;) // Application loop
{
//---> Write instruction <--- //
I2caRegs.I2CMDR.bit.STT = 1;
I2caRegs.I2CSAR = 0x70; //Write addr
I2caRegs.I2CCNT = 3; //3bytes=2bytes addr + 1 byte instr
I2caRegs.I2CDXR = 0x02; //instr
I2caRegs.I2CMDR.bit.STP = 1;
// I2caRegs.I2CMDR.all = 0x2620; //Send data to setup EEPROM address
//---> Read values <--- //
I2caRegs.I2CMDR.bit.STT = 1;
I2caRegs.I2CSAR = 0x71; //Read addr
I2caRegs.I2CCNT = 1; //6bytes=2bytes per coordinate
Values[0] = I2caRegs.I2CDRR;
/*for(i=0;i<6;i++)
{
Values[i] = I2caRegs.I2CDRR;
}*/
I2caRegs.I2CMDR.all = 0x2C20; //Send restart as master receiver
I2caRegs.I2CMDR.bit.STP = 1;
} // end of for(;;)
} // end of main
void I2CA_Init(void)
{
// I2caRegs.I2CSAR = 0x38; // Slave address - EEPROM control code
I2caRegs.I2CPSC.all = 6; // Prescaler - need 7-12 Mhz on module clk for 60MHz CPU
I2caRegs.I2CCLKL = 4200; // NOTE: must be non zero
I2caRegs.I2CCLKH = 4200; // NOTE: must be non zero
I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts
I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset, Stop I2C when suspended
I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO
I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT,
return;
}
//EOF
Führte aber leider auch nicht zum Ergebnis.
Falls es relevant ist ich nutze das Code Composer Studio V4.
Falls jemand hier Erfahrungen mit TI DSPs oder Vorschläge jeglicher Art zu meinen beiden Code-Versuchen hat wäre ich sehr dankbar.
Grüße
Stephan
-
hallo,
habs jetzt hinbekommen und falls mal jemand den BMA020 mit TI C2000 DSPs nutzen will poste ich mal meinen, durchaus verbesserungswürdigen, Code, welcher hier bereits gepostete Codeschnipsel enthält.
Code:
//I2C test
#include "DSP280x_Device.h" // DSP280x Headerfile Include File
#include "DSP280x_Examples.h" // DSP280x Examples Include File
// Prototype statements for functions found within this file.
void I2CA_Init(void);
int Values[6]={0,0,0,0,0,0};
Uint16 instr=0x02;
int i,dx=0,dy=0,dz=0;
double D2G,gx=0,gy=0,gz=0;
void main(void)
{
InitSysCtrl(); // Step 1. Initialize System Control:
InitI2CGpio(); // Step 2. Initalize GPIO only for I2C functionality
I2CA_Init(); // Step 4. Initialize all the Device Peripherals
D2G=0.00390625; // 4g/1024
for(;;) // Application loop
{
I2caRegs.I2CSAR = 0x38; //Set slave address
I2caRegs.I2CCNT = 1; //Set count to 1 Byte for instr 0x02
I2caRegs.I2CDXR = 0x02; //Send instr
I2caRegs.I2CMDR.bit.TRX = 1; //Set to Transmit mode
I2caRegs.I2CMDR.bit.MST = 1; //Set to Master mode
I2caRegs.I2CMDR.bit.FREE = 1; //Run in FREE mode
I2caRegs.I2CMDR.bit.STP = 1; //Stop when internal counter becomes 0
I2caRegs.I2CMDR.bit.STT = 1; //Send the start bit, transmission will follow
while(I2caRegs.I2CSTR.bit.XRDY == 0){}; //Do nothing till data is shifted out
I2caRegs.I2CCNT = 6; //read 6 bytes from sensor
I2caRegs.I2CMDR.bit.TRX = 0; //Set to Recieve mode
I2caRegs.I2CMDR.bit.MST = 1; //Set to Master mode
I2caRegs.I2CMDR.bit.FREE = 1; //Run in FREE mode
I2caRegs.I2CMDR.bit.STP = 1; //Stop when internal counter becomes 0
I2caRegs.I2CMDR.bit.STT = 1; //Repeated start, Reception will follow
for(i = 0; i < 6; i++)
{
while(I2caRegs.I2CSTR.bit.RRDY == 0){}; //I2CDRR not ready to read?
Values[i] = I2caRegs.I2CDRR;
}
DELAY_US(100); //wait for new data provided
dx=Values[0]; //dataadaptation by malthy & Sternthaler
dx=(dx|((Values[1]<<8))>>6);
gx=dx*D2G;
dy=Values[2];
dy=(dx|((Values[3]<<8))>>6);
gy=dy*D2G;
dz=Values[4];
dz=(dx|((Values[5]<<8))>>6);
gz=dz*D2G;
} // end of for(;;)
} // end of main
void I2CA_Init(void)
{
I2caRegs.I2CSAR = 0x38; // Slave address - EEPROM control code
I2caRegs.I2CPSC.all = 6; // Prescaler - need 7-12 Mhz on module clk for 60MHz CPU
I2caRegs.I2CCLKL = 42; // NOTE: must be non zero
I2caRegs.I2CCLKH = 21; // NOTE: must be non zero
I2caRegs.I2CIER.all = 0x3E; // Enable SCD,XRDY,RRDY,ARDY,NACK interrupts
I2caRegs.I2CMDR.bit.IRS = 1; // Take I2C out of reset, Stop I2C when suspended
I2caRegs.I2CFFTX.all = 0x0000; // Enable FIFO mode and TXFIFO
I2caRegs.I2CFFRX.all = 0x0000; // Enable RXFIFO, clear RXFFINT,
return;
}
//EOF
An der Stelle nochmals danke an die "Code-Sponsoren".
Das einzige was mich im Betrieb stört ist, dass die Ergebnisse nicht konstant bleiben selbst wenn ich den Sensor fest einspanne. Dabei treten manchmal Sprünge von bis zu 0.5g auf, was für meine anschließende Aufgabe tötlich sein wird. Hat schon mal jemand in dem Zusammenhang mit den Filtern rumgespielt ?
-
Hallo,
ich weiß nicht ob dass hier noch relevant ist, aber falls nochmal jemand auf schwankende Werte kommt kann ich empfehlen die Einstellung des im Sensor befindlichen Tiefpasses zu checken. Bei mir war die Einstellung für "bandwidth" (14h,bits 2-0) nämlich auf 750Hz, abweichend von der Standardbelegung mit 25Hz. Dadurch hatte ich bei einem Wertebereich von +/-256 einen Fehler von ca. +/-10. Mit 25Hz komm ich auf +/-2 und bin für meine Anwendung ausreichend schnell.
In dem Sinne fröhliches Beschleunigen