VictorJAM.zapto.org
Arduino  Programación 

2020-08-08

Como NO leer un botón y como SI debemos hacerlo. (2)

Este tutorial es un extracto del tutorial que cree para el foro de Arduino, si quieres ver el tutorial completo, ver los comentario y/o los añadidos al tutorial visita Como NO leer un botón y como SI debemos hacerlo.

Ya hemos leído un botón y hemos eliminado el debounce por software, ahorrándonos un condensador. Pero vamos a complicar la cosa.

Un botón puede estar en cuatro estados:

  • Suelto que es cuando no lo tocas y solo lo miras. En este estado tendrá un valor, en nuestro caso estará a HIGH tal y como lo enchufamos. Generalmente es el estado que menos nos interesa ya que no haremos nada en él.
  • Apretándolo. Justo ese momento en el que el botón pasa de estar suelto a apretado, en nuestro ejemplo pasa del estado HIGH a LOW. Este si es útil, como hemos visto en el apartado anterior.
  • Apretado. Aquí ya lo mantenemos pulsado y su valor será LOW. En este estado podemos hacer cosas, pero ya sabes, el loop es rápido y se ejecutará muchas veces cuando lo mantengas pulsado.
  • Soltándolo. Justo ese momento en el botón pasa de estar apretado a estar suelto. En nuestro caso es cuando se pasa de LOW a HIGH. También es útil para hacer cosas, dependiendo de lo que queramos hacer. Cuando sale de este estado, se queda de nuevo en suelto.
Recordar: estamos usando una configuración pull-up. Si usamos otro tipo de configuración los valores HIGH/LOW podrán interpretarse de otra manera.

Así que sabiendo esto se lo podemos añadir a nuestro código para determinar en que estado está el botón:

/*
 * 5. Leyendo un botón con anti rebote por software y determinando su estado.
 *
 *
 * NOTA: en el ejemplo "anterior" estado guardaba el valor de la variable, como
 * ahora vamos a tener un estado de verdad cambiamos ese nombre de variable a
 * valor para hora usar un estado como estado propiamente dicho.
 */

#define APRETADO    0
#define SUELTO      1
#define APRETANDOLO 2
#define SOLTANDOLO  3
 
const int boton = 2; // Botón asignado en el pin 2.
int   anterior;      // guardamos el estado anterior.
int   valor;         // valor actual del botón.
int   estado;
unsigned long temporizador;
unsigned long tiemporebote = 50;

void setup() {
  Serial.begin(9600);
  pinMode(boton,INPUT_PULLUP);
  pinMode(13,OUTPUT); // Vamos a usar el led de la placa como señalización.
  valor    = HIGH;
  anterior = HIGH;
}
  
void loop() {
  // Si el estado es igual a lo leído, la entrada no ha cambiado lo que
  // significa que no hemos apretado el botón (ni lo hemos soltado); asi que
  // tenemos que parar el temporizador.
  if ( valor==digitalRead(2) ) {
    temporizador = 0;
  }
  // Si el valor distinto significa que hemos pulsado/soltado el botón. Ahora
  // tendremos que comprobar el estado del temporizador, si vale 0, significa que
  // no hemos guardado el tiempo en el que se ha producido el cambio, así que
  // hemos de guardarlo.
  else
  if ( temporizador == 0 ) {
    // El temporizador no está iniciado, así que hay que guardar
    // el valor de millis en él.
    temporizador = millis();
  }
  else
  // El temporizador está iniciado, hemos de comprobar si el
  // el tiempo que deseamos de rebote ha pasado.
  if ( millis()-temporizador > tiemporebote ) {
    // Si el tiempo ha pasado significa que el estado es lo contrario
    // de lo que había, asi pues, lo cambiamos.
    valor = !valor;
  }

  // Ahora comprobamos el estado. Recordad que si el botón vale "1" estará suelto,
  // "0" y el botón estará apretado. Si pasa de "1" a "0" es que lo estamos apretando
  // y si es al contrario es que lo estamos soltando.
  if ( anterior==LOW  && valor==LOW  ) estado = APRETADO;
  if ( anterior==LOW  && valor==HIGH ) estado = SOLTANDOLO;
  if ( anterior==HIGH && valor==LOW  ) estado = APRETANDOLO;
  if ( anterior==HIGH && valor==HIGH ) estado = SUELTO;

  // Recuerda que hay que guardar el estado anterior.
  anterior = valor;

  // Ahora vamos a ver que podemos hacer con el estado.
  switch ( estado ) {
    case SUELTO:   digitalWrite(13,LOW);  break; // Apagamos el led.
    case APRETANDOLO: Serial.write("Has apretado el botón"); break; // Mandamos un mensaje.
    case APRETADO: digitalWrite(13,HIGH); break; // Encendemos el led.
    case SOLTANDOLO: Serial.write("Has soltado el botón"); break; // Mandamos un mensaje.
    default: break;
  }
}

Podéis jugar un poco ahora con el Arduino. Si miráis el Arduino, no está haciendo nada que veamos; pero cuando pulsamos el botón: plas! se enciende el led y envía un mensaje. Si lo mantenéis pulsado el led sigue encendido, pero no hace nada mas. Cuando lo sueltas, el led se apaga! y envía un mensaje.

Vamos a jugar un poco más pero, uff.. que perrería... escribir tanto... venga hagamos una pequeña librería para leer botones y ahorrarnos código.