¿Cómo leer los datos de este sensor?

2

Estoy usando MLX90393 IC del magnetómetro de Melexis. Más específicamente, estoy usando el tablero de distribución por 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 he asegurado de progresar lentamente (comenzando por encender los LED, luego escribiendo en las pantallas LCD, etc.) y ahora quiero probar con la detección. Sin embargo, estoy realmente luchando con esto. He leído el protocolo I2C muchas veces para intentar entenderlo y creo que estoy empezando a hacerlo.

Estoy utilizando una placa Nucleo STM32F303K8 para comunicarme con el IC. Estoy usando un LDC serie 16x2 estándar 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. He buscado en el sitio web de mbed los códigos de ejemplo para comenzar y no he encontrado ninguno. Ni siquiera puedo encontrar una biblioteca, aunque su guía de inicio rápido (no puede encontrar un enlace, simplemente descarga un PDF) afirma que hay una en el sitio mbed. He podido encontrar 2 en otra parte, una AQUÍ de GitHub y una AQUÍ para ESP32. El problema es que estos son ejemplos para usar diferentes equipos. El ESP32 está escrito para el Arduino, y no quiero quedarme atascado haciendo Arduino para siempre, así que prefiero no usar eso. He intentado convertirlo para usar con mbed pero obviamente no he tenido éxito. Intenté lo mismo con el código de GitHub, pero tampoco tuve éxito con eso.

A través de estos dos ejemplos, he intentado descifrarlos y convertirlos para usarlos en mbed y he creado el siguiente código:

CÓDIGO ACTUALIZADO PARA EL USO DE LA VERSIÓN ACTUAL.

#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);
    }
}

He ejecutado el código Arduino en el hardware STM32 y he logrado que los datos se muestren en un monitor serie. Cuando ejecuto mi código, obtengo -1 lectura en los 3 ejes.

He cubierto el alcance de las líneas de datos, y puedo confirmar que las líneas SDA y SCL coinciden con las del código de Arduino en funcionamiento, por lo que la mayoría está funcionando. Parece que estoy descifrando los datos incorrectamente, o los estoy mostrando incorrectamente. Uno de esos 2 como el monitor de serie está mostrando algo incorrecto. Esto significa que todo está 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, los registros correctos se leen y se escriben, y los datos se devuelven. He confirmado esto comparando las señales con la versión del código Arduino que funciona .

Antes de preguntar '¿Puede alcanzar este bit' o 'Puede medir eso', lea los registros de chat completos AQUÍ y que mostrará todo lo que he hecho hasta ahora para llegar a este punto.

Solo necesito saber cómo hacer que ese último bit funcione para mostrar la información correctamente.

    
pregunta Curious

2 respuestas

2

Trabajar con el OP y desarrollar la investigación explicada en mi respuesta a esta pregunta relacionada " El escáner I2C no funciona correctamente ", los mismos dos problemas deben solucionarse primero:

  • Desoldar STM32F303K8 Nucleo-32 (NUCLEO-F303K8) en los puentes de soldadura SB16 y SB18 cuando se usan las funciones Mbed I2C.
  • Utilice la llamada "extendida" de 4 parámetros Mbed i2c.write() con la placa Nucleo-32 STM32F303K8.

Como se señaló en otra respuesta, un analizador lógico sería útil en esta situación (y debería usarse, si es posible) los siguientes problemas fueron encontrados y solucionados sin usar uno, dentro del tiempo limitado disponible:

  • La dirección I2C correcta de 7 bits del sensor es 0x0C, pero las llamadas Mbed I2C quieren la versión de 8 bits.

    Las versiones anteriores del código fueron engañadas por un error de impresión en los documentos de SparkFun para su tablero de ruptura con este sensor, donde dijeron que la dirección era 0xC0.

    También algunas versiones de código no cambiaron a la izquierda el valor de la dirección I2C, sin embargo, las funciones Mbed I2C quieren que la dirección se les pase como una versión de 8 bits (por ejemplo, 0x18 en este caso). Así que la solución fue pasarlo como 0x0C << 1 o 0x18 (la misma cosa) a las llamadas I2C de Mbed.

  • Como se señaló en esa otra pregunta vinculada, el acceso I2C usando esta placa Núcleo STM32F303K8 solo es exitoso cuando se usa la Mbed i2c.write() y i2c.read() funciones, con (hasta) 4 parámetros (3 requeridos, 4to opcional) y sin usar el parámetro único de nivel inferior i2c.write() y i2c.read() 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 mediante el sensor. Eso dejó el problema final en la lectura y visualización de los valores del sensor en el código Mbed.

    Mirando en esa parte del código, eliminé la parte que estaba leyendo del sensor varias veces y verificando 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);

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 de trabajo de Arduino, y el punto de la pregunta era llegar a esa etapa. El código puede usarse como punto de partida y mejorarse con la verificación de errores & informes de estado, etc.

Nuevamente, se pueden realizar investigaciones adicionales sobre el comportamiento de I2C de las bibliotecas Mbed y el sensor con un analizador lógico, cuando haya disponible un analizador (y más tiempo).

    
respondido por el SamGibson
2

En lugar de adivinar y hacer modificaciones convulsivas aleatorias a su código, debe obtener un analizador lógico barato ($ 7) de eBay, del cual descarga software gratuito y decodificador I2C, y obtiene I2C Rastros desde su bus de hardware.

Inmediatamenteverásisudirecciónescorrectaono,ycómoresponde(ono)eldispositivo.

MuchosámbitosdigitalesdepropósitogeneralmáscarostienendecodificadoresI2Cenlaactualidad,peroeldispositivode$7hacesutrabajobien.

Seestáembarcandoeneldiseñointegrado,queteníacomoobjetivoproducirseñalizacióndehardware.Elusodeherramientasdehardwareparaanalizarlasseñalesresultantesesunanecesidad.Estedeberíasertupuntodepartida,todolodemásessecundario.Buscarunospocosminutosenelrastreocapturadoleahorrarádíasde"ingeniería aleatoria".

    
respondido por el Ale..chenski

Lea otras preguntas en las etiquetas