INTRODUCCIÓN.
En gran cantidad de dispositivos actuales se puede encontrar un contador electrónico, son innumerables los elementos que incorporan algún tipo de contador electrónico. Del mismo modo hay en libros o artículos de electrónica o en la misma red, donde se describen contadores, sencillos o más complejos, pero todos diseñados con el mismo fin, contar unos eventos que se producen con cierta regularidad, aunque a veces no tanto.
EL CONTADOR.
En unos de mis artículos se describe un contador de dos dígitos capaz de mostrar registros desde 00 a 99. Estoy refiriéndome al artículo contador de 00 a 99, en ese caso se trata de un contador realizado mediante circuitos integrados de tipo comercial de la serie CMOS 4000 (serie cuatro mil). Sin embargo en esta ocasión, aprovechando las posibilidades que nos ofrecen los microcontroladores y en concreto Arduino, trataré de describir cómo realizar uno de estos contadores de eventos. El detector de entrada, puede ser cualquier elemento y de cualquier forma, lo importante es que, entregue una señal digital adecuada, para su lectura.
El siguiente es un ejemplo de aplicación, por cierto, este circuito ya se ha estudiado en esta otra práctica.
En principio vamos a necesitar de un sistema antirrebote (en inglés debouncing) que sea fiable. Dos pulsadores para proporcionar los pulsos que vamos a contar, uno para aumentar y el otro para disminuir sus respectivas cuentas. Por lo tanto, una variable val para leer si se presiona el pulsador y otra variable val2 para comparar con la lectura anterior. De esta forma podemos saber si ha cambiado el estado de la entrada. Una variable botonStado que guarde el estado del pulsador. Un variable que guarde el número de pulsaciones. Con estas variables, vamos a crear un código que lleve la cuenta a medida que ésta aumente y la muestre en el monitor de Arduino, así, siempre habrá constancia de las pulsaciones que se han producido.
Vamos a empezar por escribir el listado del código que sea capaz de contar y mostrar la cuenta desde 0 hasta 99. De esta forma resolveremos los problemas que se presenten y lo haremos poco a poco de manera que podamos abordarlos con seguridad de no abandonar por que los problemas nos abrumen.
El siguiente listado está bastante bien comentado y espero que no haya problemas para seguirlo, en caso de necesitar ayuda, diríjase al Autor que, le atenderá tan pronto disponga de tiempo o diríjase al foro de Arduino.
Este es el listado del código, puede copiarlo desde aquí y pegarlo en su editor de texto preferido, para seguir el proyecto.
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 |
/* * contadordepulsos.ino * * Contador de dos dígitos de 00 a 99 * * Cada vez el pin de entrada va de ALTO a BAJO, el pin de salida * es basculado de ALTO a BAJO o de BAJO a ALTO. Hay un retraso * mínimo entre basculados para evitar los rebotes del circuito. * * Fecha: 30/08/10 * 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 buttonCounter =0; // contador para el número de pulsos de botón int lightMode = 0; // Esta la luz EN o AP <span style="color: #00ccff;">void setup()</span> { <span style="color: #00ccff;">pinMode</span>(switchPin, INPUT); // pone el pin switch como entrada <span style="color: #00ccff;">pinMode</span>(ledPin, OUTPUT); <span style="color: #00ccff;">Serial.begin</span>(9600); // Comunicación serie puesta a 9600bps botonStado = <span style="color: #00ccff;">digitalRead</span>(switchPin); // lee el estado inicial // buttonCounter = 92; // lo uso para saltarme los 91 primeros. Despues se quita } <span style="color: #00ccff;">void loop()</span>{ val = <span style="color: #00ccff;">digitalRead</span>(switchPin); //lee el valor de entrada y almaca en val delay(10); // 10 milisegundos son una cantidad de tiempo buena val2 = <span style="color: #00ccff;">digitalRead</span>(switchPin); // lee 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 buttonCounter + + ; if (<span style="color: #00ccff;">lightMode</span> == 0) { // esta la luz AP? <span style="color: #00ccff;">lightMode</span> = 1; // conecta la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin, <span style="color: #993300;">HIGH</span>); } <span style="color: #00ccff;">else</span> { lightMode = 0; // apaga la luz! digitalWrite(ledPin, <span style="color: #993300;">LOW</span>); } <span style="color: #00ccff;">Serial.print</span>("Número de pulsaciones: "); // muestro las if (buttonCounter <10) <span style="color: #00ccff;">Serial.print</span>("0"); // pulsaciones <span style="color: #00ccff;">Serial.println</span>(buttonCounter, DEC); // habidas } if (buttonCounter >= 99){ buttonCounter = 0; } } botonStado = val; // guardar el nuevo estado en la variable } } |
Si ha seguido los pasos descritos hasta ahora, es de suponer que todo ha salido bien. En otro caso, vuelva sobre sus pasos y analice donde está el error cometido, para poder seguir. Con esto, tenemos resuelta la primera parte del proyecto que habíamos planteado al principio.
Analizando lo que hemos hecho, podemos abordar la segunda parte; la cual, deducimos que se puede considerar una copia casi idéntica del anterior código, naturalmente hay que realizar algún cambio para que sirva nuestros intereses. Veamos estos puntos a modificar.
En primer lugar, la cuenta de las pulsaciones deberá ser llevada por una variable vval que guarde las pulsaciones. Como en el caso anterior, vval2 será la variable que usaremos para el rebote mecánico del pulsador.
Probemos este código, ¡ah!, pero antes hagamos los cambios. Para hacer más fácil las modificaciones, añadiremos un 2 a las variables, exceptuando val y val2, a las que antepondremos una v. Por supuesto que modificaremos el número del pin en el caso de la entrada del pulsador (switchPin2= 9) y la salida del LED (ledPin2 = 3) que ocuparan los pines libres que siguen al anterior.
La línea que representa el contador, se bebe modificar ya que ahora el contador disminuye o sea, es regresivo. Con esto, cada presión del pulsador se identifica con la resta de un dígito sobre la cuenta anterior. Esta es la nueva forma del «contador».
1 2 |
if (vval == LOW) { // compruebe si el botón es presionado buttonCounter2 -- ; |
Esta línea que sigue, tampoco es necesaria: // if (buttonCounter2 > -10) Serial.print(«0»); // pulsaciones, ya que en este caso, no creo necesario anteponer un «0» al contador.
Sin embargo es conveniente prestar atención al contador ya que estamos en sentido regresivo y el signo – (menos), puede causarnos algún retraso en conseguir la solución. Hay que prestar atención a la comparación, siga los pasos del código y comprenderá mejor el funcionamiento.
Este es el código del contador regresivo, lo puede copiar de aquí, pegarlo en su editor de texto y compilarlo, 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 |
/* * Contadorregresivo.pde ... * * Fecha: 30/08/10 * Autor: V. Garcia * */ int switchPin2 = 9; // switch se conecta al pin 9 int ledPin2 = 3; // el LED se conecta al pin 3 int vval; // variable para lectura del estado del pin int vval2; // variable para leer el estado delayed/debounced int botonStado2; // variable para mantener el estado del botón int buttonCounter2 = 0 ; // contador para el número de pulsos de botón int lightMode2 = 0; // Esta la luz EN o AP <span style="color: #00ccff;">void setup()</span> { <span style="color: #00ccff;">pinMode</span>(switchPin2, INPUT); // pone el pin switch como entrada <span style="color: #00ccff;">pinMode</span>(ledPin2, OUTPUT); <span style="color: #00ccff;">Serial.begin</span>(9600); // Comunicación serie puesta a 9600bps botonStado2 = <span style="color: #00ccff;">digitalRead</span>(switchPin2); // lee el estado inicial // buttonCounter2 = -92; // usado para saltarme los 91 primeros. Después se quita } <span style="color: #00ccff;">void loop()</span>{ vval = <span style="color: #00ccff;">digitalRead</span>(switchPin2); // lee el valor de entrada y almacénalo en val <span style="color: #00ccff;">delay</span>(10); // 10 milisegundos son una cantidad de tiempo buena vval2 = <span style="color: #00ccff;">digitalRead</span>(switchPin2); // lee la entrada otra vez para comprobar saltos if (vval == vval2) { // asegurar que conseguimos 2 lecturas constantes if (vval != botonStado2) { // el estado de botón ha cambiado! if (vval == LOW) { // compruebe si el botón es presionado buttonCounter2 -- ; if (<span style="color: #00ccff;">lightMode</span>2 == 0) { // esta la luz AP? <span style="color: #00ccff;">lightMode</span>2 = 1; // conecta la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin2, HIGH); } <span style="color: #00ccff;">else</span> { <span style="color: #00ccff;">lightMode</span>2 = 0; // apaga la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin2, LOW); } <span style="color: #00ccff;">Serial.print</span>("Numero de pulsaciones: "); // muestro las // if (buttonCounter2 > -10) <span style="color: #00ccff;">Serial.print</span>("0"); // pulsaciones <span style="color: #00ccff;">Serial.println</span>(buttonCounter2, DEC); // habidas } if (buttonCounter2 <= -99){ buttonCounter2 = 0; } } botonStado2 = vval; // guardar el nuevo estado en la variable } } |
COMBINAR LOS DOS CÓDIGOS.
Hemos logrado que los dos códigos realicen lo que teníamos previsto. Eso sí, los contadores, cuentan, cada uno en su dirección, lo que habíamos previsto. El caso es que ambos deben formar parte de un mismo código. Este es el reto actual. Cómo lo vamos a abordar.
Debe observarse que se han realizado unos pequeños cambios en cada subrutina, de modo que puedan compartir el código y cumplan con lo previsto. Se ha creado una nueva subrutina para la presentación en el monitor de Arduino, los resultados que se van produciendo en la medida que se generan las pulsaciones.
Esta rutina la he llamado anota(), por que eso es lo que hace. La he sacado fuera del código principal para que si al interesado no le aporta información en su aplicación, pueda prescindir de ella, eliminando las llamadas a dicha rutina y la misma.
En el listado que sigue, puede observarse lo descrito. Si está interesado en el código, aquí lo puede descargar, para su utilización, como siempre cópielo en su editor de texto preferido y compílelo con su Arduino, para cargarlo y comprobar su buen 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 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
/* * doblecontador.pde * * Contador de dos dígitos de 00 a 99 y a 00. * * En el monitor, muestra los pulsos de cada pulsador y tambien * muestra el total de pulsaciones entre ambos pulsadores. * * Cada vez que presionamos un pulsador, el pin de salida correspondiente * bascula de ALTO a BAJO o de BAJO a ALTO. Hay un retardo * máximo entre pulsos para evitar los rebotes del circuito. * * Fecha: 31/08/10 * Autor: V. Garcia * * Consume 2984 bytes compilado con version 0013Alpha. */ int switchPin = 9; // switch se conecta al pin 9 int switchPin2 = 10; // switch se conecta al pin 10 int switchPin3 = 11; // pin de reset int ledPin = 2; // el LED se conecta al pin 2 int ledPin2 = 3; // el LED se conecta al pin 3 int val = 0; // variable para lectura del estado del pin int val2 = 0; // variable para leer el estado delayed/debounced int vval = 0; // variable para lectura del estado del pin int vval2 = 0; // variable para leer el estado delayed/debounced int pac = 0; // puesta cero o reset. int botonStado; // variable para mantener el estado del botón int botonStado2; // variable para mantener el estado del botón int buttonCounter =0; // contador para el número de pulsos de botón int buttonCounter2 =0;// contador para el número de pulsos de botón <span style="color: #00ccff;">int lightMode</span> = 0; // Esta la luz EN o AP <span style="color: #00ccff;">int lightMode</span>2 = 0; // Esta la luz EN o AP <span style="color: #00ccff;">void setup()</span> { <span style="color: #00ccff;">pinMode</span>(switchPin, INPUT); // pone el pin switch como entrada <span style="color: #00ccff;">pinMode</span>(switchPin2, INPUT); // pone el pin switch como entrada <span style="color: #00ccff;">pinMode</span>(switchPin3, INPUT); // pone el pin switch como entrada <span style="color: #00ccff;">pinMode</span>(ledPin, OUTPUT); <span style="color: #00ccff;">pinMode</span>(ledPin2, OUTPUT); <span style="color: #00ccff;">Serial.begin</span>(9600); // Comunicación serie puesta a 9600bps botonStado = <span style="color: #00ccff;">digitalRead</span>(switchPin); // lee el estado inicial botonStado2 = <span style="color: #00ccff;">digitalRead</span>(switchPin2); // lee el estado inicial // buttonCounter = 92; // lo uso para saltarme los 91 primeros. Después se quita } <span style="color: #00ccff;">void loop()</span>{ val = <span style="color: #00ccff;">digitalRead</span>(switchPin); // lee el valor de entrada y almacena en val <span style="color: #00ccff;">delay</span>(10); // 10 milisegundos son una cantidad de tiempo buena val2 = <span style="color: #00ccff;">digitalRead</span>(switchPin); // lee la entrada otra vez para comprobar saltos if (val == val2) { // asegurar 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 (<span style="color: #00ccff;">lightMode</span> == 0) { // esta la luz AP? <span style="color: #00ccff;">lightMode</span> = 1; // conecta la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin, HIGH); } else { <span style="color: #00ccff;">lightMode</span> = 0; // apaga la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin, LOW); } buttonCounter ++ ; anota(); } if (buttonCounter >= 99){ buttonCounter = 0; } } botonStado = val; // guardar el nuevo estado en la variable } // --- // vval = <span style="color: #00ccff;">digitalRead</span>(switchPin2); // lee el valor de entrada y almacena en val delay(10); // 10 milisegundos son una cantidad de tiempo buena vval2 = <span style="color: #00ccff;">digitalRead</span>(switchPin2); // lee la entrada otra vez para comprobar saltos if (vval == vval2) { // asegurar que conseguimos 2 lecturas constantes if (vval != botonStado2) { // el estado de botón ha cambiado! if (vval == LOW) { // compruebe si el botón es presionado if (<span style="color: #00ccff;">lightMode</span>2 == 0) { // esta la luz AP? <span style="color: #00ccff;">lightMode</span>2 = 1; // conecta la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin2, HIGH); } else { <span style="color: #00ccff;">lightMode</span>2 = 0; // apaga la luz! <span style="color: #00ccff;">digitalWrite</span>(ledPin2, LOW); } buttonCounter2 -- ; anota(); } if (buttonCounter2 <= -99){ buttonCounter2 = 0; } } botonStado2 = vval; // guardar el nuevo estado en la variable } if (pac == 1) { // consulta si se ha pulsado reset buttonCounter = 0 ; // si se ha pulsado buttonCounter2 = 0 ; // pone a cero los contadores y anota(); // envía el flujo al monitor } } <span style="color: #00ccff;">void anota()</span> { <span style="color: #00ccff;">Serial.print</span>("Pulsaciones Incremento: "); // muestro las if (buttonCounter <10) Serial.print("0"); // pulsaciones + <span style="color: #00ccff;">Serial.print</span>(buttonCounter, DEC); // habidas // <span style="color: #00ccff;">Serial.print</span>(" Decremento: "); // muestro las <span style="color: #00ccff;">Serial.println</span>(buttonCounter2, DEC); // habidas - <span style="color: #00ccff;">Serial.print</span>(" Total pulsaciones: "); <span style="color: #00ccff;">Serial.println</span>(buttonCounter - buttonCounter2, DEC); } |
Por cierto, un dato que esta pendiente de aclarar, he añadido un tercer pulsador switch, para poder poner a cero (Reset), en cualquier momento. Ahora, ya puede disfrutar de un doble contador de eventos. Piense usted en una aplicación para darle una utilidad, por ej. un contador para una cancha deportiva. Es una idea.
Como siempre, comentarios, criticas y sugerencias para mejorar este artículo, son bienvenidos y apreciados.
Ok gracias los contactos 12 y 13 del arduino son los comunes del positivo del display?
Hola Francisco Jose.
En efecto, las salidas D12 y D13 del Aeduino van a los comunes del display (revisa si es CC o CA tu display).
Saludos.
Buenas puede poner el listado de componentes y el esquema final con el boton de reset gracias.
Los displays son de Catodo Comun verdad?
Hola Francisco Jose.
Los valores de los componentes son 7 resistencias de 220 a 270 ohms para los displays y 2 resistencias de 270 para los dígitos.
2 pulsadores NA. y 2 Displays de CA.
En cuanto al código de reset es algo más elaborado y no dispongo de tiempo en estos momentos.
Saludos.