Control de flujo liquido más modulo reloj tipo RTC_DS3231

Hola, el incoveniente que tengo es que cuando agrego las lineas para incluir un reloj en el schetch de flujo se me queda como colgado y en el serial muestra Imagen 01

Creo que el problema esta en las interupciones, he colocado unas lineas como esta

noInterrupts()

...codigo...

Interrupts()

y no he tenido buenos resultados

Codigo del reloj por un lado, funcionó , salida imagen 03

#include <Wire.h>     // incluye libreria para interfaz I2C
#include <RTClib.h>   // incluye libreria para el manejo del modulo RTC

RTC_DS3231 rtc;       // crea objeto del tipo RTC_DS3231

void setup () {
  Serial.begin(9600);                             // inicializa comunicacion serie a 9600 bps
  if (! rtc.begin()) {                            // si falla la inicializacion del modulo
    Serial.println("Modulo RTC no encontrado !"); // muestra mensaje de error
    while (1);                                    // bucle infinito que detiene ejecucion del programa
  }
}

void loop () {
  DateTime fecha = rtc.now();     // funcion que devuelve fecha y horario en formato
                                  // DateTime y asigna a variable fecha
  Serial.print(fecha.day());      // funcion que obtiene el dia de la fecha completa
  Serial.print("/");              // caracter barra como separador
  Serial.print(fecha.month());    // funcion que obtiene el mes de la fecha completa
  Serial.print("/");              // caracter barra como separador
  Serial.print(fecha.year());     // funcion que obtiene el año de la fecha completa
  Serial.print(" ");              // caracter espacio en blanco como separador
  Serial.print(fecha.hour());     // funcion que obtiene la hora de la fecha completa
  Serial.print(":");              // caracter dos puntos como separador
  Serial.print(fecha.minute());   // funcion que obtiene los minutos de la fecha completa
  Serial.print(":");              // caracter dos puntos como separador
  Serial.println(fecha.second()); // funcion que obtiene los segundos de la fecha completa

  delay(1000);                    // demora de 1 segundo
}

imagen 03.JPG

El codigo para medición de flujo de liquido (agua), funcionó , salida imagen 02

volatile int NumPulsos;         //variable para la cantidad de pulsos recibidos
int PinSensor = 2;              //Sensor conectado en el pin 2
float factor_conversion=7.11;   //para convertir de frecuencia a caudal
float volumen=0;
long dt=0;                      //variación de tiempo por cada bucle
long t0=0;                      //millis() del bucle anterior

//---Función que se ejecuta en interrupción---------------
void ContarPulsos ()  
{ 
  NumPulsos++;                  //incrementamos la variable de pulsos
} 

//---Función para obtener frecuencia de los pulsos--------
int ObtenerFrecuecia() 
{
  int frecuencia;
  NumPulsos = 0;        //Ponemos a 0 el número de pulsos
  interrupts();         //Habilitamos las interrupciones
  delay(1000);          //muestra de 1 segundo
  noInterrupts();       //Deshabilitamos  las interrupciones
  frecuencia=NumPulsos; //Hz(pulsos por segundo)
  return frecuencia;
}

void setup() 
{ 
  
  Serial.begin(9600); 
  pinMode(PinSensor, INPUT); 
  attachInterrupt(0,ContarPulsos,RISING);   //(Interrupción 0(Pin2),función,Flanco de subida)
  Serial.println ("Envie 'r' para restablecer el volumen a 0 Litros"); 
  t0=millis();
} 

void loop ()    
{
  if (Serial.available()) {
    if(Serial.read()=='r')volumen=0;    //restablecemos el volumen si recibimos 'r'
  }
  float frecuencia=ObtenerFrecuecia(); //obtenemos la frecuencia de los pulsos en Hz
  float caudal_L_m=frecuencia/factor_conversion; //calculamos el caudal en L/m
  dt=millis()-t0;                                 //calculamos la variación de tiempo
  t0=millis();
  volumen=volumen+(caudal_L_m/60)*(dt/1000);      // volumen(L)=caudal(L/s)*tiempo(s)

   //-----Enviamos por el puerto serie---------------
  Serial.print ("Caudal: "); 
  Serial.print (caudal_L_m,3); 
  Serial.print ("L/min\tVolumen: "); 
  Serial.print (volumen,3); 
  Serial.println (" L");
}

imagen 02.JPG

Pero cuando las integro se me cuelga, y obtengo como resultado em serial imagen 01

volatile int NumPulsos; //variable para la cantidad de pulsos recibidos
int PinSensor = 2;    //Sensor conectado en el pin 2
float factor_conversion = 7.50; //para convertir de frecuencia a caudal
float volumen = 0;
long dt = 0; //variación de tiempo por cada bucle
long t0 = 0; //millis() del bucle anterior

//---Función que se ejecuta en interrupción---------------
void ContarPulsos ()
{
  NumPulsos++;  //incrementamos la variable de pulsos
}

//---Función para obtener frecuencia de los pulsos--------
int ObtenerFrecuecia()
{
  int frecuencia;
  NumPulsos = 0;   //Ponemos a 0 el número de pulsos
  interrupts();    //Habilitamos las interrupciones
  delay(1000);   //muestra de 1 segundo
  noInterrupts(); //Deshabilitamos  las interrupciones
  frecuencia = NumPulsos; //Hz(pulsos por segundo)
  return frecuencia;
}
//***********************
#include <Wire.h>     // incluye libreria para interfaz I2C
#include <RTClib.h>   // incluye libreria para el manejo del modulo RTC

RTC_DS3231 rtc;       // crea objeto del tipo RTC_DS3231
//***********************

void setup()
{

  Serial.begin(9600);
  pinMode(PinSensor, INPUT);
  attachInterrupt(0, ContarPulsos, RISING); //(Interrupción 0(Pin2),función,Flanco de subida)
  Serial.println ("Envie 'r' para restablecer el volumen a 0 Litros");
  t0 = millis();

  //***********************
  if (! rtc.begin()) {                           // si falla la inicializacion del modulo
    Serial.println("Modulo RTC no encontrado !");  // muestra mensaje de error
    while (1);                                     // bucle infinito que detiene ejecucion del programa
  }
  //***********************
}
void loop ()
{

  //***********************
  DateTime fecha = rtc.now();     // funcion que devuelve fecha y horario en formato
  // DateTime y asigna a variable fecha
  Serial.print(fecha.day());      // funcion que obtiene el dia de la fecha completa
  Serial.print("/");              // caracter barra como separador
  Serial.print(fecha.month());    // funcion que obtiene el mes de la fecha completa
  Serial.print("/");              // caracter barra como separador
  Serial.print(fecha.year());     // funcion que obtiene el año de la fecha completa
  Serial.print(" ");              // caracter espacio en blanco como separador
  Serial.print(fecha.hour());     // funcion que obtiene la hora de la fecha completa
  Serial.print(":");              // caracter dos puntos como separador
  Serial.print(fecha.minute());   // funcion que obtiene los minutos de la fecha completa
  Serial.print(":");              // caracter dos puntos como separador// put your main code here, to run repeatedly:
  Serial.println(fecha.second());
  //***********************

  if (Serial.available()) {
    if (Serial.read() == 'r')volumen = 0;         //restablecemos el volumen si recibimos 'r'
  }
  float frecuencia = ObtenerFrecuecia();          //obtenemos la frecuencia de los pulsos en Hz
  float caudal_L_m = frecuencia / factor_conversion; //calculamos el caudal en L/m
  dt = millis() - t0;                             //calculamos la variación de tiempo
  t0 = millis();
  volumen = volumen + (caudal_L_m / 60) * (dt / 1000); // volumen(L)=caudal(L/s)*tiempo(s)

  //-----Enviamos por el puerto serie---------------
  Serial.print ("Caudal: ");
  Serial.print (caudal_L_m, 3);
  Serial.print ("L/min\tVolumen: ");
  Serial.print (volumen, 3);
  Serial.println (" L");
}

imagen 01.JPG

A la conclución que llegue es que cuando comento la linea

DateTime fecha = rtc.now();

ya no se cuelga, pero me quedo sin reloj. Por lo que lei puede ser conflicto con las interrupciones pero no logro solucionarlo.

Bueno, gracias por detenerse a leer, espero tu ayuda

Empieza probando esto

float frecuencia = (float) ObtenerFrecuecia();          //obtenemos la frecuencia de los pulsos en Hz

No dio resultado, la verdad, no le encuentro la vuelta.

Creo que resolví el problema

#include <Wire.h>     // incluye libreria para interfaz I2C
#include <RTClib.h>   // incluye libreria para el manejo del modulo RTC

volatile int NumPulsos; //variable para la cantidad de pulsos recibidos
int PinSensor = 2;    //Sensor conectado en el pin 2
float factor_conversion = 7.50; //para convertir de frecuencia a caudal
float volumen = 0;
unsigned long dt = 0; //variación de tiempo por cada bucle
unsigned long t0 = 0; //millis() del bucle anterior
unsigned long start;

RTC_DS3231 rtc;       // RTC_DS1307 rtc;

//---Función que se ejecuta en interrupción---------------
void ContarPulsos ()
{
  NumPulsos++;  //incrementamos la variable de pulsos
}

void setup()
{

  if (!rtc.begin()) {                           // si falla la inicializacion del modulo
      Serial.println("Modulo RTC no encontrado !");  // muestra mensaje de error
      while (1);                                     // bucle infinito que detiene ejecucion del programa
  }
  if (rtc.lostPower()) {
      Serial.println("RTC lost power, lets set the time!");
      // following line sets the RTC to the date & time this sketch was compiled
      rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
      // This line sets the RTC with an explicit date & time, for example to set
      // January 21, 2014 at 3am you would call:
      // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }

  Serial.begin(9600);
  pinMode(PinSensor, INPUT);
  attachInterrupt(0, ContarPulsos, RISING); //(Interrupción 0(Pin2),función,Flanco de subida)
  Serial.println ("Envie 'r' para restablecer el volumen a 0 Litros");
  t0 = millis();

}

void loop () {

  if (Serial.available()) {
      if (Serial.read() == 'r')
          volumen = 0;         //restablecemos el volumen si recibimos 'r'
  }

  if (millis() - start >= 1000UL){ //Uptade every one second, this will be equal to reading frecuency (Hz).
      detachInterrupt(0);//Disable interrupt when calculating
      MuestroFechaHora();

      float caudal_L_m = NumPulsos / factor_conversion; //calculamos el caudal en L/m
      dt = millis() - t0;                             //calculamos la variación de tiempo
      t0 = millis();
      volumen += (caudal_L_m / 60) * (dt / 1000); // volumen(L)=caudal(L/s)*tiempo(s)

      //-----Enviamos por el puerto serie---------------
      Serial.print ("Caudal: ");
      Serial.print (caudal_L_m);
      Serial.print ("L/min\tVolumen: ");
      Serial.print (volumen);
      Serial.println (" L");
      start = millis(); // Uptade lasmillis
      NumPulsos = 0;
      attachInterrupt(0, ContarPulsos, RISING); //(Interrupción 0(Pin2),función,Flanco de subida)

  }
}

void MuestroFechaHora() {
  char buffer[40];

  //***********************
  DateTime fecha = rtc.now();     // funcion que devuelve fecha y horario en formato
  // DateTime y asigna a variable fecha
  sprintf(buffer, "%02d/%02d/%04d %02d:%02d:%02d", fecha.day(), fecha.month(), fecha.year(), fecha.hour(), fecha.minute(), fecha.second());
  Serial.println(buffer);
}

Funcionó, Si!!, veo lineas nuevas

if (rtc.lostPower()) {

codigo

}

y sacaste la interrupcion del setup.

Porque?

Usaste el detachInterrupt, yo intente con noInterrupts(), pero no es lo mismo

El codigo esta casi rediseñado, gracias por la ayuda

Esto quedó de mi simulación

if (rtc.lostPower()) {

codigo

}

es algo que no conocía de la librería RTClib que me gustó, si el RTC no esta inicializado, simplemento lo pone en hora. Muy bueno!!

Saqué la interrupción del setup porque la uso a cada momento. No cambia nada. Cada 1000 milisegundos vuelvo a activar la interrupción. Es basicamente lo mismo pero de otro modo.

Algo mas
noInterrupt() detiene TODAS las interrupciones y tu solo debes detener la que estas usando.
Ese era el problema principal por lo que Serial no funcionaba

Si miras aca noInterrupts() - Arduino Reference
verás que noInterrupts detiene todas las interrupciones y como dice ahi,

Disables interrupts (you can re-enable them with interrupts()). Interrupts allow certain important tasks to happen in the background and are enabled by default. Some functions will not work while interrupts are disabled, and incoming communication may be ignored. Interrupts can slightly disrupt the timing of code, however, and may be disabled for particularly critical sections of code.

Algunas funciones no van a funcionar mientras las interrupciones esten desabilitadas y las comunicaciones que ingresen serán ignoradas.

Resalto solo la parte relevante.