PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : problem mit SRF02



sterncapture
23.03.2008, 10:19
Hallo zusammen ,ich hab ein Problem mit dem SRF02,ich hab bis jetzt nur falsche Messung bekommen. ich versuche euch zu erklären was ich genau mache:
-benutze ein STK500
-benutze die ATMEGA8515L
-SRF02
-programmiere mit dem AVR studio 4 also mit c
-benutze die Bibliothek von P.Fleury. hab versucht da was zu ändern wir z.B. Port und Pin nun für SDA und SCL.
-auslesen mit dem Programm :Hterm. eingestellt auf 9600.data 8,stop1 und Parity none

Also den Sensor steuere ich mit dem I2C Schnittstelle und auslesen mit RS232 am PC.
Ich hab am Sensor die Pullup wiederstände angebaut .und kann ausschliessen dass ein Hardware fehler gibt.
Also wenn ich mit (start Debugging) versuche ,bleibt bei i2c_start(0xE0); hängen.
Wenn ich kompiliere läuft alles ok aber beim auslesen bekomme ich nur 255.Ich weiß dass die 255 bekommt man wenn der Sensor nicht mit messen fertig ist aber ich weiß nicht wie ich es bringe fertig zu sein .-)
Also ich würde mich freuen wenn jemand von euch mir sagen kann was ich hier falsch mache.
Hier ist mein Code
.


#include <avr/io.h>
#include "i2cmaster.h"
#define SRF 0xE0
#define F_CPU 8000000UL
#include <util/delay.h>
#define BAUD 9600
#include <avr/iom8515.h>
#include <avr/sfr_defs.h>
#define SDA 0 // SDA Port E, Pin 0
#define SCL 1 // SCL Port E, Pin 1
#define SDA_PORT PORTE // SDA Port E
#define SCL_PORT PORTE // SCL Port E



// USART_INIT--
void initusart(void) // Hauptfunktion
{
unsigned char x; //Hilfsvariable
// #idef UBRRL //USART-Schnittstelle
UBRRL = (F_CPU / (16UL*BAUD)) -1; //Baudrate mit TAKT und Baud
UCSRB |= (1<<TXEN) | (1<<RXEN); //Sender und Empfänger ein
UCSRC |= (1<< URSEL) | (1<< UCSZ1) | (1<<UCSZ0); //ansync 8bit

x = UDR;
}

void sendeusart(int x)
{
while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich
{
}

UDR = x;

}
int distance;
int main(void)

{


int distance =0;
i2c_init();
initusart();
//sendeusart(distance);
unsigned char Lbyte,Hbyte;


DDRE = 0xff;
PORTE = 0xff;


while(1)
{
i2c_init();
i2c_start(0xE0);
i2c_write(0x00);
i2c_write(0x51);
i2c_stop();

_delay_ms(70);



i2c_start(0xE0);

i2c_write(0x02);
i2c_start(0xE0);
i2c_write(0xE1);

Lbyte=i2c_readNak();

Hbyte=i2c_readAck();

distance=(Hbyte*256)+Lbyte;

i2c_stop();


sendeusart(distance);

}

}

ich würde mich sehr freuen für eine Antwort.danke jungs:-)
Alexandra

bernhard1366
25.03.2008, 10:12
Hallo,

ich hab da mal was gehört von den internen Pullups am AVR Board, dass man die aktiviert, sobald man den Pin auf 1 also Eingang stellt. Brauchst du da noch die externen Widerstände für den IIC _ Bus?? Genaueres kann ich dir aber nicht sagen, da ich kein AVR Board benutze und nur mit PICs arbeite.

Aber da könnte auch ein Problem in deiner Routine sein.
Versuchs mal so:

i2c_init();
i2c_start();
i2c_write(0xE0);
i2c_write(0x00);
i2c_write(0x51);
i2c_stop();

_delay_ms(70);

i2c_start();
i2c_write(0xE0);
i2c_write(0x02);
i2c_stop();
i2c_start();
i2c_write(0xE1);

Lbyte=i2c_readNak();

Hbyte=i2c_readAck();

distance=(Hbyte*256)+Lbyte;

i2c_stop();

Kannst Du bei deinen Routinen generell schon bei i2c_start() eine Geräteadresse übergeben? Bist du da sicher? Das mit dem Restart vor dem Auslesen würde ich durch einen i2c_stop() ersetzten(wie oben im Codestück). Blinkt beim Messen eigentlich die Led, damit man davon ausgehen kann, dass der Senor auch misst?

uffi
25.03.2008, 13:36
Meiner Meinung nach hat Bernhard mit beiden Hinweisen unrecht:
1. Die internen Pullups an SDA und SCL sind im AVR bei I2C immer deaktiviert, egal was im PORT Register für die beiden Pins steht.
2. Die Funktion i2c_start(address + {0 oder 1 für Schreiben bzw. Lesen}) erfordert zwingend den o.g. Inhalt als Parameter.

Meiner Meinung nach liegt Dein Fehler hier, Auszug aus Deinem Code:

i2c_start(0xE0); <- Fehler, besser i2c_start(0xE1);
i2c_write(0xE1); <- Fehler, löschen

Lbyte=i2c_readNak(); <- wie bernhard geschrieben hat: hinter den nächsten Befehl schieben

Hbyte=i2c_readAck();


Direkt vor dem Lesen (mit i2c_readAck) müßte es richtig heißen:
i2c_start(0xE1)

Du kannst nicht einfach ohne i2c_start von Schreiben auf Lesen wechseln.

Gruß, Dirk.

bernhard1366
25.03.2008, 17:09
Hallo,

ich sollte meine Vorlaute Klappe halten. Ich werd keine Kommentare mehr über das AVR abgeben, weils ja auch nicht mein Gebiet ist.

Hier das Code Beispiel aus der Doku des Sensors SRF10:

Srf10_slaveid_read = Srf10_slaveid + 1
'Messvorgang in starten
I2cstart
I2cwbyte Srf10_slaveid
I2cwbyte 0
I2cwbyte 81 'in Zentimetern messen
I2cstop

Warteaufmessung:
Waitms 1
Firmware = Srf10_firmware(&He0)
If Firmware = 255 Then Goto Warteaufmessung

I2cstart
I2cwbyte Srf10_slaveid
I2cwbyte 2 Leseregister festlegen
I2cstop
I2cstart
I2cwbyte Srf10_slaveid_read
I2crbyte Hib , Ack
I2crbyte Lob , Nack
I2cstop

Ich hab blöderweise bei i2c_read übersehen, dass sterncapture die beiden Zeilen für das Auslesen von Hbyte und Lbyte verwechselt hat. Es muss so wie in diesem Auszug sein, dann gehts.

mfg.

sterncapture
25.03.2008, 17:19
Hallo Jungs!

Danke für Eure Hilfe. Aber leider funktioniert es immer noch nicht. Ich bekomme immer 255 als Antwort. Ich kann nicht i2c_start() so schreiben, sonst gibt es eine Fehlermeldung. Weil ich die Bibliothek von Pfleury benutze. Aber ich verstehe immer noch nicht, wieso beim Debugg das Programm bei i2c_start(0*E0). Der Sensor blinkt immer und signalisiert, dass er misst, aber ich bekomme immer 255. Jungs, ich bin echt ratlos. Fällt Euch vielleicht noch eine andere Lösung ein. Bitte helft mir!!!! :-)

Mit freundlichen Grüßen
Alexandra

sterncapture
25.03.2008, 17:34
danke bernhard1366:-) kannst du bitte den Code von dem SFR10 auf C sprache übersetzen ,umzu sehen ob es so funktionieren kann,da leider meine kenntnisse was C programmieren angeht nicht so toll sind.
danke sehr .

MFG
Alexandra

bernhard1366
25.03.2008, 17:39
Hallo Sterncaptue

Ich kenne die Bibliothek von Pfleury nicht, da meine IIC - Routinen selber geschrieben sind, also werde ich darüber auch nichts mutmaßen.
Hast du deinen Fehler beim Auslesen schon ausgebessert?
Also du musst zuerst das Hbyte auslesen und dazu den Befehl i2c_readACK() verwenden und dann das Lbyte mit i2c_readNAK().

uffi
26.03.2008, 11:53
Hallo Sterncapture,

lautet Dein Code zum Lesen nun so?

i2c_start(0xE1);
Hbyte=i2c_readAck();
Lbyte=i2c_readNak();
i2c_stop();

Lies Dir bitte noch mal meinen Comment oben durch, ich hab noch kleinere Fehler ausgebessert.

Ansonsten schreib bitte nochmal genau, mit welchem Code Du nun arbeitest.

Gruß, Dirk.

sterncapture
31.03.2008, 13:56
Hallo uffi;
danke für die Erklärung,ich hab genau geschrieben ,was du mir gesagt hast ,leider das Ergibniss ist immer das gleiche hier ist mein Code nochmal :


#include <avr/io.h>
#include "i2cmaster.h"
#define SRF 0xE0
#define F_CPU 8000000UL
#include <util/delay.h>
#define BAUD 9600
#include <avr/iom8515.h>
#include <avr/sfr_defs.h>
#define SDA 0 // SDA Port E, Pin 0
#define SCL 1 // SCL Port E, Pin 1
#define SDA_PORT PORTE // SDA Port E
#define SCL_PORT PORTE // SCL Port E



// USART_INIT--
void initusart(void) // Hauptfunktion
{
unsigned char x; //Hilfsvariable
// #idef UBRRL //USART-Schnittstelle
UBRRL = (F_CPU / (16UL*BAUD)) -1; //Baudrate mit TAKT und Baud
UCSRB |= (1<<TXEN) | (1<<RXEN); //Sender und Empfänger ein
UCSRC |= (1<< URSEL) | (1<< UCSZ1) | (1<<UCSZ0); //ansync 8bit

x = UDR;
}

void sendeusart(int x)
{
while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich
{
}

UDR = x;

}
int distance;
int main(void)

{


int distance =0;
i2c_init();
initusart();
sendeusart(distance);
unsigned char Lbyte,Hbyte;


DDRE = 0xff;
PORTE = 0xff;

while(1)
{

i2c_init();

i2c_start(SRF);
i2c_write(0x00);
i2c_write(0x51);

i2c_stop();

_delay_ms(70);

i2c_start(SRF);

i2c_write(0x02);

i2c_stop();

i2c_start(0xE1);

Hbyte=i2c_readAck();

Lbyte=i2c_readNak();

distance=(Hbyte*256)+Lbyte;

sendeusart(distance);

i2c_stop();

}

}

Danke und ich hoffe das du mir hilfen kannst :-)
Gruss Alexandra

uffi
01.04.2008, 12:30
Hallo Alexandra,

ich habe mir Deinen Code angesehen und kann - bis auf ein paar Unschönheiten - keinen plausiblen Grund finden für den beschriebenen Fehler.

Aber ich hab noch folgende Idee:
- könnte es sein, dass Du im makefile das Assembler-File i2cmaster.S nicht mit kompilieren läßt? Du musst das makefile aus der Bibliothek von Peter Fleury benutzen und dort unter Assembler-Sourcen das File i2cmaster.S aufführen.

Wie stellst Du eigentlich fest, dass Du am I2C Bus nur $FF liest?
Es könnte doch auch sein, dass Deine RS232 Routine fehlerhaft ist.
Um das zu überprüfen, würde ich den gelesenen Wert im EEPROM speichern (das habe ich unten im Code eingefügt).

Ansonsten empfehle ich Dir, Deinen Code wie folgt abgeändert zu übernehmen (Änderungen in Fettdruck):

#include <inttypes.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <math.h>

#include <avr/io.h>
#include "i2cmaster.h"
#define SRF 0xE0
#define F_CPU 8000000UL
#include <util/delay.h>
#define BAUD 9600
#include <avr/iom8515.h>
#include <avr/sfr_defs.h>
#define SDA 0 // SDA Port E, Pin 0
#define SCL 1 // SCL Port E, Pin 1
#define SDA_PORT PORTE // SDA Port E
#define SCL_PORT PORTE // SCL Port E

unsigned int distance EEMEM; // reserve storage space in EEPROM

// USART_INIT--
void initusart(void) // Hauptfunktion
{
unsigned char x; //Hilfsvariable
// #idef UBRRL //USART-Schnittstelle
UBRRL = (F_CPU / (16UL*BAUD)) -1; //Baudrate mit TAKT und Baud
UCSRB |= (1<<TXEN) | (1<<RXEN); //Sender und Empfänger ein
UCSRC |= (1<< URSEL) | (1<< UCSZ1) | (1<<UCSZ0); //ansync 8bit
x = UDR;
}

void sendeusart(int x)
{
while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich
UDR = x;
}

int main(void)
{
i2c_init(); // einmal zu Anfang reicht
initusart();
sendeusart(distance);
unsigned char Lbyte,Hbyte;

DDRE = 0xff;
PORTE = 0xff;

while(1)
{
i2c_start(SRF);
i2c_write(0x00);
i2c_write(0x51);
i2c_stop();

_delay_ms(70);

i2c_start(SRF);
i2c_write(0x02);
i2c_stop();

i2c_start(0xE1);
Hbyte=i2c_readAck();
Lbyte=i2c_readNak();
i2c_stop();

distance=(Hbyte*256)+Lbyte;
eeprom_write_word(&distance,distance); //save to EEPROM

sendeusart(distance);
}
}

Auszug aus dem makefile:

# Target file name (without extension).
TARGET = "Dein Dateiname"

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c

# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC = i2cmaster.S

Gruß, Dirk.

sterncapture
04.04.2008, 10:58
Hallo Dirk,ich hab versucht die letzte Zeit den sensor zum laüfen zu bringen aber immer noch kein Erfolg.-(
der File i2cmaster.S ist schon im Source Files und wenn ich es kompeliere bekomme ich als Antwort :kein fehler vorhandeln.die RS232 Verbindung ist in ordung weil, wenn ich den Sensor von der Mikrokontroller raussiehe,dann lese ich die variable 'x' als empfangener wert .hab versucht mit deinem Programm und so sieht aus:

#include <inttypes.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <math.h>

#include <avr/io.h>
#include "i2cmaster.h"
#define SRF 0xE0
#define F_CPU 8000000UL
#include <util/delay.h>
#define BAUD 9600L
#include <avr/iom8515.h>
#include <avr/sfr_defs.h>
#define SDA 0 // SDA Port E, Pin 0
#define SCL 1 // SCL Port E, Pin 1
#define SDA_PORT PORTE // SDA Port E
#define SCL_PORT PORTE // SCL Port E

unsigned int distance EEMEM; // reserve storage space in EEPROM

// USART_INIT--
void initusart(void) // Hauptfunktion
{
unsigned char x; //Hilfsvariable
// #idef UBRRL //USART-Schnittstelle
UBRRL = (F_CPU / (16L*BAUD)) -1; //Baudrate mit TAKT und Baud
UCSRB |= (1<<TXEN) | (1<<RXEN); //Sender und Empfänger ein
UCSRC |= (1<< URSEL) | (1<< UCSZ1) | (1<<UCSZ0); //ansync 8bit
x = UDR;
}

void sendeusart(int x)
{
while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich

UDR = x;
}

int main(void)
{
i2c_init();
initusart();
sendeusart(distance);
unsigned char Lbyte,Hbyte;

DDRE = 0xff;
PORTE = 0xff;

while(1)
{
i2c_init(); muss ein sonst blinkt der sensor nicht

i2c_start(SRF);
i2c_write(0x00);
i2c_write(0x51);
i2c_stop();

_delay_ms(75);

i2c_start(SRF);
i2c_write(0x02);
i2c_stop();

i2c_start(0xE1);

Hbyte=i2c_readAck();
Lbyte=i2c_readNak();
i2c_stop();
distance=(Hbyte*256)+Lbyte;

eeprom_write_word(&distance,distance); //save to EEPROM

sendeusart(distance);
}
}
ich bekomme jetzt die 0 als antwort(benutze Hyper Terminal fürs Auslesen) was ich komisch finde weil ,die distance ist nicht mehr gleich 0 wie beim vorjerigen Programm.
ich weiss nicht woran es liegt ,dass der sensor immer kein Messwerte gibt .
also ich arbeite mit dem AVR4 Studio.kannst bitte mal guckenich da noch machen kann,oder vielleicht hast ein anderen Programm auf C sprache oder assembler die ich benutzen kann.
bitte Dirk ich verlasse mich auf dich ,bin echt kurz vom Aufgeben.
danke
schöne Grüsse
Alexandra

uffi
04.04.2008, 13:25
Alexandra,

mit source file meintest Du hoffentlich das makefile.

Hab ich das richtig verstanden:

+ bei Deinem ersten Program war distance = $FF (das entspricht dem Lesen des Low Bytes als $FF z.B. wenn der I2C Bus nur auf high steht und das High Byte ist noch der Wert aus der Initialisierung).

+ beim aktuellen Programm ist distance = $00 (das entspricht ja dem Wert bei Initialisierung).

Eigentlich müßte distance doch ein 2-Byte Wert sein, also $FFFF oder $0000, oder?

Was steht denn nach dem Programmlauf im EEPROM für distance?

Gruß, Dirk.

sterncapture
11.04.2008, 03:27
hallo Dirk,die Disatance ist ja 0 dec oder 000 hex.so kann ich das lesen.die EEPROM distance kann ich nicht lesen da ich nur den Wet 0 lesen kann mit dem Programm .
kannst du mir bitte sagen,was ich noch für möglichkeit hab , den sensor zum Messen zu bringen ?scheint die sache echt sehr schwer irgendwie für mich ?
keine Ahnung aber irgendwie ,will der sensor mit mir incht reden :-=
danke
Schöne Grüsse Alexandra

uffi
12.04.2008, 22:31
Also mir fällt dann noch ein:

Häng mal ein Oszilloskop and SDA und SCL und schau Dir an, was da abgeht.

Gruss, Dirk.

sterncapture
12.04.2008, 22:40
hallo Dirk.hab ich schon gemacht und man sieht dass irgendetwas übertragen werd.also ein Zeichen hat man aufjedenfall.das heisst es werd was übertragen.
Ich versuche jetzt mit der Atmega16 statt die 8515 und gucken wir was passieren werd.bis jetzt hab ich probleme mit dem Flach Programm aber hoffe bis nexte woche hab ich schon in griff danke und schönen abend noch
grüsse
alexandra

uffi
13.04.2008, 17:11
Kannst Du denn am Oszi die gesendeten und empfangenen Bytes erkennen? z.B die Addresse und den Befehl, der geschrieben wird und dann später Addresse+1 und das gelesenen Byte?

Du mußt immer schauen, wenn SCL low ist, wie dann die SDA Leitung steht.

So kannst Du die Fehlersuche eingrenzen.

Gruß, Dirk.

sterncapture
22.04.2008, 11:27
hallo Dirk.vielen dank für deine Hilfe,du hast mir echt sehr geholfen.Den Sensor funktionniert jetzt und ist alles ok.
Es lag an den Mikroschip:hab jetzt ein ATmega 16 und an die Pin von SCL und SDA.bin echt froh dass alles so gut gelaufen ist .
Danke nochmal
Alexandra
Schöne Grüsse :-)

s.frings
07.06.2010, 17:48
Hallo sterncapture,
was zeigt denn die LED am Modul im gut-Fall an?

s.frings
08.06.2010, 12:48
Ich hab meinen inzwischen auch ans Laufen bekommen. Die Led blitzt bei jeder Messung kurz auf.