Proyecto Arduino · nivel 1

Abrir una puerta con un servo y un botón

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.


Paso 1Qué hace falta

Paso 2Las conexiones

Cuatro cables en total: tres del servo y dos del pulsador (uno de ellos comparte el GND).

Diagrama esquemático: el servo conectado al pin 9, 5V y GND; el pulsador entre el pin 2 y GND.
Vista esquemática — qué va contra qué

El servo

Cable del servoVa a
Naranja o amarillo (señal)pin 9
Rojo (+)5V
Marrón o negro (−)GND

El pulsador

Pata del pulsadorVa a
Una patapin 2
La otra pataGND
No hace falta resistencia El código usa INPUT_PULLUP, que activa una resistencia que el Arduino ya tiene adentro.
Ojo con el pulsador de 4 patas Las patas están unidas de a pares, así que hay una forma correcta y una incorrecta de ponerlo. Si no funciona, girá el botón 90° en la protoboard y listo.
El mismo circuito dibujado tal como queda armado en la protoboard, con el pulsador a caballo del canal del medio.
Lo mismo, pero armado en la protoboard

Paso 3El programa

Todo lo que se puede tocar está arriba, en las constantes. El resto podés dejarlo como está.

AbrirPuerta/AbrirPuerta.ino
/*
  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.

Paso 4Cargarlo en la placa

Desde la consola, con arduino-cli

Conectá la placa por USB y averiguá en qué puerto quedó:

terminal
arduino-cli board list

Compilar:

terminal
arduino-cli compile --fqbn arduino:avr:uno AbrirPuerta

Y subir — cambiando el puerto por el que te mostró el primer comando:

terminal
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.

Desde el Arduino IDE

  1. Abrir AbrirPuerta/AbrirPuerta.ino.
  2. Elegir la placa en Herramientas → Placa (por ejemplo Arduino UNO) y después el puerto.
  3. Apretar Subir, la flechita →.

La librería Servo ya viene con el IDE: no hay que instalar nada.

Mac con chip M1 / M2 / M3 / M4

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:

terminal
softwareupdate --install-rosetta --agree-to-license

Paso 5Para jugar con los valores

VariableQué hace
ANGULO_CERRADOPosición con la puerta cerrada (0° por defecto)
ANGULO_ABIERTOPosición con la puerta abierta (90° por defecto)
MS_POR_GRADOLa velocidad: más grande = más lento (15 ms por grado)
PIN_SERVO / PIN_BOTONSi querés usar otros pines

Para que abra más, subí ANGULO_ABIERTO: el SG90 llega hasta unos 180°.

Paso 6Si algo no anda

No reacciona al botón

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 vibra, o la placa se reinicia sola

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.

La puerta arranca al revés

Intercambiá los valores de ANGULO_CERRADO y ANGULO_ABIERTO.

Fuerza el tope y hace ruido

El servo está empujando contra la puerta. Acercá ANGULO_ABIERTO y ANGULO_CERRADO a la posición real de los topes.

Cómo funciona el código

  1. Lee el botón con un filtro de tiempo (antirrebote), para que un contacto imperfecto no haga temblar la puerta.
  2. Define un ángulo objetivo según el botón: abierto o cerrado.
  3. Mueve el servo de a un grado cada 15 ms hacia ese objetivo. Por eso el movimiento se ve suave en lugar de un golpe seco — y como no usa delay(), el programa nunca se queda congelado: responde al botón incluso en mitad del movimiento.