Hora del código #55
Al trabajar con los sensores AHT20 y BMP280 para una estación meteorológica, dos mecanismos técnicos destacan por su importancia: la verificación CRC en el AHT20 y el cálculo de t_fine en el BMP280.
1. Verificación CRC en el AHT20
Función del CRC
El AHT20 implementa un CRC8 (Cyclic Redundancy Check) para detectar errores en la transmisión I²C. Cada lectura incluye 6 bytes de datos más 1 byte de CRC calculado sobre los primeros 6 bytes.
Algoritmo CRC8
El polinomio utilizado es:
CRC[7:0] = 1 + X⁴ + X⁵ + X⁸
Representación hexadecimal: 0x31
Implementación en MicroPython:
def calcular_crc(datos):
crc = 0xFF # Valor inicial
for byte in datos:
crc ^= byte
for _ in range(8):
if crc & 0x80:
crc = (crc << 1) ^ 0x31
else:
crc = crc << 1
crc &= 0xFF
return crcProceso de verificación
El sensor envía 7 bytes totales:
- Byte 0: Estado.
- Bytes 1-5: Datos de humedad y temperatura.
- Byte 6: CRC.
El microcontrolador calcula el CRC de los bytes 0-5.
Compara el CRC calculado con el byte 6 recibido.
Si no coinciden, descarta la lectura.
2. Compensación de Temperatura con t_fine en el BMP280
El problema
Los sensores piezorresistivos como el BMP280 responden tanto a cambios de presión como de temperatura. Las lecturas de presión deben compensarse térmicamente para obtener valores precisos.
Variable t_fine
t_fine es un entero de 32 bits con signo que almacena la temperatura en alta resolución. Se calcula durante la compensación de temperatura y se utiliza posteriormente para compensar la presión.
Cálculo de t_fine
Código del datasheet:
BMP280_S32_t t_fine;
BMP280_S32_t bmp280_compensate_T_int32(BMP280_S32_t adc_T)
{
BMP280_S32_t var1, var2, T;
// Componente lineal
var1 = ((((adc_T>>3) - ((BMP280_S32_t)dig_T1<<1)))
* ((BMP280_S32_t)dig_T2)) >> 11;
// Componente cuadrático (no-linealidad)
var2 = (((((adc_T>>4) - ((BMP280_S32_t)dig_T1))
* ((adc_T>>4) - ((BMP280_S32_t)dig_T1))) >> 12)
* ((BMP280_S32_t)dig_T3)) >> 14;
t_fine = var1 + var2;
// Temperatura en centésimas de grado
T = (t_fine * 5 + 128) >> 8;
return T;
}Uso en compensación de presión
El algoritmo de presión utiliza t_fine directamente:
BMP280_U32_t bmp280_compensate_P_int64(BMP280_S32_t adc_P)
{
BMP280_S64_t var1, var2, p;
// Usa t_fine previamente calculado
var1 = ((BMP280_S64_t)t_fine) - 128000;
var2 = var1 * var1 * (BMP280_S64_t)dig_P6;
var2 = var2 + ((var1*(BMP280_S64_t)dig_P5)<<17);
var2 = var2 + (((BMP280_S64_t)dig_P4)<<35);
var1 = ((var1 * var1 * (BMP280_S64_t)dig_P3)>>8)
+ ((var1 * (BMP280_S64_t)dig_P2)<<12);
var1 = (((((BMP280_S64_t)1)<<47)+var1))
*((BMP280_S64_t)dig_P1)>>33;
if (var1 == 0) return 0;
p = 1048576 - adc_P;
p = (((p<<31) - var2) * 3125) / var1;
var1 = (((BMP280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25;
var2 = (((BMP280_S64_t)dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)dig_P7)<<4);
return (BMP280_U32_t)p;
}Impacto de la compensación
Sin compensación térmica: - Error de ±2 hPa por cada 10°C de variación. - Equivale a ±17 metros de error en altitud.
Con compensación mediante t_fine: - Precisión típica: ±1 hPa absoluto. - Precisión relativa: ±0.12 hPa (±1 metro de altitud).
Implementación en MicroPython
Ambos mecanismos se implementan en el código adaptado:
# Verificación CRC (AHT20)
if calcular_crc(datos[0:6]) != datos[6]:
return None # Descarta lectura corrupta
# Compensación térmica (BMP280)
t_fine = calcular_t_fine(adc_T) # Calcular primero
presion = compensar_presion(adc_P, t_fine) # Usar en presión