Casi cualquier aparato electrónico hoy en día incluye una tecla, botón, pulsador o switch. Los proyectos con arduino no son la excepción y virtualmente cualquier idea que desarrollemos dispondrá de al menos un par de botones.

En este tutorial hablaremos sobre como se puede conectar un botón al arduino y como podemos hacer para procesar correctamente las señales que envían. Además veremos como realizar aplicaciones más avanzadas con botones, por ejemplo: como detectar pulsaciones largas, doble o triple clic, etc.

 

Materiales necesarios para las prácticas

Para completar los ejercicios propuestos en esta página recomendamos adquirir los siguiente materiales:

Utilizaremos el led en el pin 13 del arduino para realizar las prácticas sin la necesidad de conectar leds externos.

 

¿Cómo conectar un botón a arduino?

Para conectar un botón al arduino conviene tener en mente ciertos puntos:

  • Un botón puede conectarse a cualquier pin de arduino (digital o analógico, ya que los analógicos usualmente funcionan también como digitales).
  • Existen dos configuraciones posibles: con resistencia pull-up o resistencia pull-down.
  • Configuraremos el pin seleccionado como entrada digital.
  • Debemos tomar en cuenta los rebotes y el ruido eléctrico en el software.
  • Es necesario utilizar una resistencia pull-up o pull-down, ya sea interna o externa.

Las dos formas que existen para conectar un botón al arduino se visualizan en los siguientes diagramas:

Botón con resistencia pull-upBotón con resistencia pull-down

Visto en el protoboard quedaría como se muestra más abajo, siendo el botón colocado del lado izquierdo del protoboard el que está conectado con pull-up, mientras que el derecho esta conectado con una resistencia pull-down.

Boton configuración pull-up y pull-down

 

El valor de las resistencias en este caso no es crítico, pero debemos considerar que valores menores causarán que circule una corriente mayor cuando se oprime el botón, mientras que los valores mayores pueden permitir que el ruido se introduzca al pin de entrada.

Los valores típicos para resistencia pull-up o pull-down son de 1 a 10 KOhms.

 

¿Para que sirve una resistencia pull-up o pull-down?

La función primordial de las resistencias en el circuito del botón es mantener un estado lógico conocido cuando el botón no está siendo accionado.

Esto es necesario ya que las entradas del microcontrolador, si se dejan al aire, no poseen un estado determinado y pueden ir a cualquiera de dos estados posibles de forma aleatoria. Según la necesidad, se pueden colocar las resistencias en pines de entrada, obteniendo los siguientes efectos:

  • La resistencia pull-up mantiene un estado alto en el pin mientras el pulsador no es accionado, el estado activo del botón es BAJO (cuando se presiona).
  • La resistencia pull-down mantiene un estado bajo mientras el pulsador no es accionado, el estado activo del botón es ALTO (cuando se presiona).

El microcontrolador AVR incluido en el arduino UNO, posee en cada pin de entrada una resistencia pull-up que se puede activar bajo control de nuestro programa, evitándonos tener que colocar de forma externa este componente. Sin embargo, no todos los microcontroladores poseen esta característica y por esta razón es común encontrar este componente colocado de forma externa en la mayoría de los circuitos.

 

Armado del circuito para las prácticas con botón o pulsador

El circuito que armaremos en el protoboard para la realización de las prácticas que se proponen a continuación es el siguiente:

circuito boton practicas con arduino

Aprovecharemos el led que viene conectado por defecto en el pin 13 del arduino y por esta razón no necesitamos otro aditamento como dispositivo de salida. Estaremos utilizando ambos botones con resistencia pull-up externa.

 

Realizar la programación del botón o pulsador con arduino

El siguiente ejemplo muestra como encender un led con un pulsador y apagar con otro botón. Es un ejemplo muy sencillo pero que ilustra muy bien el uso de las funciones pinMode() y digitalRead(). Como en la mayoría de nuestros programas, hemos procurado comentar bastante para hacer que el código sea fácil de entender.

En este programa hemos leído el estado de los pines a variables intermedias, ya que lo usamos dentro de los cursos para que los estudiantes se familiaricen con el uso de las variables, pero puede saltarse este paso y colocar directamente la función digitalRead() dentro de las condiciones.

/**
   GeekFactory - "INNOVATING TOGETHER"
   Distribucion de materiales para el desarrollo e innovacion tecnologica
   www.geekfactory.mx

   EJEMPLO DE ENTRADAS DIGITALES 2

   EJEMPLO ON/OFF LED CON 2 BOTONES, EN ESTE EJEMPLO SE ENCIENDE EL LED
   CON UN BOTON Y SE APAGA CON OTRO BOTON DISTINTO, EL LED PERMANECE EN
   EL ESTADO CORRESPONDIENTE AL ULTIMO BOTON ENCENDIDO.
*/

// ASIGNACION DE PINES
const int pinon = 2;
const int pinoff = 3;
const int pinled = 13;

// VARIABLES DE ESTADO DE BOTONES
int estaon = HIGH;
int estaoff = HIGH;

void setup() {
  // CONFIGURAR PINES COMO ENTRADAS
  pinMode(pinon, INPUT);
  pinMode(pinoff, INPUT);
  // CONFIGURAR PIN DE LED COMO SALIDA
  pinMode(pinled, OUTPUT);
}

void loop() {
  // LEER EL ESTADO DE PINES DE BOTON A VARIABLES
  estaon = digitalRead(pinon);
  estaoff = digitalRead(pinoff);

  // SE OPRIMIO EL BOTON DE ENCENDIDO?
  if (estaon == LOW) {
    // ENTONCES ENCENDEMOS EL LED
    digitalWrite(pinled, HIGH);
  }

  // SE OPRIMIO EL BOTON DE APAGADO?
  if (estaoff == LOW) {
    // ENTONCES APAGAMOS EL LED
    digitalWrite(pinled, LOW);
  }
}

 

Eliminar rebotes y el ruido de un botón en arduino

El ruido eléctrico y el fenómeno conocido como rebote, son problemas que debemos tomar en cuenta al procesar la señal proveniente de un botón.

El fenómeno del rebote se da debido a las imperfecciones que existen en los contactos internos del pulsador. El problema es especialmente notorio cuando se atiende un botón mediante interrupciones, ya que el microcontrolador verá varios cambios de estado antes de que la señal se estabilice y tengamos un estado lógico definido en el pin de entrada.

La siguiente imagen nos muestra como se ve la señal típica proveniente de un pulsador.

senal de boton pulsador

El ruido eléctrico es otro de los problemas que debemos considerar al incorporar botones en nuestros proyectos. Una chispa en la cercanía de nuestro circuito, ruido en la red eléctrica, rayos, descargas electrostáticas o la manipulación directa del circuito electrónico (PCB) pueden causar que nuestro microcontrolador “vea” un estado activo en el pin de entrada por algunos instantes y realice la acción asignada a un botón, es decir, se pueden realizar activaciones falsas del botón debidas a perturbaciones externas.

Debido a la situación explicada anteriormente, es necesario elaborar el software para que funcione a pesar de las imperfecciones en la señal de entrada. El algoritmo más sencillo que hemos probado es el siguiente:

  1. Leer continuamente el estado del pin y detectar el flanco (descendente o ascendente) que indica que se ha pulsado un botón
  2. Esperar un tiempo prudente (alrededor de 10 a 100 mili segundos) hasta que se estabilice la señal
  3. Leer nuevamente el estado del pin y comprobar que se encuentre en el estado deseado
  4. Ejecutar la acción asignada al botón, una vez que nos aseguramos que efectivamente fue presionado.

Este algoritmo garantiza principalmente dos cosas:

  • Elimina las falsas activaciones del botón por ruido eléctrico
  • Se encarga de cualquier efecto de los rebotes.

Básicamente lo que hacemos es “muestrear” en dos momentos distintos la señal del botón y garantizar que el estado lógico que buscamos esta presente. Vamos ahora a mejorar un poco el programa anterior, incluyendo este algoritmo para la eliminación de rebotes y ruido eléctrico.

 

Programación de botón con eliminación de rebotes y ruido eléctrico

La siguiente programación es una mejora del ejercicio anterior en la cual se mejora la resistencia a ruido eléctrico, aplicando el algoritmo descrito en la sección anterior.

/**
   GeekFactory - "INNOVATING TOGETHER"
   Distribucion de materiales para el desarrollo e innovacion tecnologica
   www.geekfactory.mx

   EJEMPLO DE ENTRADAS DIGITALES 5

   EJEMPLO ON/OFF LED CON 2 BOTONES, EN ESTE EJEMPLO SE ENCIENDE EL LED
   CON UN BOTON Y SE APAGA CON OTRO BOTON DISTINTO, EL LED PERMANECE EN
   EL ESTADO CORRESPONDIENTE AL ULTIMO BOTON ACTIVADO.

   ADICIONALMENTE EN ESTE EJEMPLO PROPONEMOS UNA DOBLE COMPROBACIÓN PARA
   EVITAR QUE EL RUIDO ELÉCTRICO INTERFIERA EN NUESTRO CIRCUITO. DE ESTA
   MANERA ES MUCHO MÁS SERGURO DE USAR EN APLICACIONES REALES.
*/

// ASIGNACION DE PINES
const int pinon = 2;
const int pinoff = 3;
const int pinled = 13;

// VARIABLES DE ESTADO DE BOTONES
int estaon = HIGH;
int estaoff = HIGH;

void setup() {
  // CONFIGURAR PINES COMO ENTRADAS
  pinMode(pinon, INPUT);
  pinMode(pinoff, INPUT);
  // CONFIGURAR PIN DE LED COMO SALIDA
  pinMode(pinled, OUTPUT);
}

void loop() {
  // LEER EL ESTADO DE PINES DE BOTON A VARIABLES
  estaon = digitalRead(pinon);
  estaoff = digitalRead(pinoff);

  // SE OPRIMIO EL BOTON DE ENCENDIDO?
  // HACEMOS DOBLE COMPROBACION DEL ESTADO DEL BOTÓN
  if (estaon == LOW) {
    // ESPERAMOS ANTES DE COMPROBAR NUEVAMENTE
    delay(50);
    if (estaon == LOW ) {
      // ENTONCES ENCENDEMOS EL LED
      digitalWrite(pinled, HIGH);
    }
  }

  // SE OPRIMIO EL BOTON DE APAGADO?
  // HACEMOS DOBLE COMPROBACION DEL ESTADO DEL BOTÓN
  if (estaoff == LOW) {
    // ESPERAMOS ANTES DE COMPROBAR NUEVAMENTE
    delay(50);
    if (estaoff == LOW) {
      // ENTONCES APAGAMOS EL LED
      digitalWrite(pinled, LOW);
    }
  }
}

 

Programación avanzada de botones con arduino usando una librería

Para los ejemplos siguientes estaremos utilizando la librería GFButton que debe instalarse en nuestro IDE para poder compilar los ejemplos.

Realizaremos el ejercicio de prender un led con un botón y apagarlo con otro, pero ahora utilizaremos la librería para apoyarnos. Como podemos ver, hemos movido algo del código a la librería, quedando nuestro programa mucho más compacto.

Aprovechando que se simplifica el programa, podemos incluir sentencias para enviar datos al monitor serial y saber que está pasando en cada momento.

/**
   GeekFactory - "INNOVATING TOGETHER"
   Distribucion de materiales para el desarrollo e innovacion tecnologica
   www.geekfactory.mx

   Basic example for the GFButton library. This example shows the basic library usage with
   the polling (synchronous) API. This is the easiest and more intuitive way to use the library.
*/

#include "GFButton.h"

// Create two button instances on pins 2 & 3
GFButton buttonOn(2);
GFButton buttonOff(3);

/**
   PROGRAM INITIALIZATION
*/
void setup() {
  // Prepare serial interface
  Serial.begin(9600);

  // Show dialog to serial monitor
  Serial.println(F("----------------------------------------------------"));
  Serial.println(F("            GFBUTTON LIBRARY TEST PROGRAM           "));
  Serial.println(F("             http://www.geekfactory.mx             "));
  Serial.println(F("----------------------------------------------------"));
}

/**
   MAIN PROGRAM LOOP
*/
void loop() {
  // Check if "on" button is pressed
  if (buttonOn.isPressed()) {
    Serial.println(F("On button is pressed"));
    // Turn on the led
    digitalWrite(13, HIGH);
  }

  // Check if "off" button is pressed
  if (buttonOff.wasPressed()) {
    Serial.println(F("Off button was pressed"));
    // Turn off the led
    digitalWrite(13, LOW);
  }
}

 

Detección de pulsaciones largas en un botón usando una librería

En este ejemplo vamos a aprender a detectar el tiempo que dura oprimido un botón, con esto podemos realizar acciones solamente si el botón permanece oprimido durante mas del tiempo programado.

En nuestro ejemplo a continuación, vamos a realizar la programación de dos botones: Uno encenderá un led si se mantiene oprimido más de 5 segundos y el otro apagará el led si se mantiene oprimido más de 5 segundos. Cualquier otra acción en los botones NO tendrá efecto en el estado de los leds.

/**
   GeekFactory - "INNOVATING TOGETHER"
   Distribucion de materiales para el desarrollo e innovacion tecnologica
   www.geekfactory.mx

   EJEMPLO PARA EL USO AVANZADO DE BOTONES. EN ESTE EJEMPLO DETECTAMOS CUANDO
   SE HA DEJADO OPRIMIDO UN BOTON POR MAS DE 5 SEGUNDOS (EL TIEMPO PUEDE SER CONFIGURADO)
   Y SOLAMENTE ACTUA EN CASO DE QUE SE DETECTE ESTA CONDICION.

   ESTE EJEMPLO ESTÁ BASADO EN LA LIBRERÍA GFBUTTON DESARROLLADA POR GEEK FACTORY.
*/
#include "GFButton.h"

// CREAR INSTANCIAS DE LOS BOTONES EN LOS PINES 2 Y 3
// SE PUEDE UTILIZAR CUALQUIER PIN DEL ARDUINO PARA LOS BOTONES
// YA QUE LA LIBRERIA NO DEPENDE DE INTERRUPCIONES
GFButton btn1 = GFButton(2);
GFButton btn2 = GFButton(3);

void setup() {
  // PREPARAR COMUNICACION SERIAL
  Serial.begin(9600);

  // CONFIGURAR PIN DE SALIDA
  pinMode(13, OUTPUT);

  // CONFIGURAR MANEJADORES DE EVENTOS (FUNCIONES CALLBACK)
  btn1.setHoldHandler(button1_on_hold);
  btn2.setHoldHandler(button2_on_hold);

  // CONFIGURAR TEMPORIZADOR DE REBOTES EN 100 MILISEGUNDOS
  btn1.setDebounceTime(100);
  btn2.setDebounceTime(100);

  // MOSTRAR DIALOGO INICIAL EN EL MONITOR SERIAL
  Serial.println(F("----------------------------------------------------"));
  Serial.println(F("    PROGRAMACION DE BOTONES CON LIBRERIA GFBUTTON   "));
  Serial.println(F("             http://www.geekfactory.mx             "));
  Serial.println(F("----------------------------------------------------"));
}

void loop() {
  // SIEMPRE DEBEMOS LLAMAR AL METODO PROCESS DE CADA INSTANCIA
  btn1.process();
  btn2.process();

  // PODEMOS REALIZAR OTRAS TAREAS DENTRO DEL CICLO PRINCIPAL
}

// MANEJADOR DE EVENTOS DEL BOTON DE ENCENDIDO
void button1_on_hold(GFButton & button)
{
  // EL EVENTO SE DISPARARA VARIAS VECES, ACTUAREMOS DISTINTO LA PRIMERA VEZ
  // EL METODO ISFIRSTHOLD() DETERMINA SI ES LA PRIMERA VEZ QUE SE LLAMA AL MANEJADOR DE EVENTOS
  if (button.isFirstHold())
  {
    // PODEMOS OBTENER LA CANTIDAD DE TIEMPO QUE SE HA MANTENIDO PRESIONADO EL BOTON
    // ESTA CANTIDAD ESTA EXPRESADA EN MILISEGUNDOS
    Serial.print(F("BOTON OPRIMIDO DURANTE "));
    Serial.print(button.getHoldTime() / 1000);
    Serial.println(F(" SEGUNDOS."));
    // ENDENDER EL LED
    Serial.println(F("ENCENDER LED"));
    digitalWrite(13, HIGH);
  } else {
    // IMPRIMIMOS PUNTOS MIENTRAS EL BOTON ESTE OPRIMIDO
    Serial.print('.');
  }
}

// MANEJADOR DE EVENTOS DEL BOTON DE APAGADO
void button2_on_hold(GFButton & button)
{
  // EL EVENTO SE DISPARARA VARIAS VECES, ACTUAREMOS DISTINTO LA PRIMERA VEZ
  // EL METODO ISFIRSTHOLD() DETERMINA SI ES LA PRIMERA VEZ QUE SE LLAMA AL MANEJADOR DE EVENTOS
  if (button.isFirstHold())
  {
    // PODEMOS OBTENER LA CANTIDAD DE TIEMPO QUE SE HA MANTENIDO PRESIONADO EL BOTON
    // ESTA CANTIDAD ESTA EXPRESADA EN MILISEGUNDOS
    Serial.print(F("BOTON OPRIMIDO DURANTE "));
    Serial.print(button.getHoldTime() / 1000);
    Serial.println(F(" SEGUNDOS."));
    // APAGAR EL LED
    Serial.println(F("APAGAR LED"));
    digitalWrite(13, LOW);
  } else {
    // IMPRIMIMOS PUNTOS MIENTRAS EL BOTON ESTE OPRIMIDO
    Serial.print('.');
  }
}

 

Detección de doble y triple clic en un botón usando una librería

En algunas situaciones, puede ser necesario detectar cuando el usuario hace doble o triple clic en un botón. En este caso podemos hacer uso de las funcionalidades de programación mediante eventos que provee nuestra librería.

El siguiente ejemplo demuestra como hacer que se puedan encender o apagar un par de leds dando doble clic en el botón asociado a cada led. El programa ignorará las pulsaciones sencillas y solamente actuará cuando se oprima 2 veces seguidas el mismo botón en menos de un segundo.

/**
   GeekFactory - "INNOVATING TOGETHER"
   Distribucion de materiales para el desarrollo e innovacion tecnologica
   www.geekfactory.mx

   EJEMPLO PARA EL USO AVANZADO DE BOTONES. EN ESTE EJEMPLO DETECTAMOS CUANDO
   SE HA DADO "DOBLE CLICK" EN UN BOTÓN Y SOLAMENTE SE REALIZA ALGUNA ACCIÓN
   CUANDO SE DETECTA ESTA CONDICIÓN.

   ESTE EJEMPLO ESTÁ BASADO EN LA LIBRERÍA GFBUTTON DESARROLLADA POR GEEK FACTORY.
*/
#include "GFButton.h"

// CREAR INSTANCIAS DE LOS BOTONES EN LOS PINES 2 Y 3
// SE PUEDE UTILIZAR CUALQUIER PIN DEL ARDUINO PARA LOS BOTONES
// YA QUE LA LIBRERIA NO DEPENDE DE INTERRUPCIONES
GFButton btn1 = GFButton(2);
GFButton btn2 = GFButton(3);

void setup() {
  // PREPARAR COMUNICACION SERIAL
  Serial.begin(9600);

  // CONFIGURAR PIN DE SALIDA
  pinMode(13, OUTPUT);

  // CONFIGURAR MANEJADORES DE EVENTOS (FUNCIONES CALLBACK)
  btn1.setClicksHandler(button1_on_click);
  btn2.setClicksHandler(button2_on_click);

  // CONFIGURAR TEMPORIZADOR DE REBOTES EN 100 MILISEGUNDOS
  btn1.setDebounceTime(100);
  btn2.setDebounceTime(100);

  // MOSTRAR DIALOGO INICIAL EN EL MONITOR SERIAL
  Serial.println(F("----------------------------------------------------"));
  Serial.println(F("    PROGRAMACION DE BOTONES CON LIBRERIA GFBUTTON   "));
  Serial.println(F("             http://www.geekfactory.mx             "));
  Serial.println(F("----------------------------------------------------"));
}

void loop() {
  // SIEMPRE DEBEMOS LLAMAR AL METODO PROCESS DE CADA INSTANCIA
  btn1.process();
  btn2.process();

  // PODEMOS REALIZAR OTRAS TAREAS DENTRO DEL CICLO PRINCIPAL
}

// MANEJADOR DE EVENTOS DEL BOTON DE ENCENDIDO
void button1_on_click(GFButton & button)
{
  Serial.print(F("DETECTADOS VARIOS CLICKS EN 1 SEGUNDO: "));
  Serial.println(button.getClicks());
  // ENCENDER LED AL DETECTAR DOBLE CLICK
  if (button.getClicks() >= 2) {
    Serial.println(F("ENCENDER LED"));
    digitalWrite(13, HIGH);
  }
}

// MANEJADOR DE EVENTOS DEL BOTON DE APAGADO
void button2_on_click(GFButton & button)
{
  Serial.print(F("DETECTADOS VARIOS CLICKS EN 1 SEGUNDO: "));
  Serial.println(button.getClicks());
  // APAGAR EL LED AL DETECTAR DOBLE CLICK
  if (button.getClicks() >= 2) {
    Serial.println(F("APAGAR LED"));
    digitalWrite(13, LOW);
  }
}

 

shares