La lectura de datos de aceleración ADXL345 parece extraña - STM8

0

después de descubrir finalmente cómo crear una conexión SPI de software, ahora puedo leer los datos de un sensor de aceleración ADXL345. Pero me parecen bastante extraños, estos son algunos valores de muestra:

X: -252 Y: -532 Z: 9616

Estos valores se miden en modo + -16g con total precisión (así que básicamente tenemos 4mg / LSB). Estos valores están en mG (por ejemplo, un valor de 1000 representaría 1G). No entiendo bien por qué el valor Z es tan alto?

Inicializo el ADXL345 con este código:

write_command = ((0x00 | 0x31) << 8) | 0b01001011;//set SPI 3wire & 16g range & full-res
write_command = ((0x00 | 0x2D) << 8) | 0x08; //Enable measurements

Envío los valores a través de uart a un convertidor UART / USB. Los valores cambian si comienzo a mover la placa del sensor, así que creo que mi parte de lectura es correcta:

//read X-Axis
x0 = readRegister(0x80 | 0x32);
x1 = readRegister(0x80 | 0x33);

//read Y-Axis
y0 = readRegister(0x80 | 0x34);
y1 = readRegister(0x80 | 0x35);

//read Z-Axis
z0 = readRegister(0x80 | 0x36);
z1 = readRegister(0x80 | 0x37);

//convert in milli-G [4.0mg/LSB] in +/- 16g mode @ full-res
x = ((x1 << 8) | x0);
y = ((y1 << 8) | y0);
z = ((z1 << 8) | z0);

*x_val = x * 4;
*y_val = y * 4;
*z_val = z * 4;

¿Tiene alguna idea de lo que hago mal en la parte de procesamiento de datos?

    
pregunta binaryBigInt

2 respuestas

2

Poniendo mi comentario original en una respuesta ahora que has pegado tu código aquí.

  1. Mi sospecha era correcta: estás perdiendo tu byte superior al apartarlos, porque has declarado z0 / z1 como uint8_t. Entonces (z0 < < 8) siempre se convierte en 0x00. Haz estos uint16_t en su lugar.
  2. Creo que su comunicación probablemente esté bien, como mencionó, pero una forma de comprobarlo es verificar el registro de WHO_AM_I. La mayoría de los dispositivos tienen algo como esto (podría llamarlo diferente). El registro ADXL345 WHO_AM_I está en 0x00 y está codificado a 0xE5 (o 345 octales, yuk yuk, ingenieros de dispositivos analógicos inteligentes). Lo primero que debe hacer su función enableADXL () es verificar este registro y buscar la respuesta codificada como se esperaba. Si no coincide, su canal de comunicaciones está roto, por lo que no tiene sentido continuar.
  3. Como parece que está imprimiendo x, y y z (no x_val, y_val y z_val), 1g será de aproximadamente 250 LSB, así que nuevamente verifique que su dispositivo no esté de lado porque su X El valor del eje es -252.

Pero creo que el # 1 te solucionará.

    
respondido por el Joel Wigton
0

Creo que tus conversiones implícitas podrían estarte arruinando. Esto es del código en su enlace:

    uint8_t x0 = 0;
    uint8_t x1 = 0;

    int16_t x = 0;

    //read X-Axis
    x0 = readRegister(0x80 | 0x32);
    x1 = readRegister(0x80 | 0x33);

    //convert in milli-G [4.0mg/LSB] in +/- 16g mode @ full-res
    x = ((x1 << 8) | x0);

    *x_val = x * 4;

Como x1 es un uint8_t, la instrucción (x1 << 8) desplaza todos los bits, dejando solo ceros. En su lugar, pruebe este encasillado:

    x = (((uint16_t)(x1) << 8) | x0);

O, simplemente puedes declarar x1 como uint16_t.

De forma similar, dependiendo de su compilador, es posible que deba hacer una conversión explícita del valor uint16_t a un valor int16_t cuando se lo asigne a x. En conjunto, esto se vería como:

'x = (int16_t)(((uint16_t)(x1) << 8) | x0);'
    
respondido por el bitsmack

Lea otras preguntas en las etiquetas