Ich habe einen Code für dem C18 Compiler geschrieben, um mit meinem
PIC18F45k22 über I2C mit dem MPU6050 zu kommunizieren. Ich habe die
Initialisierung geschrieben, und den MPU so konfiguriert, dass ich am
Interrupt-Pin ein Signal erhalte, wenn die Daten bereit sind. Ich kann
aber kein Signal messen, d.h. der Fehler müsste irgendwo in der
Initialisierung oder der I2C-Kommunikation liegen, i finde aber keine.
Kann sich bitte jemand von euch diesen Code ansehen.
Danke
Jetzt habe ich mit derselben I2C Routine ein Programm für den HMC5883L
geschrieben und es hat funktioniert.
Har irgendjemand eine Ahnung woran das liegen könnte?
M.H. schrieb:> ausgeführt wird bleibt der SDA Pin dauerhaft auf 0, das Programm hängt> sich auf.
Was sagt denn die externe Beschaltung deines I2C? Alles beachtet
(pullups, spannungslevel und so)?
Die Pull Up habe ich, die Spannungspegel passen, da die kommunikation am
Anfang und die mit dem HCM5883L funktioniert. Ich versorge den PIC mit
5V und den MPU6050 + HMC5883L mit 3.3V.
M.H. schrieb:> Ich versorge den PIC mit> 5V und den MPU6050 + HMC5883L mit 3.3V.
Warum?
Datenblatt des MPU6050:
VDD: max. 3.46V
VLogic: max. VDD, d.h. 3.46V
High Level an I2C: 0.7*VLOGIC to VLOGIC + 0.5V, d.h. max. 4V.
Hast du das beachtet? Hast du das geregelt? Warum überhaupt zwei
Spannungsversorgungen und nicht einfach alles mit 3.3V?
Das selbe gilt übrigens für den HMC5883L, siehe Datenblatt Seite 7
'SINGLE SUPPLY REFERENCE DESIGN', steht explizit bis 3.6V sowohl VDD als
auch I/O des uC.
Ich habe 2 Versorgunfsspannungen, da am PIC auch noch ein 5V LCD hängt.
Die Spannung auf dem Bus kann nicht zu hoch werden, da die pull up die
auf 3.3V sind. Der PIC erkennt die 3.3V als high, sonst würde es mit dem
HMC5883L ja auch nicht funktionieren.
Die Lösung mit den 2 Spannungen ist nur vorübergehend mit meinem Test
Board. Wenn alles funktioniert werde ich dann eine Platine machen, auf
der alles mit 3.3V arbeitet.
> ausgeführt wird bleibt der SDA Pin dauerhaft auf 0, das Programm hängt> sich auf.
Welchen Wert haben die Pullup-Widerstände? Die werden nämlich meist zu
gross gemacht, dann kommen die Leitungen SDA und SCK (wie bei Dir) nicht
hoch. Für 3.3 Volt sind meist 1k2 oder 1k5 nötig.
Die Pull Up sind 4.7k. Das fürfte aber nicht das Problem sein, da das
Signal auf dem Oszi gut ausschaut und die Kommunikation mit dem HCM5883L
funktioniert. Das Sigak bleib auf >0.5V, es wird activ auf 0 gezogen.
Wenn es mit dem einen IC geht, ist kein Beweis dafür, dass es auch mit
dem anderen gehen muss, HCM5883L und MPU6050 sind doch verschiedene ICs.
Mach die Widerstände mal kleiner, ist doch kein Problem.
Also wenn's mit dem einen IC funktioniert, sollte deine Implementierung
passen (ich benutze auch PICs, habe aber die I2C Routinen selbst
implementiert, daher weiß ich nicht ob man bestimmte Eigenarten bei den
vorgefertigten beachten muss)
Deine Adressen stimmen hoffentlich so weit (konnte ich nicht überprüfen,
da sie im Code-Ausschnitt fehlen).
Dann hast du im MPU Code so einen WHO_AM_I, schon mal ohne probiert?
Vielleicht stimmt da etwas nicht und der MPU hängt danach. Zumal du den
MPU in einer Dauerschleife non-stop initialisierst.
Probiere mal es so wie beim HCM zu machen, initialiesieren, ohne
WHO_AM_I, und in einer Dauer-Schleife Werte auslesen.
Als WHO_AM_I hast du 0x68, d.h. 100 0100, genauso wie im Datenblatt,
jedoch steht ein paar Zeilen weiter drunter 11 0100, d.h. 0x52, als
Default Wert. Ich verstehe den Unterschied nicht, aber vielleicht
einfach mal die ganze Überprüfung weg lassen.
Hast du die Möglichkeit das Programm zu debuggen? Pic-Kit 3, ICD 2, ICD
3, ...
Oder hast du nur ein Programmiergerät?
Entweder über den Debugger oder durch ansteuern einer LED kannst du auch
einmal überprüfen wo sich dein PIC aufhängt (was er vermutlich tut).
D.h. ob die Initialisierungsroutine durchgeführt wird, oder an welcher
Stelle er nicht weiter macht.
Hast du den IC selbst verlötet oder auf einem fertigen Board gekauft?
Ich hatte auch hin und wieder Probleme, als ich noch nicht alles richtig
implementiert hatte, dass sich der PIC (in meinem Fall 24F) nach einem
falschen Befehl jedes mal in der I2C Routine aufgehängt hat. Ich weiß
bis heute nicht ob es am PIC oder am Beschleunigungsensor (ein anderer
als deiner) lag, der nach dem falschen Befehl einfach nicht mehr
reagierte. Erst nach einem Trennen der Stromversorgung hat es wieder
ordnungsgemäß funktioniert.
Für dich heißt das: Trenne hin und wieder mal die Stromversorgung, nicht
dass sich ein IC nach längerem rum probieren aufgehängt hat und den Bus
blockiert.
Hier ist ein neuer Code, mit dem funktioniert es auch nicht.
Ich bin das Programm mit dem PICkit3 im einzelschritt durchgegangen. Ich
habe die Zeile bei der sich das Programm blockiert mit einem Kommentar
versehen. Es passiert bereits beim ersten Durchlauf der while-Schleife.
Frank M. schrieb:> Hast du den IC selbst verlötet oder auf einem fertigen Board gekauft?
Ich habe so eine kleine Platine mit diesem IC bei ebay gekauft.
Also bei der Intitialisierung schreibst du ja auch schon, und da hängt
sich nichts auf, d.h. der IC könnte funktionieren. Daher würde ich
einfach vor und nach dem Write Befehl, und auch sonst, auch mal noch ein
IdleI2C1(); setzen, genauso wie in der MPU6050_Write_Reg Funktion du es
gemacht hast, die ja anscheinend tadellos funktioniert.
Ebenso mach mal die Schleife ganz raus und setze eine leere Schleife an
das Ende der Main() Routine. Dann starte das Programm und pausiere
danach, dann ist es irgendwie 'übersichtlicher' und es besteht nicht die
Gefahr dass die Schleife ein paar mal durchläuft und dann hängt.
Es ist noch ein kleiner Fehler drin:
Wenn du die Daten lesen willst:
1
IdleI2C1();
2
StartI2C1();
3
WriteI2C1(MPU6050_ADDRESS);// Write Hier hängt sich das Programm auf
4
WriteI2C1(MPU6050_RA_ACCEL_XOUT_H);
5
StopI2C1();
6
StartI2C1();
7
WriteI2C1(MPU6050_ADDRESS+1);// Read
Du stoppst und startest den Bus neu, was so nicht gehen sollte.
(Datenblatt S.37 steht auch nicht Stop, sondern nur Start) Du musst
stattdessen eine Repeated Start condition senden, wie genau der Befehl
in der Microchip Library heist, weiß ich nicht, vermutlich
1
RestartI2C();
Vielleicht macht es einen Durchlauf und danach hängt er?
Jetzt ohne schleife: Wenn ich die Zeile MPU6050_Read_Acc_XYZ(&x,&y,&z);
in Einzelschritt mit Step over überspringe hängt sich das Programm nicht
auf, auf dem Display wird für x,y,z 0 ausgegeben. Wenn ich in die
Funktion springe (step into) hängt sich das Programm beim ersten
WriteI2C1(MPU6050_ADDRESS); auf.
Irgendwie komisch, da der Befehl ja bei den Command Bytes schreiben
funktioniert. Hast du die Idle Routinen eingefügt?
Vielleicht schreibst du auch bei den Command Bytes irgendetwas falsches,
probiere einmal die unnötigen auszukommentieren und nur die aller
wichtigsten (d.h. damit der IC angeschalten wird) einzubauen. Vielleicht
ist er auch schon standarmäßig an und du musst vorerst gar kein Command
Byte senden.
Und mach sicher, dass du hin und wieder auch die gesamte Stromversorgung
trennst, damit sich der uC sowie die MPU komplett neu initialisieren
muss und nicht noch irgendwelche falsche Informationen weiter verwendet.
Sorry, aber momentan wüsste ich sonst nicht was schief geht.
Ich werde mir in den kommenden Tagen meine eigene I2C bibliothek
schreiben, dann weis ich genau, was der pic macht. Ich werde bericht
erstatten wenn ich fertig bin...
Was würde ihr bei der bibliothek mache, wenn z.B. kein ACK vom slave
kommt?