PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : i2c(twi) srf10 atmega128



andy999
11.06.2008, 14:41
Hallo @ all,

ich habe ein großes Problem bezüglich der Vorgehensweise beim Auslesen
meines Ultraschalls srf10. Der US ist per I2C(TWI) an meinen ATMEGA128
angeschlossen. Ich bräuchte nun einen Pseudocode, wie ich von der
Reihenfolge her theoretisch den US ansprechen kann und den Abstand zum
hinderniss auslesen kann. Addressiert sind die US's bereits. Es geht
also nur ums ansprechen und auslesen aber wie muss ich vorgehen?
Programmieren würde ich gerne in C/C++

Es wäre super, wenn mir jemand bei meinem Problem helfen könnte.


Gruß Andy

andy999
11.06.2008, 18:04
habe es selber probiert...Mit mäßigem Erfolg. Das Problem ist zwar, dass ich die Messung starte, aber ich kein Ergebnis erhalte.

Im Anhang findet ihr meinen Quellcode.

Findet jemand einen Fehler oder jemand ne idee was vergessen wurde oder was ich anderst machen sollte?

uffi
12.06.2008, 10:36
Hallo Andy,

Du hast vor dem Auslesen vergessen, das Register auf 2 zu setzen. Dir fehlen vor dem Lesen folgende Code-Zeilen:

i2c_start(US_address + I2C_WRITE);
i2c_write(0x02);
i2c_stop();
Erst danach darf kommen:

busy = i2c_start(US_address + I2C_READ);

// address I2C device ultrasonic sensor with read access

if (busy == 0) //vorher == 0

{
distance_low = i2c_readAck(); // read one byte
distance_high = i2c_readNak();
distance = (distance_low*256)+distance_high;
//i2c_stop(); // release I2C bus
}

else

{
i2c_stop(); // release I2C bus
}
Ausserdem solltest Du die Stop-Condition nach dem Lesen nicht auskommentieren. Sonst wartet der SRF10, ob noch was kommt auf dem I2C Bus.

Gruß, uffi.

MoeJoeHH
01.08.2008, 10:11
Hallo,

einen Fehler habe ich auch noch gefunden: die Formel zur Berechnung der Entfernung ist laut Datenblatt

d = (Highbyte *256)+Lowbyte, nicht andersherum. Außerdem muss doch das register zum auslesen gewechselt werden?

Ich habe aber auch ein Problem, und zwar, dass die Leitungen SDA und SCL super funktionieren, wenn kein Sensor dranhängt, schließe ich den Sensor an, sind die Leitungen dauerhaft low...

Kann dies an zu groß gewählten Pull-Ups liegen?

Verwenden tue ich auch einen Atmega128, SRF10 und 4,7k Pull-Ups.

Vielen Dank schonmal für Antworten


Hier nochmal mein Code:



void getDistanceVal_USDS1(void)
{
unsigned char busy=255, result_highByte=0, result_lowByte=0;

//issue measuring command
i2c_start_wait(ADDRESS_USDS1+I2C_WRITE);
i2c_write(W_COMMANDREGISTER);
i2c_write(MEASURE_CM);
i2c_stop();

//wait for measure ready
while (busy==255){
//while measurement is running firmware reads as 255
busy = getUSDSstatus(ADDRESS_USDS1);
}

i2c_start_wait(ADDRESS_USDS1+I2C_WRITE);
i2c_write(R_DIST_HIGHBYTE); //read register2
i2c_stop();

i2c_start_wait(ADDRESS_USDS1+I2C_READ);
result_highByte = i2c_read(0); //read one byte
i2c_stop();

i2c_start_wait(ADDRESS_USDS1+I2C_WRITE);
i2c_write(R_DIST_LOWBYTE); //read register3
i2c_stop();

i2c_start_wait(ADDRESS_USDS1+I2C_READ);
result_lowByte = i2c_read(0); //read one byte
i2c_stop();

actualDistance_USDS1 = (int) (result_highByte*256 + result_lowByte); //in globaler Variable speichern
}

MoeJoeHH
01.08.2008, 13:56
So, ich nochmal:

Ich konnte den Fehler weiter einkreisen. Ich benutze das i2c-Framework von peter fleury. Dort wird in der Funktion "i2c_readAck()" darauf gewartet, dass die Hardware das TWINT-Bit auf 0 setzt und somit anzeigt, dass die Übertragung beendet wurde:



while(!(TWCR & (1<<TWINT)));


Offenbar passiert das aber nicht, leider suche ich nun schon seit geraumer Zeit vergeblich nach einer Lösung, hat jemand von Euch eine Idee?

Vielen Dank,
Moe

MoeJoeHH
01.08.2008, 15:08
Hallo, da ich es immer gut finde, am Ende eines Threads auch eine Lösung stehen zu haben: Ich habe den Fehler gefunden:

Das Problem war in der while-Schleife, in der ich auf das Ende der Messung warte:



//wait for measure ready
while (busy==255){
//while measurement is running firmware reads as 255
busy = getUSDSstatus(ADDRESS_USDS1);
}



hier muss auf jeden Fall ein delay rein, anscheinend verschluckt sich sonst der Sensor. richtig sollte es also so lauten:



//wait for measure ready
while (busy==255){
_delay_ms(1); //wait 1ms
//while measurement is running firmware reads as 255
busy = getUSDSstatus(ADDRESS_USDS1);
}


Der Vollständigkeit halber nochmal die getUSDSstatus-Funktion (USDS:ultra sonic distance sensor):




unsigned char getUSDSstatus(unsigned char address)
{
unsigned char busy=0;

//PORTA ^= BIT4; //TODO: remove debugging LED
i2c_start_wait(address + I2C_WRITE);
i2c_write(R_FIRMWAREREGISTER);

i2c_rep_start(address + I2C_READ);
busy = i2c_readAck(); //read one byte
i2c_stop();

return busy;
}


Gruß, Moe