Estoy luchando por 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.
Encontré un ejemplo en línea, pero no da el valor correcto en Lux, la ecuación utilizada allí es esta:
/*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 incorrectos de acuerdo con mi medidor de lux que tengo como referencia y, por ejemplo, el medidor de lux dice que es 420 lux dentro de la oficina. 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 asegurarme al 100% de que no es un problema relacionado con el sensor.
El resultado es muy parecido si solo tomo result = raw&0x0FFF;
, pero luego falla en 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 código 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 antigua fórmula que se me ocurrió, pero da resultados aún más ridículos que la anterior 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 anterior.
Además, me sorprende que dentro de la hoja de datos, TI no proporcionó una fórmula de conversión.
Cualquier ayuda es muy apreciada.
En la página 20
de la hoja de datos se da la descripción detallada del cálculo. Del valor de ejemplo dado de los comentarios, 0x5461
obtenemos el 0x5
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
el 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 ejecutarlo aquí .
Preste mucha atención a los tipos de datos utilizados, es posible que también le hayan causado problemas.
463
están en hexadecimal.lux
es una medida subjetiva (coincidente con el ojo humano), muy afectada por las longitudes de onda además de la intensidad. Por lo tanto, realmente necesita proporcionar condiciones idénticas para ambos sensores al medir. Y puede probar la prueba continua para verificar cómo cambian los valores al aumentar o disminuir la luz. Si cambian gradualmente sin muchos saltos, es una buena indicación de que se miden correctamente (hasta el sesgo del sensor...)
Eugenio Sh.
david kasabji
Eugenio Sh.
david kasabji
Eugenio Sh.
Eugenio Sh.
david kasabji
Transeúnte
Eugenio Sh.
Transeúnte
Eugenio Sh.
Bence Kaulics