Como hacer un sistema para corte de agua [SOLUCIONADO]

Hola a todos

Me gustaría hacer un sistema de corte de agua,

La idea es que un sensor de flujo de pulsos cuando detecte el movimiento de agua se ponga a contar el tiempo, cuando este tiempo> x se active un rele

No tengo mucha idea de programación

Gracias por vuestra ayuda

Lee las Normas del foro.

Edita el post para que el código luzca como todo el foro en Español.

Gracias por responder,

Esto es lo que tengo hecho (lo he copiado y modificado) , pero no me termina de funcionar

volatile int NumPulsos; //variable para la cantidad de pulsos recibidos
int PinSensor=3;    //Sensor conectado en el pin 3
int TiempoFuga=4000; //Tiempo de fuga es de 4 segundos
long TiempoAgua=0;
long dt=0; //variacion de tiempo por cada bucle
long t0=0; // del bucle anterior
int rele1=24;
unsigned long  tnow=millis();

//---Funcion que se ejecuta en interrupcion---------------
void ContarPulsos ()  
     { NumPulsos++; } //incrementamos la variable de pulsos

void setup() 
{ 
  Serial.begin(9600); 
  pinMode(PinSensor, INPUT);
  pinMode(rele1,OUTPUT);
  attachInterrupt(1,ContarPulsos,RISING);//(Interrupcion 1(Pin3),funcion,Flanco de subida) int 0 pin2; int
  t0=millis();
} 

void loop ()    
{
  dt=millis()-t0; //calculamos la variacion de tiempo
  t0=millis();
if(ContarPulsos >0){
 if((tnow-TiempoAgua)>TiempoFuga){
  digitalWrite(rele1,HIGH);  //Activamos la bobina del relé 
  delay(1000);               //durante 1 segundo
  digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé
  delay(1000);               //durante 1 segundos
}}
else(TiempoAgua=tnow);//Si no se mueve el agua actualizamos el tiempo
}

No lo había puesto por si otra persona tenía otra opción (siempre es bueno tener una segunda opción)

Gracias

Puedes explicar que hace esto

void loop ()    
{
  dt=millis()-t0; //calculamos la variacion de tiempo
  t0=millis();
if(ContarPulsos >0){
 if((tnow-TiempoAgua)>TiempoFuga){
  digitalWrite(rele1,HIGH);  //Activamos la bobina del relé 
  delay(1000);               //durante 1 segundo
  digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé
  delay(1000);               //durante 1 segundos
}}
else(TiempoAgua=tnow);//Si no se mueve el agua actualizamos el tiempo
}

Jamas tnow que se supone es millis() se entera del tiempo porque al modificarlo cambiaste cosas importantes.
Si usas t0 entonces sigue con t0 y no lo llames luego tnow.

Gracias por responder,

He hecho unos cambios( El Sensor de flujo es de tipo YF-S201, pero solo quiero detectar el inicio del movimiento del agua. Cuando inicia el movimiento la señal baja el voltaje hasta 2.7 V)

int TiempoFuga=3000; //Tiempo de fuga es de 3 segundos
long MovimientoAgua=0;
float Sensor;
int rele1=24;


void setup() 
{ 
  Serial.begin(9600); 
  pinMode(rele1,OUTPUT);
 } 

void loop ()    
{
  Sensor = analogRead(A0);
if(Sensor<950 && Sensor>500){ 
    MovimientoAgua=millis();{
 if(MovimientoAgua>TiempoFuga){
  digitalWrite(rele1,HIGH);  //Activamos la bobina del relé 
  delay(1000);               //durante 1 segundo
  digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé
 
}}}
else(MovimientoAgua=0);//Si no se mueve el agua actualizamos el tiempo
 digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé
}

Pero sigue sin funcionar

Que hago mal?

Gracias

He hecho unos cambios( El Sensor de flujo es de tipo YF-S201, pero solo quiero detectar el inicio del movimiento del agua. Cuando inicia el movimiento la señal baja el voltaje hasta 2.7 V)

Son pulsos, no puedes medir pulsos con un tester. Si los pulsos son tales que su valor medio sea 2.7V eso leerás.

Gracias, es cierto el multímetro me daba un valor irreal

Ahora lo estoy intentando con interrupciones, pero sigue sin funcionar

  int sensor = 3; // Pin digital para el sensor 3
  volatile int pulsos = 0; // Variable que almacena el número de pulsos
  long tiempoMovimiento = 0; // Variable para calcular el tiempo transcurrido 
  int tiempoFuga=5000; //Tiempo de fuga es de 5 segundos
  int rele1=24;
  
  void flujo() 
  { pulsos++; }// Incrementa en una unidad el número de pulsos
     
  void setup()
  {
    pinMode(sensor, INPUT); // Pin digital 
    interrupts(); // Habilito las interrupciones
    attachInterrupt(1, flujo, RISING);  // Interrupción "flujo"  en el pin digital 3
  }
   
  void loop ()
  {
    if (flujo>5){
       tiempoMovimiento = millis(); // Inicio el tiempo
    if( tiempoMovimiento > tiempoFuga)
    {
  digitalWrite(rele1,HIGH);  //Activamos la bobina del relé 
  delay(1000);               //durante 1 segundo
  digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé
}}
else(tiempoMovimiento=0);{//Si no se mueve el agua actualizamos el tiempo
 digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé
}  }

Gracais x todo

Tu código tiene muchos errores. Usas la interrupción pero no la desactivas ni reactivas jamás.
todo lo que esta luego del else esta mal, etc etc

Mira este hilo donde corrijo un problema similar y quedó resuelto

Medir litros requeridos con caudalimetro

En este caso el valor limite se ingresapor teclado Serie

SePointVolumen es la variable.

Gracias x contestar, pero sigue sin funcionar,

Cuando se detiene el caudalímetro los pulsos no se resetean
Cuando le mando el programa al Mega el rele se queda abierto
Cuando se alcanza el tiempo de fuga el rele hace 2 ciclos(solo se tiene que hacer un ciclo)

const int sensor    =3;      // Pin digital para el sensor de flujo
volatile int pulsos = 0;      // Variable que almacena el número de pulsos
unsigned long tiempoMovimiento= 0; // Variable para el tiempo transcurridos
int rele1=24;
int tiempoFuga=5000; //Tiempo de fuga es de 5 segundos
 
// Rutina de servicio de la interrupción (ISR)
void flujo() 
{  pulsos++;} // Incrementa en una unidad el número de pulsos

void setup() {
  Serial.begin(9600);
  pinMode(rele1,OUTPUT); // Pin  salida
  pinMode(sensor, INPUT_PULLUP); // Pin digital como entrada con conexión PULL-UP interna
  interrupts(); // Habilito las interrupciones
  attachInterrupt(digitalPinToInterrupt(sensor), flujo, RISING);  
 }
 
void loop () {
  if (pulsos>0) {
     tiempoMovimiento = millis(); // Guardo el tiempo de movimiento de agua
  if (millis() > tiempoFuga) {// Si el tiempo de movimiento >que tiempoFuga
    
         digitalWrite(rele1,HIGH);  //Activamos la bobina del relé 
         delay(1000);               //durante 1 segundo
         digitalWrite(rele1,LOW);   //Desactivamos la bobina del relé // 
           
          Serial.println("Cerrar válvula.");
          Serial.print("Se ha alcanzado el limite de tiempo : ");
          Serial.println(tiempoMovimiento);
      }
      else 
          Serial.println(tiempoMovimiento);
          Serial.print("Correcto : ");
      pulsos =0; // Pongo nuevamente el número de pulsos a cero
      tiempoMovimiento = millis(); // Actualizo el nuevo tiempo
  }

}

Gracias por tu ayuda

Ese código y el que te puse esta mal ahora que me doy cuenta porque la interrupcion debe detenerse para hacer las lecturas y en los dos códigos eso no pasa.

Y ademas copiaste todo con esto

 if (pulsos>0) {
     tiempoMovimiento = millis(); // Guardo el tiempo de movimiento de agua

pero no cerraste la llave y arrastra el resto del código.
Además no se para que usas esa consulta?

Mas tarde te lo corrijo, pero solo eso corregiré lo de la interrupción. El resto lo dejo para que lo pienses tu.

Gracias,

La idea es si se detecta movimiento de agua (pulsos>0) se empiece a contar el tiempo y cuando este tiempo >de tiempoFuga se activen los reles

Lo ideal para un detector de fugas es hacerlo por tiempo, pero si me da muchos problemas lo haré por litros

La idea es si se detecta movimiento de agua (pulsos>0) se empiece a contar el tiempo y cuando este tiempo >de tiempoFuga se activen los reles

Lo que planteas no tiene sentido porque tu sistema sigue contando siempre porque nunca bloqueas las interrupciones.

Para que activas 1 segundo y luego paras?

Este código funcionará para tu caudalímetro y marcará 0 cuando este detenido.
De aqui en adelante lo sigues tu.

unsigned long tiempoMovimiento = 0; // Variable para el tiempo transcurridos
unsigned long tiempoFuga       = 5000; //Tiempo de fuga es de 5 segundos

const int sensorPin           = 3;    // Pin digital para el sensor de flujo
const int measureInterval     = 2500;
volatile int pulseConter;
 
// YF-S201
const float factorK = 7.5;
 
float volume = 0;
long t0 = 0;
 
void ISRCountPulse() {
   pulseConter++;
}
 
float GetFrequency() {
   pulseConter = 0;
 
   interrupts();
   delay(measureInterval);
   noInterrupts();
 
   return (float)pulseConter * 1000 / measureInterval;
}
 
void SumVolume(float dV)
{
   volume += dV / 60 * (millis() - t0) / 1000.0;
   t0 = millis();
}
 
void setup() {
   Serial.begin(9600);
   attachInterrupt(digitalPinToInterrupt(1), ISRCountPulse, RISING);
   t0 = millis();
}
 
void loop() {
   // obtener frecuencia en Hz
   float frequency = GetFrequency();
 
   // calcular caudal L/min
   float flow_Lmin = frequency / factorK;
   SumVolume(flow_Lmin);
 
   Serial.print(" Caudal: ");
   Serial.print(flow_Lmin, 3);
   Serial.print(" (L/min)\tConsumo:");
   Serial.print(volume, 1);
   Serial.println(" (L)");
}

sino puedes usar este codigo

const int rele = 2;   //establesco pines
const int sensor = 3;
int state;   //variable que ocupa el estado del sensor 
int tiempoespera = 1000;   //establesco tiempo de espera 1sec
int tiemporele = 1000;   //establesco tiempo de rele encendido 1sec

void setup() {
  pinMode(rele, OUTPUT);   //explico que rele es salida
}
void loop() {
  state = digitalRead(sensor);   //guardo el estado del sensor

  while(state == LOW) {   //while- mientras no pase agua seguira atrapado el programa
    state = digitalRead(sensor);   //actualiso el estado del sensor   
  }
  delay(tiempoespera);   //el tiempo que pasa entre la primera señal de paso de agua a que se activa el rele
  digitalWrite(rele, HIGH);   //activo rele
  delay(tiemporele);   //tiempo del rele encendido
  digitalWrite(rele, LOW);   //apago el rele
}

PD: no tiene los pulsos que antes usabas porque como es un sensor de onda cuadrada solo tiene los valores HIGH y LOW por lo que al primer HIGH por el paso de agua correra el resto del programa
deberia servir

Gracias x responder,

No funciona, el sensor es un imán que cuando hace contacto manda los 5v y cuando no hace contacto manda 0v, hay veces que se queda de una manera o de otra

Y el que te di yo mide caudal o no mide, verifica los pines del caudalímetro. Tal vez no se correspondan con el tuyo.

Medirá caudal y luego puedes determinar desde ahi si hay agua o no hay.

Gracias Surbyte

Si he cambiado el pin y faltaba en el setup pinMode(sensorPin,INPUT);

Si los l/hora es una media y al detener se resetea

El consumo si que me sirve, porque puedo poner un máximo(ejemplo 1000 litros), pero al detener el agua no se resetea(como lo puedo hacer?)

El sistema que utilizo para cortar el agua es una electroválvula con solenoide lach( se envía un pulso con una polaridad(max 30 DC) y se abre. se envía la polaridad invertida y se cierra). Este sistema soporta muy bien el la humedad

Como al detener el agua no se resetea.
Yo creo que tu confundes cosas.
Una cosa es caudal instantaneo y otra es volumen acumulado
Que no se resetea?

El consumo se acumula, el caudal instantáneo, no se suma es una media

Caudal: 0.000 (L/min) Consumo:0.0 (L)
Caudal: 10.773 (L/min) Consumo:0.4 (L) Se inicia el movimiento
Caudal: 12.747 (L/min) Consumo:1.0 (L)
Caudal: 12.747 (L/min) Consumo:1.5 (L)
Caudal: 11.253 (L/min) Consumo:2.0 (L)
Caudal: 0.960 (L/min) Consumo:2.0 (L)
Caudal: 0.000 (L/min) Consumo:2.0 (L)se detiene el movimiento
Caudal: 0.000 (L/min) Consumo:2.0 (L)

Se detiene movimiento y que dice
Caudal 0

Consumo 2.0 litros
Si quieres ahi resetea tu consumo.

No comprendo que no entiendes.

Caudal son litros/unidad de tiempo y consumo en ESTE CASO acumula todo lo consumido.
lo quieres resetear cada vez que caudal diga 0.0 pues resetealo.

Te dije antes en el post#12

Este código funcionará para tu caudalímetro y marcará 0 cuando este detenido.
De aqui en adelante lo sigues tu.

De ahi en adelante lo sigues tu es lo que estas preguntando 1 y otra vez.

Ahora tienes algo que te dice 0.0 L/min, aplica entonces si caudal es 0.0 o sea que no tienes agua circulando y entonces todo lo demas o sea pon en 0.0 el volumen acumulado, inicia tu tiempo y bla bla bla.

Es solo que tienes que experimentar un poco y entender lo que estas haciendo y no compiar como loco todo lo que ves x internet.

Se que no sabes, y lo dejaste claro al comienzo, pero es bueno leer un poco y entender lo que se pretende hacer.

Gracias por tu ayuda, empezar siempre cuesta

Ya funciona :slight_smile: :slight_smile: , lo único es que el relé está siempre activado

float volumenMaximo = 2; //caudal maximo 1000 litros
const int sensorPin = 3;    // Pin digital para el sensor de flujo
const int measureInterval = 2000;
int rele=24;
volatile int pulseConter;
const float factorK = 5.5; // YF-S201
float volumen = 0;
long t0 = 0;
 
void ISRCountPulse() {
   pulseConter++;
}
 
float GetFrequency() {
   pulseConter = 0;
 
   interrupts();
   delay(measureInterval);
   noInterrupts();
   return (float)pulseConter * 1000 / measureInterval;
}
 
void SumVolume(float dV)
{
   volumen += dV / 60 * (millis() - t0) / 1000.0;
   t0 = millis();
}
 
void setup() {
   Serial.begin(9600);
   pinMode(sensorPin,INPUT);
   pinMode(rele,OUTPUT);
   attachInterrupt(digitalPinToInterrupt(sensorPin), ISRCountPulse, RISING);
   t0 = millis();
  }
 
void loop() {
   
   float frequency = GetFrequency();// obtener frecuencia en Hz
   float flow_Lmin = frequency / factorK;// calcular caudal L/min
   SumVolume(flow_Lmin);
 
   Serial.print(" Caudal: ");
   Serial.print(flow_Lmin,1);
   Serial.print(" (L/min)\tConsumo:");
   Serial.print(volumen,1);
   Serial.println(" (L)");

    if (volumen >volumenMaximo){
         digitalWrite(rele,HIGH);  //Activamos la bobina del relé 
         delay(1000);               //durante 1 segundo
         digitalWrite(rele,LOW);   //Desactivamos la bobina del relé // 
         Serial.println("Cerrar valvula.");
         Serial.print("Se ha alcanzado el limite de tiempo : ");   
         volumen=0;// Se resetea el volumen
    }
else if (flow_Lmin==0){
          volumen=0;// Se resetea el volumen       
} 
}