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
Ich habe mit dem Oszi gemessen und gesehen, dass der Fehler in der I0C Routine selbst liegen müsste. Während der Befehl
1 | MPU6050_Write_Reg(MPU6050_RA_ACCEL_CONFIG,0b00011000); // +/- 16 g |
ausgeführt wird bleibt der SDA Pin dauerhaft auf 0, das Programm hängt sich auf. Die I2C-Lib ist die, die bereits im C18 enthalten ist.
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.
Sobald sich das Programm blockiert ist die SDA-Leitung auf Masse. In ASM-Listing werden diese beiden Zeilen in eine Endlosschleife ausgeführt.
1 | 0D16 B0C7 BTFSC SSP1STAT, 0, ACCESS |
2 | 0D18 D7FE BRA 0xd16 |
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?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.