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 (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.

circuito2x7segm
Fig. 1

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.

/*
 *  contadordepulsos.pde
 *
 *  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

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
//  buttonCounter = 92;   // lo uso para saltarme los 91 primeros. Despues se quita
}

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); // 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 (lightMode == 0) {    // esta la luz AP?
          lightMode = 1;         // conecta la luz!
          digitalWrite(ledPin, HIGH); 
        } else {
          lightMode = 0;               // apaga la luz!
          digitalWrite(ledPin, LOW); 
        }
      Serial.print("Número de pulsaciones:   ");   // muestro las
     if (buttonCounter <10)  Serial.print("0");    //  pulsaciones       Serial.println(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».

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.

/*
 * 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

void setup() { 
  pinMode(switchPin2, INPUT);  // pone el pin switch como entrada
  pinMode(ledPin2, OUTPUT);
  Serial.begin(9600);        // Comunicación serie puesta a 9600bps
  botonStado2 = digitalRead(switchPin2);   // lee el estado inicial
//  buttonCounter2 = -92;     // lo uso para saltarme los 91 primeros. Después se quita
}
void loop(){
  vval = digitalRead(switchPin2);  // lee el valor de entrada y almacénalo en val
  delay(10);    // 10 milisegundos son una cantidad de tiempo buena
  vval2 = digitalRead(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 (lightMode2 == 0) {    // esta la luz AP?
          lightMode2 = 1;         // conecta la luz!
          digitalWrite(ledPin2, HIGH); 
        } else {
          lightMode2 = 0;               // apaga la luz!
          digitalWrite(ledPin2, LOW); 
        }
      Serial.print("Numero de pulsaciones: ");   // muestro las
//     if (buttonCounter2 > -10)  Serial.print("0"); // pulsaciones
      Serial.println(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.

/*
 *  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

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

void setup() {
  pinMode(switchPin, INPUT);   // pone el pin switch como entrada
  pinMode(switchPin2, INPUT);  // pone el pin switch como entrada  
  pinMode(switchPin3, INPUT);  // pone el pin switch como entrada     
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);  
  Serial.begin(9600);       // Comunicación serie puesta a 9600bps
  botonStado = digitalRead(switchPin);   // lee el estado inicial
  botonStado2 = digitalRead(switchPin2); // lee el estado inicial  
//  buttonCounter = 92;  // lo uso para saltarme los 91 primeros. Después se quita
}

void loop(){
  val = digitalRead(switchPin); // lee el valor de entrada y almacena en val
  delay(10);    // 10 milisegundos son una cantidad de tiempo buena
  val2 = digitalRead(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 (lightMode == 0) {    // esta la luz AP?
          lightMode = 1;         // conecta la luz!
          digitalWrite(ledPin, HIGH); 
        } else {
          lightMode = 0;               // apaga la luz!
          digitalWrite(ledPin, LOW); 
        }
      buttonCounter ++   ;               
      anota();
      } 
      if (buttonCounter >= 99){
         buttonCounter = 0; 
       }  
    }
    botonStado = val;     // guardar el nuevo estado en la variable
  }
  // --- //
    vval = digitalRead(switchPin2); // lee el valor de entrada y almacena en val
  delay(10);             // 10 milisegundos son una cantidad de tiempo buena
  vval2 = digitalRead(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 (lightMode2 == 0) {    // esta la luz AP?
          lightMode2 = 1;         // conecta la luz!
          digitalWrite(ledPin2, HIGH); 
        } else {
          lightMode2 = 0;               // apaga la luz!
          digitalWrite(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
     }
 } 
 
void anota() {
    Serial.print("Pulsaciones Incremento: ");   // muestro las
     if (buttonCounter <10)  Serial.print("0"); //  pulsaciones +
     Serial.print(buttonCounter, DEC);         // habidas
//
     Serial.print(" Decremento: ");            // muestro las
     Serial.println(buttonCounter2, DEC);      // habidas -  
    
     Serial.print("      Total pulsaciones: ");        
     Serial.println(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.

CONTADOR DECIMAL DOBLE.

Deja un comentario

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.