Correo: [email protected] - Teléfono: +56979962128

En este completo tutorial aprenderás a utilizar un pulsador con Arduino, con diferentes configuraciones de circuitos. También verás como usar el botón pulsador para varias aplicaciones y aprovechar algunas de las capacidades de Arduino, por ejemplo, interrupciones.

 

El circuito básico del pulsador

Para el circuito necesitarás:

Aquí está el circuito que haremos.

Foto boton

 

Pasos para construir el circuito:

  • Asegúrate de apagar el Arduino.
  • Enchufa el botón pulsador en el medio de la placa de prueba, como en la imagen.
  • En la pata de un botón, conecta un cable (negro si es posible) a un pin GND en la placa Arduino. En el caso de no tener la placa de MCI.
  • Los terminales de los pines superior izquierdo e inferior izquierdo del botón están conectados entre sí, y las terminales de los pines superior derecho e inferior derecho están conectados entre sí. Si has conectado el cable GND en el lado izquierdo, conecta otro cable en el lado derecho, para que no estén conectados entre sí. Este otro cable va a un pin digital, por ejemplo, el 4. Si necesitas ayuda con el uso de una protoboard revisa este tutorial para más ayuda en el caso de no tener la placa MCI.

Por ahora no hay resistencia involucrada en el circuito. En el siguiente de esta publicación detallaremos más sobre esto. Además, si desea obtener más información sobre los pines de Arduino, consulta esta guía de asignación de pines de Arduino Uno .

Código Arduino para leer el estado del pulsador

Lo que intentamos hacer aquí es simplemente leer el estado del botón e imprimirlo por el puerto serial.

Imprime el estado del pulsador

Aquí está el código para imprimir el estado del botón.

// Pin del botón
#define BUTTON_PIN 4

// Tiempo de debounce en milisegundos
const unsigned long DEBOUNCE_MS = 50;

// Variables de estado
int lastButtonState = HIGH; // Estados posibles: HIGH (no presionado), LOW (presionado)
unsigned long lastDebounceTime = 0; // Última vez que cambió el estado

void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP); // Resistencia pull-up interna
// Inicializar estado
lastButtonState = digitalRead(BUTTON_PIN);
}

void loop() {
int reading = digitalRead(BUTTON_PIN);

// Si el estado cambia, reiniciar el temporizador de debounce
if (reading != lastButtonState) {
lastDebounceTime = millis();
}

// Si ha pasado el tiempo de debounce, considerar el nuevo estado estable
if ((millis() - lastDebounceTime) > DEBOUNCE_MS) {
// Solo actúar si el estado estable es diferente al último estado impreso
if (reading != lastButtonState) {
lastButtonState = reading;

// Para `INPUT_PULLUP`, LOW = presionado
bool pressed = (reading == LOW);

// Imprimir estado interpretado
Serial.print("Boton: ");
Serial.println(pressed ? "PRESIONADO" : "NO PRESIONADO");
}
}

// Opcional: mantener un pequeño retardo para no saturar el puerto serie
// delay(5);
}

Analicemos este código un poco más.

Código para configurar el pulsador

#define BUTTON_PIN 4

Primero creamos un #define para el pin del botón, por lo que no necesitamos escribir “4” cada vez que queramos usar este pin en nuestro código. Esto sera más práctico, especialmente si quieres conectar el botón a otro pin más adelante. De esta manera, solo necesita modificar una línea del código, que se encuentra en la parte superior del programa, por lo tanto, es fácil de encontrar.

void setup()
{
  Serial.begin(9600);

La función void setup() se llamará primero, solo una vez. Lo que hacemos aquí es inicializar la comunicación en serie, de modo que podamos usar el monitor en serie para imprimir los datos que obtuvimos del botón.

  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

Así es como inicializa el botón pulsador en su código. En el void setup(), usa la función pinMode() con 2 argumentos: primero el pin del botón (aquí BUTTON_PIN será reemplazado por “4”) y luego el modo que queremos para el pin. Como vamos a leer datos del botón, no escribir, elegimos un modo de entrada. Y luego todavía tenemos 2 opciones: INPUT o INPUT_PULLUP. 

Como no tenemos ningún resistor en nuestro circuito, usaremos INPUT_PULLUP para usar el resistor pull up interno de la placa Arduino. Ten en cuenta que en este tutorial no voy a profundizar en la explicación de INPUT_PULLUP, pero si quieres saber más puedes ver este tutorial .

Código para leer el estado del pulsador

void loop()
{
  Serial.println(digitalRead(BUTTON_PIN));

Ahora el pin para el botón se inicializa como entrada, y entramos en el void loop(), que se llamará una y otra vez un número infinito de veces.

Para leer el estado del botón, usamos la función digitalRead(), con un argumento: el pin del botón. El resultado de esa función será HIGH o LOW. Aquí, debido a que estamos en una configuración pull up (con INPUT_PULLUP), cuando el botón no esté presionado, leerá HIGH. Cuando se presiona el botón, leerá LOW.

Luego, ponemos el resultado de digitalRead() en la función Serial.println(), que simplemente imprimirá los datos en el monitor serie.

Ahora puedes probar el código compilándolo y cargándolo en tu Arduino.

Abre el monitor serie y presiona/suelta el pulsador varias veces.

Verás algo como esto:

Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: PRESIONADO
Boton: PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: PRESIONADO
Boton: PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO
Boton: NO PRESIONADO

El valor que obtiene de digitalRead() es HIGH o LOW, se convertirá en 1 (HIGH) o 0 (LOW) y eso se interpreta en que debe arrojar por el monitor serial los estados de “PRESIONADO” o “NO PRESIONADO”.

 

Uso de resistencias pull up/down

Básicamente, cuando se conecta un botón pulsador a un pin digital, el valor que lee Arduino está entre 0V y 5V. Si el valor está cerca de 0V, obtendrá LOW en su código, y si está cerca de 5V, obtendrá el valor HIGH. Esta parte esta dentro del codigo que agregamos al principio dentro del pinMode de nuestro botón. 

Si no se coloca ningúna resistencia, el valor puede estar “flotando” entre 0V y 5V, lo que le dará resultados aleatorios y extraños en nuestro código. Al agregar una resistencia, puede forzar que el estado predeterminado sea LOW o HIGH. Y cuando presione el botón, el estado se convertirá en el opuesto. Esto es bastante útil, pues se evitan errores o malas lecturas de un botón.

Así que tenemos 3 opciones aquí:

  • Sin resistencia, pero usa el modo INPUT_PULLUP para activar la resistencia pull-up interna (forzará el voltaje de lectura predeterminado a 5V – HIGH).
  • Agrega una resistencia pull-up (valor predeterminado: HIGH).
  • Agrega una resistencia desplegable pull-down (valor predeterminado: LOW).

Para obtener más detalles sobre las resistencias pull up/down, lea este tutorial INPUT_PULLUP .

¿Por qué deberíamos considerar las opciones 2 y 3, si podemos construir el circuito sin ninguna resistencia? Bueno, porque la resistencia pull up interna es bastante débil en comparación con lo que vamos a agregar manualmente en el circuito. Esto podría dar lugar a resultados poco fiables, por ejemplo, si tienes cables más largos.

Pulsador Arduino con resistencia pull up externa

Para este circuito, necesitarás una resistencia de 10k Ohm y todos los demás componentes que usamos anteriormente. (En este caso no se puede aplicar directamente con el botón que tenemos en la placa MCI)

Placa boton2
  • Antes de modificar el circuito, asegúrate de apagar el Arduino para evitar cualquier riesgo para su hardware.
  • Para el cable de tierra (negro) y el cable de datos (azul), es lo mismo que antes. Asegúrate de que estén en diferentes lados del botón, por ejemplo, GND en el lado izquierdo y pin digital en el lado derecho.
  • Agrega la resistencia de 10 kOhm al mismo lado que la conexión del pin digital; en este ejemplo, en el lado derecho. La otra pata de la resistencia va a una línea diferente en el protoboard, y desde esta pata, agregas un cable (rojo) al pin de 5V del Arduino. Esta es la resistencia pull up, que se asegurará de que el voltaje predeterminado que lea sea de 5 V, por lo tanto, HIGH en el código.

Ahora, aquí está el código para esta variación.

#define BUTTON_PIN 4

void setup()
{
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
}

void loop()
{
  byte buttonState = digitalRead(BUTTON_PIN);
  
  if (buttonState == LOW) {
      Serial.println("BOTON PRESIONADO");
  }
  else {
      Serial.println("BOTON NO PRESIONADO");
  }
  delay(100);
}

Como puedes ver, el código es el mismo, solo modificamos el modo en la función pinMode(). En lugar de usar INPUT_PULLUP, que configurará el pin como INPUT + activar la resistencia interna, solo usamos INPUT. Este codigo es más sencillo para ejemplificar en comparación del primero, para el botón incorporado de la placa MCI.

Pulsador Arduino con resistencia pull down externa

Para este circuito también usaremos una resistencia de 10k Ohm.

Foto boton2

El principio es el mismo, pero ten en cuenta que las cosas son un poco diferentes aquí:

  • Una vez más, asegúrate de apagar el Arduino antes de hacer nada.
  • Vas a agregar la resistencia de 10k Ohm en el lado conectado a tierra. Entonces, comenzando desde una pata del botón, tiene la resistencia y luego un cable (negro) conectado a GND.
  • El cable conectado al pin digital ahora debe estar en el mismo lado que la resistencia; en este ejemplo, las conexiones de pin digital y GND están en el lado izquierdo (y no en lados opuestos).
  • Agrega un cable (rojo) entre una pata del botón, desde el lado opuesto de GND, aquí en el lado derecho, y 5V.

Y aquí está el código.

#define BUTTON_PIN 4

void setup()
{
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
}

void loop()
{
  byte buttonState = digitalRead(BUTTON_PIN);
  
  if (buttonState == HIGH) {
      Serial.println("BOTON PRESIONADO");
  }
  else {
      Serial.println("BOTON NO PRESIONADO");
  }
  delay(100);
}

Como puedes ver, también usamos el modo INPUT en la función pinMode().

Pero ahora, cuando leemos el estado del botón pulsador, LOW significa que el botón no está presionado. Así que tenemos que cambiar la forma en que analizamos los datos en nuestro código. Eso es lo que puedes ver en la línea 13: si el estado es HIGH, ahora significa que se presionó el botón.

¿Que valor de resistencia escoger?

El valor de la resistencia viene condicionado por la corriente que pasa al accionar el interruptor, y por un concepto llamado la “autoridad del Pull Down/up” que está relacionado con el ruido en la medición.

  • Una resistencia muy pequeña, tendrá mucha autoridad, pero permitirá el paso de una mayor corriente, lo que supone mayor consumo y mayor calentamiento.
  • Una resistencia muy grande, dejará pasar poca corriente, pero tendrá poca autoridad, por lo que será más susceptible a mediciones incorrectas debidas a ruido.

 

Detectar un cambio de estado

Genial, ahora puedes leer el estado del botón y hacer algo diferente en tu código, ya sea que el botón esté presionado o no.

Pero, ¿Qué sucede si se desea detectar no el estado en sí mismo, sino un cambio de estado? Por ejemplo, cuando el estado del botón pasa de “no presionado” a “presionado” (presionar), o al contrario (soltar). Dependiendo de su aplicación, eso puede ser muy útil.

Y para eso podemos usar 2 métodos: interrupciones y sondeo (polling).

Para esos 2 métodos, un código que te ayudará a comenzar con una comprensión básica y algunos enlaces a otros tutoriales detallados más abajo.

Usar interrupciones con el pulsador

Con las interrupciones, básicamente puedes crear una función que se llamará cuando ocurra un cambio determinado en un pin digital. La llamada de esta función “interrumpirá” el flujo normal del programa.

Solo ciertos pines digitales pueden usarse para interrupciones. En Arduino Uno, puede usar los pines 2 y 3. Como el botón está actualmente conectado al pin 4, necesitamos modificar el circuito.

El circuito esta con la resistencia desplegable externa, pero esta vez el cable de datos está conectado al pin digital 3.

Ahora, el código para detectar cuando se suelta el botón:

#define BUTTON_PIN 3

volatile byte buttonReleased = false;

void buttonReleasedInterrupt() {
  buttonReleased = true;
}

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN),
                  buttonReleasedInterrupt,
                  FALLING);
}

void loop() {
  if (buttonReleased) {
    buttonReleased = false;
    // do something here, for example print on Serial
    Serial.println("Button released");
  }
}

La forma de inicializar el botón es la misma que antes.

Luego creamos una nueva función llamada buttonReleasedInterrupt(). Esta función se llamará cuando se active la interrupción, con el modo FALLING, lo que significa que el estado del botón va de HIGH a LOW.

Entonces, cuando se suelta el botón (el estado pasa de HIGH a LOW), se llama a la función. Establecemos un valor booleano (marcado como “volatile“, porque lo modificamos dentro de una interrupción) en verdadero, y en el void loop(), verificamos ese valor booleano. Si es cierto, entonces sabemos que se ha soltado el botón. Volvemos a establecer el booleano en falso y hacemos cualquier acción que queramos, por ejemplo, podemos imprimir “Button released” en el monitor serie.

Nota importante: no uses Serial directamente dentro de una función de interrupción.

Si desea una explicación más detallada, puedes revisar este tutorial sobre las interrupciones de Arduino , que también muestra todos los pros y contras para usar las interrupciones correctamente.

Detectar cambios de estado con sondeo

Probemos otra forma de comprobar si se ha soltado el botón, sondeando continuamente el estado.

#define BUTTON_PIN 3

byte lastButtonState = LOW;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
}

void loop() {
  byte buttonState = digitalRead(BUTTON_PIN);
  if (buttonState != lastButtonState) {
    lastButtonState = buttonState;
    if (buttonState == LOW) {
      // do an action, for example print on Serial
      Serial.println("Button released");
    }
  }
}

Nuevamente, inicializamos el botón de la misma manera que lo hicimos antes.

También mantenemos una variable global llamada lastButtonState, para que podamos comparar el estado del botón actual que leemos con el anterior.

En el void loop(), comprobamos constantemente el estado del botón. Si el estado es diferente al anterior, significa que ha pasado algo: o acabamos de pulsar el botón, o acabamos de soltarlo. En ambos casos guardamos el estado actual como último estado.

Y luego verificamos si el estado es LOW. Si es así, en nuestra configuración de resistencia desplegable, significa que hemos soltado el botón. Si estuviera utilizando la configuración pull up, tendría que hacer lo contrario: verificar si el estado es HIGH.

Rebote el botón

El problema con el código anterior es que cuando se ejecuta, en algunas ocasiones puede aver varios “Button released” cuando solo suelta el botón una vez.

Esto se debe a que el botón “rebota” físicamente cuando lo tocas (pasando de LOW a HIGH y de HIGH a LOW muchas veces en un breve intervalo), como cuando dejas caer una pelota al suelo. La pelota no solo llega al suelo y se queda aquí, sino que rebota varias veces antes de estabilizarse. Esto es similar para el botón pulsador.

Afortunadamente podemos resolver esto en nuestro código.

#define BUTTON_PIN 3

byte lastButtonState = LOW;

unsigned long debounceDuration = 50; // millis
unsigned long lastTimeButtonStateChanged = 0;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
}

void loop() {
  if (millis() - lastTimeButtonStateChanged > debounceDuration) {
      byte buttonState = digitalRead(BUTTON_PIN);
      if (buttonState != lastButtonState) {
      lastTimeButtonStateChanged = millis();
      lastButtonState = buttonState;
      if (buttonState == LOW) {
        // do an action, for example print on Serial
        Serial.println("Button released");
      }
    }
  }
}

Lo que hacemos aquí es básicamente ignorar cualquier resultado del botón pulsador durante un período de tiempo determinado después de que el estado haya cambiado. De esta forma, podemos evitar leer el estado cuando el botón está rebotando físicamente.

Para hacer esto, antes de leer el estado del botón, verificamos si la duración desde la última vez que cambió el estado es mayor que el debounceDuration que hemos establecido, aquí 50 milisegundos. Si es así, leemos el estado del botón. Y luego, si encontramos que el estado es diferente al último, restablecemos la variable lastTimeButtonStateChanged a la hora actual con millis(). Al hacer esto, tendremos que esperar nuevamente la próxima vez, al menos 50 milisegundos. Para obtener una explicación más detallada del mecanismo de rebote.

Conclusiones

En este tutorial de pulsadores con Arduino has aprendido a:

  • Crear correctamente un circuito con un botón conectado a tu placa Arduino,
  • Leer el estado del botón,
  • Usar este estado o cambio de estado en varios casos de uso.

Para ir más allá, te animo a que consultes este tutorial sobre cómo encender y apagar un LED con un pulsador . En el tutorial verás cómo incluir el pulsador en varias aplicaciones sencillas mediante LEDs. También obtendrá una explicación mucho más completa sobre el mecanismo de rebote.

Traducido desde: Arduino Push Button – Complete Tutorial – The Robotics Back-End (roboticsbackend.com)

Preguntas frecuentes

¿Qué necesito para conectar un pulsador a Arduino?

Una placa Arduino, una protoboard, algunos cables y el pulsador. Es uno de los circuitos más simples que se pueden armar y la base para cualquier proyecto que reaccione a la acción del usuario.

¿Por qué un pulsador necesita una resistencia pull-up o pull-down?

Porque sin ella el pin queda flotante cuando el botón no está presionado y su lectura es impredecible. La resistencia fija un nivel conocido por defecto: pull-up deja el pin en alto y pull-down lo deja en bajo.

¿Se puede usar un pulsador con interrupciones en Arduino?

Sí. Además de leer el botón dentro del bucle principal, se puede asociar a una interrupción para que el Arduino reaccione al instante sin tener que estar consultando el pin continuamente.

¿Cómo leo el estado de un pulsador en Arduino?

Configurando el pin como entrada en setup y usando digitalRead en el bucle. El valor devuelto será HIGH o LOW según el estado del botón y la configuración de resistencias que se haya elegido.

Aprende esto en un curso

Si prefieres verlo en vivo y con alguien que resuelva tus dudas, estos cursos presenciales de MCI Educación cubren el tema de este tutorial: