# esp32_temp_display.py
# MicroPython para ESP32 - Lee RTD y Termopar en mV/°C y muestra temperatura en LCD I2C 16x2
# Daniel: ajusta pines y VREF según tu electrónica.
from machine import Pin, ADC, SoftI2C
from lcd_api import LcdApi
from i2c_lcd import I2cLcd
import time
# ----------------- CONFIGURACIÓN LCD I2C -----------------
I2C_ADDR = 0x27 # dirección I2C del adaptador del LCD (ajusta si es otra)
TOTAL_ROWS = 2
TOTAL_COLS = 16
SCL_GPIO = 22
SDA_GPIO = 21
I2C_FREQ = 100000
i2c = SoftI2C(scl=Pin(SCL_GPIO), sda=Pin(SDA_GPIO), freq=I2C_FREQ)
lcd = I2cLcd(i2c, I2C_ADDR, TOTAL_ROWS, TOTAL_COLS)
lcd.backlight_on()
lcd.clear()
# ----------------- CONFIGURACIÓN ADC -----------------
ADC_PIN_RTD = 36 # GPIO36 (VP) -> ADC1_CH0
ADC_PIN_TC = 39 # GPIO39 (VN) -> ADC1_CH3
adc_rtd = ADC(Pin(ADC_PIN_RTD))
adc_tc = ADC(Pin(ADC_PIN_TC))
adc_rtd.atten(ADC.ATTN_11DB) # hasta ~3.3 V
adc_tc.atten(ADC.ATTN_11DB)
# Resolución 16 bits
VREF = 3.3 # Voltaje de referencia práctico (ajustar con multímetro)
# ----------------- PARÁMETROS SENSOR -----------------
# Fórmulas de entrada ya acondicionadas (en mV/°C y mV)
RTD_SLOPE_mV_PER_C = 5.0
RTD_OFFSET_mV = -30.0
TC_SLOPE_mV_PER_C = 4.0
TC_OFFSET_mV = -3.99
# Número de muestras para promediar
SAMPLES = 20
SAMPLE_DELAY = 0.01 # segundos
# Rango válido del termopar
TC_MIN_C = 20.0
TC_MAX_C = 60.0
# ----------------- FUNCIONES AUXILIARES -----------------
def adc_to_voltage(adc_obj):
"""Convierte lectura ADC (0..65535) a voltios (V)."""
raw = adc_obj.read_u16()
return (raw / 65535.0) * VREF
def read_avg_voltage(ad c_obj, samples=SAMPLES, delay=SAMPLE_DELAY):
"""Promedia varias lecturas ADC para reducir ruido."""
total = 0.0
for _ in range(samples):
total += adc_to_voltage(adc_obj)
time.sleep(delay)
return total / samples
def voltage_to_mV(v):
"""Convierte de voltios a milivoltios."""
return v * 1000.0
def temp_from_mV(sensor_mV, slope, offset):
"""Convierte mV del sensor a °C usando la pendiente y offset."""
return (sensor_mV - offset) / slope
def round_to_half_degree(t):
"""Redondea la temperatura a múltiplos de 0.5 °C."""
return round(t * 2.0) / 2.0
def format_temp(t):
"""Devuelve texto con un decimal, ej: '24.5 C'."""
return "{:.1f} C".format(t)
# ----------------- BUCLE PRINCIPAL -----------------
lcd.clear()
lcd.putstr("Iniciando...")
time.sleep(1)
while True:
# Leer voltajes promediados
v_rtd = read_avg_voltage(adc_rtd)
v_tc = read_avg_voltage(adc_tc)
# Convertir a mV
rtd_mV = voltage_to_mV(v_rtd)
tc_mV = voltage_to_mV(v_tc)
# Calcular temperaturas
temp_rtd = temp_from_mV(rtd_mV, RTD_SLOPE_mV_PER_C, RTD_OFFSET_mV)
temp_tc = temp_from_mV(tc_mV, TC_SLOPE_mV_PER_C, TC_OFFSET_mV)
# Redondeo a 0.5 °C
temp_rtd_disp = round_to_half_degree(temp_rtd)
temp_tc_disp = round_to_half_degree(temp_tc)
# Limitar rango del termopar
if temp_tc_disp < TC_MIN_C:
temp_tc_disp = TC_MIN_C
elif temp_tc_disp > TC_MAX_C:
temp_tc_disp = TC_MAX_C
# Mostrar en LCD
line1 = "RTD:{:>6}".format(format_temp(temp_rtd_disp))
line2 = "TC :{:>6}".format(format_temp(temp_tc_disp))
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr(line1)
lcd.move_to(0, 1)
lcd.putstr(line2)
time.sleep(1) # refresco cada segundo