Caudalimetro - interrupts / noInterrupts

Buenas tardes a todos! No soy un gran sabio en todo este tema, pero de momento le estoy encontrando la motivación a este mundo!
Os comento el problema que tengo y aunque he estado buscando por la red información para solucionarlo, he sido incapaz de entender y aplicar, así que no me queda otra salida (a priori) que consultarlo públicamente.

Proyecto: Un sistema que me permita medir un flujo de agua depositado en un recipiente activando una electroválvula que permitirá el paso del el flujo del liquido haciéndolo pasar por el caudalímetro.

Lógica: Cuando el nivel de agua sea X, activar el relé de la electroválvula de 12v para permitir el paso del flujo por el caudalímetro calculando a su vez la cantidad de agua extraída.

Consulta/Problema: He ido incorporando partes del código según me he ido informando de los distintos elementos, con el objetivo de validar las distintas funciones por separado e incorporadas. El punto clave viene en la parte del código para la lectura de los valores del caudalímetro. En este caso, me ayude de la información del portal de Luis Llamas, y aunque su versión literal sobre el caudalímetro funciona de maravilla, al incorporarlo junto al mío llega un punto en que deja de correr.

Después de intentar seccionarlo, he llegado a la conclusión de que el problema proviene en la función de interrupción para el cálculo de L/min, atendiendo a que en esa parte del código se incorporan Interrupts y NoInterrupts.

Aquí es donde me detengo, ya que según he leído creo que entro en "bucle" con un IF de millis() para temporalizar la ejecución de todo el código. Es decir, que por una parte defino una variable como tiempo de espera, mientras que para la función del caudalímetro también se define una variable para el periodo de calculo de flujo.

He probado: tiempoespera < variablecaudalimetro, tiempoespera > variablecaudalimetro, tiempoespera = variablecaudalimetro, y sin poder subsanar el error de "bloqueo". Según he leído, las interrupciones bloquean también las actualizaciones de millis() con lo que, según todo lo que he podido ir probando el problema puede venir en la creación de un lapso de tiempo.

Os dejo el código con la voluntad de poder aclarar este punto del que no he pedido salir.

Agradeceré cualquier aportación que pueda liberarme de este punto sin retorno en el que estoy del mismo modo que de cualquier comentario, observación o aportación para futuros en cuanto a estructura, disposición, ...

gracias de antemano,
saludos!

// C++ code
//

const int Agua = A0;
const int Rele_bomba = 8;
const int Caudalimetro = 2;
byte estado=0;

//variable de tiempo
unsigned long tiempoanterior =0;
unsigned long tiempoahora;
int vt_espera =2400;

int i = 0;  //CONTADOR

//VARIABLES HUMEDAD
int Humedad=0;
float vHumedad=0;

//*****************CAUDALIMETRO **************************
const int measureInterval = 2500;
volatile int pulseConter;

// YF-S201
const float factorK = 7.5;

// FS300A
//const float factorK = 5.5;

// FS400A
//const float factorK = 3.5;

float volume = 0;
long t0 = 0;


void ISRCountPulse()
{
   pulseConter++;
}

float GetFrequency()
{
   pulseConter = 0;

   interrupts();
   delay(measureInterval);
   noInterrupts();

   return (float)pulseConter * 1000 / measureInterval;
}

//***FIN *****************CAUDALIMETRO **************************

void setup()
{
   Serial.begin(9600);
   pinMode(Rele_bomba,OUTPUT);
   pinMode(Caudalimetro,OUTPUT);
   
   digitalWrite(Rele_bomba, LOW);

   attachInterrupt(digitalPinToInterrupt(Caudalimetro), ISRCountPulse, RISING);
}

void loop() 
{
   
float vAgua = analogRead(Agua);

Serial.println ("**************************************");
Serial.println ("           NUEVA LECTURA    ");
Serial.println ("**************************************");
Serial.print(" Estado= ");
Serial.print(estado);
Serial.print(" /  Contador= ");
Serial.println(i);
Serial.print("Humedad =");
Serial.print(vAgua);
Serial.println("%");
 
  if(vAgua >= 250)
  {
      switch (estado)
      {
        case 0:
          Serial.println ("  --> Iniciando....");

          Serial.print(" e= ");
          Serial.print(estado);

          estado = 1;
          break;
        
        case 1:
          digitalWrite(Rele_bomba, HIGH);
          //********************CAUDALIMETRO **************************
          // obtener frecuencia en Hz
          float frequency = GetFrequency();
        

          // calcular caudal L/min
          float flow_Lmin = frequency / factorK;

          Serial.print("Frecuencia: ");
          Serial.print(frequency, 0);
          Serial.print(" (Hz)\tCaudal: ");
          Serial.print(flow_Lmin, 3);
          Serial.println(" (L/min)");
          //***FIN *****************CAUDALIMETRO **************************
         
          estado = 2;
          break;
        case 2:
          Serial.println ("  --> Finalizado.");

          Serial.print(" e= ");
          Serial.print(estado);

          i=i+1;
          estado = 0;
          break;
      }
      
  }
  else
  {
      //Mensaje principal

      Serial.println ("  -->No se han alcanzado valores de nivel de agua");
     
     digitalWrite(Rele_bomba, LOW);

     i=i+1;

     
    
  }
  delay(9000);
}

De donde sacaste este delay()? detienes la ejecución del código por 9 segundos y mientras que estas contando?
cuando se mide caudal o RPM se cuentan pulsos x minuto, pero como no se puede detener por minuto se leen x segundo y se hace la conversión a litros o RPM

Esto esta perfecto

   interrupts();
   delay(measureInterval);
   noInterrupts();

Solo te digo que al final si quieres una pausa para presentar no uses delay() usa millis(). Ve a documentación y estudia como se usa millis() en reemplazo de delay().
Usando millis() el código no se detiene y prestará atención a la rutina de lectura con fluidéz.

Prueba este código solo para asegurarnos

volatile int CantPulsos;	//Variable que acumula los pulsos recibidos
int LxM;			//Variable que acumula el calculo de Litros por Minuto 
int pinsensor = 2;		//Numero de pin donde conectamos el sensor
float FacConv = 7.5; 		//Factor de Conversion para calcular caudal
const int Caudalimetro  = 2;


void rpm ()  {			//Función que se ejecuta durante la interrupción
	CantPulsos++;		//Incrementa el contador de pulsos
} 


void setup() { 
	pinMode(pinsensor, INPUT); 		//inicializa el pin digital 2 como entrada
	Serial.begin(9600); 			//inicializa el puerto serie
 	attachInterrupt(digitalPinToInterrupt(Caudalimetro), rpm, RISING); 	//(Interrupcion 0(Pin2),funcion rpm,Flanco de subida, cuando pasa de LOW a HIGH)
} 


void loop () {
	CantPulsos = 0;      			//Pone en 0 el contador de pulsos
 	Interrupts();            		//Habilitamos las interrupciones, equivalente a sei();
 	delay (1000);      			//Esperamos un segundo
 	noInterrupts();            		//Deshabilitamos las interrupciones, equivalente a cli();
 	LxM = (CantPulsos / FacConv); 		//Calcula los Litros por Minuto 
 	Serial.print (LxM, DEC); 		//Imprime la cantidad de litros por minuto
 	Serial.print (" Litros/min\r\n");		//Imprime "Litros/min" y salta a una nueva linea
}

Por que cambiaste el measureIntervala 2500? si todo es mas simple!!

Hola @Surbyte ! Gracias por tu respuesta!

Disculpa, ese delay fue fruto ya de la desesperación y pruebas que realicé con el fin de poder entender que estaba pasando en mi código y descubrir porqué no funciona.

La verdad es que probé también incorporando milli(). Adjunto el código, incorporé también tu aportación de código. Comentar que el origen del cálculo del código anterior tiene referencia a este link. (supongo que de aquí que estuviese bien :grinning: )

Probé tu código solo y funcionó bien! Mostraba los datos deseados, ahora bien al incorporarlo en el código extenso pasa que:

  1. Ok --> Función millis() y lectura de humedad siempre que [vagua] no supere los 250.
  2. Ok--> Función millis() y lectura de humedad para el SWITCH en CASE 0 y CASE 1.
  3. No OK --> una vez hecho el CASE 1. Allí deja de correr y Serial.print ya no hace nada, si tan solo pasar al CASE 2.

Espero que podáis ayudarme, por más que intento entenderlo no doy con el que está pasando y porqué (aunque tendrá su explicación jejejj)

Gracias,

const int Agua = A0;
const int Rele_bomba = 8;
const int Caudalimetro = 2;
byte estado=0;

//variable de tiempo
unsigned long tiempoanterior =0;
unsigned long tiempoahora;
int vt_espera =3000;

int i = 0;  //CONTADOR

//VARIABLES HUMEDAD
int Humedad=0;
float vHumedad=0;

//*****************CAUDALIMETRO **************************

int LxM; //variable foro

const int measureInterval = 2500;
volatile int pulseConter;

// YF-S201
const float factorK = 7.5;

float volume = 0;
long t0 = 0;


void ISRCountPulse()
{
   pulseConter++;
}

//***FIN *****************CAUDALIMETRO **************************

void setup()
{
   Serial.begin(9600);
   pinMode(Rele_bomba,OUTPUT);
   pinMode(Caudalimetro,OUTPUT);

   digitalWrite(Rele_bomba, LOW);

   attachInterrupt(digitalPinToInterrupt(Caudalimetro), ISRCountPulse, RISING);
}

void loop() 
{
   
float vAgua = analogRead(Agua);
tiempoahora = millis();

  if ((tiempoahora - tiempoanterior) >= vt_espera)
  {
      //Mensaje principal
      Serial.println("");
      Serial.println("---Nuevo Inicio de Loop----");
      Serial.print(tiempoahora);
      Serial.print(" / ");
      Serial.print(tiempoanterior);
      Serial.print(" / ");
      Serial.print(vt_espera);
      Serial.print(" R= ");
      Serial.print(tiempoahora - tiempoanterior);
      Serial.print(" /   e= ");
      Serial.print(estado);
      Serial.print("  /  Count= ");
      Serial.println(i);
      Serial.print("Humedad =");
      Serial.print(vAgua);
      Serial.println("%");
      
      
      
      tiempoanterior = tiempoahora;
  
  
  if(vAgua >= 250)
  {
    i=i+1;
      switch (estado)
      {
        case 0:
          Serial.println ("  --> Iniciando....");

          Serial.print(" ei= ");
          Serial.print(estado);

          //tiempoanterior = tiempoahora;
          estado = 1;
          Serial.print(" //  ef= ");
          Serial.println(estado);
          break;
        
        case 1:
          digitalWrite(Rele_bomba, HIGH);
          
          //************FORO*****************
          	pulseConter = 0;      			//Pone en 0 el contador de pulsos
            interrupts();            		//Habilitamos las interrupciones, equivalente a sei();
            delay (1000);      			//Esperamos un segundo
            noInterrupts();            		//Deshabilitamos las interrupciones, equivalente a cli();
            LxM = (pulseConter / factorK); 		//Calcula los Litros por Minuto 
            Serial.print (LxM, DEC); 		//Imprime la cantidad de litros por minuto
            Serial.print (" Litros/min\r\n");
            //*********************************

          //tiempoanterior = tiempoahora;
          Serial.print(" ei= ");
          Serial.print(estado);
          estado = 2;
          Serial.print(" //  ef= ");
          Serial.println(estado);
          break;

        case 2:
          Serial.println ("  --> Finalizado.");

          Serial.print(" ei= ");
          Serial.print(estado);
          estado = 0;
          Serial.print(" //  ef= ");
          Serial.println(estado);

          //tiempoanterior = tiempoahora;
          
          break;

        default:
          Serial.println ("  !!Etapa de DEFAULT");

          Serial.print(" ei= ");
          Serial.print(estado);
          estado = 0;
          Serial.print(" //  ef= ");
          Serial.println(estado);
      }
      tiempoanterior = tiempoahora;
  }
  else
  {
    Serial.println ("  -->No se han alcanzado valores de nivel de agua");
    digitalWrite(Rele_bomba, LOW);
    tiempoanterior = tiempoahora;
    i=i+1;
  }
  }

}

Ahora me percato que mides con A0 algo y a eso lo llamas humedad. Vaya a saber qué es porque no lo has explicado.
Este sensor es el que hacer que las lecturas del caudalímetro tengan sentido.
Pues te has enrollado solo entonces.

Si el código que te he puesto sirve..
Prueba este código que es una ligera variante del tuyo

const int Agua = A0;
const int Rele_bomba = 8;
const int Caudalimetro = 2;
byte estado = 0;

//variable de tiempo
unsigned long tiempoanterior = 0;
unsigned long tiempoahora;
int vt_espera = 2400;

int i = 0;  //CONTADOR

//VARIABLES HUMEDAD
int Humedad = 0;
float vHumedad = 0;

//*****************CAUDALIMETRO **************************
const int measureInterval = 1000;
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 pulseConter;
}

//***FIN *****************CAUDALIMETRO **************************

void setup() {
  Serial.begin(9600);
  pinMode(Rele_bomba, OUTPUT);
  pinMode(Caudalimetro, OUTPUT);
  digitalWrite(Rele_bomba, LOW);
  attachInterrupt(digitalPinToInterrupt(Caudalimetro), ISRCountPulse, RISING);
}

void loop(){

  float vAgua = analogRead(Agua);

  Serial.println ("**************************************");
  Serial.println ("           NUEVA LECTURA    ");
  Serial.println ("**************************************");
  Serial.print(" Estado= ");
  Serial.print(estado);
  Serial.print(" /  Contador= ");
  Serial.println(i);
  Serial.print("Humedad =");
  Serial.print(vAgua);
  Serial.println("%");

  if (vAgua >= 250)   {
    switch (estado)    {
      case 0:
        Serial.println ("  --> Iniciando....");
        Serial.print(" e= ");
        Serial.print(estado);
        estado = 1;
        break;
      case 1:
        digitalWrite(Rele_bomba, HIGH);
        //********************CAUDALIMETRO **************************
        // obtener frecuencia en Hz
        float frequency = GetFrequency();
        // calcular caudal L/min
        float flow_Lmin = (float) frequency / factorK;
        Serial.print("Frecuencia: ");
        Serial.print(frequency, 0);
        Serial.print(" (Hz)\tCaudal: ");
        Serial.print(flow_Lmin, 3);
        Serial.println(" (L/min)");
        //***FIN *****************CAUDALIMETRO **************************
        estado = 2;
        break;
      case 2:
        Serial.println ("  --> Finalizado.");
        Serial.print(" e= ");
        Serial.print(estado);
        i = i + 1;
        estado = 0;
        break;
    }
  }
  else  {
    //Mensaje principal
    Serial.println ("  -->No se han alcanzado valores de nivel de agua");
    digitalWrite(Rele_bomba, LOW);
    i = i + 1;
  }
}

Hola de nuevo!
Agradecerte nuevamente tu aportación! :slight_smile:

Referente a A0: He conectado un sensor de nivel de agua, con el objetivo de detectar el nivel en el recipiente que comentaba en el planteamiento de mi proyecto. Con este articulo la función para que tanto la electrovalvula como el caudalimetro inicien su funcición.

He probado con tu código. Funciona, pero me encuentro en el mismo problema del que partía.

Cuando inicio empiezo mostrando un "encabezado" con los valores informativos. El objetivo es ir actualizando esto valores cada X tiempo, por ejemplo cada 5''. [en pruebas siempre inicio con vAgua < 250].

Hasta aquí, todo correcto. En el Serial.print va mostrando el mensaje de forma pausa y según el ciclo establecido. (añadí un delay() antes del cierre del loop)
*


       NUEVA LECTURA    

Estado= 0 / Contador= 0
Humedad =137.00%
-->No se han alcanzado valores de nivel de agua*

(sucesivamente actualizando el valor de Humedad [vAgua] e incrementando el Contador [i])

Una vez, el sensor detecta agua y éste incrementa su valor >250, entra en:

if (vAgua >= 250)   {
    switch (estado)    {
      case 0:
        Serial.println ("  --> Iniciando....");
        Serial.print(" e= ");
        Serial.print(estado);
        estado = 1;
        break;
      case 1:
        digitalWrite(Rele_bomba, HIGH);
        //********************CAUDALIMETRO **************************
        // obtener frecuencia en Hz
        float frequency = GetFrequency();
        // calcular caudal L/min
        float flow_Lmin = (float) frequency / factorK;
        Serial.print("Frecuencia: ");
        Serial.print(frequency, 0);
        Serial.print(" (Hz)\tCaudal: ");
        Serial.print(flow_Lmin, 3);
        Serial.println(" (L/min)");
        //***FIN *****************CAUDALIMETRO **************************
        estado = 2;
        break;
      case 2:
        Serial.println ("  --> Finalizado.");
        Serial.print(" e= ");
        Serial.print(estado);
        i = i + 1;
        estado = 0;
        break;
    }

pero aquí está mi problema y es que nunca llega a entrar en CASE 2 del SWITCH.

[Datos del monitor serie]
*
NUEVA LECTURA


Estado= 0 / Contador= 21
Humedad =346.00%
--> Iniciando....
e= 0**************************************
NUEVA LECTURA


Estado= 1 / Contador= 21
Humedad =340.00%
Frecuencia: 0 (Hz) Caudal: 0.000 (L/min)


       NUEVA LECTURA    

Estado= 2 / Contador= 21
Humedad =351.00%


a demás, la pausa del delay() queda "perdida" y en el ciclo no vuelve a entrar en el IF.

Entonces pensé:

  • Quizá la variable vAgua pierde el valor. Pero veo que me la sigue enviando en el "encabezado" de Serial.print.
  • Leí que las interrupciones dejaban sin función a los delay's(). Pero probé con millis() y tampoco funcionó.

así que vuelvo a estar en el punto de partida y sin conseguir entender:

  • ¿Por qué no entra dentro del CASE2?
  • ¿Cómo puedo mantener la "pausa" una vez vAgua>250?
  • ¿Porqué una vez ejecuta el CASE 1, luego no vuelve a ejecutar el IF?

Espero que puedas ayudarme a resolver mis dudas y problemática.
Gracias nuevamente,

Ahora te entiendo.
A ver cual es el problema?
Agrega esto al final del else

else {
    //Mensaje principal
    Serial.println("  -->No se han alcanzado valores de nivel de agua");
    digitalWrite(Rele_bomba, LOW);
    i = i + 1;
    estado = 0;
  }

Si por alguna razón mientras esta en la máquina de estados no pasó por el estado 2 nunca ira al estado 0 y ese es tu problema
cuando

  if (vAgua >= 250) {

es falso entonces debes propiciar que la máquina de estados se reinicie y lo logras con estado = 0

Hola!

He puesto el estado = 0; en el ELSE pero aun así sigo teniendo el mismo problema. Y es que ya me sabe mal insistir tanto, pero no consigo entender el porqué está ocurriendo esto :sob:

Adjunto nuevamente el código con el que estoy trabajando.

const int Agua = A0;
const int Rele_bomba = 8;
const int Caudalimetro = 2;
byte estado = 0;

//variable de tiempo
unsigned long tiempoanterior = 0;
unsigned long tiempoahora;
int vt_espera = 2400;

int i = 0;  //CONTADOR

//VARIABLES HUMEDAD
int Humedad = 0;
float vHumedad = 0;

//*****************CAUDALIMETRO **************************
const int measureInterval = 1000;
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 pulseConter;
}

//***FIN *****************CAUDALIMETRO **************************

void setup() {
  Serial.begin(9600);
  pinMode(Rele_bomba, OUTPUT);
  pinMode(Caudalimetro, OUTPUT);
  digitalWrite(Rele_bomba, LOW);
  attachInterrupt(digitalPinToInterrupt(Caudalimetro), ISRCountPulse, RISING);
}

void loop(){

  float vAgua = analogRead(Agua);

  Serial.println ("**************************************");
  Serial.println ("           NUEVA LECTURA    ");
  Serial.println ("**************************************");
  Serial.print(" Estado= ");
  Serial.print(estado);
  Serial.print(" /  Contador= ");
  Serial.println(i);
  Serial.print("Humedad =");
  Serial.print(vAgua);
  Serial.println("%");

  if (vAgua >= 250)   {
    switch (estado)    {
      case 0:
        Serial.println ("  --> Iniciando....");
        Serial.print(" e= ");
        Serial.print(estado);
        estado = 1;
        break;
      case 1:
        digitalWrite(Rele_bomba, HIGH);
        //********************CAUDALIMETRO **************************
        // obtener frecuencia en Hz
        float frequency = GetFrequency();
        // calcular caudal L/min
        float flow_Lmin = (float) frequency / factorK;
        Serial.print("Frecuencia: ");
        Serial.print(frequency, 0);
        Serial.print(" (Hz)\tCaudal: ");
        Serial.print(flow_Lmin, 3);
        Serial.println(" (L/min)");
        //***FIN *****************CAUDALIMETRO **************************
        estado = 2;
        break;
      case 2:
        Serial.println ("  --> Finalizado.");
        Serial.print(" e= ");
        Serial.print(estado);
        i = i + 1;
        estado = 0;
        break;
    }
  }
  else  {
    //Mensaje principal
    Serial.println ("  -->No se han alcanzado valores de nivel de agua");
    digitalWrite(Rele_bomba, LOW);
    i = i + 1;
    estado=0;
  }
  delay(5000);
}

Te adjunto .txt con algunos datos de los que recibo por el Monitor Serie. He intentado escribir las secuencias de los textos mostrado a menudo que van sucediendo.

Ahora veo que la variable de estado si cambia en valor de 0, 1 y 2, pero el serial.print del Case 2 nunca lo llega a mostrar.

gracias por tu colaboración, seguro que tiene una explicación lógica, pero te aseguro que por más pruebas, cambios y por más que me lo mire o lea, soy incapaz de detectar dónde se pierde.

Sólo se que el único tramo de código donde genera el "desorden" es cuando va a la función.

float GetFrequency() {
  pulseConter = 0;
  interrupts();
  delay(measureInterval);
  noInterrupts();
  return pulseConter;
}

gracias!
Serial.txt (2,4 KB)

Encontré el problema y te doy la solución pero no se porque ocurre esto.
Me ha sucedido ya antes y la única solución es poner el case con {} de este modo

            case 1:{
              digitalWrite(Rele_bomba, HIGH);
              float frequency = GetFrequency();
              float flow_Lmin = (float)frequency / factorK;
              Serial.print("Frecuencia: ");
              Serial.print(frequency);
              Serial.print(" (Hz)\tCaudal: ");
              Serial.print(flow_Lmin);
              Serial.println(" (L/min)");
              estado = 2;
              }
              break;

Ahi funciona.

Hola!

Ahora si que hace todo el recorrido! Perfecto, gracias!! :slight_smile:

Sólo me queda por resolver el tema del delay(), ya que una vez ejecuta todo el SWITCH ésta función queda sin operativa.

He intentado poner un IF con millis(), tal y como mostré en la primera versión del código, pero tampoco ha funcionado. Una vez ejecuta la función donde incorporamos interrupts/noInterrups, tal y como he leído la pausa deja de tener valor.

float GetFrequency() {
  pulseConter = 0;
  interrupts();
  delay(measureInterval);
  noInterrupts();
  return pulseConter;
}

¿Porqué quiero una pausa? es para que no me imprima ni tener que estar comprobando tan seguido las distintas ejecuciones. La aplicación del proyecto estará comprometida a ciertas horas concretas del día y es por eso que no creo que tenga demasiado sentido hacer el loop() en periodos tan cortos.

Por lo demás, como comento, diste en el clavo! Gracias! :ok_hand: :+1:

Te puse solo la solución y olvidé todo el resto acá lo tenia hecho.

#include <Arduino.h>
const int Agua = A0;
const int Rele_bomba = 8;
const int Caudalimetro = 2;
int estado = 0;

//variable de tiempo
unsigned long tiempoanterior = 0;
unsigned long tiempoahora;
int vt_espera = 2400;

int i = 0;  //CONTADOR

//VARIABLES HUMEDAD
int Humedad = 0;
float vHumedad = 0;


//*****************CAUDALIMETRO **************************

const int measureInterval = 1000;
volatile int pulseConter;

// YF-S201
const float factorK = 7.5;

float volume = 0;
long t0 = 0;
unsigned long t;

void ISRCountPulse() {
  pulseConter++;
}

float GetFrequency() {

  return pulseConter;
}

//***FIN *****************CAUDALIMETRO **************************
void setup() {
  Serial.begin(9600);
  pinMode(Rele_bomba, OUTPUT);
  pinMode(Caudalimetro, OUTPUT);
  digitalWrite(Rele_bomba, LOW);
  attachInterrupt(digitalPinToInterrupt(Caudalimetro), ISRCountPulse, RISING);
}

void loop() {

  float vAgua = analogRead(Agua);

  if (millis() - t > 1000UL) {
    Serial.println("**************************************");
    Serial.println("           NUEVA LECTURA    ");
    Serial.println("**************************************");
    Serial.print(" Estado= ");
    Serial.print(estado);
    Serial.print(" /  Contador= ");
    Serial.println(i);
    Serial.print("Humedad = ");
    Serial.print(vAgua);
    Serial.println("");

    if (vAgua >= 250) {
      switch (estado) {
      case 0:
        Serial.println("  --> Iniciando....");
        Serial.print(" e= ");
        Serial.print(estado);
        estado = 1;
        break;
      case 1: {
          digitalWrite(Rele_bomba, HIGH);
          //********************CAUDALIMETRO **************************
          // obtener frecuencia en Hz
          //interrupts();
          //delay(measureInterval);
          //noInterrupts();
          pulseConter = 100;
          //float frequency = GetFrequency();
          float frequency = 100;
          // calcular caudal L/min
          float flow_Lmin = (float)frequency / factorK;
          Serial.print("Frecuencia: ");
          Serial.print(frequency, 0);
          Serial.print(" (Hz)\tCaudal: ");
          Serial.print(flow_Lmin, 3);
          Serial.println(" (L/min)");
          estado = 2;
        }
        break;
      case 2:
        Serial.println("  --> Finalizado.");
        Serial.print(" e= ");
        Serial.print(estado);
        i = i + 1;
        estado = 0;
        break;
      default: estado = 0;
        break;
      }
    }
    else {
      //Mensaje principal
      Serial.println("  -->No se han alcanzado valores de nivel de agua");
      digitalWrite(Rele_bomba, LOW);
      i = i + 1;
      estado = 0;
    }
    t = millis();
  }
}

Ve a documentación y estudia como se usa millis().

Hola!

debo agradecerte tu ayuda y colaboración! Ahora el código funciona perfectamente! Solucionaste todas mis dudas y errores! Gracias!!

Seguiré leyendo y mirando temas relacionados con el fin de poder ir incorporando nuevas funcionalidades a mi proyecto!

Gracias! Saludos!:slight_smile:

La conclusión de tu problema es algo para lo cual aún no tengo respuesta.
Porque algunas veces el while case no funciona a menos que uses {} en algun case.
Es curioso, tal vez un bug del compilador. No he encontrado la razón.
Tal vez abra un tema para debatirlo.

@Surbyte no es un bug, es debido a esto

float frequency = 100; // calcular caudal L/min 
float flow_Lmin = (float)frequency / factorK; 

Cuando se declaran variables locales hay que poner las llaves justamente para determinar su ámbito.

Por lo visto, si hay declaraciones de variables y no están las llaves el compilador "pasa de largo" por ese case.

Debe ser, gracias @anon90500195, me tenia muy mal ese tema.

Te digo que costó encontrar la explicación (y en realidad es una interpretación personal porque no encontré nada explicito), en la mayoría de los documentos que leí que explican como funciona switch(), no hablan de las variables locales y menos de las llaves.

De tanto buscar, encontré un artículo de MS sobre C++ y ahí explica (aunque no muy claro) lo del ámbito de las variables declaradas dentro de los case.

Un bloque interno de una instrucción switch puede contener definiciones con inicializadores siempre que sean accesibles, es decir, siempre que las rutas de ejecución posibles no las omitan. Los nombres proporcionados mediante estas declaraciones tienen ámbito local. Por ejemplo:

using namespace std;
int main(int argc, char *argv[])
{
    switch( tolower( *argv[1] ) )
    {
        // Error. Unreachable declaration.
        char szChEntered[] = "Character entered was: ";

    case 'a' :
        {
        // Declaration of szChEntered OK. Local scope.
        char szChEntered[] = "Character entered was: ";
        cout << szChEntered << "a\n";
        }
        break;

    case 'b' :
        // Value of szChEntered undefined.
        cout << szChEntered << "b\n";
        break;

    default:
        // Value of szChEntered undefined.
        cout << szChEntered << "neither a nor b\n";
        break;
    }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.