¿Fórmula / ecuación de conversión OPT3001?

2

Estoy luchando para encontrar una fórmula de conversión real para convertir el valor RAW en un resultado que tenga sentido. Estoy usando un sensor OPT3001 de TI y ATTiny25 como MUC.

He encontrado un ejemplo en línea, pero no da el valor correcto en Lux, la ecuación utilizada es la siguiente:

/*Convert to LUX*/
//extract result & exponent data from raw readings
result = raw&0x0FFF;
exponent = (raw>>12)&0x000F;
lux=0.01*pow(2,eksponent)*result;

Esto da valores erróneos según mi medidor de Lux que tengo como referencia y, por ejemplo, el medidor de lux dice que es 420 lux dentro de Office ... la ecuación anterior me da el resultado 110 Lux , que no es realista. El sensor funciona bien ya que lo reemplacé por uno nuevo, para estar al 100% de que no se trata de un problema relacionado con el sensor.

El resultado está muy cerca si tomo solo result = raw&0x0FFF; , pero luego falla a valores más altos (cuando coloco mi sensor debajo de la bombilla de la lámpara).

No creo que sea un error dentro de mi código I2C, pero adjuntaré aquí también la parte de mi coude para UpdateLight:

// I2C OPT address
#define OPT_ADDR_W  0x88
#define OPT_ADDR_R  0x89

// I2C OPT registers
#define OPT_RESULT_REG  0x00
#define OPT_CONFIG_REG  0x01

// OPT config bits - automatic full scale mode, 100 ms conversion, single-shot
#define OPT_CONFIGURATION_H 0xC2
#define OPT_CONFIGURATION_L 0x00

void UpdateLight(void)
{
    uint8_t error = 0;
    // start conversion
    I2C_Start();
    error |= I2C_Write(OPT_ADDR_W);
    error |= I2C_Write(OPT_CONFIG_REG);
    error |= I2C_Write(OPT_CONFIGURATION_H);
    error |= I2C_Write(OPT_CONFIGURATION_L);
    I2C_Stop();

    // wait for conversion
    _delay_ms(150);

    // set result register
    I2C_Start();
    error |= I2C_Write(OPT_ADDR_W);
    error |= I2C_Write(OPT_RESULT_REG);
    I2C_Stop();

    // read data and update scratchpad
    I2C_Start();
    error |= I2C_Write(OPT_ADDR_R);
    if (error == 0)
    {
        scratchpad[1] = I2C_Read(1);
        scratchpad[0] = I2C_Read(0);
    }
    else
    {
        // report error value
        scratchpad[1] = 0xFF;
        scratchpad[0] = 0xFF;
    }
    I2C_Stop();
    }

Y esta es mi fórmula anterior que se me ocurrió, pero da resultados aún más ridículos que los anteriores de internet:

   // calculate light ( LUX = (MANTISA << EXPONENT) / 100 )
   light = (int16_t)((float)((uint32_t)((spad[SPAD_MSB] << 8) | spad[SPAD_LSB]) << (uint32_t)((spad[SPAD_MSB] >> 4) & 0x0F)) / (83865.60 / LIGHT_MULTIPLIER));
   debug_printf("L_RAW: %02X%02X\r\n", spad[SPAD_MSB], spad[SPAD_LSB]);
   debug_printf("L_VAL: %d\r\n", light); 

Agregando las líneas de salida de las declaraciones de impresión anteriores:

  

L: 5460 - 824

     

L: 5464 - 824

     

L: 5462 - 824

     

L: 5462 - 824

El primer valor debe ser RAW MSB y LSB, y el segundo es el valor convertido a Lux, utilizando la fórmula que aparece más arriba.

Además, me sorprende que dentro de la Hoja de datos, TI no haya proporcionado una fórmula de conversión.

Cualquier ayuda es muy apreciada.

    
pregunta David Kasabji

1 respuesta

3

En la página 20 de la hoja de datos se proporciona una descripción detallada del cálculo. Del valor de ejemplo dado de los comentarios 0x5461 obtenemos el 0x5 para el valor del exponente, que corresponde a 0.32 lux per LSB . La mantisa es 0x461 o 1121 en decimal. El valor resultante es 1121*0.32=358.72lux , que está cerca del rango esperado.

El código de conversión de trabajo:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint16_t raw = 0x5461;
    uint16_t result, exponent;
    float lux;

    result = raw & 0x0FFF;
    exponent = (raw>>12) & 0x000F;

    lux=0.01*(1<<exponent)*result;

    printf("%f\n", lux);
    return 0;
}

O ejecútelo aquí .

Por favor, preste mucha atención a los tipos de datos utilizados, también podrían haberle causado problemas ...

    
respondido por el Eugene Sh.

Lea otras preguntas en las etiquetas