Saltar al contenido

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 crc

Proceso de verificación

  1. El sensor envía 7 bytes totales:

    • Byte 0: Estado.
    • Bytes 1-5: Datos de humedad y temperatura.
    • Byte 6: CRC.
  2. El microcontrolador calcula el CRC de los bytes 0-5.

  3. Compara el CRC calculado con el byte 6 recibido.

  4. 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

Código fuente del proyecto original

Código fuente en Micropython

https://www.youtube.com/watch?v=ke_LGPfT4rA