Saltar al contenido
IDE libre

Proyecto

Proyecto: cerradura de cajón abierta desde el celular con ESP32-C3 Super Mini y servo

Paso a paso de una cerradura con servo SG90 y LED en la ESP32-C3 Super Mini, controlada desde el celular por la red Wi-Fi de la propia placa, con contraseña.

Por Prof. Rodrigo Faustino · Actualizado el · 11 min de lectura

Métricas de este artículo

Palabras
2159
Caracteres
11.961
Tiempo de lectura
~11 min

Este proyecto junta dos cosas que a los alumnos les encantan: un motor que se mueve y el celular. Una pequeña cerradura hecha con un servo SG90 sujeta el cajón de un armario (o la tapa de una caja); el celular entra en la red Wi-Fi creada por la propia placa, abre una página y, con la contraseña correcta, toca Abrir. La placa gira el servo, enciende un LED verde y, pasado un tiempo, se cierra sola.

La placa es la ESP32-C3 Super Mini, lo bastante pequeña para quedar escondida dentro de la caja. Las piezas son las de la ruta de PWM: el servo, un LED y una resistencia. El programa usa lo que enseñan los artículos anteriores — el servidor web en la placa y el PWM del servo — y agrega lo que hace que un proyecto parezca terminado: estados, contraseña y tiempo.

Una palabra sobre seguridad, para acordar con el curso desde el comienzo: esto es una cerradura de juguete, ideal para la caja de un juego de pistas, el armario de materiales del aula o una alcancía. No sirve para proteger nada de valor: un destornillador abre la caja, y la contraseña en una página simple no resiste a alguien decidido. Aprovecha para discutir por qué las cerraduras electrónicas de verdad son más complicadas de lo que parecen.

Un celular con una página que dice Cajón, está cerrado, y los botones Abrir y Cerrar, en la dirección 192.168.4.1. Una flecha lleva la solicitud GET /abrir con la contraseña hasta la ESP32-C3 Super Mini, que tiene red propia, comprueba la contraseña y trata las rutas. Ella devuelve una página nueva y comanda el servo SG90 por el GPIO7, con 0 grados cerrado y 90 grados abierto, y el LED verde por el GPIO6, encendido cuando está abierto.
El camino de un toque en el celular hasta la cerradura. No hay internet ni router: el celular conversa directo con la placa.

Lo que vas a necesitar

  • una ESP32-C3 Super Mini (ficha);
  • un micro servo SG90 (ficha);
  • un LED verde y una resistencia de 220 Ω (ficha del LED);
  • protoboard y cables;
  • para la cerradura: un trozo de palito de helado o de plástico sujeto al brazo del servo, que entra en un tope pegado al cajón; cinta doble faz o pegamento caliente;
  • un celular con Wi-Fi.
FastTeacherPara profesores

Del programa al semestre planificado

  • Plan de enseñanza y calendario montados solos
  • Diario de clases listo para pegar en el SIGA
  • Diapositivas y listas de ejercicios con solucionario
Conocer FastTeacher

Versión Community gratis · Windows

Paso 1: las conexiones

Conexiones de la ESP32-C3 Super Mini: 5V al V+ del servo SG90, GPIO7 a la señal del servo con PWM de 50 Hz, GND al GND del servo; GPIO6 al ánodo del LED verde por una resistencia de 220 Ω y GND al cátodo.
El servo va en los 5 V del USB; el LED, con su resistencia, muestra desde lejos si el cajón está abierto.

El SG90 tiene tres cables: marrón (GND), rojo (V+) y naranja (señal). La señal va en el GPIO7. La alimentación va en el pin 5V de la Super Mini, que trae los 5 V del USB-C: la lección del servo explica que el motor consume picos de corriente al moverse y, conectado a los 3,3 V, puede hacer caer la tensión de la placa hasta reiniciarla. El LED, con la resistencia de 220 Ω en serie, va en el GPIO6.

Los pines evitan el GPIO8 (LED azul de la placa), el GPIO9 (botón BOOT), el GPIO2 (configuración del chip en el arranque) y el GPIO20 y el GPIO21 (serie del REPL), como en la ficha de la placa.

Paso 2: la cerradura como una máquina de estados

Antes de la red, el corazón del proyecto: la cerradura tiene dos estados, cerrado y abierto, y el programa necesita saber siempre en cuál está. Es el patrón de la lección máquina de estados: una variable guarda el estado, y funciones pasan de uno al otro haciendo todo lo que exige el cambio — mover el servo, encender o apagar el LED, anotar la hora.

El servo recibe el ángulo por el ancho del pulso, a 50 Hz: en la lección, 500 µs son 0° y 2400 µs son 180°. Aquí, 0° es cerrado y 90° es abierto. Abre el ejemplo con el circuito y mira girar el brazo del servo en la vista 2D.

from machine import Pin, PWM
import time

servo = PWM(Pin(7), freq=50, duty_u16=0)   # 50 Hz, todavía sin pulso
led = Pin(6, Pin.OUT, value=0)

TRANCADA, ABERTA = 0, 90                    # grados

def mover(graus):
    pulso_us = 500 + graus * 1900 // 180     # 0° = 500 µs ... 180° = 2400 µs
    servo.duty_ns(pulso_us * 1000)

estado = None

def trancar():
    global estado
    mover(TRANCADA)
    led.value(0)
    estado = 'cerrado'
    print('cerrado')

def abrir():
    global estado
    mover(ABERTA)
    led.value(1)
    estado = 'abierto'
    print('abierto')

trancar()
time.sleep(1)
abrir()
time.sleep(1)
trancar()
time.sleep(1)
servo.duty_u16(0)   # sin pulso: el servo deja de forzar y ahorra energía

La última línea es un detalle que hace diferencia en una caja: después de llegar al ángulo, el servo puede quedar sin pulso. No se mueve solo (los engranajes lo sostienen), deja de hacer ese zumbido y deja de gastar corriente.

Paso 3: contraseña, rutas y cerrar sola

La página del celular va a pedir direcciones como /abrir?senha=1234 y /fechar. El programa necesita:

  1. separar la ruta (/abrir) de los parámetros (senha=1234), como en el artículo del servidor web;
  2. comprobar la contraseña antes de abrir — cerrar no necesita contraseña;
  3. cerrarse solo después de un tiempo abierto, para que nadie olvide el cajón sin cerrar.

El tercer ítem usa ticks_ms() y ticks_diff(), de la lección ticks: al abrir, el programa anota la hora; en cada vuelta del bucle, comprueba si ya pasó el tiempo. El ejemplo simula una secuencia de solicitudes — una contraseña equivocada, una correcta y un largo silencio — sin red, solo con la lógica, y con un tiempo corto de 3 segundos para que quepa en el ejemplo.

from machine import Pin, PWM
from time import ticks_ms, ticks_diff, sleep_ms

servo = PWM(Pin(7), freq=50, duty_u16=0)
led = Pin(6, Pin.OUT, value=0)
SENHA = '4821'
FECHA_SOZINHA_MS = 3000      # en el proyecto, unos 30 s; aquí corto para el ejemplo

def mover(graus):
    servo.duty_ns((500 + graus * 1900 // 180) * 1000)

estado = 'cerrado'
aberta_desde = 0

def tratar(pedido):
    global estado, aberta_desde
    caminho, _, consulta = pedido.partition('?')
    params = dict(p.split('=', 1) for p in consulta.split('&') if '=' in p)
    if caminho == '/abrir':
        if params.get('senha') != SENHA:
            return 'contraseña incorrecta'
        mover(90); led.value(1)
        estado, aberta_desde = 'abierto', ticks_ms()
        return 'abierto'
    if caminho == '/fechar':
        mover(0); led.value(0); estado = 'cerrado'
        return 'cerrado'
    return 'no encontré ' + caminho

# (momento en ms, solicitud que llega del celular)
pedidos = [(200, '/abrir?senha=1111'), (900, '/abrir?senha=4821'), (6000, '/fechar')]
inicio = ticks_ms()
while pedidos or estado == 'abierto':
    agora = ticks_diff(ticks_ms(), inicio)
    if pedidos and agora >= pedidos[0][0]:
        t, p = pedidos.pop(0)
        print('%5d ms  %-20s -> %s' % (agora, p, tratar(p)))
    if estado == 'abierto' and ticks_diff(ticks_ms(), aberta_desde) >= FECHA_SOZINHA_MS:
        mover(0); led.value(0); estado = 'cerrado'
        print('%5d ms  (nadie lo cerró)     -> cerrado solo' % agora)
    sleep_ms(20)
servo.duty_u16(0)

Lee la salida con el curso: la contraseña equivocada no abre nada, la correcta abre, y tres segundos después la cerradura se cierra sola. La última solicitud, /fechar, encuentra el cajón ya cerrado — y no hay ningún problema en eso: cerrar lo que ya está cerrado es seguro. Pensar en lo que pasa cuando un comando llega "a destiempo" es un hábito de quien escribe programas que mueven cosas físicas.

FastMindAsistente de IA local

La IA que recuerda tu vida y vive en tu ordenador

  • Memoria a largo plazo con la fuente de cada respuesta
  • Funciona sin conexión: tus datos se quedan en tu PC
  • Lee PDF, diapositivas, fotos y grabaciones de reuniones
Descargar gratis para Windows

Plan Esencial gratis para siempre

Paso 4: la página y la red propia de la placa

La placa crea su propia red Wi-Fi en modo punto de acceso (network.AP_IF), como muestra el artículo del servidor web. El celular se conecta a ella, y la página queda siempre en la dirección 192.168.4.1. La red tiene una contraseña de Wi-Fi (en WPA2, tiene que tener por lo menos 8 caracteres) — es la primera barrera; la contraseña de la cerradura es la segunda.

El programa completo, con el servidor, queda abajo. Usa socket, que el simulador todavía no ofrece como servidor, por eso este fragmento es para grabar en la placa. La estructura es la misma del artículo del servidor web: aceptar la conexión, leer la primera línea de la solicitud, responder una página y cerrar. Como accept() espera a un cliente, el servidor usa un tiempo límite (settimeout) para que el bucle vuelva de vez en cuando y compruebe si es hora de cerrar solo.

import network, socket
from machine import Pin, PWM
from time import ticks_ms, ticks_diff

servo = PWM(Pin(7), freq=50, duty_u16=0)
led = Pin(6, Pin.OUT, value=0)
SENHA = '4821'
FECHA_SOZINHA_MS = 30_000

ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(ssid='cajon-del-aula', key='cambiar-esta-clave', security=network.AUTH_WPA2_PSK)

def mover(graus):
    servo.duty_ns((500 + graus * 1900 // 180) * 1000)

estado, aberta_desde = 'cerrado', 0
mover(0)

PAGINA = """<!doctype html><meta charset=utf-8><meta name=viewport content="width=device-width">
<title>Cajón</title><h1>Cajón {estado}</h1><p>{aviso}</p>
<form action=/abrir><input name=senha type=password inputmode=numeric placeholder=contraseña>
<button>Abrir</button></form><p><a href=/fechar>Cerrar ahora</a></p>"""

def responder(cliente, aviso=''):
    corpo = PAGINA.format(estado=estado, aviso=aviso)
    cliente.send(b'HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n')
    cliente.send(corpo.encode())

servidor = socket.socket()
servidor.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
servidor.bind(('0.0.0.0', 80))
servidor.listen(2)
servidor.settimeout(0.5)          # vuelve al bucle cada medio segundo

while True:
    if estado == 'abierto' and ticks_diff(ticks_ms(), aberta_desde) >= FECHA_SOZINHA_MS:
        mover(0); led.value(0); estado = 'cerrado'
    try:
        cliente, _ = servidor.accept()
    except OSError:
        continue                  # nadie pidió nada: comprueba el tiempo de nuevo
    try:
        linha = cliente.recv(512).decode().split('\r\n')[0]   # "GET /abrir?senha=4821 HTTP/1.1"
        caminho = linha.split(' ')[1] if ' ' in linha else '/'
        rota, _, consulta = caminho.partition('?')
        params = dict(p.split('=', 1) for p in consulta.split('&') if '=' in p)
        aviso = ''
        if rota == '/abrir':
            if params.get('senha') == SENHA:
                mover(90); led.value(1); estado, aberta_desde = 'abierto', ticks_ms()
            else:
                aviso = 'Contraseña incorrecta.'
        elif rota == '/fechar':
            mover(0); led.value(0); estado = 'cerrado'
        responder(cliente, aviso)
    finally:
        cliente.close()

Para probar: graba como main.py, enciende la placa, busca la red cajon-del-aula en el celular, conéctate con la contraseña del Wi-Fi y abre http://192.168.4.1 en el navegador. Cambia las dos contraseñas antes de usarla de verdad.

Cómo encuentra el celular a la placa

En el modo punto de acceso, la placa hace el papel que hace el router en casa: anuncia el nombre de la red, acepta a quien tiene la contraseña y da una dirección a cada aparato que entra. La propia placa queda siempre con el 192.168.4.1, y por eso la dirección de la página nunca cambia — a diferencia del modo estación, en el que el router elige el número y hay que mirar en el Serial cuál fue.

Algunos celulares, al entrar en una red sin internet, avisan que "la red no tiene acceso a internet" y preguntan si quieres seguir conectado. La respuesta es sí: la página de la cerradura no necesita internet. Si el celular insiste en cambiar de red solo, apaga los datos móviles durante la prueba.

Qué protege la contraseña (y qué no protege)

Vale la pena mirar con cuidado el camino de la contraseña, porque enseña mucho sobre seguridad en la práctica:

  • la contraseña del Wi-Fi (WPA2) cifra todo lo que pasa por el aire entre el celular y la placa. Quien está fuera de la red no puede leer las solicitudes;
  • ya dentro de la red, la página es HTTP simple, sin cifrado. Y la contraseña de la cerradura va en la dirección (/abrir?senha=4821), que queda en el historial del navegador del celular. Cualquier persona a quien le presten el celular puede descubrirla;
  • el programa compara la contraseña y listo: no hay límite de intentos. Con cuatro dígitos, existen 10 mil combinaciones, y un programa que pruebe todas termina rápido.

Cada uno de esos puntos tiene una mejora posible, y son excelentes desafíos para el curso: enviar la contraseña en un formulario con POST (sale de la dirección), bloquear por un minuto después de tres errores seguidos y cambiar la contraseña desde una página de configuración. Ninguno convierte la cerradura en una caja fuerte, pero cada uno cierra una puerta — y entender qué puertas quedaron abiertas es exactamente lo que se espera de quien diseña sistemas.

Paso 5: la parte mecánica

La cerradura más simple es un pestillo: un brazo largo en el servo, que en 0° entra en un tope fijo al cajón y en 90° sale del camino.

  1. sujeta el servo por dentro del mueble, al lado del cajón, con cinta doble faz gruesa o un soporte;
  2. pega un palito de helado al brazo del servo para que quede más largo;
  3. con la cerradura en 0°, marca dónde toca el palito al cajón y pega ahí un tope (un trozo de madera o de EVA firme);
  4. prueba abrir y cerrar varias veces antes de pegar todo definitivamente. Si el servo fuerza y tiembla al final del recorrido, ajusta el ángulo de 0° a 5° o 10°: la lección del servo recuerda que los extremos varían de un servo a otro.

Paso 6: probar como usuario

Antes de dar el proyecto por terminado, pásale el celular a un compañero que no haya acompañado el armado y pídele que abra el cajón. Observa sin ayudar. ¿Encontró la red? ¿Entendió que tenía que abrir el navegador? ¿Sabía la contraseña? ¿Supo si el cajón estaba abierto o cerrado?

Este tipo de prueba muestra lo que el autor del proyecto no ve: un nombre de red confuso, un botón demasiado pequeño, la falta de un aviso cuando la contraseña está equivocada. La página del ejemplo ya muestra el estado en el título y un aviso de contraseña equivocada; el LED verde ayuda a quien está lejos de la pantalla. Anota lo que le extrañó al compañero y mejora una cosa por vez.

Paso 7: energía, si la caja está lejos del enchufe

Con la radio Wi-Fi encendida todo el tiempo como punto de acceso, la placa gasta como un aparato siempre despierto — el artículo baterías en la ESP32 muestra que, en ese régimen, una batería común dura horas, no semanas. Para una caja lejos del enchufe, hay dos caminos: alimentar por el USB con un cargador de celular (el más simple) o cambiar el proyecto para que la placa duerma y solo cree la red cuando alguien apriete un botón. El segundo camino es un buen proyecto de continuación, que junta este artículo con el de baterías.

Problemas comunes

  • La placa se reinicia cuando el servo se mueve: revisa que el servo esté en el 5V y no en el 3V3, y que el cable USB y la fuente aguanten la corriente. Un capacitor electrolítico entre el 5V y el GND, cerca del servo, ayuda en muchos casos.
  • La red no aparece en el celular: revisa que la contraseña del Wi-Fi tenga por lo menos 8 caracteres. El Serial muestra los mensajes de error de ap.config.
  • La página abre, pero el servo no se mueve: revisa el cable de la señal en el GPIO7 y que el GND del servo esté conectado al GND de la placa — sin la tierra común, el pulso no tiene referencia.

Ideas para ir más lejos

  • Registro de quién abrió: guarda en un archivo la hora de cada apertura y cada contraseña equivocada, como en el artículo guardar datos en la ESP32. Tres contraseñas equivocadas seguidas pueden bloquear la cerradura por un minuto.
  • Sensor de cajón abierto: un botón o un reed switch (con un imán en el cajón) muestra si el cajón fue realmente cerrado antes de cerrar con llave.
  • Dos placas: la cerradura puede recibir el comando de un "control remoto" hecho con otra placa, por ESP-NOW, sin celular.

Lo que enseña este proyecto

Una cerradura parece un objeto simple, pero su programa ya tiene la forma de muchos sistemas de verdad. Hay un estado que necesita ser siempre conocido y coherente con el mundo físico: el LED encendido tiene que significar cajón abierto, siempre. Hay comandos que llegan de afuera, en cualquier orden y a cualquier hora, y el programa necesita responder a cada uno sin confundirse — incluso a los que no tienen sentido, como cerrar lo que ya está cerrado. Hay tiempo: la cerradura se cierra sola, y para eso el programa no puede quedarse parado esperando una solicitud. Y hay seguridad, que no es un interruptor de encendido y apagado, sino una lista de riesgos que se elige tratar o aceptar.

Un buen cierre para el curso es pedir que cada grupo escriba, en una hoja, los tres riesgos que su proyecto todavía tiene y qué haría para disminuir cada uno. Es el mismo ejercicio que hacen los equipos de ingeniería antes de lanzar un producto.

Para continuar

Las bases de este proyecto están en la ruta PWM (lección del servo), en la ruta Wi-Fi y HTTP (lección Wi-Fi) y en la ruta Tiempo sin trabarse (ticks y máquina de estados). El artículo PWM en la ESP32 profundiza en el servo, y el servidor web en la ESP32, en las páginas.

Fuentes

Para practicar en PyPlaca

Rutas

Lecciones

Fichas de componentes

FastMindAsistente de IA local

La IA que recuerda tu vida y vive en tu ordenador

  • Memoria a largo plazo con la fuente de cada respuesta
  • Funciona sin conexión: tus datos se quedan en tu PC
  • Lee PDF, diapositivas, fotos y grabaciones de reuniones
Descargar gratis para Windows

Plan Esencial gratis para siempre

FastTeacherPara profesores

Del programa al semestre planificado

  • Plan de enseñanza y calendario montados solos
  • Diario de clases listo para pegar en el SIGA
  • Diapositivas y listas de ejercicios con solucionario
Conocer FastTeacher

Versión Community gratis · Windows

FastMindAsistente de IA local

La IA que recuerda tu vida y vive en tu ordenador

  • Memoria a largo plazo con la fuente de cada respuesta
  • Funciona sin conexión: tus datos se quedan en tu PC
  • Lee PDF, diapositivas, fotos y grabaciones de reuniones
Descargar gratis para Windows

Plan Esencial gratis para siempre