En este completo tutorial aprenderás a utilizar un pulsador con Arduino, con diferentes configuraciones de circuitos. También verá cómo usar el botón pulsador para varias aplicaciones y aprovechar algunas de las capacidades de Arduino, por ejemplo, interrupciones.
Voy a usar una placa Arduino Uno, pero este tutorial también funciona para cualquier otra placa Arduino que puedas encontrar.
¡Empecemos!
El circuito básico del pulsador
Para el circuito necesitarás:
Aquí está el circuito que haremos.

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.
- 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
Por ahora no hay resistencia involucrada en el circuito. En el siguiente de esta publicación hablaremos 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 10 veces por segundo.
Imprime el estado del pulsador
Aquí está el código para imprimir el estado del botón 10 veces por segundo.
#define BUTTON_PIN 4
void setup()
{
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop()
{
Serial.println(digitalRead(BUTTON_PIN));
delay(100);
}
Analicemos este código línea por línea.
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 te hará la vida más fácil, 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 y, 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.
delay(100);
}
Justo después de leer el estado del botón e imprimirlo, agregamos un delay() de 100 milisegundos, lo que significa que vamos a realizar esta acción aproximadamente 10 veces por segundo. Después de salir del void loop(), se vuelve a llamar, etc., etc.
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:
1
1
1
1
0
0
0
0
1
1
1
1
Cada 100 milisegundos tendrán una nueva línea, con 0 o 1.
Como escribí anteriormente, el valor que obtiene de digitalRead() es HIGH o LOW, pero cuando lo envías a través de Serial, se convertirá en 1 (HIGH) o 0 (LOW).
Entonces, cuando no se presiona el botón, verás impreso “1”, y cuando se presiona el botón, verás “0”.
Mejora: Imprime un mensaje más explícito
Este primer código es excelente como un ejemplo mínimo para ver los datos que provienen del botón pulsador. Pero en una aplicación real, es posible que desee hacer cosas más interesantes que simplemente imprimir el estado del botón. Por ejemplo, podría leer el estado del botón, mantenerlo dentro de una variable y luego, según el valor, realizar una acción específica.
Usemos el siguiente código de Arduino.
#define BUTTON_PIN 4
void setup()
{
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop()
{
byte buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW) {
Serial.println("Button is pressed");
}
else {
Serial.println("Button is not pressed");
}
delay(100);
}
La fase de configuración es la misma. Y como puede ver en loop(), ahora almacenamos el valor que obtuvimos de digitalRead() en una variable, a la que llamamos buttonState. El tipo de datos para esta variable es byte, que es lo que necesita para los valores HIGH y LOW.
Luego, con una estructura if simple, verificamos si el estado es LOW, lo que significa que, en nuestra configuración con la resistencia pull up interna de Arduino, el botón está presionado. Cuando detectamos esto, podemos decidir hacer cualquier acción que queramos. Y si la condición es falsa, lo que significa que el estado es HIGH (porque solo hay 2 estados posibles), sabemos que el botón no está presionado.
Ahora puede ejecutar este código y ver “Button is not pressed” impreso cada 100 milisegundos, y cuando presiona el botón, “Button is pressed”.
Button is not pressed
Button is not pressed
Button is not pressed
Button is not pressed
Button is pressed
Button is pressed
Button is pressed
Button is not pressed
Button is not pressed
Esta es una buena mejora con respecto al código anterior, que nos brinda más contexto y permite que el código crezca con más funcionalidades.
Uso de resistencias pull up/down
Por ahora no hemos usado ninguna resistencia en nuestro circuito; de hecho, lo hicimos, pero esta es la resistencia interna de Arduino.
Básicamente, cuando 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.
Si no coloca ninguna resistencia, el valor puede estar “flotando” entre 0V y 5V, lo que le dará resultados aleatorios y extraños. 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.
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 (valor predeterminado: LOW).
Para obtener más detalles sobre las resistencias pull up/down, lea este tutorial INPUT_PULLUP .
Entonces, ya hemos usado la opción 1, ahora veamos cómo trabajar con la opción 2 y 3.
¿Y 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.

- 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.
#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("Button is pressed");
}
else {
Serial.println("Button is not pressed");
}
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.
Pulsador Arduino con resistencia pull down externa
Para este circuito también usaremos una resistencia de 10k Ohm.

El principio es el mismo, pero tenga 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("Button is pressed");
}
else {
Serial.println("Button is not pressed");
}
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.
Detectar un cambio de estado
Genial, ahora puede 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 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, daré una introducción, y un código que te ayudará a comenzar con una comprensión básica, pero si desea saber más, he incluido algunos enlaces a otros tutoriales detallados más abajo.
Usar interrupciones con el pulsador
Con las interrupciones, básicamente puede 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.
Aquí está el circuito 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 lo ejecuta, en algunas ocasiones puede ver 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)