Programando con pulsadores (Vídeo)
Un pulsador es un actuador de dos estados: encendido y apagado. Lo usaremos para realizar tareas que requieran de un interruptor. Este es el aspecto de un pulsador:
Como los pulsadores sólo tienen dos estados podemos usar una codificación digital, representando el estado encendido con un 1 y apagado con un 0. Cabe destacar que los pulsadores necesitan una entrada de 5V para funcionar. Así, de las cuatro patillas de las que dispone, una estará conectada a 5V, otra a un pin digital de Arduino y otra a GND. Además, entre la patilla del pulsador y la conexión a GND hay conectada una resistencia de 10K (10.000Ω).
Esquema de montaje
En el esquema de montaje usado el pulsador estará conectado al pin digital 2. Para todos los ejemplos siguientes usaremos el mismo modelo:
DigitalReadSerial: Mostrando el estado de un pulsador
En este sketch vamos a leer continuamente el estado del botón (encendido/apagado) y lo mostraremos por el monitor serie.
// Nombramos como pushButton al pulsador conectado en el pin 2 int pushButton = 2; void setup() { // Inicializamos la comunicación serie a 9600 bits por segundo Serial.begin(9600); // Establecemos el pulsador como entrada (actuador) pinMode(pushButton, INPUT); } void loop() { // Almacenamos en la variable buttonState el valor digital leído del pulsador int buttonState = digitalRead(pushButton); // Enviamos al puerto serie el estado del botón Serial.println(buttonState); delay(1000); // Esperamos un segundo para garantizar la estabilidad de las lecturas }
Button: Pulsadores y leds
El código de ejemplo Button comprueba periódicamente el estado del pulsador. Si está accionado, se enciende el led conectado al pin digital 13. En caso de no estarlo, apagamos el led.
// Definición de constantes para declarar los pines del pulsador y led const int buttonPin = 2; // Pin para el pulsador const int ledPin = 13; // Pin para el led // Variable modificable int buttonState = 0; // Variable para leer el estado del pulsador void setup() { // Inicializamos el pin del led en modo salida pinMode(ledPin, OUTPUT); // Establecemos el pin del pulsador en modo entrada pinMode(buttonPin, INPUT); } void loop() { // Leemos el estado del pulsador y lo almacenamos en buttonState buttonState = digitalRead(buttonPin); // Comprobamos si el botón ha sido pulsado (estado HIGH) if (buttonState == HIGH) { // Si el pulsador está accionado, encendemos el led digitalWrite(ledPin, HIGH); } else { // Si el pulsador no está accionado, apagamos el led digitalWrite(ledPin, LOW); } }
Debounce: Nada es perfecto
En este apartado vamos a comentar un problemilla de los pulsadores, que es común en la gran mayoría de sensores y actuadores. Todos estos dispositivos requieren un margen de tiempo entre acciones para no ofrecer resultados erróneos. Por ejemplo, imaginemos que estamos usando PWM para dar valores de brillo creciente a un led. Si no dejamos un tiempo entre asignación de valores, no podremos ver correctamente las transiciones.
En el caso de los pulsadores es el mismo que el de los teclados de ordenador. Los pulsadores a menudo generan falsas transiciones encendido/apagado al pulsarlos, debido al funcionamiento físico del pulsador. Así, estas transiciones pueden ser leídas como múltiples pulsaciones en un espacio de tiempo muy breve, llevando a errores a nuestro programa.
En este sketch se trata cómo solucionar este problema de «rebote» (debounce), comprobando el estado durante un margen de tiempo pequeño para asegurarnos de que el pulsador está definitivamente pulsado. Si no lo comprobamos, analizar el pulsador una sola vez podría generar resultados impredecibles.
En este código aparece por primera vez la función millis(), usada para controlar el tiempo transcurrido desde que se pulsó el botón. El objetivo del programa es resolver el mismo problema que en el sketch Button anterior. Por ello, haremos uso de un led en el pin 13 junto al pulsador.
// Definición de constantes para declarar los pines del pulsador y led const int buttonPin = 2; // El numero de pin del pulsador const int ledPin = 13; // El numero del pin del LED // Variables modificables int ledState = HIGH; // Estado actual del led, inicializado en HIGH int buttonState; // Almacena el estado actual del pulsador int lastButtonState = LOW; // Representa el estado anterior del pulsador, establecido en LOW // Variables declaradas como long, ya que el tiempo (medido en milisegundos) // pasará a ser un número muy grande en poco tiempo long lastDebounceTime = 0; // El último instante en el que el pulsador cambió de estado long debounceDelay = 50; // Tiempo de "rebote" en el que no cambiamos el estado void setup() { // Declaramos el botón como entrada y el led como salida pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); // Establecemos el estado inicial del LED digitalWrite(ledPin, ledState); } void loop() { // Leemos el estado del pulsador en la variable local reading int reading = digitalRead(buttonPin); // Comprobamos si se acaba de pulsar el botón // Por ejemplo, si el pulsador ha cambiado de LOW a HIGH), y hemos // esperado suficiente desde la última pulsación para ignorar cualquier interferencia // Si el pulsador ha cambiado debido a ruido o pulsación if (reading != lastButtonState) { // Actualizamos el contador de "rebote" con el instante de tiempo actual lastDebounceTime = millis(); } // Comprobamos si el momento actual menos el último instante en el que el // pulsador cambió de estado es mayor que el tiempo establecido para debounce if ((millis() - lastDebounceTime) > debounceDelay) { // Sea cual sea el estado leído del pulsador, está en ese estado más tiempo // que el establecido para "rebote". Por tanto, es el estado definitivo // Si el botón ha cambiado de estado, se actualiza su estado if (reading != buttonState) { buttonState = reading; // Sólo cambiamos el estado del LED si el estado del pulsador es HIGH if (buttonState == HIGH) { ledState = !ledState; } } } // Establecemos el estado del LED digitalWrite(ledPin, ledState); // Actualizamos lastButtonState (estado anterior del pulsador)con // la variable reading (última lectura) para que esté actualizado // para la siguiente iteración del bucle lastButtonState = reading; }
Quizá el código puede ser algo complicado de entender. Realmente su funciomiento es sencillo:
- Si detectamos que ha cambiado el estado del pulsador, almacenamos el instante en el que detectamos el cambio.
- Si ha transcurrido más tiempo que el establecido como «rebote» y hemos detectado un cambio de estado, actualizamos dicho estado con el valor del pulsador leído (buttonState = reading).
- Finalmente, sólo actualizamos el valor del led si el estado del pulsador es HIGH.
StateChangeDetection: Conteo de pulsaciones
En algunos casos nos puede resultar interesante saber cuántas veces se ha pulsado el botón. Para ello, necesitamos detectar cuándo ha cambiado su estado y mantener la cuenta del número de veces. Esto se conoce como detección de cambio de estado.
En este programa, por cada vez que el pulsador pase de estado Apagado a Encendido enviaremos un mensaje al monitor serial con información relevante. Además, cada vez que acumulemos cuatro transiciones Apagado-Encendido cambiaremos el estado del led.
// Declaración de constantes const int buttonPin = 2; // pulsador en el pin 2 const int ledPin = 13; // LED en el pin 13 // Declaración de variables int buttonPushCounter = 0; // Contador de pulsaciones int buttonState = 0; // Estado actual del pulsador int lastButtonState = 0; // Estado anterior del pulsador void setup() { // Inicializamos pulsador, led y comunicación serie pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); } void loop() { // Leemos el estado del pulsador buttonState = digitalRead(buttonPin); // Comparamos el estado del botón con el último estado (detección de cambio) if (buttonState != lastButtonState) { // Si el estado ha cambiado, incrementamos el contador if (buttonState == HIGH) { // Si el estado actual es HIGH el pulsador se ha activado buttonPushCounter++; // Mostramos información en el monitor serial, indicando número de pulsaciones Serial.println("Pulsador ON"); Serial.print("Numero de pulsaciones: "); Serial.println(buttonPushCounter); } else { // Si el estado actual es LOW el pulsador se ha desactivado Serial.println("Pulsador OFF"); } // Delay de 50 milisegundos para evitar bouncing (interferencias entre pulsaciones) delay(50); } // Actualizamos lastButtonState con el estado actual del pulsador lastButtonState = buttonState; // Encendemos el led cada cuatro pulsaciones, comprobando el módulo // de la división entre el número de pulsaciones y 4. Si las pulsaciones // son múltiplo de 4 encendemos el led if (buttonPushCounter % 4 == 0) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }
Otras consideraciones
Cuando un pulsador está abierto (no presionado), no hay conexión entre las dos patillas. Por ello, el pin está conectado a tierra (a través de la resistencia) y leemos un valor LOW. Cuando el pulsador está cerrado (presionado), establece una conexión entre las dos patillas, conectando el pin al voltaje, por lo que leemos un valor HIGH. Es decir, el pin está todavía conectado a tierra, pero la resistencia mantiene el flujo de corriente, por lo que el camino de menor resistencia es a +5V.
Estudiante de Ingeniería Informática en la intensificación de Tecnologías de la Información. Universidad de Murcia.
Redes de Comunicaciones, Seguridad e Internet of Things.
Hola, que tal amigos? Muy buena onda la web.
Como saben que resistencias poner en el circuito? De donde sacan la info?
Un saludo. Gracias de antemano.
La resistencia que necesita cada componente puedes consultarla en su datasheet. Ahí también puedes ver cosas como el voltaje que necesita y sus características.
Un datasheet es un documento del fabricante en el que se resume el funcionamiento y las características del componente.
Espero haberte ayudado.