Levitador
neumático PID
Un ventilador empuja aire por un tubo transparente; un láser mide dónde está la bola y la ESP32 decide, cincuenta veces por segundo, cuánto soplar. Tú lo ves y lo controlas desde esta página.
Programa PRI · José Luis Castro Góngora · Universidad Nacional de Colombia, Sede Bogotá

Lo esencial, en seis frases
- La bola sube si el aire que la empuja pesa más que ella, y baja si pesa menos. Hay una sola velocidad de aire \(v_0\) que la deja quieta, y esa velocidad es la misma a cualquier altura.
- Por eso la altura se comporta como un integrador: un poquito de aire de más y la bola sube sin parar. Sin control no flota, se va al techo o al piso.
- El sensor láser VL53L1X, en la tapa, mide la distancia a la bola; la ESP32 calcula el error \(e = r - y\) y mueve el PWM del ventilador con un PID.
- \(K_p\) empuja según qué tan lejos está la bola, \(K_d\) frena según qué tan rápido va, y \(K_i\) corrige lo que se queda pegado cuando algo roba aire.
- Una válvula de fuga con servo roba aire de verdad: es la perturbación \(D(s)\) de los talleres, pero la ves y la sientes.
- En el laboratorio en vivo conectas la ESP32 por USB o Bluetooth y ves todo en tiempo real, junto a un gemelo digital que corre el modelo al lado de la bola real. Sin computador, la pantalla a color y la perilla del equipo hacen lo mismo.
Pantalla y perilla
Una TFT de \(1{,}3''\) a color muestra la altura, el setpoint, el PWM y la gráfica de los últimos \(24\) s. Con la perilla cambias setpoint, modo, perfil y ganancias; pulsación larga arranca o para.
Tubo que habla en colores
Treinta LED detrás del tubo: el celeste marca el setpoint, el de la bola se pinta verde, amarillo o rojo según el error, y el fondo brilla con el PWM. Desde lejos se ve si el control va bien.
Reto: tú contra el PID
Manejas el ventilador con la perilla y la bola tiene que seguir una secuencia de escalones. La ESP32 mide tu \(\text{IAE}\) y la página lo compara con el del PID. Spoiler: el retardo te gana.
Gemelo digital
El modelo no lineal corre en el navegador con el mismo PID y el mismo setpoint. Si la bola real y la virtual se separan, el modelo te está diciendo qué le falta. Un botón ajusta \(v_0\), \(\tau\) y \(v_{\max}\) con tus datos.
Perturbación que se ve
Un servo SG90 abre una ventana en el embudo y deja escapar aire. Así compruebas en la mesa por qué el P solo deja error y el PI no.
Autoajuste y cascada
Con un botón la ESP32 hace la prueba del relé, mide \(K_u\) y \(P_u\) y propone ganancias. Con el tacómetro del ventilador puedes cerrar un lazo interno de velocidad.
De abajo hacia arriba: aire, panal, tubo, bola, láser
Gira el modelo con el dedo o el ratón. El botón «Corte» abre las piezas por la mitad para ver por dentro: el embudo, el panal que endereza el aire y el puerto de la válvula.

El ventilador sopla hacia arriba
Un ventilador de PC de \(80\times80\) mm y cuatro hilos toma aire por debajo de la base (por eso las patas) y lo empuja hacia el embudo. El cuarto hilo recibe el PWM de \(25\ \text{kHz}\); el tercero devuelve dos pulsos por vuelta: el tacómetro.
El embudo y el panal ordenan el aire
El aire sale del ventilador girando. El embudo lo lleva de \(76\) a \(44\) mm y el panal de celdas hexagonales de \(6\) mm le quita el remolino. Sin panal la bola gira y baila de lado; con panal sube derecha. El panal también es el piso donde descansa la bola.
La válvula de fuga roba aire cuando tú quieras
En un costado del embudo hay un puerto de \(18\) mm tapado por una aleta. Un servo la abre de \(0\) a \(90^\circ\). Abierta, parte del aire se escapa antes de llegar a la bola: eso es una perturbación a la entrada de la planta.
El tubo y la bola
Tubo de acrílico de \(50\) mm por fuera, \(44\) por dentro y \(500\) de largo. La bola de ping-pong mide \(40\) mm y pesa \(2{,}7\) g: entre la bola y la pared queda una rendija de \(2\) mm por donde se cuela el aire. Esa rendija es la que hace que la bola flote estable de lado.
La caja: cerebro, pantalla y perilla
La ESP32 vive en una caja impresa al lado de la base, con la pantalla TFT y la perilla en la tapa. Por la tapa ves el estado sin abrir el computador; por USB o Bluetooth, la página recibe los datos \(50\) (USB) o \(25\) (BLE) veces por segundo.
La tira de LED detrás del tubo
Cuatro abrazaderas impresas sujetan \(50\) cm de tira WS2812B contra la parte de atrás del tubo, con los LED mirando hacia la bola. Cada LED cubre \(16{,}7\) mm de altura.
El láser mide desde arriba
El VL53L1X va en la tapa, mirando hacia abajo por una ventana de \(10\) mm. Mide la distancia por tiempo de vuelo cincuenta veces por segundo. La altura es \(y = d_0 - d\), donde \(d_0\) es la distancia con la bola en reposo (se calibra con un comando). La tapa tiene seis ventilas en arco: el aire tiene que salir, si no el tubo se presuriza.



Del aire a una ecuación
Antes de controlar hay que saber qué estamos controlando. Vamos en bloques pequeños: primero las fuerzas, después el equilibrio.
Las dos fuerzas sobre la bola
Hacia abajo, el peso: \(mg\).
Hacia arriba, el empuje del aire. Lo que importa no es la velocidad del aire sola, sino la velocidad del aire respecto a la bola: si la bola subiera tan rápido como el aire, no sentiría viento.
\(v_a\): velocidad media del aire en el tubo. \(\dot y\): velocidad de la bola. \(c\): agrupa densidad del aire, área y forma (no hace falta conocerlo, se despeja con el equilibrio). El valor absoluto conserva el signo: si la bola baja más rápido que el aire, el empuje sigue siendo hacia arriba.
Segunda ley de Newton
Masa por aceleración igual a la suma de fuerzas, positivo hacia arriba:
\[m\,\ddot y = c\,(v_a-\dot y)\lvert v_a-\dot y\rvert - m g\]Es no lineal por el cuadrado. No es grave: en el siguiente paso la vamos a mirar de cerca alrededor del punto de flotación.
El equilibrio: bola quieta
Quieta significa \(\dot y = 0\) y \(\ddot y = 0\). Entonces \(0 = c\,v_0^2 - mg\), es decir:
\[v_0 = \sqrt{\frac{m g}{c}}\qquad\Longleftrightarrow\qquad c\,v_0^2 = m g\]Lee esto con calma: la velocidad de aire que deja la bola quieta no depende de la altura \(y\). A \(5\) cm o a \(40\) cm, el aire necesario es el mismo. Esa es la razón de todo lo que sigue.
Medir \(v_0\) en vez de calcular \(c\)
No necesitas conocer \(c\). En la práctica subes el PWM a mano hasta que la bola flota quieta: ese PWM es \(u_0\) (alrededor de \(48\,\%\) en el modelo) y fija \(v_0\). El autoajuste por relé también lo encuentra solo.
Linealizar: la bola es un integrador con un polo
Linealizar es hacer zoom: cerca del equilibrio, la curva del empuje se parece a una recta. Escribimos cada variable como su valor de equilibrio más un cambio pequeño \(\delta\).
Cambio de variable
\(v_a = v_0 + \delta v_a\), \(\ \dot y = 0 + \delta\dot y\). Llamamos \(w = v_a - \dot y\) a la velocidad relativa; en el equilibrio vale \(w = v_0\).
Pendiente del empuje
Para \(w>0\), \(F_a = c\,w^2\). Su derivada es \(\dfrac{dF_a}{dw} = 2 c w\), que en el equilibrio vale \(2 c v_0\). Entonces:
\[\delta F_a \approx 2 c v_0\,(\delta v_a - \delta \dot y)\]Ecuación lineal
El peso es constante y se cancela con \(c v_0^2\). Queda \(m\,\delta\ddot y = 2 c v_0(\delta v_a - \delta\dot y)\). Dividimos por \(m\) y usamos \(c = mg/v_0^2\):
\[\frac{2 c v_0}{m} = \frac{2 g}{v_0} \equiv \beta \qquad\Rightarrow\qquad \delta\ddot y + \beta\,\delta\dot y = \beta\,\delta v_a\]Laplace con condiciones iniciales en cero
\[\frac{Y(s)}{V_a(s)} = \frac{\beta}{s\,(s+\beta)}\]Dos polos, y cada uno tiene un significado físico:
- Polo en \(s = 0\): integrador. Si sobra un poco de aire, la bola no se va a otra altura de equilibrio: sube a velocidad constante hasta chocar con la tapa. La altura es la integral de un exceso de aire.
- Polo en \(s = -\beta\): la bola alcanza al aire. Con \(v_0 \approx 2{,}4\ \text{m/s}\), \(\beta = 2g/v_0 \approx 8{,}2\ \text{s}^{-1}\): la velocidad de la bola se acomoda a un cambio del aire en unos \(1/\beta \approx 0{,}12\ \text{s}\).
El ventilador, el sensor y la función de transferencia completa
Ventilador: primer orden
El rotor tiene inercia: si cambias el PWM \(u\) de golpe, el aire tarda en acomodarse. Se modela como primer orden:
\(K_v \approx 50\ \tfrac{\text{mm/s}}{\%}\) (con \(100\,\%\) el aire va a unos \(5\ \text{m/s}\)) y \(\tau \approx 0{,}35\ \text{s}\). Ambos se miden en la práctica; el gemelo digital los ajusta.
Sensor: casi perfecto, pero con retardo
El VL53L1X entrega una medida cada \(20\ \text{ms}\) y la ESP32 actúa en el siguiente ciclo. Ese retraso se modela como \(e^{-T_d s}\) con \(T_d \approx 30\ \text{ms}\).
El retardo no cambia la amplitud, solo resta fase: \(-\omega T_d\) radianes. A \(4\ \text{rad/s}\) son \(7^\circ\) menos de margen de fase. Pequeño, pero existe, y es la razón de que el límite real de \(K_p\) sea menor que el de Routh.
Multiplicamos los tres bloques en serie (ventilador, bola, sensor):
Unidades: \(y\) en mm, \(u\) en \(\%\) de PWM. Por eso las ganancias del PID salen en \(\%/\text{mm}\): \(K_p = 0{,}08\) significa «si la bola está \(10\) mm abajo, sube el PWM \(0{,}8\,\%\)».
| Parámetro | Valor del modelo | Qué es | Cómo se mide en la mesa |
|---|---|---|---|
| \(m\) | \(2{,}7\ \text{g}\) | masa de la bola | balanza de cocina (o el dato de la bola reglamentaria) |
| \(v_0\) | \(2{,}4\ \text{m/s}\) | aire que equilibra el peso | sale de \(u_0\): \(v_0 = K_v u_0\) |
| \(u_0\) | \(48\,\%\) | PWM de flotación | modo manual: sube \(u\) hasta que la bola flote; o el autoajuste |
| \(\beta\) | \(8{,}17\ \text{s}^{-1}\) | polo de la bola | \(\beta = 2g/v_0\) |
| \(K_v\) | \(50\ \tfrac{\text{mm/s}}{\%}\) | ganancia del ventilador | anemómetro, o el ajuste del gemelo digital |
| \(\tau\) | \(0{,}35\ \text{s}\) | constante de tiempo del ventilador | escalón de PWM y curva de rpm del tacómetro: \(63{,}2\,\%\) del cambio |
| \(T_d\) | \(30\ \text{ms}\) | retardo de medida | periodo de muestreo más tiempo de cálculo |
El lazo cerrado, con el método de clase
Antes de hablar de estabilidad, la función de transferencia en lazo cerrado. Usamos los movimientos del profe: nombra, ecuación, despeja, apaga, límite.
Nombra y escribe una ecuación por sumador y por bloque
\[E = R - Y \qquad U = C\,E \qquad Y = G\,(U - D)\]Despeja \(Y\)
Sustituye \(U\) y \(E\): \(Y = G\,(C(R-Y) - D)\). Pasa los \(Y\) a la izquierda: \(Y(1 + CG) = CG\,R - G\,D\).
\[Y(s) = \underbrace{\frac{C G}{1 + C G}}_{T(s)}\,R(s) \;-\; \frac{G}{1 + C G}\,D(s)\]El error, apagando una entrada a la vez
\[E(s) = \frac{1}{1 + C G}\,R(s) \;+\; \frac{G}{1 + C G}\,D(s)\]Límite: error en estado estacionario (después de comprobar estabilidad)
Cambio de setpoint \(R = r_0/s\) con un P (\(C = K_p\)). Como \(G\) tiene un \(1/s\), \(G(0) \to \infty\):
\[e_{ss} = \lim_{s\to 0} s\,\frac{1}{1 + K_p G}\,\frac{r_0}{s} = 0\]Sistema tipo 1: llega al setpoint aunque solo tengas P. La válvula es otra historia: con \(D = d_0/s\),
\[e_{ss} = \lim_{s\to 0} \frac{G}{1 + K_p G}\,d_0 = \frac{d_0}{K_p}\]Con \(K_p = 0{,}08\ \%/\text{mm}\) y una válvula que roba el equivalente a \(d_0 = 6\,\%\) de PWM, la bola queda \(6/0{,}08 = 75\ \text{mm}\) abajo. El integrador del PI pone un \(1/s\) antes de la perturbación y ese error se vuelve cero. Esto lo vas a medir en el experimento 1.
Qué hace cada ganancia, viéndolo
Mueve los deslizadores. Arriba ves la bola respondiendo a un cambio de setpoint de \(100\) mm y, a los \(8\) s, a la válvula que se abre. Abajo, dónde quedan los polos del lazo cerrado.
\(K_p\): el resorte
Empuja proporcional a la distancia. Más \(K_p\): llega más rápido, pero oscila más. Solo no puede con la válvula: deja \(d_0/K_p\) de error.
\(K_d\): el amortiguador
Reacciona a la velocidad de la bola y la frena antes de pasarse. Agrega amortiguamiento, pero amplifica el ruido del láser: por eso lleva el filtro \(N\).
\(K_i\): la memoria
Suma el error en el tiempo. Mata el error de la válvula. Mucho \(K_i\): sobreimpulso y oscilación lenta, y si el ventilador se satura, «windup».
Altura de la bola
Mando del ventilador
Polos del lazo cerrado
Lectura
Esta simulación usa el modelo lineal \(G(s)\) con el retardo, en tiempo continuo. El laboratorio usa el modelo no lineal y el PID digital del firmware, así que los números cambian un poco: esa diferencia también enseña.
Estabilidad: Routh con un P, y márgenes del PID
Ya tenemos el lazo cerrado. Ahora sí: ¿hasta dónde puedo subir \(K_p\) sin que la bola empiece a oscilar sola?
Ecuación característica con \(C = K_p\) (sin retardo)
\(1 + K_p G(s) = 0\). Multiplica por \(s(s+\beta)(\tau s+1)\):
\[\tau s^3 + (1 + \tau\beta)s^2 + \beta s + K_p K_v \beta = 0 \;\Rightarrow\; 0{,}35 s^3 + 3{,}861 s^2 + 8{,}175 s + 408{,}8 K_p = 0\]No falta ningún coeficiente y todos son positivos si \(K_p>0\): pasa el atajo. Toca hacer Routh.
Arreglo de Routh
\(s^3\) \(0{,}35\) \(8{,}175\) \(s^2\) \(3{,}861\) \(408{,}8K_p\) \(s^1\) \(\dfrac{3{,}861\cdot 8{,}175 - 0{,}35\cdot 408{,}8K_p}{3{,}861}\) \(0\) \(s^0\) \(408{,}8K_p\) Primera columna positiva: \(K_p > 0\) y \(31{,}56 - 143{,}1K_p > 0\).
\[0 < K_p < 0{,}2206\ \tfrac{\%}{\text{mm}}\]Frecuencia de la oscilación en el límite
Con \(K_p = 0{,}2206\) la fila \(s^1\) se anula. El polinomio auxiliar de la fila \(s^2\): \(3{,}861 s^2 + 90{,}18 = 0\Rightarrow s = \pm j\,4{,}83\). Periodo \(2\pi/4{,}83 \approx 1{,}30\ \text{s}\).
Con el retardo de \(30\) ms el límite lineal baja a \(K_u \approx 0{,}167\) y el periodo sube a \(P_u \approx 1{,}50\ \text{s}\). La prueba del relé con \(h = 8\) en el modelo no lineal da \(K_u \approx 0{,}14\) y \(P_u \approx 1{,}7\ \text{s}\): la oscilación de \(\pm 75\) mm ya no es «pequeña» y la ganancia efectiva del arrastre cambia. Que no coincidan exacto también es una lección.


El PID que corre en la ESP32, y lo que lo hace distinto
El controlador de clase es \(C(s) = K_p + \tfrac{K_i}{s} + K_d s\). El que va en el microcontrolador tiene cuatro detalles que lo hacen funcionar en la vida real.
1 · Realimentación anticipada \(u_0\)
El PID no arranca de cero: arranca del PWM que ya deja la bola flotando. Así el integrador solo corrige lo que falta, no todo el peso.
2 · Peso del setpoint \(b\)
Con \(b = 0{,}6\) el proporcional ve solo el \(60\,\%\) del salto de setpoint. Como la planta ya integra, el integrador del PID deja un cero lento que causa sobreimpulso; \(b\) lo compensa sin cambiar cómo se rechaza la perturbación.
3 · Derivada sobre la medida, filtrada
\(D(s) = -\dfrac{K_d s}{s/N + 1}Y(s)\). Derivar \(y\) en vez de \(e\) evita el pico de mando cuando cambias el setpoint. Discretizada con Tustin, \(T_s = 0{,}02\):
4 · Antiwindup condicional
El PWM solo va de \(0\) a \(100\,\%\). Si el mando está saturado y el error empuja en la misma dirección, el integrador deja de sumar: \(I_{k+1} = I_k + K_i T_s e_k\) solo cuando ayuda.
Lo innovador, con su porqué
Autoajuste por relé (Åström–Hägglund)
La ESP32 reemplaza el PID por un relé: \(u = u_0 \pm h\) según el signo del error. La bola entra en una oscilación límite de amplitud \(a\) y periodo \(P_u\). La primera armónica da:
Es la versión segura de «subir \(K_p\) hasta que oscile»: la amplitud la limitas tú con \(h\). Además el relé corrige su propio centro: si la mitad con más aire dura más que la otra, sube \(u_0\); al final \(u_0\) queda en el PWM de flotación. De \(K_u\) y \(P_u\) salen las reglas de la tabla.
Lazo en cascada con el tacómetro
El PID de altura ya no manda PWM: pide rpm. Un PI interno, más rápido, mueve el PWM hasta lograr esas rpm. Si el ventilador cambia (se calienta, baja el voltaje, tiene zona muerta), el lazo interno lo corrige antes de que la bola lo note. Es lo que se hace en motores y drones.
Gemelo digital
En el navegador corre la ecuación no lineal del paso 02 con el mismo PID digital. Ves las dos bolas a la vez. El botón «Ajustar gemelo» busca \(v_0\), \(\tau\) y \(v_{\max}\) que mejor predicen tus datos (predicción a \(0{,}6\) s, mínimos cuadrados).
Perturbación física controlada
La válvula se mueve desde la página: un deslizador o un «golpe» de 2 s. Es la \(D(s)\) de los talleres de perturbaciones, pero con aire de verdad.
Perfiles de setpoint
La ESP32 genera la referencia: fija, escalones, seno de \(8\) s o rampa triangular de \(40\) mm/s. Con el seno ves el desfase del lazo; con la rampa, el error de seguimiento. El sistema ya tiene un integrador; con el \(K_i\) del PID el lazo es tipo 2, así que la rampa se sigue sin error en estado estacionario.
Equipo autónomo
Pantalla, perilla y LED hacen que funcione sin computador, para mostrarlo en una feria o en el colegio. Por Bluetooth, la misma página sirve desde un celular Android o un portátil sin cables.
| Regla | \(K_p\) | \(K_i\) | \(K_d\) | Cuándo usarla |
|---|---|---|---|---|
| Ziegler–Nichols PID | \(0{,}6K_u\) | \(1{,}2K_u/P_u\) | \(0{,}075K_uP_u\) | rápida y agresiva, sobreimpulso alto |
| Tyreus–Luyben PI | \(K_u/3{,}2\) | \(K_p/(2{,}2P_u)\) | \(0\) | suave, buen punto de partida |
| «Sin sobreimpulso» | \(0{,}2K_u\) | \(0{,}4K_u/P_u\) | \(0{,}066K_uP_u\) | cuando la bola no debe tocar la tapa |
Conecta la ESP32 y mira el control mientras pasa
Conecta la ESP32 por cable y pulsa USB, o enciéndela y pulsa Bluetooth (Chrome o Edge). Sin hardware, pulsa Simular: corre el mismo firmware dentro del navegador, con una planta un poco distinta al modelo para que el gemelo tenga algo que aprender.
Modo
Setpoint
Ganancias
Perturbación
Autoajuste por relé
Reto: tú contra el PID
40 s de escalones. Manejas el PWM con el deslizador «PWM manual», con las flechas ↑ ↓ o con la perilla del equipo. Gana el \(\text{IAE}\) más bajo.
Equipo
Medido en vivo
Gemelo digital
Polos con estas ganancias
Consola serie
Diez experimentos y lo que deberías ver
Cada uno sirve con la ESP32 o con el simulador. Anota lo que mides: con el botón «Grabar CSV» te llevas los datos para el informe.
Solo P contra la válvula
\(K_p = 0{,}08\), \(K_i = K_d = 0\), \(b = 1\). Cambia el setpoint: llega sin error (tipo 1). Abre la válvula al \(100\,\%\): la bola baja y se queda abajo. Mide el error y compáralo con \(d_0/K_p\).
Buscar el límite
Solo P. Sube \(K_p\) de \(0{,}02\) en \(0{,}02\). ¿Con cuánto empieza a oscilar sin parar? Compáralo con Routh (\(0{,}22\)), con el lineal con retardo (\(0{,}167\)) y con el relé (\(\approx 0{,}14\)). ¿Por qué el real es menor?
El amortiguador
Con \(K_p = 0{,}12\) (oscila), sube \(K_d\) poco a poco. La oscilación muere. Ahora sube \(N\) a \(40\): mira la gráfica de \(u_D\), se llena de ruido del láser.
La memoria
Vuelve al PID por defecto y repite el experimento 1. La válvula ya no deja error: \(u_I\) sube justo lo que roba la válvula. Duplica \(K_i\): ¿qué pasa con el sobreimpulso?
Windup
Pon \(r = 400\) y \(u_0 = 30\). El ventilador se satura un rato. Compara la bajada a \(r = 150\) con el antiwindup del firmware y piensa qué pasaría sin él (en el simulador, el gemelo te deja verlo).
El peso del setpoint
Escalones de \(100\) a \(300\) con \(b = 1\) y con \(b = 0{,}6\). La respuesta a la válvula es igual en los dos casos; la del setpoint, no. ¿Por qué? (Pista: \(b\) no aparece en \(1 + CG\)).
Relé y reglas de sintonía
Haz el autoajuste con \(h = 8\). Anota \(K_u\) y \(P_u\) y compáralos con el modelo no lineal (\(\approx 0{,}14\) y \(1{,}7\) s) y el lineal (\(0{,}167\) y \(1{,}50\) s). Aplica las tres reglas y mide \(M_p\) y \(t_s\) de cada una.
Gemelo y cascada
Graba \(30\) s con escalones y ajusta el gemelo. ¿Cuánto cambiaron \(v_0\) y \(\tau\)? Luego pasa a Cascada: compara qué tan parejo queda \(u\) y la respuesta a escalones.
Seno y rampa
Perfil seno: mide cuánto se atrasa \(y\) respecto a \(r\) y compáralo con la fase de \(T(j\omega)\) en \(\omega = 2\pi/8\). Perfil rampa con \(K_i = 0\) y luego con \(K_i > 0\): ¿cuándo desaparece el error de seguimiento? Piensa en el tipo del sistema.
Tú contra el PID
Haz el reto dos veces. Mira la gráfica: ¿dónde te pasas? Casi siempre es porque reaccionas tarde: la bola ya va rápido cuando corriges. Eso que tú no ves a tiempo es lo que \(K_d\) mide.
Siete piezas impresas en 3D
Todas las piezas salen del modelo paramétrico. Los STL ya vienen acostados sobre la cara plana: los abres en el laminador (Cura, PrusaSlicer, Bambu Studio) y los mandas sin girarlos.







| Pieza | Archivo | Medidas (mm) | Material | Ajustes | Soportes |
|---|---|---|---|---|---|
| P1 Base con patas | P1_base_patas.stl | \(109\times109\times34\) | PLA o PETG | capa 0,2 · 3 perímetros · relleno 25 % | No |
| P2 Difusor con panal | P2_difusor_panal.stl | \(100\times110\times105\) | PETG (mejor) o PLA | capa 0,2 · 3 perímetros · relleno 20 % · boquilla 0,4 | No (el puerto Ø18 puentea) |
| P3 Aleta de la válvula | P3_aleta_valvula.stl | \(42\times26\times2{,}5\) | PLA | capa 0,15 · 100 % | No |
| P4 Tapa del sensor | P4_tapa_sensor.stl | \(56\times59\times24\) | PLA o PETG | capa 0,2 · 3 perímetros · relleno 25 % | No |
| P5 Caja de electrónica | P5_caja_electronica.stl | \(105\times85\times40\) | PLA | capa 0,2 · 2 perímetros · relleno 15 % | Sí, solo en los huecos laterales (o sin, con puentes) |
| P6 Tapa de la caja | P6_tapa_caja.stl | \(105\times85\times5\) | PLA (cambia de color en la capa del grabado si quieres el nombre resaltado) | capa 0,2 · relleno 20 % | No |
| P7 Abrazadera LED | P7_clip_led_x4.stl (imprime 4) | \(55\times52\times12\) | PETG (flexa mejor) o PLA | capa 0,2 · 4 perímetros · relleno 30 % | No |
Antes de imprimir todo, imprime solo los últimos \(10\) mm del encaje de P2 (corta la pieza en el laminador) y prueba que el tubo entre ajustado. Si queda flojo o duro, cambia HOLGURA en levitador_cad.py y vuelve a generar: todos los encajes se mueven juntos.
La lista de compras con precios está en la cotización.
Base
Pon el ventilador sobre P1 con la etiqueta hacia abajo (sopla hacia arriba: la flecha de flujo del marco apunta al embudo). Encima va P2. Los cuatro M4 × 40 atraviesan las tres piezas.
Válvula
Mete el SG90 por la ventana de la pared de P2 con el eje mirando hacia la boca del puerto, atorníllalo, llévalo a \(0^\circ\) (comando
V 0) y monta la aleta tapando el puerto.Tubo y tapa
El tubo entra en el encaje de P2 hasta apoyarse en el borde del panal. Mete la bola. Atornilla el VL53L1X en P4 mirando hacia abajo por la ventana y pon la tapa.
Tira de LED
Corta \(50\) cm (30 LED) de la cinta por la línea de corte. Ponla detrás del tubo con los LED mirando hacia el tubo y la flecha de datos apuntando hacia arriba (la entrada DIN queda abajo). Mete las cuatro abrazaderas P7 a presión: el bolsillo aprieta la cinta.
Caja, pantalla y perilla
Pega la pantalla en la cuna de P6 con dos puntos de silicona caliente, vidrio hacia la ventana. La perilla se atornilla con su tuerca M7 por arriba. Arma la placa perforada según la sección 12, atorníllala en los postes de P5 y saca los cables por el agujero lateral.
Conexiones
FAN_PWM_INVERTIDO). El tacómetro es de colector abierto: la resistencia de \(10\ \text{k}\Omega\) va a \(3{,}3\) V, nunca a \(12\) V. La tira de LED se alimenta del LM2596, no del pin de \(5\) V de la ESP32.| Señal | Pin ESP32 | Va a | Nota |
|---|---|---|---|
| I2C SDA / SCL | 21 / 22 | VL53L1X | cable trenzado si pasa de \(50\) cm; el firmware usa \(400\) kHz |
| XSHUT | 13 | VL53L1X | reinicia el sensor al arrancar |
| SPI SCK / MOSI | 18 / 23 | TFT: SCL / SDA | la pantalla no tiene CS: modo SPI 3, \(40\) MHz |
| DC / RES / BLK | 16 / 17 / 5 | TFT | BLK en alto enciende la luz de fondo |
| Perilla A / B / pulsador | 32 / 33 / 4 | KY-040: CLK / DT / SW | pull-up internos; si salta de a dos pasos cambia ENC_DIV |
| PWM ventilador | 25 | base del 2N2222 por 1 kΩ | \(25\) kHz, 10 bits, lógica invertida |
| Tacómetro | 34 | cable verde + 10 kΩ a 3V3 | dos pulsos por vuelta |
| Servo | 26 | señal del SG90 | \(50\) Hz, \(1\)–\(2\) ms |
| Datos LED | 27 | DIN de la tira por 330 Ω | 30 LED, brillo 60/255 por defecto (comando LED) |
FAN_PWM_INVERTIDO = false y FAN_FREQ = 20000. Pierdes el tacómetro, así que el modo Cascada no estará disponible.Firmware y protocolo
Instala
Arduino IDE 2 → Gestor de tarjetas: esp32 de Espressif. Gestor de bibliotecas: VL53L1X (Pololu), Adafruit ST7735 and ST7789, Adafruit GFX y Adafruit NeoPixel. Abre
levitador_pid.ino, elige «ESP32 Dev Module» y en Partition Scheme pon «Huge APP (3MB No OTA)»: con Bluetooth el programa no cabe en la partición normal. Con PlatformIO usa elplatformio.iniincluido (ya trae todo eso).Prueba sin la página
Al encender, la pantalla dice «Levitador PID» y la tira se apaga. Monitor serie a \(115200\): escribe
?y debe responder una líneaI {…}.M 1y luegoUM 40enciende el ventilador al \(40\,\%\). En el celular, una app como nRF Connect debe ver «Levitador-PRI».Cierra el monitor serie
Solo un programa puede tener el puerto abierto. Ciérralo antes de pulsar «Conectar ESP32» en esta página.
| Comando | Qué hace | Ejemplo |
|---|---|---|
M n | Modo: 0 apagado, 1 manual, 2 PID, 3 cascada, 4 relé, 5 reto | M 2 |
R mm | Setpoint de altura (\(20\) a \(420\)) | R 250 |
P n | Perfil: 0 fijo, 1 escalones, 2 seno, 3 rampa | P 2 |
G kp ki kd | Ganancias del PID | G 0.08 0.04 0.03 |
B b · N n | Peso del setpoint · filtro de la derivada | B 0.6 |
U0 % · UM % | PWM de flotación · PWM manual | U0 48 |
V % | Apertura de la válvula de fuga | V 100 |
TUNE h | Autoajuste por relé con amplitud \(h\) | TUNE 12 |
CI kp ki · RPM n | Lazo interno de velocidad · rpm con \(100\,\%\) | CI 0.01 0.05 |
LED n | Brillo de la tira (\(0\) a \(255\)) | LED 120 |
CAL · SAVE · ? | Calibrar \(d_0\) · guardar en memoria · pedir parámetros | CAL |
La ESP32 responde con una línea por mensaje. La telemetría sale \(50\) veces por segundo:
D,ms,y,r,u,rpm,uP,uI,uD,valvula,modo,perfil
D,48210,201.4,200.0,47.83,1490,0.42,-0.31,0.12,0,2,0
Por Bluetooth es el mismo texto, en el servicio UART de Nordic (6E400001-…), a \(25\) datos por segundo. Las líneas I {…} traen los parámetros, A {…} el resultado del relé y RETO {…} tu puntaje. Esta página lee exactamente eso; el simulador del navegador habla el mismo protocolo, así que lo que pruebas sin hardware funciona igual con hardware.
Cuánto cuesta, pieza por pieza
Precios con IVA consultados el 27 de octubre de 2026 en tiendas de Bogotá. «Verificado» quiere decir que el precio salió de la página del producto ese día; «estimado» es un rango típico que conviene confirmar antes de comprar.
| Componente | Cant. | Unitario | Subtotal | Dónde |
|---|---|---|---|---|
| Electrónica | ||||
| ESP32 DevKit 30 pines CP2102 (micro USB) | 1 | $ 38.500 | $ 38.500 | Electronilab verificado |
| Sensor láser VL53L1X (4 m, I2C, XSHUT) | 1 | $ 31.900 | $ 31.900 | Electronilab verificado |
| Pantalla TFT IPS 1,3" 240×240 ST7789 (7 pines) | 1 | $ 27.965 | $ 27.965 | JA-Bots (23.500 + IVA) verificado |
| Encoder rotativo KY-040 con pulsador | 1 | $ 6.950 | $ 6.950 | Electronilab verificado |
| Servo SG90 | 1 | $ 11.000 | $ 11.000 | Ferretrónica verificado |
| Reductor LM2596 (3 A) | 1 | $ 6.900 | $ 6.900 | Electronilab verificado |
| Cinta WS2812B 60 LED/m IP65, 1 m (se usan 50 cm) | 1 | $ 42.900 | $ 42.900 | Electronilab verificado agotado hoy |
| Ventilador 80×80×25 mm 12 V, 4 pines PWM con tacómetro | 1 | $ 35.000 | $ 35.000 | MercadoLibre / tiendas de PC estimado |
| Fuente 12 V 2 A, plug 2,1 mm | 1 | $ 17.900 | $ 17.900 | Electronilab verificado agotado hoy |
| Jack hembra 2,1 mm | 1 | $ 440 | $ 440 | Electronilab verificado agotado hoy |
| Interruptor basculante KCD1 | 1 | $ 4.500 | $ 4.500 | Electronilab verificado |
| Transistor 2N2222 | 2 | $ 110 | $ 220 | Electronilab verificado |
| Placa universal FR-4 7 × 9 cm | 1 | $ 4.500 | $ 4.500 | Electronilab verificado |
| Resistencias, condensador 1000 µF, borneras, headers y cable | 1 | $ 12.000 | $ 12.000 | cualquier tienda estimado |
| Mecánica | ||||
| Tubo de acrílico Ø50 × Ø44 mm, 50 cm | 1 | $ 45.000 | $ 45.000 | acrílicos / MercadoLibre estimado |
| Bolas de ping-pong 40 mm (paquete) | 1 | $ 8.000 | $ 8.000 | papelería / deportes estimado |
| Tornillería M4×40, M3×10, M2×8 y tuercas | 1 | $ 6.000 | $ 6.000 | ferretería estimado |
| Tabla MDF 200 × 300 mm (opcional) | 1 | $ 8.000 | $ 8.000 | ferretería estimado |
| Impresión 3D | ||||
| Filamento PLA, 306 g (impresora propia; rollo ELEGOO de 1 kg a $ 93.900) | 1 | $ 28.733 | $ 28.733 | Electronilab verificado |
| Alternativa: mandar a imprimir (306 g × $ 450/g) | 1 | $ 137.700 | $ 137.700 | servicios en Bogotá referencia |
| Electrónica | $ 240.675 | |||
| Mecánica | $ 67.000 | |||
| Total con impresora propia | $ 336.408 | |||
| Total mandando a imprimir | $ 445.375 | |||
| Pieza impresa | PLA aprox. |
|---|---|
| P1 Base con patas | 29 g |
| P2 Difusor con panal | 125 g |
| P3 Aleta | 2 g |
| P4 Tapa del sensor | 19 g |
| P5 Caja | 66 g |
| P6 Tapa de la caja | 22 g |
| P7 Abrazaderas LED ×4 | 20 g |
| Total con purga y bordes (+8 %) | 306 g |
Para que salga más barato
- Electronilab manda gratis los pedidos web de más de $ 300.000: con esta lista casi llegas; pide todo junto.
- Si alguien del grupo tiene impresora, la impresión baja de unos $ 138 mil a unos $ 29 mil.
- Un ventilador de 4 pines usado de un PC viejo funciona igual. Revisa que diga PWM y que tenga 4 cables.
- Los servicios de impresión cotizan distinto: unos por gramo (referencia $ 450/g) y otros por tiempo de máquina. Manda los STL y pide precio con PLA al 20 %.
La hoja con todos los precios y enlaces está en cotizacion/cotizacion_levitador.csv (se abre en Excel). Fuentes: páginas de producto de Electronilab, Ferretrónica y JA-Bots; tarifas de impresión de Kojak Graphic (desde $ 90/g más tiempo de máquina) y un anuncio de MercadoLibre a $ 450/g en Bogotá.
Del primer encendido a la bola flotando, en orden
- LM2596 a 5,0 V con el multímetro, sin nada conectado a la salida.
- Ventilador solo: modo Manual, sube el PWM. A \(0\,\%\) debe estar quieto (o al mínimo), a \(100\,\%\) a tope. Si va al revés, cambia
FAN_PWM_INVERTIDO. - Calibrar: modo Apagado, bola en reposo sobre el panal, botón «Calibrar \(d_0\)». La altura debe leer \(\approx 0\).
- Encontrar \(u_0\): modo Manual, sube despacio hasta que la bola flote y suba muy lento. Ese número es \(u_0\): pásalo al deslizador \(u_0\).
- Primer lazo: modo PID con las ganancias por defecto, \(r = 200\). Si oscila, baja \(K_p\) a la mitad.
- Autoajuste: «Iniciar prueba» con \(h = 8\) y el setpoint a media altura (\(r \approx 220\)). Aplica la regla «Sin sobreimpulso» y luego afina.
- Pantalla y perilla: gira la perilla y mira el campo de abajo en la pantalla; clic pasa al siguiente campo (setpoint, modo, perfil, ganancias, válvula); pulsación larga arranca o para el PID.
- Guardar: «Guardar en la ESP32». La próxima vez arranca con esas ganancias.
- Si la bola gira o golpea la pared: revisa que el tubo esté vertical y que el panal no tenga hilos de plástico. Una bola con una línea de marcador te deja ver si gira.
Descargas
| Archivo | Qué es | Estado |
|---|---|---|
stl/P1…P7_*.stl | Las siete piezas para imprimir, ya orientadas en la cama (P7 se imprime cuatro veces). | Mallas cerradas, un cuerpo |
step/levitador_ensamble.step | Ensamble con 24 componentes con nombre y color. En Fusion 360: Archivo → Abrir, o el script. | Generado del modelo |
step/*.step | Un STEP por pieza (impresas P y compradas C). | Generado del modelo |
fusion360/Levitador_PID/ | Script de Fusion: importa el ensamble, crea parámetros de usuario y juntas para animar bola, hélice y válvula. | Sin ejecutar en Fusion |
cad/levitador_cad.py | Código paramétrico (CadQuery) del que sale todo lo anterior. | Funciona |
firmware/levitador_pid/ | Firmware de la ESP32 (Arduino y PlatformIO): lazo, pantalla, perilla, LED y Bluetooth. | Revisado, sin compilar en placa |
modelo/modelo_levitador.py | Modelo, Routh, PID, márgenes, simulación no lineal y relé con python-control. | Probado |
render/ | Renders del ensamble y el video de funcionamiento. | Generado |
diagramas/ | Diagrama de bloques y de conexiones (SVG y PNG). | Generado |
cotizacion/cotizacion_levitador.csv | Lista de compras con precios, tiendas y enlaces. | 27 oct 2026 |
Levitador PID · Programa PRI · Control 2026-2 · El modelo, el CAD, el firmware y esta página salen del mismo juego de parámetros.