Funcion para chequear varias entradas digitales

Hola a todos...

Mi proyecto necesito chequear 9 entradas digitales, y filtrarlas (debounce) algunos segundos, y no todas el mismo tiempo.

Asi que pense en hacer una funcion.
Pero me esta comiendo el coco....

int Entradas(int &M_Var, int &I_Var, int Time){
  
  if(M_Var != digitalRead(I_Var)){
    unsigned long StarTime = millis();
    if(millis()- StarTime > (Time*1000)){
      M_Var = digitalRead(I_Var);
    }
  }
  return;
}

M_Var es una marca para el loop, I_Var es el numer del pin de la entrada y time el tiempo en segundos.

Entonces si M_Var es distinto a la lectura digital del pin, capturamos el tiempo de millis, y lo comparamos restando el tiempo actual menos el tiempo de comienzo deben ser mayor al tiempo multiplicado por 1000 para los milisegundos... Si esto se cumple asingnamos el nuevo valor a la Marca M_Var

Es que lo veo tan simple que por algun lado me debo estar equivocando...

Donde si tengo mis dudas es con el uso del & para la referencia de las variables... ya que quiero que la variable cambie dentro de la funcion.

Algun comentario?

Muchas Gracias

Eso nunca te va a funcionar.Defines una variable que es igual al valor de millis() y en la siguiente linea restas la variable al valor de millis() ...solo pueden haber pasado unos pocos milisegundos entre una linea y la otra y a poco que Time valga 1,estamos hablando de 1 segundo.La condicion dificilmente se va a cumplir.

NO te compliques usa la librería Bounce2 y asunto terminado.

jose:
Eso nunca te va a funcionar.Defines una variable que es igual al valor de millis() y en la siguiente linea restas la variable al valor de millis() ...solo pueden haber pasado unos pocos milisegundos entre una linea y la otra y a poco que Time valga 1,estamos hablando de 1 segundo.La condicion dificilmente se va a cumplir.

Claro creo que entiendo que me quieres decir....

Que el tiempo de Comienzo StarTime se va a actualizar en cada ciclo y nunca va cumplir la siguiente condición...

Entiendo...

A ver que te parece esta Idea.... uso una Marca para identificar la primera vez que la variable sea distinta que la lectura del pin, y asi solo capturo el tiempo de millis una sola vez.

int Entradas(int &M_Var, int &I_Var, int Time){
  int FM = 0;
  unsigned long StarTime;
  unsigned long CurrentTime;
  if(M_Var != digitalRead(I_Var) && (FM = 0)){
    StarTime = millis();
    FM++;
    }
  if(M_Var != digitalRead(I_Var) && (FM >= 1)){ 
      CurrentTime = millis() - StarTime;
      if(CurrentTime > (Time*1000)){
      M_Var = digitalRead(I_Var);
      FM = 0;
      }
  }
  return;
}

Pues gracias déjame que lea sobre esta librería estuve buscando por que sabia que ya alguien había tenido el mismo problema que yo... pero no fui capaz de encontrar algo.

surbyte:
Los cruces x cero ocurren cada 10 mseg asi que si no usas interrupciones puedes detectarlo, si,pero no debes usar delay().

Lo mas conveniente es usar interrupciones. Te dirá con facilidad cada 10 mseg que tienes presencia de AC.
Simple, mucho mas simple que tener algo con un RC que te dice que hay o no.

Ahora si necesitas las interrupciones para otra cosa, es otra cuestión.

Gracias por la respuesta,

Aunque antes de abrir un nuevo hilo, me atrevo a preguntar aqui...

Con esta configuración y un debounce de 2 segundos (ya me recomendaste una librería por el hilo que abrir yo)
funcionaria? o el pase por cero del optoacoplador, por ese instante cambiaría el estado de la entrada cada 10 mseg y nunca se cumpliría el debounce de 2 seg?

gracias

En que necesitas un debounce de 2 seg? Es una locura!!! Nada rebota x 2 segundos.

Mas alla de eso, la respuesta hay que darla mirando la librería, si el debounce de la librería esta hecho con millis() no pasará nada y ambos funcionarían.
Si usa delay() por supuesto que no va a funcionar.

Casi te aseguro que usa millisl(), asi que no deberíá fallar.

NOTA: Movido de un hilo de Hardware
Acabo de percatarme de algo: El hilo no es tuyo, de modo que estas desviando el tema principal a una consulta que debiste hacer en tu hilo.
Voy a mover esta consulta a tu hilo MigGo

2da falta, tienes un hilo abierto en el foro en inglés con el mismo tema que este.
Eso es doble posteo.
Decide cual queda aquel o este porque no se permiten ambos.
Acá el hilo:
Funtion to Debounce varios Digital Inputs

surbyte:
En que necesitas un debounce de 2 seg? Es una locura!!! Nada rebota x 2 segundos.

Mas alla de eso, la respuesta hay que darla mirando la librería, si el debounce de la librería esta hecho con millis() no pasará nada y ambos funcionarían.
Si usa delay() por supuesto que no va a funcionar.

Casi te aseguro que usa millisl(), asi que no deberíá fallar.

NOTA: Movido de un hilo de Hardware
Acabo de percatarme de algo: El hilo no es tuyo, de modo que estas desviando el tema principal a una consulta que debiste hacer en tu hilo.
Voy a mover esta consulta a tu hilo MigGo

Los presostatos tienden a rebotar cuando tienen algo de desgaste o suciedad (calcificacion, cal del agua) en el diafragma o por la contrapresion de un pulmón neumático.

No es que la señal rebota durante dos segundos, es que puede haber un rebote justo después de llegar a la presión de parada de bomba, por eso usar un debounce de 2 seg. Así se evita que una bomba puede encender en falso.

Es una practica bastante común en el mundo del PLC y automatización industrial.

Mil disulpas por hacer dos hilos, aquel era de hardware y este fue de software... pero igual mil disculpas.

surbyte:
2da falta, tienes un hilo abierto en el foro en inglés con el mismo tema que este.
Eso es doble posteo.
Decide cual queda aquel o este porque no se permiten ambos.
Acá el hilo:
Funtion to Debounce varios Digital Inputs

No sabia que no podia abrir temas en varios idiomas... La verdad que no lo vi en las reglas del forum.

Acabo de verificar la librería Bounce2 y usa millis() como supuse.. de modo que no tendras problemas.

surbyte:
Acabo de verificar la librería Bounce2 y usa millis() como supuse.. de modo que no tendras problemas.

Mcuhas gracias por responder...
y disulpa si de nuevo pregunto, pero no se si realmente te llego mi pregunta.

Yo no quiero detectar el cruce por cero, mas bien mi preocupación es el cruce por cero.

Si requiero que las señales de entrada se mantengan por 2 segundos para tomarlas como validas, el cruce por cero que se hace cada 10 mseg, me afectara?

Muchas gracias

Sigues sin entender que es millis(), pues ve a
Ve a Documentación => Indice de temas tutoriales => Millis() y estudia millis().

No pierdes 2 seg para luego ver el evento de cruce por cero y si te preocupa perderlo usa interrupciones.

surbyte:
Sigues sin entender que es millis(), pues ve a
Ve a Documentación => Indice de temas tutoriales => Millis() y estudia millis().

No pierdes 2 seg para luego ver el evento de cruce por cero y si te preocupa perderlo usa interrupciones.

Disculpa.. ya veo que tendré que ir a otro lado con mi duda.

Ya que veo que no se me entiende...

Muchas gracias por la ayuda.

No entiendo que es lo que no entiendes?
Dices trabajar con PLC y no sabes lo que haces millis() te envié a Documentación para que te informes.
Millis() devuelve el tiempo desde que arduino se energizó.
De modo que todo lo que use millis() no insume tiempo, no detiene el procesador.
Si tienes algo que establece un debounce de 2 segundos, puede hacer 100tos de tareas mas en menos tiempo, y entre ellas estar atento a una detección de cruce por cero.

Te lo he respondido muchas veces.

El cruce por cero genera un pulso corto, pero si pierdes dicho pulso (ahora hablo del pulso que puede durar algunos microsegundos) entonces puedes usar interrupciones.
Una interrupción se acciona con un flanco por ejemplo indicandote que hubo detección de cruce por cero y eso no afectará tu debounce ni nada. Activas un flag, lo chequeas en tu código y lo borras para la nueva interrupción y listo.
Sabes si hubo o no deteccion de cruce x cero.

Si no lo comprendes te dejo este link arduino AC Phase Control

surbyte:
No entiendo que es lo que no entiendes?

Y no crees que eso era realmente lo que tenias que preguntar? en vez de mandar la documentacion de la funciona millis (que la habia usado en el codigo, que yo mismo publique?

surbyte:
Dices trabajar con PLC y no sabes lo que haces millis()

Y tu has trabajado con PLCs? En todos los PLC las funciones de tiempo se hacen con temporizadores**, (y segun el modelo o marca, tienen su precisión) la funcion millis() no existe en los PLC (Si acaso se puede leer el registro interno del reloj del CPU, Algo que solo se usa para cosa muy muy especificas) Si quisiera saber el tiempo que un PLC llevar energizado, lo haria con un temporizador de un segundo, que de una senal de contacto de flanco de subida a un contador.

**Para funciones de tiempo y altas velocidades, como por ejemplo leer un encoder de 12000 ppr, es necesario modulos de entradas de alta velocidad y hacer funciones especificas, algunas marcas ya tienen desarrollado unos bloques en el ladder para estos casos (HSC High Speed Counters y son tan especifcos que son limitados segun el modelo del PLC). O realizar una funcion de continua lectura para nunca perder el conteo del tiempo (esto si lo debe de realizar a mano el programador)

surbyte:
Te lo he respondido muchas veces.

Lo que tu crees que entendiste de la pregunta y hasta de mala manera.

surbyte:
El cruce por cero genera un pulso corto, pero si pierdes dicho pulso (ahora hablo del pulso que puede durar algunos microsegundos) entonces puedes usar interrupciones.
Una interrupción se acciona con un flanco por ejemplo indicandote que hubo detección de cruce por cero y eso no afectará tu debounce ni nada. Activas un flag, lo chequeas en tu código y lo borras para la nueva interrupción y listo.
Sabes si hubo o no detección de cruce x cero.

Aquí esta la evidencia que nunca entendiste mi pregunta.... sigues hablando sobre la deteccion del pase por cero, interrupciones, etc....

Cuando toda mi pregunta era si el cruce por cero, me afectaría en la detección de una entrada

Y si.. ese pulso de algunos microsegundos, si afecta cambia el estado de la entrada y el código lo detecta, asi que la funcion del debounce nunca se iba a cumplir...

Aun estoy en la espera del pedido de los optoacopladores, pero realice una simulación con el proteus y el código, y no hace una detección correcta de la señal 220VAc

Es necesario hacer un debounce por hardware con un circuito R/C, para suavizar la señal de la salida del optoacoplador.

Cuando tenga los optoacopladores, y haga la prueba en fisico con el condensador, posteare (si aun puedo, Si no has borrado este post o me hayas baneado) todo el circuito y el codigo, para que alguien mas le sirva.

Saludos y muchas gracias por tu ayuda!!!

Y tu has trabajado con PLCs? En todos los PLC las funciones de tiempo se hacen con temporizadores

Trabaje con KOYO de Automation Direct, trabajé con ABB en YPF, con MODICOM en Tecpetrol. Y solo una vez con un S7 de Siemens.
Tengo mas de 400 equipos vendidos a PAN AMERICAN Energy, Tecpetrol e YPF Argentina usando KOYO DL06 de Automation Direct controlando una dosificadora de productos químicos. Midiendo nivel de un tanque de producto quimico usando una regla MTS precisión 0.5mm. Controlando la velocidad de un variador Danfoss que a su vez ajustaba la velocidad de una dosificadora Dosivac.
Los datos se envian por telemetria via MDS al centro SCADA de PAN AMERICAN Energy en la fase 2-3-4 de Electrificación de pozos petroleros, luego eliminaron a todos los locales (me incluyo) por gente de Buenos Aires.

Eso para responder si trabajé con PLCs.

Por lo demás, dejo que otro te responda.