PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Register des SRF02 über TWI bzw. I2C auslesen



master123
21.02.2010, 00:25
hallo an alle. ich hab ein problem beim auslesen der resigster vom
SRF02 Ultraschallsensor. ich verwende den sensor über twi an einem
atmega128 und 16mhz. für TWBR habe ich 72 eigetragen.

die funktion bleib an der kommentierten stelle hängen und läuft nicht
mehr weiter. kann mir da jemand weiterhelfen, wie ich über twi die
register auslesen kann??? alleine finde ich den fehler leider nicht.

das übertragen mit einer anderen funktion läuft ohne problme, nur am
empfangen / lesen gibt es schwierigkeiten.

hier hatte jemand das gleiche problem würde ich sagen:
http://www.mikrocontroller.net/topic/99910#1606143



#include <inttypes.h> // these four library headers are part of WinAVR compiler
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>

...

int main()
{
...
unsigned int range_h;
unsigned int range_l;

DDRD = 0xff;
PORTD = 0xff;

setup();

printf( "Ultraschallsensor SRF02\n");

while(1)
{
PORTA ^= ( 1 << PA2 );
i2c_transmit(0xE0,0,0x51); // srf02 ping command, result in cm
_delay_ms(120);

range_h = i2c_read(0xE0,2); // read srf02 range, high byte
range_l = i2c_read(0xE0,3); // read srf02 range, low byte

printf( "high: %d\tlow: %d\n", range_h, range_l);

//printf( "Abstand: %dcm\n", range);

}
}

char i2c_read(char address, char reg)
{
char read_data = 0;

TWCR = 0xA4; // send a start bit on i2c bus
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWDR = address; // load address of i2c device
TWCR = 0x84; // transmit
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWDR = reg; // send register number to read from
TWCR = 0x84; // transmit
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWCR = 0xA4; // send repeated start bit
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWDR = address+1; // transmit address of i2c device with readbit set
TWCR = 0xC4; // clear transmit interupt flag
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWCR = 0x84; // transmit, nack (last byte request)

//----------------------------ab hier geht es dann nicht mehr weiter-------------
while(!(TWCR & 0x80)); // wait for confirmation of transmit
read_data = TWDR; // and grab the target data
TWCR = 0x94; // send a stop bit on i2c bus
return read_data;
}

void i2c_transmit(char address, char reg, char data)
{
TWCR = 0xA4; // send a start bit on i2c bus
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWDR = address; // load address of i2c device
TWCR = 0x84; // transmit
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWDR = reg;
TWCR = 0x84; // transmit
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWDR = data;
TWCR = 0x84; // transmit
while(!(TWCR & 0x80)); // wait for confirmation of transmit
TWCR = 0x94; // stop bit
}

void setup(void)
{
TWBR = 72; // 100khz i2c bus speed
TWSR = 0; // no prescaler
PORTA &= ~( 1 << PA1 );
}

master123
21.02.2010, 12:40
Hallo noch einmal...

kann das vielleicht sein das der srf02 nicht senden kann und dadurch die schleife nie beendet wird, da nix empfangen wird??? den wenn ich ihm den befehl zum messen sende, empfängt er diesen und die led leuchtet einmal auf (also er misst einmal).

hab an die scl und sda 5v über je 3,3k rangehangen, müsste soweit eigendlich richtig sein :-S

linux_80
21.02.2010, 14:15
Hallo,

schonmal die Wartezeit zwischen start und auslesen vergrößert ?
Der SRF02 klemmt sich in der Zeit vom I2C ab, solange er misst.

Zum Testen ob die TWI-Geschichte in Deinem Prog läuft, kannst Du ja mal die Firmware auslesen, oder ohne MessStart die Register auslesen, da sollte dann immer was kommen.

master123
21.02.2010, 15:52
ich hab ebend die wartezeit auf 500ms vergrößert, es passiert leider das gleiche. an der while schleife bleibt er stehen.

zudem habe ich den teil mit "i2c_transmit(0xE0,0,0x51);" auskommentiert, so dass nur die register abgefragt werden, ohne messung. leider wie oben bleibt in der while schleife hängen.

da muss irgendwas mit dem auslesen nicht laufen, den wenn ich das register 0 auslesen will bleibt er auch an dieser stellen hängen. beim register 1 der den wert 0x80 liefern soll passiert ebenso das gleiche.

wo ist nur dieser fehler!!!!!??????!!!!!!!??????
kann es an der hardware liegen??????

linux_80
21.02.2010, 20:16
Wenn Dein primäres Ziel das Auswerten des SRF ist, würde ich jetzt den Tipp mit der I2C-Lib von P.Fleury anbringen :)
Wenn Du mit I2C basteln willst, kannst Du mal ins Wiki schauen, wie das der Reihe nach geht.

master123
21.02.2010, 20:32
über die lib von fleury hab ich das auch schon probiert. unten der code dazu. die zahlen die per printf geschrieben werden, sind dazu da um zu sehen wie weit er kommt. leider wird die zahl 12 nicht mehr ausgegeben, also es wird nur die zahl 11 ausgeben und es läuft nicht mehr weiter.




#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

#include <avr/io.h>
#include "i2cmaster.h"


#define SLAVE_ADRESSE 0xE0
#define F_CPU 16000000UL
#define BAUD 9600 //Baudrate
#define MYUBRR F_CPU/16/BAUD-1 //Werte für UBRR Register

#include <util/delay.h>
...
unsigned int read_cm(unsigned char address);

int main(void)
{

stdout = &mystdout;
USART_Init ( MYUBRR ); //USART initialisieren

printf( "*** Ultraschallsensor SRF02 ***\n");

int distance;
i2c_init();
DDRD = 0xff;
PORTD = 0xff;
read_cm(SLAVE_ADRESSE);
distance = read_cm(SLAVE_ADRESSE);

printf( " Abstand: %dcm\n", distance);

while(1);

return 0;
}

unsigned int read_cm(unsigned char address)
{
printf("1");
unsigned char lowbyte,highbyte;
unsigned int distance;
printf("2");
i2c_start_wait(address+I2C_WRITE);
printf("3");
while (i2c_write(0));
printf("4");
while (i2c_write(81));
printf("5");
i2c_stop();
printf("6");

i2c_start_wait(address+I2C_WRITE);
printf("7");
while (i2c_write(2));
printf("8");
i2c_stop();
printf("9");

_delay_ms(65);
printf("10");

i2c_start_wait(address+I2C_READ);
printf("11");
highbyte = i2c_readAck();
printf("12");
lowbyte = i2c_readNak();
printf("13");
distance = (highbyte*256)+lowbyte;
printf("14");
i2c_stop();
printf("15");

if(distance > 150)
{
PORTD = 0x00;
printf("6");
}

return distance;

}

linux_80
21.02.2010, 21:59
Ich weiss nicht wie kritisch das hier mit den Pullups ist, ich hab immer 10k. :-k

Kann es sein, das der nicht auf die 0xE0 hört, probier mal die anderen Adressen aus.

Oder noch besser, Du gibst nicht nur diese Zahl aus, sondern auch jeweils den Wert von TWSR, dann sieht man was das TWI gemacht hat. Und man sieht gleich, ob der auf E0 hört.

master123
21.02.2010, 22:28
so ich habe nach den zahlen mal die TWSR ausgeben lassen. leider kann ich auch mit datenblatt das register nicht verstehen. es steht nur twi status. hier mal ein durchlauf.

kurz zum E0 muss eigendlich richtig sein den wenn ich den sensor mit strom versorge leuchtet er einmal auf. laut datenblatt ist es dann e0. wenn ich ihn den befehl zum messen sende, leuchtet er erst ganzschwach auf und dann sofort hell. also müsste er eigendlich messen.

kannst du mir die TWSR Register erklären, hier der durchlauf. (der TWSR wert steht nach dem punkt. die zahl davor ist meine durchlauf kontrolle)

1.248
2.248
3.24
4.40
5.40
6.248
7.24
8.40
9.248
10.248
11.72

master123
21.02.2010, 22:30
wenn ich e0 auf z.b. f1 ändere macht er folgendes:

1.248
2.248
3.72

mehr nicht

master123
21.02.2010, 23:15
auch mit Pullups mit 10k statt 3,3k das gleiche

linux_80
22.02.2010, 00:15
Wenn Du die Werte nach Hex wandelst, findest Du die Erklärung im DB.

1.248 - 0xF8 -> nix passiert
2.248 - 0xF8 -> nix passiert
3. 24 - 0x18 -> SLA+W has been transmitted; ACK has been received
4. 40 - 0x28 -> Data byte has been transmitted; ACK has been received
5. 40 - 0x28 -> ...
6.248 - 0xF8 -> nix passiert
7. 24 - 0x18 -> ...
8. 40 - 0x28 -> ...
9.248 - 0xF8 -> nix passiert
10.248 - 0xF8 -> nix passiert
11. 72 - 0x48 -> SLA+R has been transmitted; NOT ACK has been received

Hier meldet sich der Slave nicht.
Ab hier kann dann gesucht werden, warum er sich nicht angesprochen fühlt (Adresse zB.). ;)

master123
22.02.2010, 22:20
ich hab heute das ganze mal mit einem oszi aufgenommen. leider muss da irgendwas mit der programmierung nicht stimmen. da der atmega128 immer das gleiche sendet. und am anfang gibt es noch schwierigkeiten mit dem pull-up :-k

kann sich das jemand erklären??????? :-s
bei der aufnahme wurde der zweite code verwendet, also der von Fleury.

linux_80
22.02.2010, 22:36
Wenn ich heut noch richtig sehe, wird immer 0xE0 gesendet, aber keine Antwort drauf kommt.
Weisst Du welcher Teil vom Programm das genau ist ?

master123
22.02.2010, 22:43
das erste bild ist der anfang und das zweite mitten drin. aber das ging von anfang bis zum ende so keine veränderung. nur mitten drin, genau in der mitte war funkstille, irgendwie 10-20ms glaube ich war ruhe danach ging es dann weiter.

hab noch eine csv datei 540kb, für genauere analyse :-S

linux_80
22.02.2010, 22:55
Hier kommt dann immer die Stelle, an dem ich nach einem TelefonJoker frage, oder
einen andern I2C-Slave probiere, zB. PCF8574 oder so :-)
um zu sehen wo's denn nun hakt (Software, Hardware, Bioware) ;)

master123
22.02.2010, 23:22
welche nummer sollte ich dann für den TelefonJoker wählen :-D

das doofe ist, ich hab nix anderes da mit i2c. ich hab vorher sonst nur mit spi gearbeitet, und war damit voll zu frieden :-). was mich wundert ist das der sensor doch gut verkauft wird aber nirgendswo etwas brauchbares gibt wo man mal vergleichen kann.

master123
22.02.2010, 23:43
hab nochmal alle anderen adressen gecheckt und nur bei e0 läuft der code bis zu 11 weiter. bei alle anderen kommt nur:
1.248
2.248
mehr nicht.

gibt es hier im forum leute die auch den SRF02 zuhause haben??? und mir über ihre erfahrungen berichten können?!?!?!?

s.frings
07.06.2010, 17:24
Ich habe auch einen SRF-02 gekauft, komme auch nicht klar.

Wenn ich die Firmware-Version auslese, erhalte ich den Wert 5. Ist das richtig? Das Datenblatt enthält dazu keine Info.

Wenn ich den Start-Befehl sende und sofort danach (also eigentlich zu früh) wieder die Firmware Version lese, bekomme ich wieder den Wert 5, ich hatte aber 255 erwartet.

Wenn ich dann 100ms warte und dann die Register 2+3 auslese, bekomme ich immer den Wert 0, ich hatte eine Zahl >15cm erwartet.

Die Led blinkt nur ganz kurz beim Einschalten, danach bleibt sie dunkel. Du hast oben beschrieben, dass die LED reagiert, wenn Du einen Start-Befehl absetzt. Was ist denn nun der Soll-Zustand? Auch hier lässt mich das Datenblatt wieder im Stich.

s.frings
08.06.2010, 12:51
Mein Sensor läuft jetzt. Die Firmware Version ist immer noch 5 (also wohl in Ordnung so), die Status Led blitzt bei jeder Messung einmal kurz auf. Mein Fehler war, dass ich beim Start-Befehl die Zahl falsch geschrieben hatte (0x81 statt 81).