from machine import Pin, ADC, PWM, I2C
from lcd_i2c import LCD
import time, math, network, socket
# =========================
# Configuración WiFi
# =========================
SSID = "TuSSID"
PASS = "TuClave"
# =========================
# Clave de usuario para cambiar persianas
# =========================
USER_PASSWORD = "1234" # cambiar según necesidad
# =========================
# Configuración hardware (igual que antes)
# =========================
adc_int = ADC(Pin(34))
adc_int.atten(ADC.ATTN_11DB)
adc_int.width(ADC.WIDTH_12BIT)
adc_ext = ADC(Pin(35))
adc_ext.atten(ADC.ATTN_11DB)
adc_ext.width(ADC.WIDTH_12BIT)
servo = PWM(Pin(23), freq=50)
sda = Pin(21, Pin.OUT)
scl = Pin(22, Pin.OUT)
i2c = I2C(0, sda=sda, scl=scl, freq=400000)
lcd_addr = i2c.scan()[0]
lcd = LCD(addr=lcd_addr, cols=16, rows=2, i2c=i2c)
lcd.begin()
boton_modo = Pin(18, Pin.IN, Pin.PULL_UP)
# =========================
# Parámetros
# =========================
T_MIN = 22.0
T_MAX = 24.0
HYST = 0.5
BETA = 3950
R0 = 10000
T0 = 298.15
DUTY_MIN = int(65535 * 0.025)
DUTY_MAX = int(65535 * 0.128)
modo_manual = False
manual_pos = 0
apertura = 0
# =========================
# Funciones
# =========================
def ntc_to_temp(adc_val, r_series=10000):
if adc_val <= 0:
return 0
v = adc_val / 4095.0 * 3.3
r_ntc = r_series * v / (3.3 - v)
t = 1.0 / (1.0/T0 + (1.0/BETA) * math.log(r_ntc/R0)) - 273.15
return t
def set_servo(percent):
duty = DUTY_MIN + int((DUTY_MAX - DUTY_MIN) * percent / 100)
servo.duty_u16(duty)
def mostrar_en_lcd(linea1, linea2=""):
lcd.clear()
lcd.print(linea1[:16])
lcd.set_cursor(0,1)
lcd.print(linea2[:16])
def decidir_apertura(t_int, t_ext, apertura_prev):
apertura = apertura_prev
if t_int < T_MIN - HYST:
apertura = 0
elif t_int > T_MAX + HYST and t_ext >= t_int:
apertura = 0
elif t_int > T_MIN:
delta = t_int - t_ext
if delta > 0:
apertura = int((delta / 8.0) * 100)
apertura = max(0, min(apertura, 100))
apertura = round(apertura / 10) * 10
return apertura
# =========================
# Conexión WiFi
# =========================
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(SSID, PASS)
while not wifi.isconnected():
time.sleep(0.5)
ip = wifi.ifconfig()[0]
print("Conectado en", ip)
mostrar_en_lcd("WiFi Conectado", ip)
# =========================
# Servidor web básico
# =========================
def web_page():
t_int = ntc_to_temp(adc_int.read())
t_ext = ntc_to_temp(adc_ext.read())
html = f"""
<html>
<head><title>Freecooling</title></head>
<body>
<h2>Freecooling ESP32</h2>
<p>Temp Int: {t_int:.1f} °C</p>
<p>Temp Ext: {t_ext:.1f} °C</p>
<p>Persiana: {apertura}%</p>
<form action="/" method="GET">
Clave:<input type="password" name="pwd"><br>
Apertura (0-100): <input type="number" name="pos" min="0" max="100"><br>
<input type="submit" value="Actualizar">
</form>
</body></html>
"""
return html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
while True:
# Control automático/manual
if not modo_manual:
nueva_apertura = decidir_apertura(ntc_to_temp(adc_int.read()), ntc_to_temp(adc_ext.read()), apertura)
if nueva_apertura != apertura:
apertura = nueva_apertura
set_servo(apertura)
# Mostrar en LCD
mostrar_en_lcd("Int:{:.1f} Ext:{:.1f}".format(ntc_to_temp(adc_int.read()), ntc_to_temp(adc_ext.read())),
"Auto:{}%".format(apertura))
# Servidor web
conn, addr = s.accept()
print('Conectado por', addr)
request = conn.recv(1024)
request = str(request)
pwd = None
pos = None
if "pwd=" in request and "pos=" in request:
try:
pwd = request.split("pwd=")[1].split("&")[0]
pos = int(request.split("pos=")[1].split(" ")[0])
if pwd == USER_PASSWORD:
pos = max(0, min(pos, 100))
apertura = pos
set_servo(apertura)
except:
pass
response = web_page()
conn.send('HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: close\n\n')
conn.sendall(response)
conn.close()