PULSADORES SIN REBOTES.
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 (término inglés Pullup) la resistencia va conectada a + (5V) o polarización baja (término inglés Pulldown) la resistencia 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Ω, así como el pulsador de botón y construya un montaje del esquema en su tabla de prototipado cerca del Arduino.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/* 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.
1 2 3 4 5 6 7 |
. . . 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.
1 2 |
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.
Cargar el programa en el Arduino.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/* 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:
1 2 3 4 5 |
// 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.
1 2 3 4 5 |
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.
1 2 3 4 5 6 7 |
void setup() { Serial.begin(9600); // establece comunicacion serie pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // conecta resistencia de polarización 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 que; solamente encienda; parpadear LEDs; imprima mensajes; etc. Pero ahora queremos que además tome decisiones.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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:
1 2 3 4 |
<span style="color: #ff0000;"> 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</span>) |
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 “{ …. }”
1 2 3 4 |
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).
1 2 3 4 5 |
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.
1 2 |
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.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
/* 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
/* * conmutador sin rebote (debounced) * * Cada vez el pin de entrada va de ALTO a BAJO (p.ej. debido a 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 son una cantidad de tiempo buena 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.
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.
muy interesante, tengo problemas con los rebotes pero con esta guía estoy seguro que solucionare mi problema, gracias.
Hola GT
Me alegra que te sirva.