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:

pulsador_2

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:

pulsador

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.

 Si desconectásemos totalmente el pin digital del pulsador, el led parpadearía de forma irregular. Esto se debe a que la entrada está «flotando», es decir, no está conectada ni a un voltaje ni a tierra. Devolvería de forma más o menos aleatoria un HIGH o LOW. Es por esto por lo que necesitamos una resistencia en el circuito.

2 opiniones en “Programando con pulsadores (Vídeo)

  • 18 enero, 2016 a las 15:07
    Link permanente

    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.

    Responder
    • 7 abril, 2016 a las 20:35
      Link permanente

      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.

      Responder

Deja un comentario