Estoy usando el Magnetómetro IC MLX90393 de Melexis. Más específicamente, estoy usando la placa de ruptura de Sparkfun . Todavía soy un principiante en lo que respecta a la programación, y esta es la primera vez que intento leer datos a través de I2C. Me aseguré de progresar lentamente (comencé cambiando los LED, luego escribiendo en los LCD, etc.) y ahora quiero probar la detección. Sin embargo, estoy realmente luchando con esto. He leído el protocolo I2C muchas veces para tratar de entenderlo y creo que estoy empezando a hacerlo.
Estoy usando una placa Nucleo STM32F303K8 para comunicarme con el IC. Estoy usando un LDC serial estándar de 16x2 para mostrar información. El IDE que estoy usando es mbed (es gratis y lo he usado antes, y no es complicado, y no requiere nada más que una PC, placa Nucleo y cable USB)
Por ahora, todo lo que quiero hacer es poder leer los datos. Busqué en el sitio web de mbed códigos de ejemplo para comenzar y no encontré ninguno. Ni siquiera puedo encontrar una biblioteca, aunque su guía de inicio rápido (no puede encontrar un enlace, solo descarga automáticamente un PDF) afirma que hay uno en el sitio de mbed. He podido encontrar 2 en otros lugares, uno AQUÍ de GitHub y otro AQUÍ para ESP32. El problema es que ambos son ejemplos del uso de diferentes equipos. El ESP32 está escrito para Arduino, y no quiero quedarme atrapado haciendo Arduino para siempre, así que prefiero no usarlo. He intentado convertirlo para usarlo con mbed pero obviamente no he tenido éxito. Intenté lo mismo con el código de GitHub, pero tampoco tuve éxito con eso.
Al revisar estos dos ejemplos, intenté descifrarlos y convertirlos para usarlos en mbed y obtuve el siguiente código:
CÓDIGO ACTUALIZADO A LA VERSIÓN ACTUAL USO.
#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);
}
}
Ejecuté el código Arduino en el hardware STM32 y logré mostrar los datos en un monitor en serie. Cuando ejecuto mi código, obtengo -1 lectura en los 3 ejes.
He analizado las líneas de datos y puedo confirmar que las líneas SDA y SCL coinciden con las del código Arduino en funcionamiento, por lo que la mayoría de esto funciona. Parece que estoy descifrando los datos incorrectamente o mostrándolos incorrectamente. Uno de esos 2 como el monitor serial muestra algo incorrecto. Esto significa que todo es correcto hasta aquí:
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);
}
Este bit no parece estar haciendo lo que debería. Todo lo demás funciona como debería, se leen y escriben los registros correctos y se devuelven los datos. Lo he confirmado comparando las señales con la versión del código Arduino que funciona .
Antes de preguntar '¿Puede medir este bit?' o '¿Puede medir eso?', lea los registros completos del chat AQUÍ y AQUÍ , que mostrarán todo lo que he hecho hasta ahora para llegar a este punto.
Solo necesito saber cómo hacer que funcione ese último bit para mostrar la información correctamente.
Trabajando con el OP y sobre la base de la investigación explicada en mi respuesta a esta pregunta relacionada " El escáner I2C no funciona correctamente ", los mismos dos problemas debían solucionarse primero:
i2c.write()
con la placa STM32F303K8 Nucleo-32.Como se señaló en otra respuesta, un analizador lógico sería útil en esta situación (y debe usarse, si es posible), se encontraron y solucionaron los siguientes problemas sin usar uno, dentro del tiempo limitado disponible:
La dirección I2C de 7 bits correcta del sensor es 0x0C, pero las llamadas I2C de Mbed quieren la versión de 8 bits.
Las versiones anteriores del código fueron engañadas por un error tipográfico en los documentos de SparkFun para su placa de conexión que usaba este sensor, donde decían que la dirección era 0xC0.
Además, algunas versiones de código no desplazaron a la izquierda ese valor de dirección I2C, sin embargo, las funciones Mbed I2C quieren que se les pase la dirección como una versión de 8 bits (por ejemplo, 0x18 en este caso). Entonces, la solución fue pasarlo como 0x0C << 1
o 0x18
(lo mismo) a las llamadas Mbed I2C.
Como se señaló en esa otra pregunta vinculada, el acceso I2C con esta placa Nucleo STM32F303K8 solo es exitoso cuando se usa el Mbed i2c.write()
y i2c.read()
las funciones, con (hasta) 4 parámetros (3 requeridos, 4to opcional) y no usando el parámetro único de nivel inferior i2c.write()
y i2c.read()
las llamadas en su lugar .
En este punto, al comparar la actividad del bus I2C en el alcance entre el código Arduino y el código Mbed, el OP pudo ver que la actividad del bus I2C ahora era idéntica, hasta el punto de activar la medición por parte del sensor. Eso dejó el problema final en la lectura y visualización de los valores del sensor en el código Mbed.
Mirando esa parte del código, eliminé la parte que estaba leyendo del sensor varias veces y comprobé si había un código de retorno incorrecto. Por lo tanto, cambié parte del código original de:
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);
}
a
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);
Así que la versión completa del código de trabajo es:
#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);
}
}
Con este código Mbed, el sensor produce una salida correcta, similar al código Arduino en funcionamiento, y el objetivo de la pregunta era llegar a esa etapa. Luego, el código puede usarse como punto de partida y mejorarse con verificación de errores e informes de estado, etc.
Una vez más, las investigaciones adicionales del comportamiento I2C de las bibliotecas Mbed y el sensor se pueden realizar con un analizador lógico, cuando se dispone de un analizador (y más tiempo).
En lugar de adivinar y hacer modificaciones convulsivas aleatorias a su código, debe obtener un analizador lógico económico ($ 7) de eBay, para el cual descarga software gratuito y un decodificador I2C, y obtiene rastros I2C de su bus de hardware.
Inmediatamente verá si su dirección es correcta o no, y cómo responde (o no) el dispositivo.
Hoy en día, muchos osciloscopios digitales de uso general más caros tienen decodificadores I2C, pero el dispositivo de $ 7 hace bien su trabajo.
Usted se está embarcando en un diseño integrado, que pretendía producir señalización de hardware. El uso de herramientas de hardware para observar las señales resultantes es imprescindible. Este debería ser tu punto de partida, todo lo demás es secundario. Buscar unos minutos en el rastro capturado le ahorrará días de "ingeniería aleatoria".
david tweed
M KS
Curioso
EE_social
Curioso
EE_social
Curioso
Curioso
Curioso
Sam Gibson
const int addr = 0x0C; // 8bit I2C address
es incorrecta, ya que la variableaddr
se pasa directamente en las llamadas de función I2C (varias) comoi2c.write(addr, config, 4);
Como sabemos por el chat, puede haber otros problemas (por ejemplo, la necesidad de usar una llamada API I2C mbed diferente) pero obtener esa dirección correcta será parte de cualquier solución :-)Curioso
Sam Gibson
addr
directamente. Eso significa queaddr
debe ser 0x18. Alternativamente, podría usaraddr << 1
en las llamadas ai2c.write()
y luegoaddr
debe ser 0x0C. Te veo mañana.Curioso
Curioso