Alarma Temporizada [Solucionado]

Estimado, soy nuevo en este ambiente, aunque conozco de electronica /PLC / programacion soy novato con arduino.

Mi problematica es la siguiente, necesito medir la disponibilidad de 4 entradas, si cualquiera de estas 4 entradas pasa de 1 a 0 automáticamente empieza un timer de 10 minutos a contar, al cabo de los 10 minutos si esa entrada o cualquiera sigue en 0 debo activar una salida. Si en el transcurso de esos 10 minutos la o las entradas que estaban en 0 pasan a 1, el timer se resetea vuelve a esperar que alguna entrada caiga para volver a empezar a contar.

Para los que comprenden programación en bloque serian las 4 entradas con un AND y luego con un tempo con retardo a la desconexion que active una salida luego de un cierto tiempo

Espero haber podido explicarme.

Gracias de antemano por la ayuda.

Saludos

Parece factible pero la filosofia del foro es que interesado suba el sketch con lo que lleva hecho y plantee dudas concretas de la parte que no le sale ,es decir ,que ha intentado hacer algo....si no tienes idea ni por donde empezar ,quizas deberias hechar un ojo a algun buen manual del apartado documentacion.necesitaras hecharle un ojo al condicional if y la funcion digitalRead para consultar el estado de los pines y comprobar si estan en1 o 0 .si tienes alguna entrada en 0 necesitaras una variable booleana que pondras a true para indicar que se empieza un contaje de tiempo ,esta variable se pondra a false en el momento que todas las entradas esten a 1.para el contaje almacenas el valor de la funcion millis() que indica el tiempo que lleva el sketch funcionando ,si comparas el valor guardado con actual ,puedes obtener el tiempo transcurrido. Puedes obtener informacion tambien de funciones y comandos en el apartado learning->reference de esta misma web

Una ayudita aunque jose tiene razón 100%

const byte ledPin1 = 10;
const byte ledPin2 = 11;
// define el resto de las salidas

const byte inputPin1 = 2; // pulsador 1
const byte inputPin2 = 3; // pulsador 2
// define el resto de las entradas
byte p1, p1Ant;
byte p2, p2Ant;
// define el resto de las variables de estado de los pulsadores

void setup() {

 pinMode(ledPin1, OUTPUT);
 pinMode(ledPin2, OUTPUT);

 pinMode(inputPin1, INPUT); 
 pinMode(inputPin2, INPUT);
}

void loop(){
 p1=digitalRead(inputPin1);
 p2=digitalRead(inputPin2);

 if (p1 == LOW && p1Ant == HIGH) {
 // Activo p1

 }

 p1Ant = p1;

 if (p2 == LOW && p2Ant == HIGH){
 // Accion p2
 }

 p2Ant = p2;
}

Aca lo ves para dos entradas. Para la parte del timer, te recomiendo veas el ejemplo del IDE BlinkWithoutDelay o el tutorial millis() hecho por Max_saeta que encuentras en DOCUMENTACION.

Gracias por las respuestas, tengo algo armado, con estos datos voy a tratar de solucionarlos y si vuelvo a atrancar tendran mi pregunta por aqui.

Saludos

Estimados creo que he encontrado una solución o así lo parece, repito soy nuevo en esto pueden encontrar algun error o algo para mejorar (por favor díganmelo)

int FaseR = 4;
int FaseS = 5;
int FaseT = 6;
int Neut = 7;
int Rele = 13;
long Inicio;
long Fin;
long Espera;




void setup() {
 Serial.begin(9600); // put your setup code here, to run once:

pinMode(FaseR,INPUT);
pinMode(FaseS,INPUT);
pinMode(FaseT,INPUT);
pinMode(Neut,INPUT);
pinMode(Rele, OUTPUT);


}

void loop() {
Espera=Inicio-Fin;
  
 int EstadoFaseR = digitalRead (FaseR);
  
 Serial.println(EstadoFaseR);

  int EstadoFaseS = digitalRead (FaseS);
  
 Serial.println(EstadoFaseS);

  int EstadoFaseT = digitalRead (FaseT);

  Serial.println(EstadoFaseT);

   int EstadoNeut = digitalRead (Neut);
  
 Serial.println(EstadoNeut);

 delay(1000);


 if (EstadoFaseR == LOW)
 {
  Inicio=millis();
 }
 else 
 {
  Fin=millis();
 }


 Serial.print("Tiempo Espera: ");
   Serial.println(Espera/1000);

 if (Espera/1000>10)
 {
  digitalWrite (Rele,HIGH);
 }
  else 
  {
    digitalWrite (Rele,LOW);
  }
  
 }

Todavia no lo he terminado para todas las variables, lo estoy probando para FaseR, pero va a ser similar para la demas variables, tambien estoy encendiendo el pin 13 para poder ver el resultado (luego va a ser un rele NC), en este caso deje un tiempo de espera de 10 segundos.La unica duda que me queda es que ESPERA cuando las entradas estan en 1 cuenta negativo, esto traera algun inconveniente?

Desde ya espero sus comentarios.

Saludos y muchas gracias

el código que presentas puede llegar a funcionar pero lo que no entiendo es que te esta dando el valor LOW HIGH de fase R porque no lo has explicado.
Si es un RELE supongo que tienes conectado una resistencia PULL DOWN de al menos 10k a masa.
Luego la parte que inicializa Incio y Fin no se a que responde.

Mi problematica es la siguiente, necesito medir la disponibilidad de 4 entradas, si cualquiera de estas 4 entradas pasa de 1 a 0 automáticamente empieza un timer de 10 minutos a contar

En tu código lees un 0 e inicias el contador y cuando llegue a HIGH detienes el mismo.
No veo que tiene que ver con el arranque del timer que tu mismo describiste.

surbyte: el código que presentas puede llegar a funcionar pero lo que no entiendo es que te esta dando el valor LOW HIGH de fase R porque no lo has explicado. Si es un RELE supongo que tienes conectado una resistencia PULL DOWN de al menos 10k a masa. Luego la parte que inicializa Incio y Fin no se a que responde. En tu código lees un 0 e inicias el contador y cuando llegue a HIGH detienes el mismo. No veo que tiene que ver con el arranque del timer que tu mismo describiste.

Perdon por no haber explicado correctamente,

Los input FaseR, FaseT, FaseS son reles que estan acoplados a lineas de tension domiciliaria, cada rele por fase. O sea que si se corta la electricidad o alguna fase el rele se corta (pasan de 1 a 0). A estos reles los tengo alimentados con una tension de 12V (con una bateria de respaldo para cuando la electricidad se va) . Por eso los INPUT pasan de 1 a 0 cuando se corta la electricidad en todas las fases o en alguna.

El porq del sistema?

En este momento tengo una alarma q me avisa con SMS a mi telefono cuando se corta la electricidad. La alarma esta acoplada directamente a un rele sobre las lineas de tension. El problema yace que en mi ciudad existen muchos microcortes de luz, entonces la alarme se vuelve loca y me envia 50 sms en cuestion de minutos. Este sistema esperaria un tiempo para avisar a la alarma que realmente esta una o varias fases cortada y enviaria 1 sms luego de x minutos de corte.

Espero haberme explicado.

Saludos y gracias

he hecho algo rapido ,a ver si puede valer.como veras he prescindido del rele de neutro,no se donde vives ,pero en españa no tendria sentido (modificalo si no),pues tenemos dos tipos de voltaje , trifasica a 380 y si falla el neutro caerian todos los reles o trifasica a 220 ,donde no se usa el neutro.acuerdate de las resistencias pulldown en las entradas.falta algun detalle ,como poner alguna linea para apagar el led 13 una vez pasado el tiempo y algo mas.no entiendo lo del rele con bateria por si se va la luz,si se va la luz y sigues alimentando los reles con bateria no sabras si se ha ido la corriente o no.yo los reles solo los alimentaria con las fases que quieras controlar y el arduino ,si con bateria.

#define TIEMPO 600000  // 10 minutos = 600000 milisegundos
#define FaseR 4
#define FaseS 5
#define FaseT 6
#define Rele 13
boolean tempAct = false; 
unsigned long tInicio;
int estado;
void setup(){
  Serial.begin(9600);
  pinMode(Rele, OUTPUT); // El resto de pines son input y por defecto 
                         //arduino los define como imput ,no hace falta definirlos  
}
void loop(){
  estado = digitalRead(FaseR) && digitalRead(FaseS) && digitalRead(FaseT);
  if (estado){
    Serial.println("Fases correctas");
    tempAct = false;
  } 
  else if (tempAct){
    if (millis() - tInicio > TIEMPO){
      Serial.println("Superado tiempo");
      digitalWrite(Rele,HIGH);
    } 
  }
  else {
      tInicio = millis();
      tempAct = true;
      Serial.println("Empezando temporizacion");
  }  
}

Estimado Jose,

su programa me ha servido para mejorar mi miprogamacion, voy a tratar de explicarme algo mejor porq veo q aun no me comprenden. Lo que necesitaria agregarle es que si todas las entradas vuelven a 1 el contador se resetee.

Aqui en Argentina la red de energia electrica es trifasica (R,S,T) mas Neutro (N). Entre Fases la tension es 380V, entre fase y neutro la tension es 220V. Tienes razon que no es necesario controlar el Neutro, ya que controlando las 3 fases contra el neutro detectariamos las fallas.

En mi sistema tengo conectado 3 reles uno para cada fase (de 220V en la parte de comado del rele, o sea, que si la fase esta conectada el rele esta activo NC - en la parte de señal llamemosla tengo conectado 12Vcc que luego del rele entrara al arduino como entrada. Resumiendo si la fase o fases estan activas el o los reles envian 12Vcc al arduino).

Para el Arduino, necesito controlar las 3 señales (Fases R,S,T) porque suele ocurrir que se cae una o dos fases solamente afectando a los equipos trifasicos que tengo en mi planta, aparte de los microcortes mencionados que tambien pueden darse en una, dos o las tres fases.

La salida arduino pin 13 solamente es para ensayar el programa una vez logrado y funcionando esta salida activara un rele de una alarma como ya explique.

Espero esta vez se haya entendido.

Saludos y mil gracias por las respuestas

Podrías hacer un simple detector de cruce por cero para cada Fase contra Neutro como este (ver parte de abajo del esquema) |500x272

Cada fase te dará una interrupción con cada semionda de la fase correspondiente. puedes usar una ISR para detectarlo, unir si quieres todos los colectores de los optos a 5V y los emisores a una resistencia común que disparará la interrupción. La interrupción debería ocurrir cada x mseg. Ahora no me acuerdo cada cuanto ocurre en una trifásica

void setup()  
{
  Serial.begin(9600);

  attachInterrupt(0, setAC, RISING);  // Interupcion al pin2 (interupt 0) para detección Cruce por Zero
}

void setAC()  // Se dispara con el cruce por cero
{
    // idear junto con un timer la forma de contar los pulsos 
}

void loop()
{

}

el sketch que puse se resetea en el momento que las tres entradas estan a 1,unicamente hay que añadir una linea para apagar el rele ,si estuviese encendido:

else {
      tInicio = millis();
      tempAct = true;
      Serial.println("Empezando temporizacion");
      if (digitalRead(Rele) == HIGH) digitalWrite(Rele,LOW);// añadir esto
  }

Si quieres controlar que fase es la que falla ,usa 3 variables de estado en vez de una,como te puso surbyte en su sketch . el tema de los reles ,seria mas facil si por los contactos pasases un positivo de 5v que vendria del pin 5v del arduino ,asi no tendrias que rebajar esos 12v a 5v para conectarlos a las entradas .comentas la conexion nc ,pero en realidad la conexion seria entre los contactos comun y na ,es decir normalmente abierto ya que en las conexiones de reles se tiene en cuenta el estado del rele cuando su bobina esta en reposo o sin excitar (una conexion comun y nc ,con la bobina sin excitar estaria llegando señal).

Bueno, al final de cuentas pude resolver el problema, lo simplifique a 2 señales de entrada, ya que tomo dos reles para controlar las tres fases y el neutro, un rele de 220V que toma una fase y el neutro y un rele de 380V que toma las otras fases. Por lo tanto con dos reles puedo controlar todo.

Dejo el codigo final con un delay de espera de 10 segundos. Muchas gracias por la ayuda.

int Fase1 = 4;
int Fase2 = 5;
int Rele = 13;
long Inicio;
long Fin;
long Espera;


void setup() {
 Serial.begin(9600); 

pinMode(Fase1,INPUT);
pinMode(Fase2,INPUT);
pinMode(Rele, OUTPUT);


}

void loop() {
Espera=Inicio-Fin;
  
 int EstadoFase1 = digitalRead (Fase1);

int EstadoFase2 = digitalRead (Fase2);
  
 Serial.println(EstadoFase1);
 Serial.println(EstadoFase2);

  

 delay(1000);


 if (EstadoFase1 == 0 || EstadoFase2 == 0 )// Funcion OR para ver estado de fases
 {
  Inicio=millis(); // Inicio Tiempo
 }
 else 
 {
  Fin=millis();
 }


 Serial.print("Tiempo Espera: ");
   Serial.println(Espera/1000);

 if (Espera/1000>10) // Tiempo Espera 10 segundos en este caso 
 {
  digitalWrite (Rele,HIGH);
 }
  else 
  {
    digitalWrite (Rele,LOW);
  }
  
 }