:
Taller de
Arduino
 
 

Un botón como switch

En este proyecto también vamos a sensar un botón, sólo que ahora cada que el bóton sea presionado, vamos a cambiar el estado de un led. Lo cambiaremos de encendido a apagado y viceversa.

Componentes

al inicio

Circuito

El circuito que usaremos es el mismo que el de proyecto sensando un bóton. Este consta de dos circuitos, uno con un led y su resistencia y el otro con el boton y su resistencia de pull down.

al inicio

Diagrama

al inicio

Código

En el sketch de este proyecto, también vamos a sensar el estado del botón con la función digitalRead() y lo vamos a guardar en una variable: estadoBoton.

Y vamos a utililizar otra variable: estadoLed, para guardar el estado del led, prendido o apagado, 0 o 1.

Cada que se oprime el botón, cambia el valor de estadoBoton de LOW a HIGH. Checaremos entonces con una instrucción if si se da este cambio y cuando se de, cambiaremos el valor de la variable estadoLed, de 1 a 0 o de 0 a 1.

Con otro if checamos el valor de estadoLed y de acuerdo a este valor, encendemos o apagamos el led con la función digitalWrite().

	   /*
	     Un boton como switch con un led

	     Cambia el estado de un led, prendido o apagado, 
	     cada que se oprime el boton

	   */
	  
	   // constantes para definir los pines del boton y del led
	   const int pinBoton = 12;   // el numero del pin con el boton
	   const int pinLed   =  9;   // el numero del pin con el LED

	   // variables para guardar los valores de los sensores y actuadores
	   int estadoBoton = 0;      // variable para leer y guardar el estado del boton
	   int estadoLed   = 0;      // variable para guardar el estado del led 
	  
	   void setup() {    
	     // inicializa el pin del led como de salida
	     pinMode(pinLed, OUTPUT);
	     // inicializa el pin del boton como de entrada
	     pinMode(pinBoton, INPUT);
	   }

	   void loop(){  
	     // lee el valor del estado del boton
	      estadoBoton = digitalRead(pinBoton); // lee el estado del boton
	  
	     if (estadoBoton == HIGH) {        // si se oprime el boton 
	         estadoLed =  1 - estadoLed;   // se cambia el valor de estadoLed de 1 a 0 o de 0 a 1 
	     }
	  
	     if (estadoLed == 1) {           // checa el estado del led
	       digitalWrite(pinLed, HIGH);   // si es 1 se prende el led
	     } else { 
	       digitalWrite(pinLed, LOW);    // si no se apaga el led
	     }
	   }

Prueba este código y ve que sucede.

Al hacerlo, te darás cuenta que este código tiene un problema. Notarás que su funcionamiento es muy errático y no responde como lo esperabamos. Esto se debe a que el microcontrolador checa el estado del botón a una frecuencia muy alta, millones de veces por segundo y por ello, mientras el sensor esté en HIGH, cambiará el estado del led un grán número de veces, dandonos así este resultado impredecible.

Una forma de resolver este problema es guardar en otra variable el estado anterior del bóton y compararlo con el actual, cambiando el estado del led solo cuando el botón cambie al estado de HIGH, después de haber estado en LOW.

	   /* 
	     Boton como switch con un led, segunda version
	     
	     Cambia el estado de un led, prendido o apagado, 
	     cuando se oprime el boton y hay un cambio en el estado anterior   

	   */
	    
	   // constantes para definir los pines del boton y del led
	   const int pinBoton = 12;      // el numero del pin con el boton
	   const int pinLed   =  9;      // el numero del pin con el LED

	   // variables para guardar los valores de los sensores y actuadores
	   int estadoBoton = 0;    // variable para guardar el estado del boton
	   int estadoLed   = 0;    // variable para guardar el estado del led 
	  
	   int estadoAnterior = LOW;   // variable para guardar el estado anterior del boton
	     
	   void setup() {
	     // inicializa el pin del led como de salida
	     pinMode(pinLed, OUTPUT); 
	     // inicializa el pin del boton como de entrada    
	     pinMode(pinBoton, INPUT); 
	   }
	    
	   void loop(){
	     // lee el valor del estado del boton
	      estadoBoton = digitalRead(pinBoton); // lee el estado del boton en pinBoton
	     // checa si el estado del boton es HIGH Y si el estado anterior es LOW
	     if ((estadoBoton == HIGH) && (estadoAnterior == LOW)){ 
	         estadoLed = 1 - estadoLed;    // si es asi cambia el estado del led
	     }

	     estadoAnterior = estadoBoton; // actualiza el estadoAnterior
	      
	     if (estadoLed == 1) {         // checa el estado del led
	       digitalWrite(pinLed, HIGH); // si es 1 prende el led
	     } else {
	       digitalWrite(pinLed, LOW);  // si no apaga el led
	     }
	   }

Ahora ya funciona mucho mejor, pero aún puede seguir teniendo un comportamiento errático. El problema ahora se debe a que cuando oprimimos el bóton, se generán una serie de pulsos entre 0 y 5 volts, los rebotes o bouncing del botón, debidos a las propiedades físicas de los materiales, láminas y resortes, con los que están construidos. Estos pulsos o brincos, se producen en tiempos muy cortos, de microsegundos, que nostros no apreciariamos. Pero el microcontrolador si los registra y por este "ruido", nuestro sketch tiene aún un comportamiento errático.

Hay muy diversas formas de resolver este problema, tanto por software como por hardware. Vamos ahora a buscar una solución revisando el estado del botón unos milisegundos despues de que detectemos que ha sido oprimido, para garantizar que su estado ya es estable y no seán estos rebotes los cambios que estemos detectando.

Lo que vamos a hacer en este nuevo sketch es que una vez que detectemos un cambio, volveremos a sensar el estado del botón en un periodo de tiempo muy corto, para así garantizar que el botón ya ha sido presionado definitivamente.

Esta es sólo una de las diferentes soluciones a este problema.

           /* 
             Boton como switch con un led, ahora con debouncing

             Cambia el estado de un led, prendido o apagado, 
             cuando se oprime el boton y hay un cambio en el estado anterior   

           */

           // constantes para definir los pines del boton y del led
           const int pinBoton = 12;   // el numero del pin con el boton
           const int pinLed   =  9;   // el numero del pin con el LED

           // variables para guardar los valores de los sensores y actuadores
           int estadoBoton = 0;    // variable para guardar el estado del boton
           int estadoLed   = 0;    // variable para guardar el estado del led 

           int estadoAnterior = LOW;   // variable para guardar el estado anterior del boton

           void setup() {
             // inicializa el pin del led como de salida
             pinMode(pinLed, OUTPUT);
             // inicializa el pin del boton como de entrada    
             pinMode(pinBoton, INPUT);
           }

           void loop(){
             // lee el valor del estado del boton
             estadoBoton = digitalRead(pinBoton); // lee el estado del boton en pinBoton
             // checa si el estado del boton es HIGH Y si el estado anterior es LOW
             if ((estadoBoton == HIGH) && ( estadoAnterior == LOW)){
               estadoLed = 1 - estadoLed;   // si es asi cambia el estado del led
               delay(10);                   // y hace un delay de 10 milisegundos antes de continuar
             }

             estadoAnterior = estadoBoton; // actualiza el estadoAnterior

             if (estadoLed == 1) {
               digitalWrite(pinLed, HIGH); // prende el led
               } else {
               digitalWrite(pinLed, LOW);  // apaga el led
               }
            }

al inicio

Variantes

Hay otras formas de solucionar el problema del debouncing. Soluciones por software, simples como ésta o con una biblioteca que puedes usar en tus sketchs. O soluciones con hardware, utilizando por ejemplo un capacitor que elimine los brincos. Búscalas en la red o en la bibliografía y pruebalas.

Utilizando las mismas ideas de este proyecto, cambia el led por los leds verde y rojos que usamos en el proyecto de sensando un switch. ¿Que es lo que tendrías que cambiar en el circuito y en el sketch?

al inicio

Referencias:

Arduino Reference: digitalRead()
Referencia Arduino: digitalRead()
Función para leer el estado de un pin digital.

Arduino Reference: if()
Arduino Reference: if()/else
Referencia Arduino: if()
Referencia Arduino: if()/else
Estructura de control para checar el valor de una condición; verdadero o falso.

al inicio

Ejemplos similares en otras páginas:

al inicio