Flow Meters sporadically log flow when there is none - Otherwise works perfectly

Here is what I’ve been using and I haven’t had that issue with it.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ArduinoOTA.h>
#include <WidgetRTC.h>

//LittleFS includes
#include <ArduinoJson.h>
#include "FS.h"
#include <LittleFS.h>

char auth[] = "";
char ssid[] = "";
char pass[] = "";

byte sensorInterrupt = 4;  // 0 = digital pin 2
byte sensorPin       = 4;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 2.25;

volatile byte pulseCount;                    //must be a volatile variable because triggered in a interrupt routine

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long totalLitres;

String currentTime;
String currentDate;
String yesterDate;

int ReCnctFlag;
int ReCnctCount;

int SThour;
int STmin;
int STsec;

bool litersResetFlag = 1;
bool flowNotifyFlage = 0;

unsigned long oldTime;

BlynkTimer timer;
BlynkTimer timer1;
WidgetRTC rtc;
WidgetTerminal terminal1(V8);
WidgetTable table;

BLYNK_ATTACH_WIDGET(table, V1);

int rowIndex;

// Set your Static IP address
IPAddress local_IP(192, 168, 0, 42);
// Set your Gateway IP address
IPAddress gateway(192, 168, 0, 1);

IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional

bool loadData() {
  File dataFile = LittleFS.open("/data.json", "r");
  if (!dataFile) {
    Serial.println("Failed to open data file");
    return false;
  }

  size_t size = dataFile.size();
  if (size > 1024) {
    Serial.println("Data file size is too large");
    return false;
  }

  // Allocate a buffer to store contents of the file.
  std::unique_ptr<char[]> buf(new char[size]);

  // We don't use String here because ArduinoJson library requires the input
  // buffer to be mutable. If you don't use ArduinoJson, you may as well
  // use configFile.readString instead.
  dataFile.readBytes(buf.get(), size);

  StaticJsonDocument<100> doc;
  auto error = deserializeJson(doc, buf.get());
  if (error) {
    Serial.println("Failed to parse config file");
    return false;
  }

  totalMilliLitres = doc["totalMilliLitres"];
  yesterDate = doc["yesterDate"].as<String>();   ////Note: loading as string from LittleFS
  return true;
}

bool saveData() {
  StaticJsonDocument<100> doc;

  doc["totalMilliLitres"] = totalMilliLitres;
  doc["yesterDate"] = yesterDate;                ////Note: but to save does not work to load as<String>..
  
  File dataFile = LittleFS.open("/data.json", "w");
  if (!dataFile) {
    Serial.println("Failed to open config file for writing");
    return false;
  }

  serializeJson(doc, dataFile);
  return true;
}

void ICACHE_RAM_ATTR pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

void setup()
{
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, LOW);
  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  WiFi.begin(ssid,pass);
  Blynk.config(auth);
  Blynk.connect();
  ArduinoOTA.setHostname("flowmeter_v5pnt4");
  ArduinoOTA.begin();

  if (!LittleFS.begin()) 
  {
    Serial.println("Failed to mount file system");
    return;
  }

  if (!loadData()) 
  {
    Serial.println("Failed to load Data");
  } 
  else 
  {
    Serial.println("Data loaded");
  }

  timer.setInterval(1000L, sendValues);
  delay(100);
  timer.setInterval(1000L, printTIME);
  delay(100);
  timer.setInterval(1000L, WiFistrength);
  delay(100);
  timer.setInterval(10000L, checkcounterReset);
  
  
  digitalWrite(sensorPin, HIGH);

  setSyncInterval(720*60);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  //totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  
}

BLYNK_CONNECTED()
{
  rtc.begin();
  ReCnctCount = 0;
  printTIME();
  Blynk.syncVirtual(V9);
  //Blynk.syncVirtual(V0);
  timer.setTimeout(5000L,[](){                                   //Lambda "Reconnection" timer function
      terminal1.println(" ");
      terminal1.println(String ("Connected ") + currentTime + " " + currentDate);
      terminal1.println(String ("Yesterdate ") + yesterDate);
      terminal1.flush();
    });
    
  Blynk.syncVirtual(V12);
  Blynk.syncVirtual(V7);
}

void loop()
{
  ArduinoOTA.handle();
  Blynk.run();
  timer.run();
  
  if (Blynk.connected())
  {                                             //If Blynk connected run as normal
    Blynk.run();
  }
  else if (ReCnctFlag == 0){                                          //test connection flag
    ReCnctFlag = 1;                                                 //set connection flag
    timer.setTimeout(60000L,[](){                                   //Lambda "Reconnection" timer function
      ReCnctFlag = 0;
      ReCnctCount++;                                                //count up reconnection attempts
      Blynk.connect();                                              //try to connect again
    });
  }
}

void sendValues()
{
    detachInterrupt(sensorInterrupt);
       
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
   
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
   
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
   
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;
     
    unsigned int frac;
   
    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
   
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
    totalLitres = (totalMilliLitres/1000);
    Blynk.virtualWrite(V0, totalMilliLitres);
    Blynk.virtualWrite(V1, totalLitres);
    Blynk.virtualWrite(V6, flowRate);
    
    if(flowRate >= 3.1 && flowNotifyFlage == true)
    {
      Blynk.notify(String ("Waters flowing @ ") + flowRate + (" L/Min"));
      flowNotifyFlage = false;
      timer.setTimeout(3600000L,[]()
      {                                   //after one hour reset notify
        flowNotifyFlage = true;
      });
    }
    
  if (!saveData())                         //save mL to little FS
  {
    Serial.println("Failed to save Data");
  } 
  else 
  {
    Serial.println("Data saved");
  }
 
}

void checkcounterReset()                         //time input
{
 if(hour() == SThour)
 {                           //daily clear total liters
  if((minute() >= STmin) && (minute() <= (STmin + 50)))
  {
    if(litersResetFlag == 0)
    {
      litersResetFlag = 1;                           //change flag so only exicute once
      Blynk.notify(String ("Yesterdays water ") + (totalMilliLitres / 1000));

    
      if(totalMilliLitres >= 1000)
      {
        Blynk.virtualWrite(V10, "add", rowIndex , yesterDate + String("  Water received"),(totalMilliLitres/1000) + String(" L")) ;
        Blynk.virtualWrite(V10, "pick", rowIndex);
        yesterDate = currentDate;
        terminal1.println(" ");
        terminal1.print(yesterDate);
        terminal1.flush();
        
        if (!saveData()) 
        {
          Serial.println("Failed to save Data");
        } else {
        terminal1.println(" ");
        terminal1.print("Saved LittleFS");
        terminal1.flush();
        }

      }
      else
      {
        Blynk.virtualWrite(V10, "add", rowIndex , yesterDate + String("    No Water"),(totalMilliLitres/1000) + String(" L")) ;
        Blynk.virtualWrite(V10, "pick", rowIndex);
        terminal1.println(" ");
        terminal1.print(yesterDate);
        terminal1.flush();
        yesterDate = currentDate;
        terminal1.println(" ");
        terminal1.print(yesterDate);
        terminal1.println("");
        terminal1.flush();

        if (!saveData()) 
        {
          terminal1.print("Failed to save Data");
          terminal1.flush();
        } else {
          terminal1.print("Data saved");
          terminal1.flush();
        }
      }
      
      rowIndex++; 
      totalMilliLitres = 0;
      Blynk.virtualWrite(V6,totalMilliLitres);
      Blynk.virtualWrite(V12, rowIndex);
    }
  }
 }

 
 
 if(hour()== 23 && litersResetFlag == 1){                            //change flag so that counter can be reset next day
    if(minute()>= 01){
      litersResetFlag = 0;
      yesterDate = currentDate;
      terminal1.println(" ");
      terminal1.print(yesterDate);
      terminal1.println(" ");
      terminal1.println(String ("Changeflag ") + currentTime + " " + currentDate);
      terminal1.flush();
      Blynk.notify("ChangeFlag");

      if (!saveData())                         //save mL to little FS
      {
        Serial.println("Failed to save Data");
      } 
      else 
      {
        Serial.println("Data saved");
      }
    }
  }
}

void printTIME()                                //what it says!
{
  currentDate = String(day())+ "/" + month();
  currentTime = String(hour())+ ":" + minute() + ":" + second();
  Blynk.virtualWrite(V4, currentTime);
}

void WiFistrength()                              //prints wifi strength
{
  long rssi = WiFi.RSSI();           
  Blynk.virtualWrite(V5,rssi);
}

BLYNK_WRITE(V0)
{
  totalMilliLitres = param.asInt();
}

BLYNK_WRITE(V2)
{
  if (param.asInt())
  {                             //manual reset Liters
    totalMilliLitres = 0;
    Blynk.virtualWrite(V1, totalLitres);
  }
}

BLYNK_WRITE(V3)
{
  if(param.asInt())
  {                             //manual uptick for testing
    totalMilliLitres += 1000; 
    Blynk.virtualWrite(V0, totalMilliLitres);
    Blynk.virtualWrite(V1, totalLitres);
  }
}

BLYNK_WRITE(V7)
{
  if(param.asInt())
  {
    flowNotifyFlage = false;
  }else{
    flowNotifyFlage = true;
  }
}

BLYNK_WRITE(V9)
{
  TimeInputParam t(param);                        //time input
  SThour = t.getStartHour();
  STmin = t.getStartMinute();
  
  litersResetFlag = 0;

  terminal1.println(" ");
  terminal1.println(String("Counter reset time ") + t.getStartHour() + ":" +
               t.getStartMinute());
  terminal1.flush();   
  
}

BLYNK_WRITE(V11)
{
  if (param.asInt()){                             //manual reset esp if needed
    Blynk.notify("Reseting ESP in 5s");
    timer.setTimeout(5000L,[]()
      {                                   //after one hour reset notify
         ESP.reset();
      });
  }
}

BLYNK_WRITE(V12)
{
  rowIndex = param.asInt();
}

BLYNK_WRITE(V14)
{
  if (param.asInt())
  {
    //Blynk.notify("ResetFlag");
    litersResetFlag = 0;
    Blynk.virtualWrite(V14, 0);
  }
}

I don’t claim to understand all of it, I got it off of another’s project here on the forum. This also uses LittleFS to store the mL every time it figures it and it worked pretty good with reboots and disconnects.

EDIT: I’m guessing you would want to remove the daily reset.