Pulsadores

Pulsadores

Introducción.

Que son los pulsadores. Pulsadores o interruptores, hay toneladas de ellos en su casa. Un interruptor es un dispositivo simple con dos posiciones, EN y AP (ENcendido y APagado). Una clase de interruptor que usted usa cada día es el interruptor de la luz. Cuando conecta, dentro del interruptor, dos cables son unidos, lo que permite fluir a la corriente que enciende la luz o la tostadora se caliente. Cuando lo desconecta, los dos cables son desunidos y corta el flujo de la corriente. Esto esta muy bien pero creo que esto no es lo que interesa aquí.

En definitiva, se trata de un mecanismo simple (los hay muy sofisticados), constituido por un par de contactos eléctricos que se unen o separan por medios mecánicos. En electricidad, los falsos contactos que se producen el ser utilizados normalmente, en algunos casos produce una chispa debido a la corriente que atraviesa los contactos, provocando que quemen en parte y ennegreciendo los contactos eléctricos, lo que a la larga acaba deteriorando dichos contactos. La chispa se produce siempre al separar los contactos (desconectar), en ocasiones parece que también salta al conectarlos, eso es debido a los rebotes mecánicos que se producen al cambiar de estado.

Esto que en electricidad se considera normal, en electrónica es un verdadero nido de problemas, debido a dichos falsos contactos. Por su propia naturaleza, al cambiar de posición un interruptor, los contactos chocan entre sí y esto significa una serie de falsos contactos que se reproducen de un modo sin control, por lo que se generan los temidos rebotes (debounce en inglés), estos rebotes, se producen incluso cuando unimos dos cables desnudos, simulando un interruptor o pulsador.

Pulsadores.

Estos pequeños pulsadores son un 1/4 ” por cada lado, son bastante económicos y se pueden ‘pinchar’ directamente en una placa de prototipado. Estos dispositivos mecánicos tienen 4 patillas, que pueden hacernos pensar que hay 4 cables que son EN y AP, pero de hecho, dos de cada lado en realidad dentro están unidos. Por tanto realmente, este pulsador es solamente un pulsador de 2 cables.

Como digo, en electrónica los rebotes suelen fastidiar a los intrépidos recién iniciados que creen en la teoría y sin embargo se salta este punto en muchas ocasiones, lo que les lleva a recordar la importancia que tiene el antirrebote.

Resistencias de polarización.

Cuando nos de desenvolvemos en el entorno de los microcontroladores, nos encontramos con un término poco común, me refiero a la polarización de una E/S, debemos saber que hay dos tipos de polarización, polarización alta la resistencia (término inglés Pullup) va conectada a + (5V) o polarización baja la resistencia (término inglés Pulldown) va conectada a masa – (0V). Siguen dos esquemas de estos términos:

 

Si disponemos los tres componentes del esquema para realizar el circuito que representa, cada vez que se presione el pulsador, el LED irá a EN (encender) y al ser liberado el pulsador el LED irá a AP (apagar).

El efecto de rebote mecánico que produce inevitablemente, el pulsador al ser presionado o al soltarlo, no permite apreciar el parpadeo en este sencillo montaje, debido a la velocidad con que se produce el parpadeo del LED, simplemente por que es inapreciable por el ojo humano. El ojo humano tiene una persistencia de alrededor de 0’1 de segundo. Vamos a seguir con otros ejemplos para ver este efecto y como evitarlo.

Pulsador.

Vamos a hacer nuestra primera prueba de botón (pulsador) conectando un LED en nuestra tarjeta Arduino. El símbolo del esquema para un pulsador de botón es algo diferente que el mostrado. Prepare un LED rojo y una resistencia de 10K Ohms, así como el pulsador de botón y construya un montaje del esquema en su tabla de prototipado cerca del Arduino.

Ha llegado la hora de ponernos a programar, llegados aquí, deberíamos decidir que tipo de entrada utilizar, analógica o digital. Para no demorar más el tema, haremos la prueba con un pin digital, ya que se trata de un pulsador que presentará 1 o 0, lo conectamos a +5V a través de una resistencia y para mantener el consumo del LED, lo conectamos con una resistencia (de 270 Ohm) para limitar su consumo dentro de términos admisibles de las salidas de Arduino (sobre los 20mA).

Analizaremos el esquema, he elegido la RPB polarización a bajo (Pulldown), por simular el efecto de un estado 0 (L) en descanso del pulsador, lo que en buena lógica es 0, es apagado y lo que es 1, es encendido, del mismo modo, cuando presione el pulsador irá a 1, el LED se encenderá, permaneciendo apagado a 0 el resto del tiempo, ¡lógico!. El resto del circuito, no tiene demasiado interés.

El código.

En primer lugar, quiero recordar al lector que debe documentar sobre la marcha los códigos, esto hará que no pierda tiempo posteriormente, cuando quiera reutilizar alguna rutina de este listado, para no volver a escribir tanto código.

Como siempre, es buena costumbre darle un nombre al principio del archivo dentro del mismo y una pequeña descripción de que hace o para que sirve, fecha de creación, autor, etc. Así que empecemos.

Este es el listado del código que utilizaremos en esta ocasión, servirá para el caso. Como se ve, es propiedad de Massimo Banzi (gracias). Copiar este código y guardarlo con el nombre pulsador03.pde en la carpeta destino de vuestros ejemplos o ejercicios, para comprobar su funcionamiento.

/* Pulsador y LED

 *
 * Detectar si el botón ha sido presionado o no y encender
 * el LED en consecuencia.
 *
 * Basado en un código de: Massimo Banzi
 *
 */

 int inPin = 10;              // pin del pulsador

void setup()     // establecer la configuración de pines a usar.
 {
  Serial.begin(9600);         //  Inicializa el puerto serie a 9600 baudios
  pinMode(inPin, INPUT);      // Inicializa el pin 10 como entrada digital
 }

void loop()                   // Lazo que se repite indefinidamente
 {
  Serial.print("Estado del pulsador: "); // muestra el "Estado del pulsador: "
  Serial.println(digitalRead(inPin));     // imprime el estado del (pulsador)
                                         // y lo muestra en decimal (0/1)
  delay (50);      // toma un poco de tiempo.
 }

Este es un código escueto, corto que, funciona, sin embargo prefiero un código que ‘diga más’, algo más completo y didáctico, si es posible. Como el que sigue:

/* Pulsador

 *
 * Detectar si el botón ha sido presionado o no y encender
 * el LED en consecuencia.
 *
 * Basado en un código de: Massimo Banzi
 *
 */

 int inPin = 10;                 // pin del pulsador
 int ledPin = 2;                 // pin del LED
 int value = 0;                  // valor que tomara el pulsador

void setup()     // establecer la configuración de pines a usar.
 {
  Serial.begin(9600);         //  Inicializa el puerto serie a 9600 baudios
  pinMode(inPin, INPUT);      // Inicializa el pin 10 como entrada digital
  pinMode(ledPin, OUTPUT);    // Inicializa el pin 2 como salida digital
 }

void loop()               // Lazo que se repite indefinidamente
 {
  value = digitalRead(inPin); // Lee el valor de la entrada digital (pulsador)
  Serial.print("Estado del pulsador: "); // muestra el "Estado del pulsador: "
  Serial.print(value, DEC);  // imprime el estado del (pulsador)
                             // y lo muestra en decimal (0/1)
  digitalWrite(ledPin, value);     // enciende el LED cuando el value es = 1.
 }

Análisis.

Como se aprecia, las líneas están comentadas en su mayoría, tampoco es necesario pasarse, aquí lo hago, para que se pueda entender por los no iniciados.

En primer lugar, se declaran las variables globales que, se usaran en cualquier parte del programa, se designan los nombres que damos a los pines de E/S y a las variables de estado o lo que se haya previsto como tal. Seguidamente, el módulo de configuración de los pines como E/S y si utilizaremos el puerto serie para comunicación que, utilizará el programa void setup(), siguen si hay las rutinas generales, aquí esta su sitio, en otro caso, se llega al lazo principal que se ejecutará sin descanso, estoy refiriéndome al módulo void loop(), con el que se da por terminado el código.

void setup()

Tenemos que decirle a Arduino que ponga el pin que designamos para el pulsador, como entrada. Esto es bastante fácil, empleando pinMode () para usar la ENTRADA, para leer el pulsador o en su lugar de SALIDA para leer el el valor del pin. Por cierto, el módulo void setup() sólo se leerá una vez, cuando se inicia o reinicia la ejecución del programa.

Lectura Digital.

Podemos usar el nuevo procedimiento digitalRead (), que solamente toma como entrada el pin a examinar. El procedimiento digitalRead () devuelve un resultado cada vez que es leído. Dicho resultado es 0 (BAJO) o 1 (ALTO) dependiendo de lo que vio cuando miró el voltaje del pin. En este caso, leemos el pin y luego pasamos el resultado como una entrada a otro procedimiento, println (), por ejemplo. Seguramente podríamos usar una variable para guardar el resultado de digitalRead () y luego usar aquella variable como entrada al println () pero esto es mucho más directo.

  . . .
  pinMode(switchpin, INPUT);  // hace switchpin, pin de entrada.
  pinMode(ledpin, OUTPUT);    // hace ledpin, pin de salida.
  . . .
  . . .
  Serial.println(digitalRead(switchpin));  // imprime el estado del (pulsador)
   . . .

El caso de la variable se verá más adelante.

  value = digitalRead(inPin); // Lee el valor de la entrada digital (pulsador)
  Serial.print(value);  // imprime el estado del (pulsador)

Escritura Digital.

Con el procedimiento DigitalWrite() pondremos el voltaje en un pin a ALTO 5V o a BAJO masa 0V y luego usaremos DigitalRead() para preguntar si aquel pin es ALTO o BAJO. Este procedimiento se usa normalmente como salida, mayormente en el módulo void loop(), como tendremos ocasión de comprobar.

Compilar el código.

Utilizando el software, libre de Arduino. Copie y pegue el código del ejercicio, en la zona habilitada para este fin. Conecte la tarjeta Arduino a su computadora (PC) y pulse el icono (nº1) de Verify.

Si todo va bien, el código saldrá bien, sin errores, a continuación pulse el icono de Upload to I/O board (es el nº 6), esta vez también cargará el programa que acaba de compilar en la memoria del Atmega (Arduino) y ahora, pulse el Serial Monitor (nº 7) para ven en la parte inferior cómo se muestra el estado del pulsador.

Compilar el programa.
Cargar el programa en el Arduino.
Monitorizar el resultado

En el monitor, se aprecia que mientras no se presiona el pulsador, la salida es 0 y cada vez que se presiona, al hacer contacto, se muestra un 1, lo que demuestra si se ha presionado o no el pulsador.

Verifique que cuando el botón es presionado, enciende el LED y cuando el botón es liberado, el LEd se apaga. Si no le funciona, trate de usar declaraciones println para eliminar fallos de su proyecto. Cuando usted aprieta el botón, hace que imprima un mensaje. Así usted puede decir si la mitad de entrada funciona o si no funciona la mitad de salida. Ahora puede guardar el archivo pulsando el icono (nº5)

-El mejor modo de destruir completamente un microcontrolador como Arduino es, alimentarlo con voltajes demasiado altos. ¡Asegúrese que sus voltajes de entrada están entre 0 y 5V! ¡Nunca conecte la batería 9V directamente en un pin de entrada, esto freirá el pin y posiblemente destruirá al microcontrolador Arduino!

Ahora, desconecte el Arduino de su computador y cambie el sistema de alimentación del Arduino, por medio de una pila de 9V, conecte dicha pila al Arduino y ya puede presionar el botón. El LED debería encenderse cuando el pulsador es presionado (la corriente es capaz de fluir) y vuelve a apagarse cuando se ha liberado el pulsador (la corriente no es capaz de fluir), esto demuestra que el Arduino una vez cargado el programa, puede funcionar de forma autónoma.

Si, ya se, el monitor tiene un ‘problema’ está mostrando continuamente la misma respuesta “Estado del pulsador: 0″ y sólo cambia a “Estado del pulsador: 1″ en el momento en que se presiona el pulsador y seguidamente se repite el “Estado del pulsador: 0″. Vaya, no es un grave problema, ya que todo funciona como se esperaba, la salvedad de lo que muestra el monitor. Como no es un verdadero problema no le daremos más importancia por el momento. El programa hace lo que se esperaba.

El caso principal es que seguimos sin apreciar el tan mencionado rebote (debuncing). En el próximo ejemplo veremos cómo se produce dicho efecto.

Tercer ejercicio.

En este momento, vamos a desarrollar el código que nos permita constatar el efecto rebote. Para este fin, he aprovechado un código de un maestro en esta materia como es H. Barragan, sólo he hecho unas pequeñas modificaciones para que se aprecie con más detalle lo que ocurre al ejecutar el programa.

/*
    Pulsador Conmutador 

  original: by BARRAGAN <http://barraganstudio.com>

  El pin usado como entrada es conectado a un pulsador y el pin
  usado como salida al LED. Cuando el pulsador es presionado,
  parpadea el LED, el LED debería apagarse cuando el pulsador es
  liberado.

  Se puede ver el efecto rebote (debouncing)

   Revisado 26 Julio 2009
   por V. Garcia.

 */ 

int direction = 1;  // usado para el ciclo de parpadeo
int switchPin = 8;  // pin digital para unir el interruptor
int ledPin = 2;    // pin para conectar el LED 

void setup() {
  Serial.begin(9600);                  // establece comunicacion serie
  pinMode(switchPin, INPUT);   // pone el pin digital 8 como la entrada
  pinMode(ledPin, OUTPUT);     // pone el pin digital 2 como la salida
} 

void loop()
 {
  if(digitalRead(switchPin) == HIGH)  // si el interruptor es presionado
   {
     direction *= -1;                  // alterna entre 1 o -1
     if (direction == 1)               // para decidir conectar o no la luz
     {
      digitalWrite(ledPin, HIGH);     // conecta la luz
     }
     else
     {
      digitalWrite(ledPin, LOW);      // desconecta la luz
     }
     Serial.print(direction);
     delay(20);                       // espera 20 milliseconds
   }
 }

Aunque está bien comentado, describiré lo que hace el programa, sobre todo, en el punto que más define el efecto rebote. El punto determinante del programa se encuentra justo en la orden direction *= -1; , es la responsable de cambiar su estado, en cada paso del programa por ese punto. Y esto se produce muy velozmente (depende del reloj del micro). No se ha provocado nada nuevo, tan solo se ha puesto de relieve el efecto que habitualmente ocurre con un contacto mecánico.

Mantenga el pulsador presionado por un momento. Que ocurre. Que sucede. Que el LED parece que parpadea, sólo lo parece, que va, realmente parpadea, dicen que alguno no ha visto parpadear a nadie tan rápido ¡Un momento! Calma. Si, parpadea, es lo que ocurre normalmente, cuando un contacto no se protege contra los rebotes. Eso es lo que yo pretendía demostrar con tanto listado de código y aquí está.

Primero las variables:

// Aquí irán los #includes XXXXXX.h si se usan y la definición de variables.

int direction = 1;  // usado para el ciclo de parpadeo
int switchPin = 8;  // pin digital para unir el interruptor
int ledPin = 2;     // pin para conectar el LED

Seguido del módulo setup() para la configuración de los pines E/S implicados en el programa y definir el puerto serie para la comunicación (definir el puerto serie, no es siempre necesario) con el PC por ejemplo.

void setup() {
  Serial.begin(9600);          // establece comunicacion serie
  pinMode(switchPin, INPUT);   // pone el pin digital 8 como la entrada
  pinMode(ledPin, OUTPUT);     // pone el pin digital 2 como la salida
}

Por cierto, cuando utilizamos los microcontroladores, en ocasiones podemos utilizar la resistencia de polarización interna del pin indicado. Con esto, ahorramos las resistencias de polarización externas que anteriormente se comentaron y su comportamiento es idéntico. Este es un buen momento para utilizar esta posibilidad, veamos cómo.

 void setup()
 {
  Serial.begin(9600);            // establece comunicacion serie
  pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH); // conecta RPA interna a alto (5V)
  pinMode(ledPin, OUTPUT);
 }

Si hubiera subrutinas en nuestro programa, se pondrían aquí, antes del siguiente módulo. Como no es el caso, el módulo que sigue es el bucle void loop() que se ejecutará continuamente.

La declaración if()

Este escenario (sketch), introduce un tipo completamente nuevo y apasionante de declaración. La declaración if. Esto es, una declaración lógica, que usted puede recordar de su clase de matemáticas de escuela primaria. Básicamente, hasta ahora hemos tenido al Arduino haciendo; solamente encienda; parpadear LEDs; imprima mensajes; etc. Pero ahora queremos que además tome decisiones.

void loop()
 {
  if(digitalRead(switchPin) == HIGH)  // si el interruptor es presionado
   {
     direction *= -1;                // alterna entre 1 o -1
     if (direction == 1)             // para decidir conectar o no la luz
     {
      digitalWrite(ledPin, HIGH);    // conecta la luz
      Serial.print(" H:");           // muestra la H de Alto.
     }
     else
     {
      digitalWrite(ledPin, LOW);     // desconecta la luz
      Serial.print(" L:");           // muestra la L de Bajo.
     }
     Serial.print(direction);
     delay(20);                       // espera 20 milliseconds
   }
 }

La declaración if, es la primera declaración que es condicional, esta sólo controla las declaraciones si una condición es verdadera. En este caso, las condiciones son el “botón se ha presionado” o el “botón no es presionado”.

Operadores de Comparación:

 x == y (x es igual a y) x != y (x no es igual a y) x < y (x es menor que y) x > y (x es mayor que y) x <= y (x es menor o igual a y) x >= y (x es mayor o igual a y)

En la primera línea del if, se compara el estado del pin de entrada perteneciente al pulsador, para saber si se ha pulsado. Si se ha presionado, el estado del pulsador será 1 (H) y por lo tanto se ejecutará lo que hay dentro del siguiente corchete “{ …. }”

   if(digitalRead(switchPin) == HIGH)  // si el interruptor es presionado
   {
    . . .
   }

En cuyo caso, se conmunta el estado de la variable direction y se consulta si su valor ahora es 1 (o -1).

     direction *= -1;      // alterna entre 1 o -1
     if (direction == 1)   // nueva compración. Para conectar o no el LED
     {
      digitalWrite(ledPin, HIGH);   // conecta el LED
      Serial.print(" H:");          // muestra la H de Alto.
     }

Si no, se ejecutará lo que sigue a else { , que puede ser lo contrario a la acción anterior.

     else
      {
       digitalWrite(ledPin, LOW);   // desconecta el LED
      Serial.print(" L:");          // muestra la L de Bajo.
      }

En este caso, también añadimos una salida para el puerto serie que permita ver el resultado de los dos estados posibles del pulsador.

   Serial.print(direction); // imprime el contenido de la variable 'direction'.
   delay(20);                // espera 20 milliseconds

Pruebe a comentar la línea delay y vuelva a compilar el código, luego modifique el valor del paréntesis (expresado en milisegundos) y vuelva a compilar el código cada vez, aprenderá de la importancia de este parámetro.

El programa de arriba, tal cual, demuestra que mientras se presiona el pulsador, el LED se enciende e incluso parpadea, aunque la presión sobre el botón sea muy rápida. Puede que si es muy rápido, a la vista no se aprecie, sin embargo, si utilizamos el monitor del sistema Arduino, éste delatará el efecto rebote. Procedamos, una vez cargado el programa en la placa de Arduino, pulse el icono 7 (corresponde al monitor), ahora, intente realizar una rápida presión del pulsador, qué ocurre, en el monitor se ve, cada letra lleva su valor asociado, como se muestra en la imagen siguiente.

Presencia de Rebote

Esto es lo que siempre trataremos de evitar. Imaginase por un momento que, hemos construido de un reloj electrónico y ha llegado el esperado momento de su puesta en hora. Qué ocurre si al realizar el programa no hemos previsto un sistema antirrebote, cree usted que puede poner en hora el minutero o acaso el segundero, sinceramente creo que le costaría incluso poner la hora actual sin más. Piense que con cada pulsación, se produce un tren de impulsos (observe la imagen anterior) que el contador del reloj interpretará como pulsos separados, de modo que será una ardua tarea la puesta en hora.

Volvamos al tema que nos ocupa, vayamos a dar solución a nuestro problema. Si usted ha hecho los cambios que le he sugerido, habrá notado que al comentar el delay, aumentan exageradamente el número de rebotes, sin embargo, si aumentó el valor del tiempo (dentro del paréntesis), por ejemplo, si subimos el valor a 200, se observa que dejan de producirse rebotes, salvo que mantengamos presionado el pulsador, cosa a todas luces, innecesaria.

 /* Pulsador Conmutador 

  original: by BARRAGAN <;http://barraganstudio.com>

  El pin usado como entrada es conectado a un pulsador y el pin usado
  como salida se conecta al LED. Cuando el pulsador es presionado,
  parpadea el LED, el LED debería apagarse cuando el pulsador es
  liberado.

  Se puede apreciar el efecto rebote (debouncing)

   Revisado 26 Julio 2009
   por V. Garcia.

 */	 

int direction = 1;  // usado para el ciclo de parpadeo
int switchPin = 8;  // pin digital para unir el interruptor
int ledPin = 2;    // pin para conectar el LED  

void setup() {
  Serial.begin(9600);          // establece comunicacion serie
  pinMode(switchPin, INPUT);   // pone el pin digital 8 como la entrada
  pinMode(ledPin, OUTPUT);     // pone el pin digital 2 como la salida
} 

void loop() { 

  if(digitalRead(switchPin) == HIGH)  // si el interruptor es presionado
  {
    direction *= -1;                  // alterna entre 1 o -1
    if (direction == 1)               // para decidir conectar o no la luz
    {
      digitalWrite(ledPin, HIGH);     // conecta la luz
      Serial.print(" H:");
    }
    else
    {
      digitalWrite(ledPin, LOW);      // desconecta la luz
      Serial.print(" L:");
    }
    Serial.print(direction);
    delay(200);                       // espera 20 milliseconds
  }
}

A pesar de todo, no es esta la solución definitiva. Hemos de dar con una forma que de ninguna manera se produzcan rebotes, o al menos que, no dependa de condiciones circunstanciales dependientes del azahar.

CIRCUITO SIN REBOTES.

He encontrado la forma de evitar los rebotes, en cuanto he considerado cómo encarar el problema. La solución pasa por leer el estado del botón cuando se produce el borde ascendente de la tensión a extremos de los contactos del pulsador e introducir inmediatamente la salida con ese estado, el resto de entradas (se llama ruido) se inhiben o anulan mediante un lapsus de tiempo. Véase la imagen de debajo para entender mejor lo dicho.

El lapsus de tiempo se puede variar para que no se lea más que el primer pulso del tren de pulsos que se generan. Y este es el listado del código que cumple estos parámetros. Puede copiar y pegar este código que sigue, en su software para comprobar su efectividad.

/*          conmutador.pde   (switch)
 *
 * Cada vez el pin de entrada va de BAJO a ALTO (p.ej. debido a apretar un
 * botón),el pin de salida es basculado de BAJO a ALTO o de ALTO a BAJO. Hay
 * un retraso mínimo entre basculados para los rebotes del circuito.
 *  (no hacer caso del ruido).
 *
 *   http://www.arduino.cc/en/Tutorial/Switch
 *
 *  David A. Mellis
 *  21 November 2006
 *
 * Modificado por V.Garcia 29072009 23:10H
 *
 *
 * Funciona correctamente, emplea 2.442 bytes.
 *
 */

int inPin = 8;         // pin8 entrada
int outPin = 2;        // pin2  salida
int previous = LOW;    // lectura anterior del pinX de entrada
int state = LOW;       // estado actual del pin de salida
int reading;           // lectura actual del pin de entrada

// las siguientes variables son largas por el tiempo medido en miliseconds,
// rápidamente se hará un número más grande que puede ser almacenado en un int.
long time = 0;         // la ultima vez que el pin de salida fue basculado
long debounce = 500;   // tiempo de rebote, se aumenta si la salida parpadea 

void setup()            // Config. pines
{
   pinMode(inPin, INPUT);
   pinMode(outPin, OUTPUT);
   Serial.begin(9600);
}

void loop()
{
  reading = digitalRead(inPin); 

// si la entrada solamente fuera de BAJO a ALTO y hemos esperado bastante
// tiempo para que ningún ruido afecte al circuito, el pin de salida bascula y
// recuerda el tiempo

  if (reading == HIGH && previous == LOW && millis()+100 - time > debounce) {
    if (state == HIGH) {
     state = LOW;
     Serial.print(" Estado Pin: L "); //muestra estado actual de variable state
     Serial.println(state);
     time = millis();
    }
    else {
     state = HIGH;
     Serial.print(" Estado Pin: H "); //muestra estado actual de variable state
     Serial.println(state);
     time = millis();
    }
  }
  digitalWrite(outPin, state);
  previous = reading;
}

El listado del código está bastante comentado, sin embargo hago recordar que en este listado hay una gran diferencia ante los listados anteriores, consiste en que si usted mantiene presionado el pulsador, no se modifica nada en la salida. Si viera un cambio, es debido a que ha cambiado el estado del pulsador, aunque sólo sea por un inapreciable instante. Ver el resultado que muestra wl monitor.

NUEVO CIRCUITO SIN REBOTES.

Hemos visto un ejemplo que funciona bien basado en la lectura del borde (o flanco) ascendente, es decir, el primer estado de ABAJO a ARRIBA. Seguidamente se muestra un nuevo ejemplo que se basa en el borde descendiente, es decir, el último estado de ARRIBA a ABAJO.

Puede copiar y pegar el siguiente listado del código y guardarlo como conmutador_ab.pde, en su software para comprobar una vez más que funciona y además que lo hace al soltar el pulsador.

 /*
 *  conmutador sin rebote (debounced)
 *
 * Cuando el pin de entrada va de ALTO a BAJO (p.ej. al liberar un botón),
 * el pin de salida es basculado de ALTO a BAJO o de BAJO a ALTO. Hay un
 * retraso mínimo entre basculados para los rebotes del circuito.
 *
 *     29/07/09
 *  Autor: V. Garcia
 */

int switchPin = 8;          // switch se conecta al pin 8
int ledPin = 2;             // el LED se conecta al pin 2

int val;                    // variable para lectura del estado del pin
int val2;                   // variable para leer el estado delayed/debounced
int botonStado;             // variable para mantener el estado del botón

int lightMode = 0;          // Esta la luz EN o AP

void setup() {
  pinMode(switchPin, INPUT); // pone el pin switch como entrada
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);           // Comunicación serie puesta a 9600bps
  botonStado = digitalRead(switchPin);  // lee el estado inicial
}

void loop(){
 val = digitalRead(switchPin); // lee el valor de entrada y almacénlo en val
 delay(10);                    // 10 milisegundos es un  tiempo bueno
 val2 = digitalRead(switchPin);// lea la entrada otra vez para comprobar saltos
 if (val == val2) {           // asegúrar que conseguimos 2 lecturas constantes
   if (val != botonStado) {   // el estado de botón ha cambiado!
     if (val == LOW) {         // compruebe si el botón es presionado
       if (lightMode == 0) {   // esta la luz AP?
        lightMode = 1;         // conecta la luz!

          digitalWrite(ledPin, HIGH);
          Serial.print("Estado: ");
          Serial.println(lightMode);
        } else {
          lightMode = 0;               // apaga la luz!
          digitalWrite(ledPin, LOW);
          Serial.print("Estado: ");
          Serial.println(lightMode);
        }
      }
    }
    botonStado = val;              // guardar el nuevo estado en la variable
  }
}

Véase en la figura que sigue los resultados que se corresponden con lo que se describe más arriba.

Sin rebotes

A DESTACAR.

Que podemos destacar en el procedimiento que se sigue para realizar el código que evita los rebotes. Si observamos con atención el comportamiento del programa, veremos que los cambios en la salida del pin #2, se producen justo en lo que se llama, flanco de bajada o borde de bajada, es decir, no en el momento de la conexión, si no en el momento de soltar o dejar de presionar.

Compruebe usted el efecto, presiones y mantenga presionado el pulsador, no ha ocurrido nada, se ha cambiado el estado del LED, ahora, suelte el pulsador, en ese momento se produce el cambio del LED, vuelva a realizar lo mismo y experimente que los cambios se producen siempre al ser liberado el pulsador. Considero probado la eliminación del efecto que se perseguía, el rebote o debounce.

Una vez comprobado que, el programa proporciona los resultados esperados, puesto que no siempre se tienen que mostrar los resultados en el monitor, se puede eliminar del código las referencias a la comunicación serie, dejando más compacto el código.

El lector, nuevamente, con unos pocos cambios puede adaptar este listado a sus proyectos.

Como siempre, comentarios, criticas y sugerencias para mejorar este artículo, son bienvenidos y apreciados.

4 comentarios en “Pulsadores

  1. El tema de los rebotes es recurrente y no es que se tenga encuenta por algunos dedicados al “cacharreo”, pero es cierto lo que se dice en este sitio.

    Me ha gustado, graicas por todo compa.

    1. Gracias Paulino por tus palabras.
      En cuanto a los pulsadores, normalmente, en los comercios del ramo suelen tener de distintos tamaños y formas, procura acudir a comercios donde se provean los talleres de reparación, suelen tener componentes de todas las marcas y siempre hay quien te echa una mano cuando necesitas “algo” fuera de lo corriente. En Valencia los puedes encontrar en el comercio Elheca en la calle Bernia, 24, tienen una página web.
      http://www.elheca.es/
      Espero haber dado respuesta a tu consulta.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>