contador de pulsos

Hola, espero puedan ayudarme.
Estoy realizando un contador de pulsos en mi arduino uno, que se activan al pulsar un botón, y los almacena en un contador (conta++) y además me enciende un relé en el pin 6. Llegado a ciertos pulsos (1,12 y 16) debe prenderme otro relé ubicado en el pin 7.

El problema me surge cuando quiero agregarle un tiempo de encendido al relé del pin6, ya que quiero que dure 3 segundos prendidos y luego se apague esperando el siguiente pulso. No obstante el relé del Pin7 debe quedarse encendido hasta recibir otro pulso.

El problema es que al momento de probar el circuito el relé del pin6 realiza 2 veces el pulso y luego se apaga. y en ocasiones el sistema falla ya que comienza a prender el pin6 y pin7 de forma alternada y no como lo programe con el contador
Espero puedan ayudarme les dejo mi código a ver si se les ocurre algo. Gracias

int estado_anterior;
int estado_boton; //Estado real del boton sin rebotes
int conta = 0;  //Variable para guardar el conteo de los pulsos
unsigned long lastDebounceTime = 0;  // ultimo momento que el pin ha cambiado
unsigned long debounceDelay = 50;    // tiempo de rebote, aumentar si hay rebotes

void setup() {
 Serial.begin(9600);
 pinMode(2, INPUT_PULLUP); //Boton
 pinMode(7, OUTPUT);  //Led
 pinMode(6, OUTPUT);  //Led
 estado_anterior = digitalRead(2); //Inicializo con el estado del boton al iniciar programa
 estado_boton = estado_anterior;
}

void loop() {
 int sensorVal = digitalRead(2);
 if (sensorVal != estado_anterior) {
   lastDebounceTime = millis();  //momento en que detecto un cambio de estado del boton
 }

 if ((millis() - lastDebounceTime) > debounceDelay) {
   //Cuando ha pasado el tiempo con una señal estable
   if (sensorVal != estado_boton) {
     estado_boton = sensorVal;
     if (estado_boton == LOW) { //Detecto flanco ascendente, poner LOW para detectar flanco descendente
         conta++;               //Incrementa el contador
       Serial.println(conta); //Imprime el valor por consola
                // Retardo
       int estado_led = digitalRead(6);
       digitalWrite(6, !estado_led);
       int estado_led2 = digitalRead(7);
       digitalWrite(7, !estado_led2);
     }
     if (conta==1)
{
  digitalWrite(6,LOW);  //Enciende el LED
  digitalWrite(7,HIGH);  //Enciende el LED
   
}
 if (conta==2)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
  delay (3000);
   digitalWrite(6,LOW);
   
}

 if (conta==3)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
   
}
 if (conta==4)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
   
}
      // Si el valor del contador es 5
if (conta==5)
{
digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
   
}
if (conta==6)
{
 digitalWrite(7,LOW);  //Apaga el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
   
}
 if (conta==7)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
 
    delay (3000);
   digitalWrite(6,LOW);
}
 if (conta==8)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
   
}
 if (conta==9)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED

    delay (3000);
   digitalWrite(6,LOW);
}
 if (conta==10)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
  
    delay (3000);
   digitalWrite(6,LOW);
}
 if (conta==11)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
  delay (3000);
   digitalWrite(6,LOW);
   
}
 if (conta==12)
{
 digitalWrite(6,LOW);  //Enciende el LED
  digitalWrite(7,HIGH);  //Enciende el LED
   
}
if (conta==13)
{
 digitalWrite(7,LOW);  //Apaga el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
}
if (conta==14)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED

    delay (3000);
   digitalWrite(6,LOW);
}
if (conta==15)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
delay (3000);
   digitalWrite(6,LOW);
   
}
 if (conta==16)
{
 digitalWrite(6,LOW);  //Enciende el LED
  digitalWrite(7,HIGH);  //Enciende el LED
   
}

if(conta==17)
{
  digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);
   delay (3000);
   digitalWrite(6,LOW);
}
if (conta==18)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
  delay (3000);
   digitalWrite(6,LOW);
   }
   if (conta==19)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
 }
 if (conta==20)
{
 digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);  //Enciende el LED
   delay (3000);
   digitalWrite(6,LOW);
}
if(conta==21)
{
  digitalWrite(7,LOW);  //Enciende el LED
  digitalWrite(6,HIGH);
   delay (3000);
   digitalWrite(6,LOW);
(conta=0);
 
}
   }
 } 
 estado_anterior = sensorVal;  //Sin esto no funciona, actualizo para el siguente loop
}

Por favor, Lee las Normas del foro.

Edita tu post, los códigos van con etiquetas.

Primero que todo edita el Post para poder ver mejor el código. Segundo, si estás teniendo tantas fallas deberías publicar el esquema de las conexiones que estás realizando, estás conectando directo el relé a la salida del Arduino? O estás usando el típico esquema con el transistor?, si estás usando el del transistor ¿le colocaste el diodo de protección en paralelo a la bobina del relé?

TIenes el eterno problema de intentar hacer dos cosas al mimo tiempo, pero los delay te lo impide. mira los tutoriales de milis. en documentación

Como te dice Peter, ese delay de 3 segundos te va a ocasionar problemas, si quieres que tu programa responda cuando lo necesitas debes quitarlo, ademas que no le veo sentido ya que enciendes el led, luego haces un delay de 3 segundos, luego apagas el led, pero inmediatamente lo vuelves a encender por lo que ni siquiera notaras cuando se apaga. Si lo que quieres es que el led esté destellando necesitas otro delay después del digitalWrite(6, LOW), asi mientras estes en la condición el led estará destellando, pero ten en cuenta que con tanto delay cuando tu oprimas el boton hay una alta probabilidad que no responda.

En la parte del boton tienes muchas cosas sin sentido que te complican las cosas
Después solo haces 2 cosas distintas con el contador, pero tu repites las instrucciones muchas veces lo que aumenta la probabilidad de un error.
Le hice muchos cambios a tu codigo para reducir esas 200 lineas, pruebalo

bool estado_anterior = true;
bool estado_boton = true;
byte conta = 0;
unsigned long lastDebounceTime;
unsigned long debounceDelay = 60;
unsigned long blink;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);  //Boton ¡OJO! esta en pull-up
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);

}

void loop()
{
  estado_boton = digitalRead(2);

  if (!estado_boton && estado_anterior &&  millis() - lastDebounceTime >= debounceDelay)  //se presiono el Boton
  { 

    conta++;
    if (conta > 21)
      conta = 0;
    Serial.println(String("El numero en el contador es: ") + conta);  //imprime el valor en consola
    lastDebounceTime = millis();

  }
  estado_anterior = estado_boton;


  if (conta > 1 && conta != 12 && conta != 16)
  {

    digitalWrite(7, LOW); //Apaga el LED

    if (millis() - blink >= 3000UL)
    {
      digitalWrite(6, !digitalRead(6));  //Enciende el LED
      blink = millis();
    }
  }

  if (conta == 1 | conta == 12 | conta == 16)
  {
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
  }
}

Esto hace lo mismo que lo quieres hacer, estoy suponiendo que quieres que el led destelle cuando conta es diferente a 1 ,12 y 16, fíjate que ya no hay delay para que el programa responda cuando tu presionas el boton, espero que no hagas solo un copy-paste (como lo hiciste con el debounce), y trates de comprender el funcionamiento.
Si sigues teniendo problemas, o si tienes alguna duda comenta.
también es bueno que mandes un diagrama de tus conexiones siguiendo las normas del foro, eso da un panorama completo del problema y es mas facil ayudar.

PERDON!!, en el post anterior no lei bien lo que dices aquí:

El problema me surge cuando quiero agregarle un tiempo de encendido al relé del pin6, ya que quiero que dure 3 segundos prendidos y luego se apague esperando el siguiente pulso. No obstante el relé del Pin7 debe quedarse encendido hasta recibir otro pulso.

Me enfoque solo a lo que resaltaste en negritas y a tu codigo.
Aqui te dejo el código ya corregido para que apague el led después de los 3 segundos. Dejo el código anterior por si te sirve de algo ver como hacer que el led destelle

Éste es el código corregido, analiza lo, pruebalo y comenta

bool estado_anterior = true;
bool estado_boton=true;
byte conta=0;
unsigned long lastDebounceTime;
unsigned long debounceDelay=60;
unsigned long tiempo;
bool start=false;
void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);  //Boton ¡OJO! esta en pull-up
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);

}

void loop()
{
  estado_boton=digitalRead(2);

  if(!estado_boton && estado_anterior &&  millis()- lastDebounceTime >= debounceDelay){         //se presiono el Boton

    conta++;
    if(conta>21)
    conta=0;
      Serial.println(String("El numero en el contador es: ") + conta);  //imprime el valor en consola
      lastDebounceTime=millis();
      if(conta>1 && conta !=12 && conta!=16)
      {
        digitalWrite(6, HIGH); // enciende el led
        digitalWrite(7,LOW);  //Apaga el LED
        start=1;                
        tiempo=millis();       //comienza el contador de tiempo
      }
      else 
      {
      start=0;
      digitalWrite(6, LOW);
      digitalWrite(7, HIGH);
      }
    }
    estado_anterior=estado_boton;

    if(start==true)
    {
      //CONTADOR DE LOS 3 SEGUNDOS
     if(millis() - tiempo >= 3000UL)   // cuenta los 3 segundos
     {
     digitalWrite(6, LOW );  //Apaga el LED
     start=false; 
     }
    }

}

Gracias, probé el código que me dejaste en el comentario y funciona muy bien, pero a veces me marca 2 veces el contador con un solo pulso, por ejemplo estoy en el pulso 5, presiono el botón y marca 6 y 7 de una vez, pienso que puede deberse a algún efecto de rebote, es posible?

De igual manera me ayudaste bastante con el tema del tiempo, para estar comenzando en este mundo de los arduinos me siento muy bien apoyado con ustedes, muchas gracias

Y para que entiendan un poco la idea del proyecto, es realizar un sistema de control de salida en una barrera vehicular. se presiona el botón y se abre la barrera (con el relé del pin 6) y y cada cierta cantidad de pulsos, se activara el relé del pin 7, el cual hace sonar una bocina y una luz roja, de esta manera se revisara a una persona al azar que quiera salir. Ahora el pulso del pin 6 (relé de apertura) debe durar 3 segundos y luego apagarse. Pero el relé de alarma (pin 7) debe quedar activado permanentemente y solo cambiara de estado cuando se vuelva a presionar el botón, de esta manera el contador seguirá avanzando y se abrirá la barrera de manera normal.
Espero se haya entendido mi proyecto y puedan ayudarme
Muchas gracias!!.

Buen dia,

para que entiendan un poco la idea del proyecto, es realizar un sistema de control de salida en una barrera vehicular

Por ahi hubieses empezado, y te ahorrabas y me ahorrabas tiempo, cuando pidas ayuda trata de dar el mayor dato posible. Como te dije anteriormente, me base a lo que tenias en tu codigo.
Bueno, lo que quieres se hace fácilmente modificando el código existente, solo es cuestión de mover de lugar unas lineas al código:

const byte barrera=6;
const byte bocina=7;

bool estado_anterior = true;
bool estado_boton=true;
byte conta=0;
unsigned long lastDebounceTime;
unsigned long debounceDelay=100;
unsigned long tiempo;
bool start=false;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);  //Boton ¡OJO! esta en pull-up
  pinMode(barrera, OUTPUT);
  pinMode(bocina, OUTPUT);

}

void loop()
{
  estado_boton=digitalRead(2);

  if(!estado_boton && estado_anterior &&  millis()- lastDebounceTime >= debounceDelay){         //se presiono el Boton

    conta++;
    if(conta>21)
    conta=0;
      Serial.println(String("El numero en el contador es: ") + conta);  //imprime el valor en consola
      lastDebounceTime=millis();
        digitalWrite(barrera, HIGH); // abre la barrera
        start=1;                
        tiempo=millis();       //comienza el contador de tiempo

      if(conta>0 && conta !=12 && conta!=16)   //cuando conta sea 0, 12 o 16 se activará la bocina y se apaga hasta la siguiente pulsación del botón
         digitalWrite(bocina, LOW);  //apaga la bocina
      else 
         digitalWrite(bocina, HIGH); //enciende la bocina
     }
    estado_anterior=estado_boton;

    if(start==true)
    {
      //CONTADOR DE LOS 3 SEGUNDOS
     if(millis() - tiempo >= 3000UL)   // cuenta los 3 segundos
     {
     digitalWrite(barrera, LOW );  // cierra la barrera
     start=false; 
     }
    }

}

Compáralos y veras que solo cambie de lugar las lineas y surte el efecto deseado

En cuanto a esto:

a veces me marca 2 veces el contador con un solo pulso, por ejemplo estoy en el pulso 5, presiono el botón y marca 6 y 7 de una vez, pienso que puede deberse a algún efecto de rebote, es posible?

Si, solo sube el tiempo en la variable unsigned long debounceDelay=60; hay pulsadores que rebotan mas que otros, ajustalo al tiempo que te trabaje mejor

Espero se haya entendido mi proyecto y puedan ayudarme

Lo hago con gusto, lo único que pido es que no hagas solo un copy-paste, si no que lo veas, lo comprendas y aprendas para tus futuros proyectos, para que esto no sea solo tiempo perdido, y si tienes alguna duda de que hace x cosa, pregunta estoy a tus ordenes al igual que muchos en este foro

Saludos

Muchas gracias!
Estuve analizando el código y note que claramente yo me estaba equivocando en la forma de realizar el código, alargando las líneas y además mezclando las funciones delay y millis.

Ahora me surge un problema con el código que me enviaste, cuando llego al número indicado ( 0, 12 y 16) se prenden ambos relés (barrera y bocina) en primera instancia, y luego de los 3 segundos el relé de barrera se apaga y el relé de la bocina queda encendido.

la idea es que llegado a esos números (0 12 y 16) solo el relé de bocina se prenda y siga así hasta presionar nuevamente el botón.

Y probé el tema del " unsigned long debounceDelay=100; " lo cambie por varios tiempos y otros pulsadores(e incluso probé haciendo el pulso eléctrico de forma manual con 2 cables juntandolos intermitentemente) y sigue el problema del rebote.

Mi conexión es la siguiente:
El botón tiene 2 conexiones, una va al negativo y la otra conectada al pin 2 de mi arduino y ademas a una resistencia de 220 Ohm que va al positivo de los 5V del arduino.

el relé de apertura de barrera: el pin S va al pin 6 del arduino y el positivo y negativo del rele van al GND y 5V del arduino

el relé de bocina: el pin S va al pin 7 del arduino y el positivo y negativo van al GND y 5V del arduino

Espero haberme dado a entender con mi explicacion de las conexiones, la verdad no se si existe la forma de cargar imagenes a este foro para poder explicarlo de mejor manera.

Muchas gracias nuevamente, sigo aprendiendo, leyendo tutoriales, pero nada más efectivo que sus consejos! gracias :slight_smile:

la idea es que llegado a esos números (0 12 y 16) solo el relé de bocina se prenda y siga así hasta presionar nuevamente el botón.

Eso es lo que hace el codigo que te deje en el post#5 al llegar a los numeros de esta linea:
if(conta>1 && conta !=12 && conta!=16). lo que hace esto es que cuando conta sea diferente a 1, 12 y 16, te va abrir la barrera y después de 3 segundo se cierra, y cuando conta sea uno, 12 o 16 la bocina suena sin abrir la barrera, y no deja de sonar si no presionas de nuevo el botón. pruebalo de nuevo
En cuanto a los rebotes lo acabo de probar y yo no tengo ese problema.

ademas a una resistencia de 220 Ohm que va al positivo de los 5V del arduino.

Aqui tienes un error, si te fijas en el void setup() dice pinMode(2, INPUT_PULLUP), por lo que no necesitas la resistencia que estas poniendo, ademas cuando uses una resistencia ya sea para hacerr pull_up o pull_down tienes que usar un valor mas alto como 10K, ese es debe ser tu problema quilata y tiene que funcionar.
Otra cosa, ¿los relay que tienes son modulos de los que venden en un pcb o es un relay solo? porque si es solo el relay no debes conectarlo directamente al arduino, ceo que ahi tambien tienes un problema, tambien puedes adjuntar imagenes usando uno de los botones que estan en la barra de herramientas, solo ten en cuenta que la imagen tiene que quedar visible, checate en las normas del foro ah viene como adjuntar imagenes

Espero se suba la imagen, del dibujo que realice del diagrama

En el se puede ver los pines 2 6 y 7 conectados al botón y 2 leds de pruebas que utilizo en el laboratorio para probar el código que me enviaste.

En esta imagen muestro el tipo de relay que estoy utilizando para el proyecto

Y en esta imagen muestro la placa con sus conexiones y los leds de prueba

El cable rojo es del los 5V de la placa
El cable negro es del GND de la placa
El cable amarillo corresponde al boton (pin 2)
El cable azul es el pin 6 que corresponde al pulso de apertura
El cable Blanco corresponde al pin 7 que es el de la bocina

Y en la parte inferior de la imagen esta el puulsador verde que utilizo con un extremo conectado al GND y el otro al pin 2 y luego a la resistencia de 10K que va al positivo de los 5V

Te envié privado con instrucciones para que leas las normas y edites tus post desde el 10 en adelante para poder visualizar las fotos directamente.
Gracias