Proyecto Arduino · nivel 1
Mientras tenés el botón apretado la puerta se abre. Al soltarlo, se cierra sola. Son cuatro cables y 60 líneas de código, y el movimiento sale suave, no de golpe.
Cuatro cables en total: tres del servo y dos del pulsador (uno de ellos comparte el GND).
| Cable del servo | Va a |
|---|---|
| Naranja o amarillo (señal) | pin 9 |
| Rojo (+) | 5V |
| Marrón o negro (−) | GND |
| Pata del pulsador | Va a |
|---|---|
| Una pata | pin 2 |
| La otra pata | GND |
INPUT_PULLUP, que activa una resistencia que el Arduino ya tiene adentro.
Todo lo que se puede tocar está arriba, en las constantes. El resto podés dejarlo como está.
/* Abrir puerta con servo y pulsador --------------------------------- Botón apretado -> la puerta se abre y queda abierta Botón suelto -> la puerta se cierra */ #include <Servo.h> // ---- Ajustes que podés tocar ---- const int PIN_SERVO = 9; // pin de señal del servo const int PIN_BOTON = 2; // pin del pulsador const int ANGULO_CERRADO = 0; // posición de puerta cerrada const int ANGULO_ABIERTO = 90; // posición de puerta abierta const unsigned long MS_POR_GRADO = 15; // más grande = más lento const unsigned long MS_ANTIRREBOTE = 30; // filtro de "ruido" del botón // --------------------------------- Servo puerta; int anguloActual = ANGULO_CERRADO; unsigned long ultimoPaso = 0; bool lecturaPrevia = HIGH; bool estadoBoton = HIGH; unsigned long ultimoCambio = 0; void setup() { pinMode(PIN_BOTON, INPUT_PULLUP); // sin apretar lee HIGH, apretado lee LOW puerta.attach(PIN_SERVO); puerta.write(anguloActual); // arranca cerrada } void loop() { // 1) Leer el pulsador filtrando el rebote mecánico bool lectura = digitalRead(PIN_BOTON); if (lectura != lecturaPrevia) { ultimoCambio = millis(); lecturaPrevia = lectura; } if (millis() - ultimoCambio > MS_ANTIRREBOTE) { estadoBoton = lectura; } // 2) Decidir a dónde tiene que ir la puerta bool botonApretado = (estadoBoton == LOW); int objetivo = botonApretado ? ANGULO_ABIERTO : ANGULO_CERRADO; // 3) Mover el servo de a un grado para que no vaya de golpe if (anguloActual != objetivo && millis() - ultimoPaso >= MS_POR_GRADO) { ultimoPaso = millis(); anguloActual += (objetivo > anguloActual) ? 1 : -1; puerta.write(anguloActual); } }
Compila sin errores ni warnings para UNO y para Nano. Ocupa 2308 bytes de programa (7% del UNO) y 62 bytes de RAM (3%): sobra lugar de sobra para agregarle cosas más adelante.
arduino-cliConectá la placa por USB y averiguá en qué puerto quedó:
arduino-cli board list
Compilar:
arduino-cli compile --fqbn arduino:avr:uno AbrirPuerta
Y subir — cambiando el puerto por el que te mostró el primer comando:
arduino-cli upload -p /dev/cu.usbmodem1101 --fqbn arduino:avr:uno AbrirPuerta
Para un Nano usá arduino:avr:nano. Si es un clon chino y el upload
falla con timeout, probá con el bootloader viejo: arduino:avr:nano:cpu=atmega328old.
AbrirPuerta/AbrirPuerta.ino.La librería Servo ya viene con el IDE: no hay que instalar nada.
Arduino no publica el compilador AVR para Apple Silicon: el que trae es sólo para Intel.
Sin Rosetta 2 la compilación falla con bad CPU type in executable, tanto desde el
IDE como desde la consola. En una Mac nueva hay que correr esto una sola vez:
softwareupdate --install-rosetta --agree-to-license
| Variable | Qué hace |
|---|---|
ANGULO_CERRADO | Posición con la puerta cerrada (0° por defecto) |
ANGULO_ABIERTO | Posición con la puerta abierta (90° por defecto) |
MS_POR_GRADO | La velocidad: más grande = más lento (15 ms por grado) |
PIN_SERVO / PIN_BOTON | Si querés usar otros pines |
Para que abra más, subí ANGULO_ABIERTO: el SG90 llega hasta unos 180°.
Casi siempre es el pulsador de 4 patas puesto en la posición equivocada. Giralo 90° en la protoboard. Si sigue sin andar, revisá que una pata vaya al pin 2 y la otra a GND.
El servo consume bastante. Si es más grande que un SG90, alimentalo con una fuente aparte de 5V (pilas o un cargador) y uní los GND de esa fuente y del Arduino. La señal sigue yendo al pin 9.
Intercambiá los valores de ANGULO_CERRADO y ANGULO_ABIERTO.
El servo está empujando contra la puerta. Acercá ANGULO_ABIERTO y
ANGULO_CERRADO a la posición real de los topes.
delay(), el programa
nunca se queda congelado: responde al botón incluso en mitad del movimiento.