Total en vez de sumar PUSH BOTTOM ¿se puede?

Hola amigos,

Logré obtener un código muy bueno gracias a este forum, sin embargo necesito mejorarlo. Actualmente en el monitor serial obtengo la siguiente lectura de un push bottom, pero lo que necesito que muestre es solamente el total, osea el # 5.

Adjunto mi código. Cualquier idea bienvenida.

<
1,
2,
3,
4,
5,

<

// this constant won't change:
const int  buttonPin = A2;    // the pin that the pushbutton is attached to
const int ledPin = 9;       // the pin that the LED is attached to

// Variables will change:
int Cantidad = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      Cantidad++;
      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(Cantidad);
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(10);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by checking the modulo of the
  // button push counter. the modulo function gives you the remainder of the
  // division of two numbers:
  if (Cantidad % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

El código debería estar entre las etiquetas code. Mira las NORMAS para que veas como hacerlo.

La salida de tu código es:

on
number of button pushes: 1
off
on
number of button pushes: 2
off
on
number of button pushes: 3
off
on
number of button pushes: 3
off
on
number of button pushes: 5
off
on
number of button pushes: 6

Y así secesivamente...

Y no entiendo que es lo que quieres. Si no quieres que te muestre nada excepto cuando llega a 5 quita todos los "Serial.print", y solo cuando cantidad sea 5 lo muestras.

// this constant won't change:
const int  buttonPin = A2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int Cantidad = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      Cantidad++;
      //Serial.println("on");
      //Serial.print("number of button pushes: ");
      //Serial.println(Cantidad);
      if (Cantidad==5) Serial.print(Cantidad);
    } else {
      // if the current state is LOW then the button went from on to off:
      //Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(10);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by checking the modulo of the
  // button push counter. the modulo function gives you the remainder of the
  // division of two numbers:
  if (Cantidad % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

Gracias Victor,

Si las salidas del código son:

<
0+1 = 1,
1+ 1 = 2,
2 + 1 = 3,
3 + 1 = 4,
4 + 1 = 5,

Pero no lo necesito solo para valores 5 sino todos los totales. Osea que lo que necesito es que lea el último numero sumado.

Tienes alguna otra idea de cómo hacerlo?

Te envié un privado @LUISRO847, sigues comentiendo faltas a las normas Edita todos y cada uno de los hilos donde tienes códigos mal posteados.

Sigo sin entender que quieres de salida.

En tu código hay una variable que se llama cantidad que es la que se incrementa en uno cada vez que pulsas el botón (Cantidad++).

¿Tu quieres que te muestre el número de veces que lo pulsas desde que empiezas a pulsar hasta que no pulses mas?

Si es así tienes que usar un tiempo. Inicializas un temporizador cuando pulses, si pasado un tiempo no has vuelto a pulsar lo muestras, que has pulsado inicias el temporizador.

// this constant won't change:
const int  buttonPin = A2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int Cantidad = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

// Variable de tiempo.
unsigned long t=0;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    
    if (buttonState == HIGH) {
      // Cada vez que pulses el botón guardas millis en t.
      t = millis();
      
      Cantidad++;
      
    } else {
    }
  
    delay(10);
  }
  lastButtonState = buttonState;
  
  // Si el temporizador es distinto 0, significa que has pulsado el botón.
  if ( t!=0 ) {
    // Restas el tiempo actual con el de t, si el tiempo transcurrido
    // es mayor del que tu fijes (aquí un segundo), muestas la cantidad
    // y reinicias el temporizador.
    if ( millis() - t > 1000 ) {
      Serial.println(Cantidad);
      t=0;
    }
  }
  

  // turns on the LED every four button pushes by checking the modulo of the
  // button push counter. the modulo function gives you the remainder of the
  // division of two numbers:
  if (Cantidad % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

Hola Victor,

Gracias, mira de hecho actualicé el código con un temporizador, para que reinicie el conteo desde uno. Al cambiarle el Serial.println==10 por ejemplo me escribe

00,
00,
00,…etc
10.
00,
00

Yo solo quiero que escriba el último número del string, p.ej:

5,…aquí terminó de contar y se reinicia, entonces imprimiría si fuera el caso:

10, se reinicia y vuelve a contar e imprime:

20, se reinicia y vuelve a contar e imprime de nuevo:

5,

Te adjunto el nuevo código con el temporizador…

// this constant won't change:
const int buttonPin = A2;      // the pin that the pushbutton is attached to
const int ledPin = 9;           // the pin that the LED is attached to

// Variables will change:
int Total;            // counter for the number of button presses
bool Lectura;          // current state of the button
bool nuevoLectura;     // previous state of the button
bool flag;
unsigned long tiempo;
unsigned long retardo = 1000;


void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
}

void loop() {

  Lectura = digitalRead(buttonPin);

  if (Lectura != nuevoLectura) {

    if (Lectura == LOW) {
      ++Total;
      Serial.print(Total);
      Serial.println(",");
      digitalWrite(ledPin, HIGH);
      tiempo = millis();
      flag = true;
    }
    else {
      if (Lectura == HIGH);
      digitalWrite(ledPin, LOW);
    }
  }

  nuevoLectura = Lectura;

  if (Lectura && millis() - tiempo >= retardo) {
    if (flag) {
      Serial.println(" ");
      Total = 0;
      flag = false;
    }
  }
}

En el código que te puse anteriormente lo que no hice fue poner la cantidad a 0. Cuando estes un tiempo sin pulsar nada (en el código un segundo), te muestra la cantidad de pulsaciones. A mi entender esa es la ultima cantidad que quieres.

Es más, lo que quieras hacer con cantidad debes hacerlo hay. Si quieres poner Cantidad a 0, la pones. Que si es multiplo de 4 encienda el led, lo haces, etc.

// this constant won't change:
const int  buttonPin = A2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int Cantidad = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

// Variable de tiempo.
unsigned long t=0;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // Aqui lees el botón con un pequeño "debounce"
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {   
    if (buttonState == HIGH) {
      // Cada vez que pulses el botón guardas millis en t.
      t = millis();     
      Cantidad++;     
    } else {
    }
    delay(10);
  }
  lastButtonState = buttonState;

  // Si el temporizador es distinto 0, significa que has pulsado el botón.
  if ( t!=0 ) {
    // Restas el tiempo actual con el de t, si el tiempo transcurrido
    // es mayor del que tu fijes (aquí un segundo), muestas la cantidad
    // y reinicias el temporizador.
    if ( millis() - t > 1000 ) {
      // AQUI TRABAJAS CON CANTIDAD. TIENES EL NUMERO DE PULSACIONES DESDE
      // QUE DEJASTE DE PULSAR. Por ejemplo:
      // Imprimirla.
      Serial.println(Cantidad); 
      // Encender el led si es multiplo de 0.
      if ( Cantidad%4==0 ) {
        digitalWrite(ledPin,HIGH);
      } else {
        digitalWrite(ledPin,LOW);
      }
      // Otro ejemplo has pulsado mas de 10 veces:
      if ( Cantidad>=10 ) Serial.println("Enhorabuena!, 10 veces!");
      // Por último la reinicias y vuelves a contar desde cero.
      Cantidad=0;
      t=0;
    }
  }
}

Me está costando entender, sobretodo porque dices que un código te da una salida, y cuando posteas ese código y lo uso me da una salida totalmente diferente.

Hola Victor,

Gracias por tu interés. Creo que necesito ampliarte la información, pues inicié diseñando el código basado en un contador de pulsos de un push botton.

Sin embargo en realidad es un sensor que envía senales digitales, ceros y unos como has de saber. Entonces cuando se activa empieza a contar, y cuando deja de recibir las senales termina de contar y empieza de nuevo.

Sin embargo esta lectura que se recoje desde el puerto serial COM, luego se guarda como un archivo txt.

El arduino lee todos los pulsos desde el 1 en adelante. Pero lo que necesito es que me imprima en el puerto serial el último número, que obviamente es la suma de los anteriores.

Ello debido a que esta lectura es recogida por un tercer programa que al leer, necesita únicamente el total de las lecturas.

Espero que esta información te da mas claridad, y de antemano gracias por tu apoyo.

Voy a revisar y probar tus sugerencias.

El código que te pase hace justamente eso: cuando hay un cambio en la señal (un pulso) empieza a contar. Transcurrido un tiempo sin recibir pulsos te devuelve el número de pulsos que ha recibido.

Bien, entonces resulta que por un lado tenemos un sensor que tiene una salida digital. Ese sensor tendrá un datasheet en el que te especificará el formato de la señal digital. Si me dices el sensor o posteas el datasheet podré saber como es el "protocolo", y una vez conozca lo que hace sabré como interpretar la información.

Ten en cuenta que si es un tren de pulsos puede ser por duración, o es una señal TTL que a lo mejor conviene rastrear con interrupciones, etc.

Hola Victor,

Te comento los resultados de las pruebas que realicé con tu código -ligeramente modificado- al contar 5 pulsos, como ves no es lo que busco sino que me dé el número 5. Tampoco me funcionó con el ejemplo de 10, siempre me da un string de números menos el que necesito.

El protocolo que utiliza el sensor es SSP del cual soy neófito, pero se que arduino convierte la señal análoga en digital, por ello recibe ceros y unos, cuando está el circuito normalmente abierto es que cuenta. Adjunto el datasheet del protocolo en mención - perdón no se adjuntó por el tamaño -

Las pruebas con interrupciones no me funcionaron pues estas sirven para leer las diferencias de voltaje en señales análogas, en nuestro caso

2,
1,
1,
1,
// this constant won't change:
const int  buttonPin = A2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int Cantidad = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

// Variable de tiempo.
unsigned long t = 0;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(115200);
}


void loop() {
  // Aqui lees el botón con un pequeño "debounce"
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      // Cada vez que pulses el botón guardas millis en t.
      t = millis();
      Cantidad++;
    } else {
    }
    delay(10);
  }
  lastButtonState = buttonState;

  // Si el temporizador es distinto 0, significa que has pulsado el botón.
  if ( t != 0 ) {
    // Restas el tiempo actual con el de t, si el tiempo transcurrido
    // es mayor del que tu fijes (aquí un milisegundo), muestas la cantidad
    // y reinicias el temporizador.
    if ( millis() - t > 100 ) {
      // AQUI TRABAJAS CON CANTIDAD. TIENES EL NUMERO DE PULSACIONES DESDE
      // QUE DEJASTE DE PULSAR. Por ejemplo:
      // Imprimirla.
      Serial.println(Cantidad);
      // Encender el led si es multiplo de 0.
      if ( Cantidad % 4 == 0 ) {
        digitalWrite(ledPin, HIGH);
      } else {
        digitalWrite(ledPin, LOW);
      }
      // Otro ejemplo has pulsado mas de 10 veces:
      if ( Cantidad >= 10 ) Serial.println(" 10!");
      // Por último la reinicias y vuelves a contar desde cero.
      Cantidad = 0;
      t = 0;
    }
  }
}

pero se que arduino convierte la señal análoga en digital, por ello recibe ceros y unos, cuando está el circuito normalmente abierto es que cuenta.

Me estas confundiendo más. Si el sensor SSP dices que tiene salida analógica, como que los convierte en 0's y 1's para leerlo con un digitalRead y sobretodo "cuando está el circuito normalmente abierto es que cuenta"...

Y luego:

Las pruebas con interrupciones no me funcionaron pues estas sirven para leer las diferencias de voltaje en señales análogas.

¿Desde cuando una interrupción sirve para eso?

No sé que tipo de sensor SSP es el que tienes.

Los que yo conozco a efectos practicos es una fotocélula compuesta de un emisor y un receptor que sirve para contar objetos en una cinta transportadora (o similar).

Generalmente tienen salida NPN con lo que cuando no hay objeto (el recpetor recibe la luz del emisor) tiene la salida a "1", y cuando un objeto pasa por el haz de luz entrega un "0" (puede que sea al revés dependiendo del tipo exacto de sensor y su electrónica asociada).

Dependiendo del tamaño del objeto y la velocidad de la cinta, ese pulso de valor "0" tiene una duración determinada.

Con ello podemos contar objetos, determinar su tamaño y por lo tanto el tipo de objeto.

Si la velocidad es lenta se puede usar digitalRead para tratar la señal, pero si la velocidad es rápida conviene hacerlo mediante interrupciones.

Ahora, insisto, MODELO/MARCA del sensor SSP.

Hola Victor,

Muchas gracias de nuevo, créeme que aprendo cada vez mas y lo poco que conozco es luego de la investigación y auto aprendizaje.

El sensor es el IR-FC 51, que es un sensor infrarrojo de corto alcance. Este se utiliza para leer objetos que pasan por una bandeja como lo indicas. Adjunto la fotografía.

Lo que aprendí era que inicialmente recibía una señal analógica (espero poder subir los pantallazos), porque estaba haciendo una AnalogRead.

Luego aprendí que puedo convertir el pin analógico en digital mediante la función DigitalRead, y fue cuando empecé a recibir 0 y 1, el sensor recibe 1 cuando no está pasando ningún objeto (entiendo que aquí el circuito está cerrado -la señal es continua-) y luego cambia a 0 cuando pasa un objeto.

Ya con estos valores busqué como tabulardor y lo mejor que encontré fue el contador aplicado al push button, y logré optimizarlo.

Sin embargo lo que ocupo es sabe cuántos objetos pasan por batch, osea si son 5, 10, 15, 20, etc...y lo que he logrado hasta el momento es que lea así:

1,
2,
3,
4,
5,

Espero que con esta información puedas ayudarme mejor, y me disculpo sino me he dado a entender bien.

Saludos.

Bien, conocía solo de vista el sensor, así que no lo he utilizado nunca. Pero he mirado algunas cosas y te explico.

Deja de ver el video de YouTube (al menos el que he visto yo), del que use la entrada analógica para leer este dispositivo. No sabe lo que está haciendo.

El IR-FC 51 se compone de un fotodiodo, un fototransistor, un potenciometro y un comparador de voltaje:

El potenciometro actua como un divisor de tensión, "fijando" una tensión en una de las patas del comparador. Sirve para ajustar el umbral de luz a la que la salida "activa".

El fotodiodo siempre está encendido y emitiendo luz. Esa luz, cuando hay un objeto cerca rebota e incide en el fototransistor. Cuanta más luz, mas conduce y hace que caiga la tensión en su colector, llegando a ser casi cero. Si no hay luz (no hay objeto) el transistor no conduce con lo que la tensión en su colector será la de alimentación. Esta tensión va a la otra pata del comparador.

El comparador hará lo siguiente: si la tensión del transistor es mayor que la del potenciometro su salida será el voltaje de alimentación. Si la tensión del transistor es menor que la del potenciometro su salida sera 0 voltios.

Como dije antes, si no hay objeto, la tensión del colector será la de alimentación y, si tenemos bien ajustado el potenciometro, será también mayor que este por lo que a la salida tendremos la alimentación. En este caso la alimentación es 5 voltios por lo tanto tenemos un "1" en la patita del arduino.

Si hay objeto, la tensión decae y comparada con el potencimetro será menor y por lo tanto su salida será 0 voltios, es decir, un 0 en el arduino.

Por lo tanto, el sensor en cuestion da una señal discreta de 0 cuando hay objeto y 1 cuando no lo hay.

¿Tiene sentido leerla con una entrada analógica? No. Esta más que claro que la salida es 0 y 1. El ADC siempre nos dará un valor cercano a 0 o cercano a 1023.

¿Podemos usar una entrada analógica para leerlo? Si, pero no como analógica, sino como digital, es decir, usando digitalRead(Ax).

Creo haberlo explicado bien, si tienes dudas pregunta.

Te aclaro lo de las interrupciones. Una interrupción se puede producir por:

  • Un cambio en el valor de un pin (CHANGE), da lo mismo si es de 0 a 1 que de 1 a 0, si el pin cambia, la interrupción se produce.
  • Un paso de 1 a 0 (FALLING) en un pin.
  • Un paso de 0 a 1 (RISING) en un pin.

En tu ejemplo cuando el objeto entra en la "vista" del sensor se produce un cambio de 1 a 0, con lo que se produce un FALLING. Cuando el objeto sale de la vista se produce un cambio de 0 a 1 (RISING).

Como ves, no se mide tensión ni se hace nada raro. Así que no tiene sentido lo que comentabas:

Las pruebas con interrupciones no me funcionaron pues estas sirven para leer las diferencias de voltaje en señales análogas.

Ahora es cuando tenemos que usarlo en tu proceso. Tu quieres contar "objetos". Me tienes que contar como "pasan" esos objetos. Por ejemplo, si es una cinta transportadora por la que pasan y vas contándolos hasta cierto numero que lo paras, o que va pasando objetos cada x tiempo, caen unos cuantos, dejan de caer durante un rato y quieres saber cuantos han caido hasta que empiecen a caer de nuevo.

También hay que saber la velocidad con la que los objetos pasan, si la velocidad es relativamente alta hay que usar interrupciones, si o si.

Intenta explicarmelo como si fuera un paleto de pueblo (que lo soy, no te voy a engañar).

Hola Victor,

De nuevo gracias por sacarme del oscurantismo, efectivamente tal y como lo describes funciona el sensor, y para mi viniendo desde la oscuridad en arduino fue un logro haber logrado capturar los cambios en el voltaje.

Lo que lee el sensor son tarjetas perforadas que van desde 0 a 20 en múltiplos de 5 osea una tarjeta puede venir con 5, 10, 15 o 20 agujeros. Estos pasan por el sensor de manera manual en un tiempo desde 1 a 2 segundos.

Y así empecé, una vez recibí - en el serial port- la señal analógica (la cual varía en el tiempo obviamente), investigué como pasar esa diferencia de voltaje a valores digitales, y por ello me introduje en el tema de las interrupciones como bien lo explicaste, sin embargo mi resultado fue infractuoso. Lo que si funcionó fue comparar el estado inicial y el estado final.

Luego leí sobre digitalRead! y que crees !uhuala! funcionó, tenía en mi monitor serial una lectura que iba de 1 a 0 y lo único que necesitaba era sumar los 0 y allí la cosa fue un poco mas fácil mas no sin cometer errores de principiante. Luego con la ayuda de este foro hallé como resetear el contador.

En resumen y sin intentar ponerme novelesco, esto me tomó muchos meses de investigación y pruebas, y este código represente meses de trabajo e investigación.

Ahora como te comentaba y es el propósito de este hilo, saber cómo podría obtener únicamente la lectura TOTAL de cada tarjeta, osea en vez de leer 1,2,3,4,5 únicamente obtenga el valor 5.

Como ves soy mas campechano que tu y no tengo el nivel técnico, entonces tómalo como una histografía del contador de tarjetas! ja ja

Copio de nuevo el código, y espero que puedas ayudarme, sino de todas maneras gracias por la lección pues siempre se aprende.

// this constant won't change:
const int buttonPin = A2;      // the pin that the pushbutton is attached to
const int ledPin = 9;           // the pin that the LED is attached to

// Variables will change:
int Total;            // counter for the number of button presses
bool Lectura;          // current state of the button
bool nuevoLectura;     // previous state of the button
bool flag;
unsigned long tiempo;
unsigned long retardo = 1000;


void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
}

void loop() {

  Lectura = digitalRead(buttonPin);

  if (Lectura != nuevoLectura) {

    if (Lectura == LOW) {
      ++Total;
      Serial.print(Total);
      Serial.println(",");
      digitalWrite(ledPin, HIGH);
      tiempo = millis();
      flag = true;
    }
    else {
      if (Lectura == HIGH);
      digitalWrite(ledPin, LOW);
    }
  }

  nuevoLectura = Lectura;

  if (Lectura && millis() - tiempo >= retardo) {
    if (flag) {
      Serial.println(" ");
      Total = 0;
      flag = false;
    }
  }
}

Algún detalle mas faltaría.

Entonces tu pasas una tarjeta que tiene agujeros (multiplos de 5) generalmente. No se como haces el proceso asi que me he tenido que imaginar que la tarjeta la coges con la mano, la pones en un útil, mueves una manivela y pasa por delante del sensor. identificandola por el número de agujeros:

Más o menos esto:

contador1.jpg

En la imagen anterior las rayas representan los huecos. Al inicio no hay tarjeta, así que el sensor te dirá que no hay objeto con un "1". Al acercar la tarjeta detectará una pared, un hueco, una pared, un hueco,... hasta que termina la tarjeta que volverá estar al aire (sin objeto, o sea 1).

En ese caso yo veo que la cantidad de pulsos será siempre uno mayor que el número de huecos. Así cuando tu pasas la tarjeta de 5 te devuelve 6 pulsos.

El proceso es relativamente lento si tarda entre 1 y dos segundos, así que no veo necesario el uso de interrupciones.

Asumo que tienes que cambiar de tarjeta manualmente, asi que el "tiempo entre tarjetas" será también relativamente grande.

El código que te puse en un principio es totalmente válido, pero lo he modificado un poco para adecuarse a la situación:

// this constant won't change:
const int  buttonPin = A2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int Cantidad = 0;            // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

// Variable de tiempo.
unsigned long t=0;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
   
    if (buttonState == LOW) {
      // Cada vez que pulses el botón guardas millis en t.
      t = millis();
      Cantidad++;
    } else {
    }
    delay(10);
  }
  lastButtonState = buttonState;
 
  // Si el temporizador es distinto 0, significa que has pulsado el botón.
  if ( t!=0 ) {
    // Restas el tiempo actual con el de t, si el tiempo transcurrido
    // es mayor del que tu fijes (aquí un segundo), muestas la cantidad
    // y reinicias el temporizador.
    if ( millis() - t > 1000 ) {           
      // Debemos tratar la cantidad.
      if ( (Cantidad-1)%5==0 ) {
        Serial.print("Has pasado una tarjeta válida de ");
        Serial.print(Cantidad-1);
        Serial.println(" agujeros");
      }
      else {
        Serial.print("Error en la tarjeta, hemos contado ");
        Serial.print(Cantidad-1);
        Serial.println(" agujeros");
      }
      // Debemos iniciar la cantidad y el timer.
      Cantidad=0;
      t=0;
    }
  }
}

Solo que ahora, detecto el cambio a LOW, detecto que la cantidad sea multiplo de cinco siempre que teniendo en cuenta que voy a recibir un pulso mas.

He montado un pulsador con dos cables, he probado el código y da:

Has pasado una tarjeta válida de 5 agujeros
Has pasado una tarjeta válida de 5 agujeros
Error en la tarjeta, hemos contado 6 agujeros
Has pasado una tarjeta válida de 5 agujeros
Has pasado una tarjeta válida de 10 agujeros
Has pasado una tarjeta válida de 15 agujeros
Has pasado una tarjeta válida de 25 agujeros

Ten en cuenta que esto son aproximaciones, ya que desconozco como tienes montado el sistema.

contador1.jpg

Hola Victor,

Estoy identificando que la función t = millis; es un temporizador que a la vez te detecta cambios de estado, lo cual es muy útil en este tipo de desarrollos.

Tus apreciaciones e inferencias son correctas desde la perspectiva teórica, en la práctica obviamente en el campo dicho diseño se pone en prueba y si es eficaz tendremos el output requerido.

Hay algunos detalles que por obvias razones tu no las tienes, pero te las comparto para que tomes una mejor apreciación.

  1. Como lo indicas, estando el circuito en reposo (sin pasar tajeta alguna), la lectura en el Serial Ploter por ejemplo es de 1..............., y al pasar la tarjeta cambia a 0,1,0,1,0,1,0,1,0,1........tal y como lo demuestras en tu esquema.

  2. Al introducir la tarjeta en la canal adaptada para el efecto, con el código anterior, empieza a leer contando 1,2,3,4,5 como he acotado. Adicionalmente enciende una led que pasa de estado LOW a HIGH. (esto lo obviaste), pero no es crítico.

  3. Con lo anterior tomé tu código y eliminé el menos 1 (como te comento las lecturas son justas entonces no es necesario disminuir -1) y reemplazé el existente obteniendo los resultados siguientes:

Error en la tarjeta, hemos contado 5 agujeros

Pareciera que lo que lee es un error, pues esa es la instrucción else (sino) en tu código. Aún así es bastante bueno, pues con una pequeña modificación logro obtener la lectura deseada (sin el texto).

Sin embargo me pareció extraño no obtener la lectura como:

Hemos pasado una tarjeta válida de 5

Mas extraño aún, que ahora el arduino tarda en enviar la lectura al Monitor Serial en aproximadamente 4 segundos..........eso si es extraño, pues antes la lectura era inmediata.

Victor, tu aporte ha sido muy valioso y por lo visto hay mucha gente interesada, mas pocos son los que aportan.

Me es difícil copiar pantallazos o pues no tengo el equipo a la mano, no es por desinterés créeme.

A qué crees que se deba el delay que existe ahora en la lectura, así como que está realizando la función else y no la if como debiera ser....

Quedo atento a tus comentarios.

  1. Como lo indicas, estando el circuito en reposo (sin pasar tajeta alguna), la lectura en el Serial Ploter por ejemplo es de 1..............., y al pasar la tarjeta cambia a 0,1,0,1,0,1,0,1,0,1........tal y como lo demuestras en tu esquema.

absorto he me, ¿cómo estas conectando el puerto serie al sensor y a la vez a un pin digital?

Tampoco me has enseñado la tarjeta con lo que todo lo que hago son HIPOTESIS. Si yo me imagino una tarjeta perforada, me la imagino como en el dibujo que te puse.

  1. Al introducir la tarjeta en la canal adaptada para el efecto, con el código anterior, empieza a leer contando 1,2,3,4,5 como he acotado. Adicionalmente enciende una led que pasa de estado LOW a HIGH. (esto lo obviaste), pero no es crítico.

Obviamente, me olvidé del led.

Con lo anterior tomé tu código y eliminé el menos 1 (como te comento las lecturas son justas entonces no es necesario disminuir -1) y reemplazé el existente

Si quitas el -1 has de tener en cuenta que el modulo de 0 entre 5, es 0, por lo tanto si cantidad es 0, te detecta algo válido.

if ( cantidad%5==0 && cantidad!=0 ) {
  // Lo que quieras hacer con cantidad. Mostrar por el puerto serie,
  // encender/apagar un led, etc. Aquí la tarjeta es VALIDA.
}
else {
  // Código a realizar cuando la tarjeta es NO VALIDA.
}
cantidad=0;
t=0;

Mas extraño aún, que ahora el arduino tarda en enviar la lectura al Monitor Serial en aproximadamente 4 segundos.

La respuesta de mi código es del tiempo de 1 segundo, que es el límite que he puesto entre tarjetas. Desconozco que más código tienes, porque no lo has compartido, pero me da la sensación de que tienes delay en algún otro sitio retrasando el código en 3 segundos mas. Consejo: deshazte de los delay.

Hola Victor,

Recuerda que los pines análogos se convierten en digitales si le asignas una función como digitalReal. Por otro lado estoy identificando que el delay proviene del sensor, que ahora toma mas tiempo en leer la tarjeta...extraño pues no lo hacía anteriormente.

De todas formas con los cambios sugeridos en el código funciona muy bien, pero haré la última actualización que me enviaste.

Podrías traducirme a lenguaje humano Cantidad%5==0? significa que son múltiplos de 5?, la otra parte && cantidad !=0 la entiendo como "y si la cantidad no es igual a 0".

Saludos.

El sensor, despues de analizar su circuito te digo que no te va dar ningún retraso. Solo puede que varie su zona de detección, es decir, la distancia.

if ( cantidad%5==0 && cantidad!=0 ) ...

Si el resto de la división entera de cantidad entre 5 es igual a 0 y cantidad es distinto de 0…

Si me has preguntado eso, no me queda mas remedio que recomendarte la lectura de los archivos adjuntos.

Aprenda C++ como si estuviera en primero.pdf (668 KB)

Aprenda-ANSI-C-Como-si-estuviera-en-primero.pdf (878 KB)

Hola todos,

Gracias Victor por tu guía y dedicación a este desarrollo que ahora es un éxito y arduino ahora es una herramienta de control.

Comparto el código con la instrucción del LED que enciende cuando está en HIGH y viceversa. Probado.

El nuevo reto es enviar estos datos hacia una base de datos MySQL vía web así como directamente, pero creo que abriré un nuevo hilo.

Saludos.

const int  buttonPin = A2;    // el pin a donde está conectado el sensor
const int ledPin = 13;       // el pin a donde está conectado el LED

// Variables will change:

int Cantidad = 0;            // contador de agujeros
int buttonState = 0;         // estado actual del contador
int lastButtonState = 0;     // estado previo del contador

// Variable de tiempo.
unsigned long t=0;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(115200);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
  
    if (buttonState == LOW) {
      // Cada vez que pulses el botón guardas millis en t.
      t = millis();
      Cantidad++;
      }
      else {
    }
    delay(10);
  }
  lastButtonState = buttonState;

  // Si el temporizador es distinto 0, significa que has pulsado el botón.
  if ( t!=0 ) {
    // Restas el tiempo actual con el de t, si el tiempo transcurrido
    // es mayor del que tu fijes (aquí un diez mili segundos), muestras la cantidad
    // y reinicias el temporizador.
    if ( millis() - t > 100 ) {          
      // Debemos tratar la cantidad.
      if ( Cantidad%5==0 && cantidad!==0 ) {
        Serial.print("Has pasado una tarjeta válida de ");
        Serial.print(Cantidad);
        Serial.println(" ");
        digitalWrite(ledPin, HIGH);
      }
      else {
        Serial.print("Error en la tarjeta, hemos contado ");
        Serial.print(Cantidad);
        Serial.println(" ");
        digitalWrite(ledPin, LOW);
      }
      // Debemos iniciar la cantidad y el timer.
      Cantidad=0;
      t=0;
    }
  }
}