Ich verwende den Magnetometer-IC MLX90393 von Melexis. Genauer gesagt verwende ich das Breakout Board von Sparkfun . Ich bin noch ein Programmieranfänger und versuche zum ersten Mal, Daten über I2C auszulesen. Ich habe darauf geachtet, langsam voranzukommen (beginnend mit dem Umschalten von LEDs, dann dem Schreiben auf LCDs usw.) und möchte mich jetzt an der Wahrnehmung versuchen. Damit tue ich mich allerdings wirklich schwer. Ich habe das I2C-Protokoll viele Male gelesen, um zu versuchen, mich damit zurechtzufinden, und ich glaube, ich beginne damit.
Ich verwende ein STM32F303K8 Nucleo-Board, um mit dem IC zu kommunizieren. Ich verwende ein standardmäßiges serielles 16x2-LDC, um Informationen anzuzeigen. Die IDE, die ich verwende, ist mbed (es ist kostenlos und ich habe es schon einmal verwendet, und es ist nicht kompliziert und erfordert nichts anderes als einen PC, ein Nucleo-Board und ein USB-Kabel)
Im Moment möchte ich nur die Daten lesen können. Ich habe auf der mbed-Website nach Beispielcodes für den Anfang gesucht und keine gefunden. Ich kann nicht einmal eine Bibliothek finden, obwohl ihre Kurzanleitung (kann keinen Link finden, es lädt nur automatisch ein PDF herunter) behauptet, dass es eine auf der mbed-Site gibt. Ich konnte 2 an anderer Stelle finden, eine HIER von GitHub und eine HIER für ESP32. Das Problem ist, dass dies beide Beispiele für die Verwendung unterschiedlicher Geräte sind. Der ESP32 ist für den Arduino geschrieben, und ich möchte nicht für immer mit Arduino stecken bleiben, also würde ich das lieber nicht verwenden. Ich habe versucht, es für die Verwendung mit mbed zu konvertieren, aber offensichtlich war ich nicht erfolgreich. Ich habe das gleiche mit dem GitHub-Code versucht, war aber auch damit erfolglos.
Beim Durchgehen dieser beiden Beispiele habe ich versucht, sie zu entschlüsseln und für die Verwendung in mbed zu konvertieren, und bin auf den folgenden Code gekommen:
CODE AUF AKTUELLE VERSION AKTUALISIERT.
#include "mbed.h"
int addr = 0x0C <<1; // 8bit I2C address
I2C i2c(PB_7 , PB_6); //sda, scl
Serial pc(PA_9, PA_10); //Tx/Rx
int main()
{
char config [4];
char data[7] = {0};
config[0] = 0x60;
config[1] = 0x00;
config[2] = 0x5C;
config[3] = 0x00;
i2c.write(addr, config, 4, false);
i2c.read(addr, data, 1);
config[0] = 0x60;
config[1] = 0x02;
config[2] = 0xB4;
config[3] = 0x02;
i2c.write(addr, config, 4, false);
i2c.read(addr, data, 1);
wait(0.25);
while (1) {
config[0] = 0x3E; // Single measurement mode, ZYX enabled
i2c.write(addr, config, 1, false);
i2c.read(addr, data, 1);
wait(0.1);
config[0] = 0x4E;
i2c.write(addr, config, 1, false); // Read command, followed by ZYX bits set
i2c.read(addr, data, 7);
if(i2c.read(addr, data, 7) == !7) {
printf("ERROR \n");
} else {
int xMag = i2c.read(data[1] * 256 + data[2]);
int yMag = i2c.read(data[3] * 256 + data[4]);
int zMag = i2c.read(data[5] * 256 + data[6]);
printf("X Axis = %d \n", xMag);
printf("Y Axis = %d \n", yMag);
printf("Z Axis = %d \n", zMag);
}
wait(5);
}
}
Ich habe den Arduino-Code auf der STM32-Hardware ausgeführt und es geschafft, die Daten auf einem seriellen Monitor anzuzeigen. Wenn ich meinen Code ausführe, bekomme ich -1 auf allen 3 Achsen gelesen.
Ich habe die Datenzeilen erfasst und kann bestätigen, dass die SDA- und SCL-Zeilen mit denen des funktionierenden Arduino-Codes übereinstimmen, sodass der Großteil davon funktioniert. Es scheint, dass ich die Daten falsch entziffere oder falsch zeige. Einer dieser 2 als serieller Monitor zeigt das Falsche an. Das heißt, bis hierhin ist alles richtig:
if(i2c.read(addr, data, 7) == !7) {
printf("ERROR \n");
} else {
int xMag = i2c.read(data[1] * 256 + data[2]);
int yMag = i2c.read(data[3] * 256 + data[4]);
int zMag = i2c.read(data[5] * 256 + data[6]);
printf("X Axis = %d \n", xMag);
printf("Y Axis = %d \n", yMag);
printf("Z Axis = %d \n", zMag);
}
Dieses Bit scheint nicht das zu tun, was es sollte. Alles andere funktioniert wie es sollte, die richtigen Register werden gelesen und beschrieben und die Daten werden zurückgesendet. Ich habe dies bestätigt, indem ich die Signale mit der Arduino-Codeversion verglichen habe, die funktioniert .
Bevor Sie fragen „Können Sie dieses Bit erfassen“ oder „Können Sie das messen“, lesen Sie bitte die vollständigen Chatprotokolle HIER und HIER , die alles zeigen, was ich bisher getan habe, um bis zu diesem Punkt zu gelangen.
Ich muss nur wissen, wie ich das letzte Bit zum Laufen bekomme, um die Informationen korrekt anzuzeigen.
In Zusammenarbeit mit dem OP und aufbauend auf der Untersuchung, die in meiner Antwort auf diese verwandte Frage " I2C-Scanner funktioniert nicht richtig " erklärt wurde, mussten zuerst dieselben zwei Probleme behoben werden:
i2c.write()
mit dem STM32F303K8 Nucleo-32-Board.Wie in einer anderen Antwort erwähnt, wäre ein Logikanalysator in dieser Situation hilfreich (und sollte nach Möglichkeit verwendet werden). Die folgenden Probleme wurden innerhalb der begrenzten verfügbaren Zeit ohne Verwendung eines gefunden und behoben:
Die korrekte 7-Bit-I2C-Adresse des Sensors ist 0x0C, aber die Mbed-I2C-Aufrufe wollen die 8-Bit-Version.
Frühere Versionen des Codes wurden durch einen Druckfehler in den SparkFun-Dokumenten für ihr Breakout-Board mit diesem Sensor in die Irre geführt, wo sie sagten, die Adresse sei 0xC0.
Einige Codeversionen haben diesen I2C-Adresswert auch nicht nach links verschoben, aber die Mbed-I2C-Funktionen möchten, dass die Adresse als 8-Bit-Version an sie übergeben wird (z. B. 0x18 in diesem Fall). 0x0C << 1
Die Lösung bestand also darin, es entweder als oder 0x18
(dasselbe) an die Mbed I2C-Aufrufe weiterzugeben .
Wie in dieser anderen verknüpften Frage erwähnt, ist der I2C-Zugriff mit diesem STM32F303K8 Nucleo-Board nur erfolgreich, wenn das Mbed i2c.write()
und i2c.read()
die Funktionen mit (bis zu) 4 Parametern (3 erforderlich, 4. optional) verwendet werden und nicht stattdessen die einzelnen Parameter i2c.write()
und Aufrufe der unteren Ebene verwendet werden i2c.read()
.
An diesem Punkt konnte das OP beim Vergleich der I2C-Busaktivität im Umfang zwischen dem Arduino-Code und dem Mbed-Code erkennen, dass die I2C-Busaktivität jetzt identisch war, bis zu dem Punkt, an dem die Messung durch den Sensor ausgelöst wurde. Damit blieb das letzte Problem beim Auslesen und Anzeigen der Werte vom Sensor im Mbed-Code.
Als ich in diesen Teil des Codes schaute, entfernte ich den Teil, der mehrmals vom Sensor gelesen wurde, und suchte nach einem falschen Rückgabecode. Daher habe ich einen Teil des ursprünglichen Codes geändert von:
config[0] = 0x4E;
i2c.write(addr, config, 1, false); // Read command, followed by ZYX bits set
i2c.read(addr, data, 7);
if(i2c.read(addr, data, 7) == !7) {
printf("ERROR \n");
} else {
int xMag = i2c.read(data[1] * 256 + data[2]);
int yMag = i2c.read(data[3] * 256 + data[4]);
int zMag = i2c.read(data[5] * 256 + data[6]);
printf("X Axis = %d \n", xMag);
printf("Y Axis = %d \n", yMag);
printf("Z Axis = %d \n", zMag);
}
Zu
config[0] = 0x4E;
i2c.write(addr, config, 1, false); // Read command, followed by ZYX bits set
i2c.read(addr, data, 7);
int xMag = ((data[1] * 256) + data[2]);
int yMag = ((data[3] * 256) + data[4]);
int zMag = ((data[5] * 256) + data[6]);
printf("X Axis = %d \n", xMag);
printf("Y Axis = %d \n", yMag);
printf("Z Axis = %d \n", zMag);
Die vollständige Version des Arbeitscodes lautet also:
#include "mbed.h"
int addr = 0x0C <<1; // 8bit I2C address
I2C i2c(PB_9 , PB_8); //sda, scl
Serial pc(PA_2, PA_3); //Tx/Rx
int main()
{
char config [4];
char data[7] = {0};
config[0] = 0x60;
config[1] = 0x00;
config[2] = 0x5C;
config[3] = 0x00;
i2c.write(addr, config, 4, false);
i2c.read(addr, data, 1);
config[0] = 0x60;
config[1] = 0x02;
config[2] = 0xB4;
config[3] = 0x02;
i2c.write(addr, config, 4, false);
i2c.read(addr, data, 1);
wait(0.25);
while (1) {
config[0] = 0x3E; // Single measurement mode, ZYX enabled
i2c.write(addr, config, 1, false);
i2c.read(addr, data, 1);
wait(0.1);
config[0] = 0x4E;
i2c.write(addr, config, 1, false); // Read command, followed by ZYX bits set
i2c.read(addr, data, 7);
int xMag = ((data[1] * 256) + data[2]);
int yMag = ((data[3] * 256) + data[4]);
int zMag = ((data[5] * 256) + data[6]);
printf("X Axis = %d \n", xMag);
printf("Y Axis = %d \n", yMag);
printf("Z Axis = %d \n", zMag);
wait(5);
}
}
Mit diesem Mbed-Code erzeugt der Sensor eine korrekte Ausgabe, ähnlich wie der funktionierende Arduino-Code, und der Punkt der Frage war, zu diesem Stadium zu gelangen. Der Code kann dann als Ausgangspunkt verwendet und mit Fehlerprüfung und Statusberichten usw. verbessert werden.
Auch hier können weitere Untersuchungen des I2C-Verhaltens der Mbed-Bibliotheken und des Sensors mit einem Logikanalysator durchgeführt werden, wenn ein Analysator (und mehr Zeit) verfügbar ist.
Anstatt zu raten und willkürlich krampfhafte Änderungen an Ihrem Code vorzunehmen, sollten Sie sich einen billigen ($ 7) Logikanalysator von eBay besorgen, für den Sie kostenlose Software und I2C-Decoder herunterladen und I2C-Traces von Ihrem Hardwarebus erhalten.
Sie sehen sofort, ob Ihre Adresse korrekt ist oder nicht und wie das Gerät reagiert (oder nicht).
Viele teurere digitale Allzweck-Oszilloskope haben heutzutage I2C-Decoder, aber das 7-Dollar-Gerät macht seine Arbeit gut.
Sie beginnen mit eingebettetem Design, was bedeutet, Hardware-Signalisierung zu erzeugen. Die Verwendung von Hardware-Tools zur Untersuchung der resultierenden Signale ist ein Muss. Dies sollte Ihr Ausgangspunkt sein, alles andere ist zweitrangig. Wenn Sie einige Minuten lang in die erfasste Spur schauen, sparen Sie Tage des "Random Engineering".
David Tweed
M KS
Neugierig
EE_sozial
Neugierig
EE_sozial
Neugierig
Neugierig
Neugierig
SamGibson
const int addr = 0x0C; // 8bit I2C address
falsch ist, da die Variableaddr
direkt in I2C-Funktionsaufrufen (mehrere) wie übergeben wird. Wiei2c.write(addr, config, 4);
wir aus dem Chat wissen, kann es jedoch andere Probleme geben (z Diese Adresse richtig zu bekommen, wird Teil jeder Lösung sein :-)Neugierig
SamGibson
addr
direkt übergibt. Das heißtaddr
muss 0x18 sein. Alternativ könnten Sieaddr << 1
in den Aufrufen auch 0x0C verwenden und müsseni2c.write()
dann 0x0C sein.addr
Fang dich morgen.Neugierig
Neugierig