Tengo un problema con la medición de mi Yf-S201

Hola chicos, muy buenos días, tengo un problema con mi proyecto, estoy realizando un sistema de riego, y sucede que el Sensor de flujo de agua YF-S201, me mide correctamente pero no regresa a 0 cuando deja de pasar agua, siempre queda en algun valor aleatorio menor al que llego a medir. Creo que el problema es en mi codigo, porque lo he probado con otros codigos y si funciona, me he guiado de aquellos para hacer este, pero me da ese error, no consigo donde está el problema. Recurro a ustedes solicitando una ayuda, tengo que entregar el trabajo la proxima semana y ya no encuentro que hacer. Aca mi codigo:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

#define I2C_ADDR 0x27

LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2);

int distance;
int BombRiegoPin = 8;
int HumedadSensor = A0;
int lectura = 0; 
int BombLlenadoPin = 5;
volatile int NumPulsos;
int waterFlowSensorPin = 2;
float factor_conversion = 7.5;

const int ultrasonicTrigPin = 12;
const int ultrasonicEchoPin = 13;

const int nivelMaximoTanque = 3;
const int nivelMinimoTanque = 10;
int porcentajeTanque;

int pantallaActual;
const int cantPantallas = 4;

unsigned long tiempo_previo = 0; // Tiempo previo para el conteo de pulsos
int frecuencia = 0;

void ContarPulsos() {
  if (millis() - tiempo_previo >= 500) {
    frecuencia = NumPulsos; // Guarda los pulsos por segundo en Hz
    NumPulsos = 0; // Reinicia el contador de pulsos
    tiempo_previo = millis(); // Guarda el tiempo actual
  }
  NumPulsos++;
}

int ObtenerFrecuencia() {
  return frecuencia;
}

int calcularPorcentajeTanque(int distancia) {
  // Mapeo la distancia a un porcentaje
  return map(distancia, nivelMinimoTanque, nivelMaximoTanque, 0, 100);
}

void mostrarCaudal() {
  frecuencia = ObtenerFrecuencia();
  float caudal_L_m = frecuencia / factor_conversion; //ecuaciones para calcular el caudal
  float caudal_L_h = caudal_L_m * 60;
  lcd.setCursor(0, 0);
  lcd.print("Caudal: ");
  lcd.print(caudal_L_m, 2);
  lcd.print(" L/m");
}

void mostrarNivelTanque() {
  lcd.setCursor(0, 0);
  lcd.print("Nivel: ");
  lcd.print(porcentajeTanque);
  lcd.print("%");
}

void mostrarEstadoBombas() {
  lcd.setCursor(0, 0);
  lcd.print("Riego: ");
  lcd.print(digitalRead(BombRiegoPin) == LOW ? "ON" : "OFF");
  lcd.setCursor(0, 1);
  lcd.print("Llenado: ");
  lcd.print(digitalRead(BombLlenadoPin) == LOW ? "ON" : "OFF");
}

void mostrarEstadoSuelo() {
  lectura = analogRead(HumedadSensor);
  lcd.setCursor(0, 0);
  lcd.print("Suelo: ");
  if (lectura >= 800) {
    lcd.print("Seco");
  } else if (lectura >= 500) {
    lcd.print("Humedo");
  } else {
    lcd.print("Mojado");
  }
}

void mostrarPantalla(int pantalla) {
  lcd.clear();
  switch (pantalla) {
    case 0: mostrarCaudal(); break;
    case 1: mostrarNivelTanque(); break;
    case 2: mostrarEstadoBombas(); break;
    case 3: mostrarEstadoSuelo(); break;
  }
}

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  pinMode(BombRiegoPin, OUTPUT);
  pinMode(waterFlowSensorPin, INPUT);
  pinMode(BombLlenadoPin, OUTPUT);
  pinMode(ultrasonicTrigPin, OUTPUT);
  pinMode(ultrasonicEchoPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(waterFlowSensorPin), ContarPulsos, RISING); //Uso de la interrupcion con flanco ascendente
}

void loop() {
  int frecuencia = ObtenerFrecuencia(); // Obtener frecuencia una vez
  float caudal_L_m = frecuencia / factor_conversion;
  float caudal_L_h = caudal_L_m * 60;

  Serial.print("FrecuenciaPulsos: ");
  Serial.print(frecuencia, 0);
  Serial.print("Hz\tCaudal: ");
  Serial.print(caudal_L_m, 3);
  Serial.print("L/m\t");
  Serial.print(caudal_L_h, 3);
  Serial.println("L/h");

  digitalWrite(ultrasonicTrigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(ultrasonicTrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(ultrasonicTrigPin, LOW);

  long duration = pulseIn(ultrasonicEchoPin, HIGH);
  distance = duration * 0.034 / 2;

  Serial.print("Distancia: ");
  Serial.print(distance);
  Serial.println(" cm");

  porcentajeTanque = calcularPorcentajeTanque(distance); // Calcular porcentaje del tanque

  Serial.print("Porcentaje del tanque: ");
  Serial.print(porcentajeTanque);
  Serial.println("%");

  lectura = analogRead(HumedadSensor);

  Serial.print("La lectura es:");
  Serial.println(lectura);

  // lecturas entre 300-1023
  if (lectura >= 800) {
    Serial.println(">> SUELO COMPLETAMENTE SECO <<");
  } else if (lectura < 800 && lectura >= 600) {
    Serial.println(">> SUELO LIGERAMENTE HUMEDO <<");
  } else if (lectura < 599 && lectura >= 501) {
    Serial.println(">> SUELO HUMEDO <<");
  } else if (lectura <= 500) {
    Serial.println(">> SUELO MUY MOJADO");
  }

  // Control de la bomba de riego //
  if (lectura >= 600 && distance < 10) { // Se puede regar, porque el tanque esta a un buen nivel
    digitalWrite(BombRiegoPin, LOW); // Enciende la bomba
  } else {
    digitalWrite(BombRiegoPin, HIGH); // Apaga la bomba si no se cumplen las condiciones
  }

  // Control de la bomba de llenado //
  if (caudal_L_m >= 2.0 && distance > nivelMaximoTanque) { // Se necesita llenar porque esta vacio
    digitalWrite(BombLlenadoPin, LOW); // Enciende la bomba
  } else {
    digitalWrite(BombLlenadoPin, HIGH); // Apaga la bomba 
  }
  mostrarPantalla(pantallaActual); 

  delay(2000);

  pantallaActual = (pantallaActual + 1) % cantPantallas; // Cambia a la siguiente pantalla

}

Revisa cómo estás manejando la variable "frecuencia". En especial en ObtenerFrecuencia() y dentro de mostrarCaudal()

1 Like

Agregó a lo que bien señala @mancera1979 :

Tienes un problema en ObtenerFrecuencia(), mira

int ObtenerFrecuencia() {
  return frecuencia;
}

Y en mostrarCaudal() haces

frecuencia = ObtenerFrecuencia();

Ahora frecuencia es una variable global, entonces lo que haces es lo mismo que

frecuencia = frecuencia;

porque ObtenerFrecuencia() devuelve el valor de la misma variable (o sea, frecuencia).

Tienes que corregir eso.

1 Like

Lo coloque asi:

int ObtenerFrecuencia() { // 
  int frecuencia = 0; // Inicializa frecuencia dentro de la función
  NumPulsos = 0;
  interrupts();
  delay(1000);
  noInterrupts();
  frecuencia = NumPulsos; // Pulsos por segundo Sensor de flujo
  return frecuencia;
}

void mostrarCaudal() {
  float caudal_L_m = frecuencia / factor_conversion; // Calculo con frecuencia 
  float caudal_L_h = caudal_L_m * 60; // caudal en L/h
  lcd.setCursor(0, 0);
  lcd.print("Caudal");
  lcd.print(caudal_L_m, 2);
  lcd.print("L/m");
  }

pero sigue igual

Intenta modificando la rutina que cuenta los pulsos:

void ContarPulsos() {
  NumPulsos++;
}

y usa la nueva función en mostrarCaudal:

float caudal_L_m = ObtenerFrecuencia / factor_conversion; // Calculo con frecuencia

Toma en cuenta que hay una variable global llamada "frecuencia" y la función ObtenerFrecuencia declara una variable local con el mismo nombre. Estas son dos variables distintas. La que se modifica en esta función es la variable local. La variable global no se modifica.

1 Like