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

I agree with @Gunner that you need some temporary logging of the values that are sent to Blynk, along with a time stamp.

Your code also sends battery voltage to Blynk every 60 seconds. Is there any correlation between battery voltage readings and these blips in the water level readings?

Superchart can often produce unexpected results because of the way that it buffers readings over a 1 minute period before averaging these readings and writing the averaged value to the database.
However, I can’t see how that could be producing these results, but it is something to bear in mind when trying to make sense of the logged values compared to what is being shown in Superchart.

A couple of comments about your code…

You’re calling the flow function from your void loop, and then using a millis() calculation to see is one second has passed and the flow rate needs to be calculated.
As you’re already using a Blynk timer, it would make more sense to let the timer call this function once every second and remove calculation - or if the exact number of millis since the last reading is needed for your flow accuracy then keep this in but remove the 1 second elapsed time check.

Also, I assume that you’re using a fairly old version of the ESP core - otherwise you’d be getting ISR not in IRAM error messages and constant reboots with your existing interrupt code.
Modern versions of the ESP core require the syntax of the interrupt function name to be changed slightly and you also either need to pre-declare the ISR functions or ensure that they appear in your code before the interrupts are initialised in void setup.

If your ESP core is out of date then I wonder if your Blynk library is also out of date (the latest is 0.6.1) and whether that could be causing any issues (although that seems like a bit of a long shot).

Pete.

1 Like

I considered this, but they didn’t register any flow for dozens of hours, and then all of the sudden the water is lost at a rate 10 times that the maximum flow of the system… This is what led me to disconnect the flow meter and ground the input. I did this right at the GPIO, and I can try again with both flow meters, but because the problem is so sporadic, it takes time to recreate/document it.

Thanks, I’m filming this project for a YouTube video, but I’ve been fighting for days with this and my hair is getting longer in each clip…

Not that I can tell, I can comment that out for now to confirm that.

Understood, I was just using gauge widgets at first, but I added the superchart as an initial debug step to see when and why we’d loose half our water.

Yes, I downgraded to 2.4.2 at some point as other people cited the newer versions as having some bugs… But I have just upgraded back to 2.7.4 and can confirm I have Blynk v0.6.1

I think I have the ICACHE_RAM_ATTR in all the right places, cuz it’s working…

It seems I can’t edit my first post with the new updated code, shall I just repost it again?

I wouldn’t comment it out, I’d add it as an additional data stream in the SuperChart and see if there is a correlation.

Yes, no problem.

Pete.

Here’s what I’m running and logging now…̶I̶ ̶r̶e̶m̶e̶m̶b̶e̶r̶ ̶o̶n̶e̶ ̶o̶f̶ ̶t̶h̶e̶ ̶r̶e̶a̶s̶o̶n̶s̶ ̶I̶ ̶d̶o̶w̶n̶g̶r̶a̶d̶e̶d̶ ̶t̶o̶ ̶2̶.̶4̶.̶2̶ ̶w̶a̶s̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶I̶ ̶w̶a̶s̶ ̶s̶e̶e̶i̶n̶g̶ ̶i̶n̶p̶u̶t̶ ̶p̶i̶n̶s̶ ̶t̶r̶i̶g̶g̶e̶r̶i̶n̶g̶ ̶w̶h̶e̶n̶ ̶t̶h̶e̶y̶ ̶s̶h̶o̶u̶l̶d̶ ̶n̶o̶t̶ ̶b̶e̶, Now it’s happening with 2.4.2 too… No Idea Why, PIN_TOP_FLOAT is currently showing as LOW, tripping that code at line 192, yet the pin is very much HIGH and should not be triggering that code. If I pull the pin high or low, it registers, but then it goes back to the wrong value. I don’t know how to describe that better…

/*
  Using Code modified from:
  Blynk Flow Sensor Water Meter- Calculates Total Water Consumption.
  Source: https://github.com/pkarun/Blynk-Flow-Sensor-Water-Meter
*/

#define BLYNK_PRINT Serial           // Uncomment for debugging

#include "settings.h"
#include "secret.h"   // <<--- UNCOMMENT this before you use and change values on config.h tab

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266mDNS.h>  // For OTA with ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

BlynkTimer timer;

int BLYNKneedsZero = 0;
int BLYNKneedsUpdate = 0;
int topFloatTripped = 0;
int bottomFloatTripped = 0;
volatile long DRINKpulseCount = 0;
volatile long WASHpulseCount = 0;
float DRINKflowRate;
float WASHflowRate;
unsigned int DRINKflowMilliLitres;
unsigned int WASHflowMilliLitres;
unsigned long DRINKtotalMilliLitres;
unsigned long WASHtotalMilliLitres;
float DRINKtotalLitres;
float WASHtotalLitres;
float DRINKtotalLitresold;
float WASHtotalLitresold;
unsigned long DRINKoldTime;
unsigned long WASHoldTime;


BLYNK_CONNECTED() { // runs once at device startup, once connected to server.

  Blynk.syncVirtual(VPIN_TOTAL_LITERS_DRINK); //gets last know value of virtual pin
  Blynk.syncVirtual(VPIN_TOTAL_LITERS_WASH); //gets last know value of virtual pin
}

// Restores last known liter count values from the virtual pin on the Blynk server
BLYNK_WRITE(VPIN_TOTAL_LITERS_DRINK)
{
  DRINKtotalLitresold = param.asFloat();
}

BLYNK_WRITE(VPIN_TOTAL_LITERS_WASH)
{
  WASHtotalLitresold = param.asFloat();
}

BLYNK_WRITE(VPIN_SET_DRINK) {  // Set Water Level in PUSH mode on virtual pin V24
  int setLitersDrink = param.asInt();
  Serial.print("Setting Drinking Water Level to ");
  Serial.println(setLitersDrink);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, setLitersDrink);
  Blynk.virtualWrite(VPIN_FLOW_RATE_DRINK, 0);
  DRINKflowRate = 0;
  DRINKflowMilliLitres = 0;
  DRINKtotalMilliLitres = 0;
  DRINKtotalLitres = setLitersDrink;
  DRINKtotalLitresold = setLitersDrink;
  Blynk.virtualWrite(VPIN_SET_DRINK, " ");
  topFloatTripped = 0;
  bottomFloatTripped = 0;
  Blynk.virtualWrite(VPIN_TOP_FLOAT, 0);
  Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 0);
  Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_BLUE);
}

BLYNK_WRITE(VPIN_SET_WASH) {  // Set Water Level in PUSH mode on virtual pin V24
  int setLitersWASH = param.asInt();
  Serial.print("Setting Washing Water Level to ");
  Serial.println(setLitersWASH);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, setLitersWASH);
  Blynk.virtualWrite(VPIN_FLOW_RATE_WASH, 0);
  WASHflowRate = 0;
  WASHflowMilliLitres = 0;
  WASHtotalMilliLitres = 0;
  WASHtotalLitres = setLitersWASH;
  WASHtotalLitresold = setLitersWASH;
  Blynk.virtualWrite(VPIN_SET_WASH, " ");
  //Blynk.setProperty(VPIN_TOTAL_LITERS_WASH, "color", BLYNK_YELLOW);
}

void ICACHE_RAM_ATTR DRINKpulseCounter()
{
  DRINKpulseCount++;
  Serial.print("DRINKpulseCount = ");
  Serial.println(DRINKpulseCount);
}
void ICACHE_RAM_ATTR WASHpulseCounter()
{
  WASHpulseCount++;
  Serial.print("WASHpulseCount = ");
  Serial.println(WASHpulseCount);

}

void flow()
{
  if ((millis() - DRINKoldTime) > 1000)   // Only process counters once per second
  {
    detachInterrupt(PULSE_PIN_DRINK);
    DRINKflowRate = ((1000.0 / (millis() - DRINKoldTime)) * DRINKpulseCount) / FLOW_CALIBRATION;
    DRINKoldTime = millis();
    DRINKflowMilliLitres = (DRINKflowRate / 60) * 1000;
    DRINKtotalMilliLitres += DRINKflowMilliLitres;
    DRINKtotalLitres = DRINKtotalLitresold - DRINKtotalMilliLitres * 0.001; // CHANGED THIS TO SUBTRACT AS WE WANT TO COUNT DOWN
    unsigned int frac;

    if (DRINKflowRate > 0) {
      // Print the flow rate for this second in liters / minute
      Serial.print("Flowing: ");
      Serial.print(int(DRINKflowRate));  // Print the integer part of the variable

      Serial.print(".");             // Print the decimal point
      frac = (DRINKflowRate - int(DRINKflowRate)) * 10; // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
      Serial.print(frac, DEC) ;      // Print the fractional part of the variable
      Serial.println("L/min");

      Serial.print("Flowing: ");  // Print the number of liters flowed in this second
      Serial.print(DRINKflowMilliLitres);
      Serial.println("mL/Sec");

      Serial.print("Drinking Water Remaining: ");  // Print the cumulative total of liters flowed since starting
      Serial.print(DRINKtotalLitres);
      Serial.println("L");
      BLYNKneedsUpdate = 1;
      BLYNKneedsZero = 1;
    }
    if (DRINKflowRate == 0 & BLYNKneedsZero == 1) {
      BLYNKneedsUpdate = 1;
      BLYNKneedsZero = 0;
    }

    DRINKpulseCount = 0;  // Reset the pulse counter so we can start incrementing again

    attachInterrupt(PULSE_PIN_DRINK, DRINKpulseCounter, FALLING);    // Enable the interrupt again now that we've finished sending output

    detachInterrupt(PULSE_PIN_WASH);
    WASHflowRate = ((1000.0 / (millis() - WASHoldTime)) * WASHpulseCount) / FLOW_CALIBRATION;
    WASHoldTime = millis();
    WASHflowMilliLitres = (WASHflowRate / 60) * 1000;
    WASHtotalMilliLitres += WASHflowMilliLitres;
    WASHtotalLitres = WASHtotalLitresold - WASHtotalMilliLitres * 0.001; // CHANGED THIS TO SUBTRACT AS WE WANT TO COUNT DOWN

    if (WASHflowRate > 0) {

      // Print the flow rate for this second in liters/minute
      Serial.print("Flowing: ");
      Serial.print(int(WASHflowRate));  // Print the integer part of the variable

      Serial.print(".");             // Print the decimal point
      frac = (WASHflowRate - int(WASHflowRate)) * 10; // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
      Serial.print(frac, DEC) ;      // Print the fractional part of the variable
      Serial.println("L/min");

      Serial.print("Flowing: ");  // Print the number of liters flowed in this second
      Serial.print(WASHflowMilliLitres);
      Serial.println("mL/Sec");

      Serial.print("Washing Water Remaining: ");  // Print the cumulative total of liters flowed since starting
      Serial.print(WASHtotalLitres);
      Serial.println("L");
      BLYNKneedsUpdate = 1;
      BLYNKneedsZero = 1;
    }

    if (WASHflowRate == 0 & BLYNKneedsZero == 1) {
      BLYNKneedsUpdate = 1;
      BLYNKneedsZero = 0;
    }

    WASHpulseCount = 0;  // Reset the pulse counter so we can start incrementing again

    attachInterrupt(PULSE_PIN_WASH, WASHpulseCounter, FALLING);    // Enable the interrupt again now that we've finished sending output

  }

}


void sendtoBlynk()  // In this function we are sending values to blynk server
{
  if (digitalRead(PIN_TOP_FLOAT) == 0 && (topFloatTripped) == 0) //When the Top float trips for the first time.
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 255);
    Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_YELLOW);
    //    DRINKtotalLitres = 30;
    //    DRINKtotalMilliLitres = 30000;
    topFloatTripped = 1;
    Blynk.notify("30% Water Level Float Tripped");
    Serial.print("30% Water Level Float Tripped at ");  // Print the cumulative total of liters flowed since starting
    Serial.print("Debug Point 1");

  }
  else if (digitalRead(PIN_TOP_FLOAT) == 1 && (topFloatTripped) == 1) // When it Un-Trips, ie; goes back up or sloshes
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 0);
    Serial.print("Debug Point 2");
  }
  else if (digitalRead(PIN_TOP_FLOAT) == 0 && (topFloatTripped) == 1) // Then It goes down again...
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 255);
  }


  if (digitalRead(PIN_BOTTOM_FLOAT) == 0 && (bottomFloatTripped) == 0)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 255);
    digitalWrite(BLUE_LED, LOW); // LED On - Stupid LED is inverted
    Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_RED);
    //    DRINKtotalLitres = 15;
    //    DRINKtotalMilliLitres = 15000;
    bottomFloatTripped = 1;
    Blynk.notify("15% Water Level Float Tripped");
    Serial.print("15% Water Level Float Tripped at ");  // Print the cumulative total of liters flowed since starting
    Serial.println(DRINKtotalLitres);
  }
  else if (digitalRead(PIN_BOTTOM_FLOAT) == 1 && (bottomFloatTripped) == 1)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 0);
    digitalWrite(BLUE_LED, HIGH); // LED Off - Stupid LED is inverted
  }
  else if (digitalRead(PIN_BOTTOM_FLOAT) == 0 && (bottomFloatTripped) == 1)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 255);
    digitalWrite(BLUE_LED, LOW); // LED On - Stupid LED is inverted
  }

  if (BLYNKneedsUpdate == 1) {
    Serial.println("Sending Values to Server");
    Serial.print("Drinking Water = ");
    Serial.println(DRINKtotalLitres);
    Serial.print("Wash Water = ");
    Serial.println(WASHtotalLitres);
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);          // Total water consumption in liters (L)
    Blynk.virtualWrite(VPIN_FLOW_RATE_DRINK, DRINKflowRate);            // Displays the flow rate for this second in liters / minute (L/min)
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, WASHtotalLitres);          // Total water consumption in liters (L)
    Blynk.virtualWrite(VPIN_FLOW_RATE_WASH, WASHflowRate);            // Displays the flow rate for this second in liters / minute (L/min)
    BLYNKneedsUpdate = 0;
  }
}

void batteryBlynk()
{
  float BatteryVoltage = (analogRead(PIN_CHASSIS_VOLTAGE)) * 0.01554955;
  Blynk.virtualWrite(V10, BatteryVoltage);
  //  if (BatteryVoltage < 12); {
  //    //Blynk.notify("Chassis Battery Below 12 Volts");
  //    Blynk.notify(BatteryVoltage);
  //  }

}

void setup()
{
  Serial.begin(9600);
  Blynk.begin(AUTH, WIFI_SSID, WIFI_PASS);
  ArduinoOTA.setHostname(OTA_HOSTNAME);  // For OTA - Use your own device identifying name
  ArduinoOTA.begin();  // For OTA

  DRINKpulseCount        = 0;
  WASHpulseCount        = 0;
  DRINKflowRate          = 0.0;
  WASHflowRate          = 0.0;
  DRINKflowMilliLitres   = 0;
  WASHflowMilliLitres   = 0;
  DRINKtotalMilliLitres  = 0;
  WASHtotalMilliLitres  = 0;
  DRINKoldTime           = 0;
  WASHoldTime           = 0;
  DRINKtotalLitresold = 0;
  WASHtotalLitresold = 0;
  BLYNKneedsUpdate = 0;

  pinMode(BLUE_LED, OUTPUT);
  digitalWrite(BLUE_LED, HIGH); // LED Off - Stupid LED is inverted
  pinMode(PULSE_PIN_DRINK, INPUT_PULLUP);  // Initialization of the variable "PULSE_PIN_DRINK" as INPUT
  pinMode(PULSE_PIN_WASH, INPUT_PULLUP);  // Initialization of the variable "PULSE_PIN_DRINK" as INPUT

  pinMode(PIN_TOP_FLOAT, INPUT_PULLUP);  // Initialization of the variable "PIN_TOP_FLOAT" as INPUT
  pinMode(PIN_BOTTOM_FLOAT, INPUT_PULLUP);  // Initialization of the variable "PIN_BOTTOM_FLOAT" as INPUT

  attachInterrupt(PULSE_PIN_DRINK, DRINKpulseCounter, FALLING);
  attachInterrupt(PULSE_PIN_WASH, WASHpulseCounter, FALLING);

  timer.setInterval(1000L, sendtoBlynk); // send values blynk server every sec (if it needs updating)
  timer.setInterval(60000L, batteryBlynk); // send values blynk server every 60 sec

}


void loop()
{

  Blynk.run();
  ArduinoOTA.handle();  // For OTA
  timer.run();
  flow();

}

it might be useful if you shared the contents of your settings.h file, as its currently impossible to work-oit which GPIOs you’re using.

Pete.

Of course! Sorry!

                           
                           
                           /////////////////////////////////////////////////////////////////
                          //                           Settings                          //
                         /////////////////////////////////////////////////////////////////

                    
/***************************************************
 *      Hardware Settings
 **************************************************/

#define PIN_CHASSIS_VOLTAGE      A0
#define PULSE_PIN_DRINK      D7
#define PULSE_PIN_WASH       D6
#define PIN_TOP_FLOAT        D2   //Also tried just  "0" and "4" with the same results.
#define PIN_BOTTOM_FLOAT     D3
#define BLUE_LED             D4

#define BLYNK_GREEN     "#23C48E"
#define BLYNK_BLUE      "#04C0F8"
#define BLYNK_YELLOW    "#ED9D00"
#define BLYNK_RED       "#D3435C"
#define BLYNK_DARK_BLUE "#5F7CD8"

/***************************************************
 *        Variable Settings
 **************************************************/

//#define FLOW_CALIBRATION 8.2 
#define FLOW_CALIBRATION 18.226

 
/***************************************************
 *        Blynk Virtual Pin Assignment
 **************************************************/

#define VPIN_TOTAL_LITERS_DRINK       V21
#define VPIN_FLOW_RATE_DRINK          V22
#define VPIN_FLOW_MILLI_LITERS_DRINK  V23 /**DONT THINK THIS IS USED**/
#define VPIN_SET_DRINK                V24


#define VPIN_TOTAL_LITERS_WASH        V25
#define VPIN_FLOW_RATE_WASH           V26
#define VPIN_FLOW_MILLI_LITERS_WASH   V27 /**DONT THINK THIS IS USED**/
#define VPIN_SET_WASH                 V28

#define VPIN_TOP_FLOAT                V30
#define VPIN_BOTTOM_FLOAT             V31

/***************************************************
 *        Server Settings
 **************************************************/
      
#define OTA_HOSTNAME "Blynk Wemos Water Flow Sensors"```

Why does topFloatTripped have brackets around it?`

I also noticed that in a couple of places you are using one ampersand in an if comparison, causing C++ to do a bitwise comparison…

Is this correct?

Pete.

Hi, I’ll be very interested in the outcome . . . I have a flow rate meter attached to Wemos D1 mini with the same issue of sporadic, random increment of total flow.

I have almost identical issues with rain gauge attached to ESP32, sporadic, random increment of total rainfall.

Both are hall-effect sensors attached to interrupts.

Both worked well and reliably on the test bench, both started playing up when installed. I believe it is related to electrical noise on the interrupt signal pin/cable. When I move, re-route or isolate the cable the amount of false reading varies noticeably.

For the water flow rate the false reading used to be in the order of a few litres/day . . . I recently added some additional equipment near the sensor (powered from a common power board, cables nearby etc) and the false reading have skyrocketed to tens-of-litres/day. . .

The senor pin cables on both sensors are quite long, I believe acting as antenna for electrical noise, therefore triggering the interrupts.

My next steps are to properly shield the cables (I may use Cat6A ground at both ends) and test from there.

Have you made any physical changes to your setup and/or new/associated devices that may be inducing noise?

Good Luck.

cul
billd

Stupid mistake…

Nope, Corrected.

I’ve spent a few hours cleaning up the code, removing useless redundant lines, and adding lots of clear debug prints.

I’ve also moved it to my local Blynk server and so I’ll let it go for a few days and see what happens.

Yes, our lost water was 20 to 30 liters at a time, all in a matter of minutes, faster than the water could possibly spin the flow meter.

Our flowmeters are connected directly to the GPIO, 4" or 10cm wire length, so I doubt that’s our problem.

I still kind of think it was the Blynk Server, and as I understand it they have a few on a CDN - So if the client connects to the wrong one or a different one it could get a crazy wrong / old number…

Like I said above, I made myself a local Blynk server and I’m working on a python script to scrape the values from my server and post it to the Blynk Cloud… I really just needed to get this done and get the YouTube video posted…

That’s not how it works.
There are 3 cloud servers, in New York, Frankfurt and Singapore. Your Blynk project only exists on one of these, and if your DNS server happens to resolve to the wrong on (either because you’ve travelled to a different part of the world, or your ISP is doing weird stuff), Blynk will redirect your connection request to the correct server.

Pete.

Cool, I stand happily corrected.

So I thought I’d licked it by switching to the local Blynk server… it seemed to work fine enough for a couple of days, but then this morning, I got up and turned on the screen, watching the serial debug data, and filled a kettle with water for coffee.

Note that the last water I used was last night at 18:15:18, Then at 03:35:28 it needed to reconnect to the server and it grabbed the last known values which were correct - I was happy with this and went ahead filling the kettle.

[18:15:17:851] Drinking Water Remaining: 35.76L␍␊
[18:15:18:360] Sending Values to Server␍␊
[18:15:18:360] Drinking Water = 35.76␍␊
[18:15:18:394] Wash Water = 23.50␍␊
[03:35:28:124] [60109974] Connecting to 192.168.10.100:8080␍␊
[03:35:28:158] [60109984] Ready (ping: 4ms).␍␊
[03:35:28:272] Retriving levels from server␍␊
[03:35:28:272] 35.76␍␊
[03:35:28:290] 23.50␍␊

Made the coffee and started getting camera gear ready to film this video, sipping on my coffee when out of the corner of my eye I see debug lines being written to the screen…

[07:48:40:590] Sending Values to Server␍␊
[07:48:40:590] Drinking Water = 34.79␍␊
[07:48:40:622] Wash Water = 22.47␍␊
[08:01:19:091] [76060541] Connecting to 192.168.10.100:8080␍␊
[08:01:19:125] [76060550] Ready (ping: 5ms).␍␊
[08:01:19:239] Retriving levels from server␍␊
[08:01:19:239] 34.79␍␊
[08:01:19:255] 22.47␍␊
[08:02:24:823] [76126271] Connecting to 192.168.10.100:8080␍␊
[08:02:24:857] [76126280] Ready (ping: 5ms).␍␊
[08:02:24:971] Retriving levels from server␍␊
[08:02:24:971] 33.82␍␊
[08:02:24:999] 21.43␍␊
[08:26:45:636] [77587045] Connecting to 192.168.10.100:8080␍␊
[08:26:45:663] [77587080] Ready (ping: 21ms).␍␊
[08:26:45:804] Retriving levels from server␍␊
[08:26:45:804] 32.85␍␊
[08:26:45:823] 20.40␍␊
[08:32:21:319] [77922726] Connecting to 192.168.10.100:8080␍␊
[08:32:21:353] [77922738] Ready (ping: 6ms).␍␊
[08:32:21:469] Retriving levels from server␍␊
[08:32:21:469] 31.89␍␊
[08:32:21:487] 19.37␍␊
[08:33:12:072] [77973478] Connecting to 192.168.10.100:8080␍␊
[08:33:12:106] [77973508] Ready (ping: 20ms).␍␊
[08:33:12:242] Retriving levels from server␍␊
[08:33:12:242] 30.92␍␊
[08:33:12:259] 18.34␍␊

I didn’t notice the events at 08:01, but at 08:26-33 I’m standing there watching it reconnecting to the server, and every time it’s lost a ~1ℓ of water from the count.

I’ve included the complete log from last night at 18:15 till now below, You can see I’ve got the DRINKpulseCount logging every pulse to the screen and it wasn’t seeing any flow - it’s only when it reconnects to the server that the level magically decreases. (although I have had it increase too, as I’ve mentioned before.)

18:15:16:921] Drinking Water =DRINKpulseCount = 1␍␊
[18:15:16:954]  35.76␍␊
[18:15:16:987] Wash Water = 23.50␍␊
[18:15:16:987] DRINKpulseCount = 2␍␊
[18:15:17:021] DRINKpulseCount = 3␍␊
[18:15:17:118] DRINKpulseCount = 4␍␊
[18:15:17:297] DRINKpulseCount = 5␍␊
[18:15:17:361] Sending Values to Server␍␊
[18:15:17:361] Drinking Water = 35.76␍␊
[18:15:17:394] Wash Water = 23.50␍␊
[18:15:17:645] DRINKpulseCount = 6␍␊
[18:15:17:817] Flowing: 0.3L/min␍␊
[18:15:17:817] Flowing: 5mL/Sec␍␊
[18:15:17:851] Drinking Water Remaining: 35.76L␍␊
[18:15:18:360] Sending Values to Server␍␊
[18:15:18:360] Drinking Water = 35.76␍␊literish
[18:15:18:394] Wash Water = 23.50␍␊
[03:35:28:124] [60109974] Connecting to 192.168.10.100:8080␍␊
[03:35:28:158] [60109984] Ready (ping: 4ms).␍␊
[03:35:28:272] Retriving levels from server␍␊
[03:35:28:272] 35.76␍␊
[03:35:28:290] 23.50␍␊
[07:48:29:010] DRINKpulseCount = 1␍␊
[07:48:29:043] DRINKpulseCount = 2␍␊
[07:48:29:043] DRINKpulseCount = 3␍␊
[07:48:29:076] DRINKpulseCount = 4␍␊
[07:48:29:076] DRINKpulseCount = 5␍␊
[07:48:29:110] DRINKpulseCount = 6␍␊
[07:48:29:144] DRINKpulseCount = 7␍␊
[07:48:29:144] DRINKpulseCount = 8␍␊
[07:48:29:177] DRINKpulseCount = 9␍␊
[07:48:29:209] DRINKpulseCount = 10␍␊
[07:48:29:209] DRINKpulseCount = 11␍␊
[07:48:29:243] DRINKpulseCount = 12␍␊
[07:48:29:277] DRINKpulseCount = 13␍␊
[07:48:29:310] DRINKpulseCount = 14␍␊
[07:48:29:310] DRINKpulseCount = 15␍␊
[07:48:29:344] DRINKpulseCount = 16␍␊
[07:48:29:376] Flowing: 0.8L/min␍␊
[07:48:29:376] Flowing: 14mL/Sec␍␊
[07:48:29:410] Drinking Water Remaining: 35.02L␍␊
[07:48:29:443] DRINKpulseCount = 1␍␊
[07:48:29:443] DRINKpulseCount = 2␍␊
[07:48:29:477] DRINKpulseCount = 3␍␊
[07:48:29:510] DRINKpulseCount = 4␍␊
[07:48:29:510] DRINKpulseCount = 5␍␊
[07:48:29:544] DRINKpulseCount = 6␍␊
[07:48:29:576] DRINKpulseCount = 7␍␊
[07:48:29:576] DRINKpulseCount = 8␍␊
[07:48:29:610] DRINKpulseCount = 9␍␊
[07:48:29:644] DRINKpulseCount = 10␍␊
[07:48:29:644] DRINKpulseCount = 11␍␊
[07:48:29:676] DRINKpulseCount = 12␍␊
[07:48:29:711] Sending DRINKpulseCount = 13␍␊
[07:48:29:743] DRINKpulseCount = 14␍␊
[07:48:29:743] DRINKpulseCount = 15␍␊
[07:48:29:777] ValuDRINKpulseCount = 16␍␊
[07:48:29:810] DRINKpulseCount = 17␍␊
[07:48:29:844] DRINKpulseCount = 18␍␊
[07:48:29:844] es tDRINKpulseCount = 19␍␊
[07:48:29:876] DRINKpulseCount = 20␍␊
[07:48:29:910] DRINKpulseCount = 21␍␊
[07:48:29:910] o SeDRINKpulseCount = 22␍␊
[07:48:29:943] DRINKpulseCount = 23␍␊
[07:48:29:977] DRINKpulseCount = 24␍␊
[07:48:30:010] rverDRINKpulseCount = 25␍␊
[07:48:30:010] DRINKpulseCount = 26␍␊
[07:48:30:043] DRINKpulseCount = 27␍␊
[07:48:30:077] ␍␊
[07:48:30:077] DrDRINKpulseCount = 28␍␊
[07:48:30:110] DRINKpulseCount = 29␍␊
[07:48:30:110] DRINKpulseCount = 30␍␊
[07:48:30:144] inkinDRINKpulseCount = 31␍␊
[07:48:30:176] DRINKpulseCount = 32␍␊
[07:48:30:210] g Water DRINKpulseCount = 33␍␊
[07:48:30:244] DRINKpulseCount = 34␍␊
[07:48:30:244] DRINKpulseCount = 35␍␊
[07:48:30:277] = 35.DRINKpulseCount = 36␍␊
[07:48:30:311] DRINKpulseCount = 37␍␊
[07:48:30:311] DRINKpulseCount = 38␍␊
[07:48:30:343] 02␍␊
[07:48:30:343] DRINKpulseCount = 39␍␊
[07:48:30:377] DRINKpulseCount = 40␍␊
[07:48:30:410] DRINKpulseCount = 41␍␊
[07:48:30:410] WashDRINKpulseCount = 42␍␊
[07:48:30:443] DRINKpulseCount = 43␍␊
[07:48:30:476] DRINKpulseCount = 44␍␊
[07:48:30:476]  WateDRINKpulseCount = 45␍␊
[07:48:30:510] DRINKpulseCount = 46␍␊
[07:48:30:543] DRINKpulseCount = 47␍␊
[07:48:30:577] r = DRINKpulseCount = 48␍␊
[07:48:30:609] DRINKpulseCount = 49␍␊
[07:48:30:609] DRINKpulseCount = 50␍␊
[07:48:30:643] 22.47DRINKpulseCount = 51␍␊
[07:48:30:676] DRINKpulseCount = 52␍␊
[07:48:30:676] DRINKpulseCount = 53␍␊
[07:48:30:710] ␍␊
[07:48:30:710] DRINKpulseCount = 54␍␊
[07:48:30:744] DRINKpulseCount = 55␍␊
[07:48:30:776] DRINKpulseCount = 56␍␊
[07:48:30:776] DRINKpulseCount = 57␍␊
[07:48:30:810] DRINKpulseCount = 58␍␊
[07:48:30:843] DRINKpulseCount = 59␍␊
[07:48:30:843] DRINKpulseCount = 60␍␊
[07:48:30:877] DRINKpulseCount = 61␍␊
[07:48:30:910] DRINKpulseCount = 62␍␊
[07:48:30:910] DRINKpulseCount = 63␍␊
[07:48:30:944] DRINKpulseCount = 64␍␊
[07:48:30:976] DRINKpulseCount = 65␍␊
[07:48:30:976] DRINKpulseCount = 66␍␊
[07:48:31:010] DRINKpulseCount = 67␍␊
[07:48:31:044] DRINKpulseCount = 68␍␊
[07:48:31:044] Flowing: 2.2L/min␍␊
[07:48:31:077] Flowing: 38mL/Sec␍␊
[07:48:31:110] Drinking Water Remaining: 34.99L␍␊
[07:48:31:143] SendiDRINKpulseCount = 1␍␊
[07:48:31:177] DRINKpulseCount = 2␍␊
[07:48:31:177] DRINKpulseCount = 3␍␊
[07:48:31:210] ng ValuDRINKpulseCount = 4␍␊
[07:48:31:243] DRINKpulseCount = 5␍␊
[07:48:31:243] DRINKpulseCount = 6␍␊
[07:48:31:276] es to SDRINKpulseCount = 7␍␊
[07:48:31:310] DRINKpulseCount = 8␍␊
[07:48:31:344] DRINKpulseCount = 9␍␊
[07:48:31:344] erver␍␊
[07:48:31:344] DDRINKpulseCount = 10␍␊
[07:48:31:376] DRINKpulseCount = 11␍␊
[07:48:31:410] DRINKpulseCount = 12␍␊
[07:48:31:443] rinkDRINKpulseCount = 13␍␊
[07:48:31:443] DRINKpulseCount = 14␍␊
[07:48:31:477] DRINKpulseCount = 15␍␊
[07:48:31:509] ing DRINKpulseCount = 16␍␊
[07:48:31:543] DRINKpulseCount = 17␍␊
[07:48:31:543] DRINKpulseCount = 18␍␊
[07:48:31:577] WaterDRINKpulseCount = 19␍␊
[07:48:31:610] DRINKpulseCount = 20␍␊
[07:48:31:610] DRINKpulseCount = 21␍␊
[07:48:31:644]  = 3DRINKpulseCount = 22␍␊
[07:48:31:676] DRINKpulseCount = 23␍␊
[07:48:31:710] DRINKpulseCount = 24␍␊
[07:48:31:710] 4.99DRINKpulseCount = 25␍␊
[07:48:31:743] DRINKpulseCount = 26␍␊
[07:48:31:777] DRINKpulseCount = 27␍␊
[07:48:31:809] ␍␊
[07:48:31:809] WasDRINKpulseCount = 28␍␊
[07:48:31:809] DRINKpulseCount = 29␍␊
[07:48:31:843] DRINKpulseCount = 30␍␊
[07:48:31:877] h WatDRINKpulseCount = 31␍␊
[07:48:31:910] DRINKpulseCount = 32␍␊
[07:48:31:910] DRINKpulseCount = 33␍␊
[07:48:31:944] er =DRINKpulseCount = 34␍␊
[07:48:31:976] DRINKpulseCount = 35␍␊
[07:48:31:976] DRINKpulseCount = 36␍␊
[07:48:32:010]  22.4DRINKpulseCount = 37␍␊
[07:48:32:043] DRINKpulseCount = 38␍␊
[07:48:32:077] DRINKpulseCount = 39␍␊
[07:48:32:077] 7␍␊
[07:48:32:077] DRINKpulseCount = 40␍␊
[07:48:32:109] DRINKpulseCount = 41␍␊
[07:48:32:143] DRINKpulseCount = 42␍␊
[07:48:32:176] DRINKpulseCount = 43␍␊
[07:48:32:176] DRINKpulseCount = 44␍␊
[07:48:32:210] DRINKpulseCount = 45␍␊
[07:48:32:243] DRINKpulseCount = 46␍␊
[07:48:32:243] DRINKpulseCount = 47␍␊
[07:48:32:276] DRINKpulseCount = 48␍␊
[07:48:32:310] DRINKpulseCount = 49␍␊
[07:48:32:310] DRINKpulseCount = 50␍␊
[07:48:32:343] DRINKpulseCount = 51␍␊
[07:48:32:377] DRINKpulseCount = 52␍␊
[07:48:32:377] DRINKpulseCount = 53␍␊
[07:48:32:409] DRINKpulseCount = 54␍␊
[07:48:32:443] Flowing: 2.1L/min␍␊
[07:48:32:443] Flowing: 35mL/Sec␍␊
[07:48:32:476] Drinking Water Remaining: 34.95L␍␊
[07:48:32:510] SendDRINKpulseCount = 1␍␊
[07:48:32:544] DRINKpulseCount = 2␍␊
[07:48:32:544] DRINKpulseCount = 3␍␊
[07:48:32:576] ing ValuDRINKpulseCount = 4␍␊
[07:48:32:610] DRINKpulseCount = 5␍␊
[07:48:32:643] DRINKpulseCount = 6␍␊
[07:48:32:643] es to SDRINKpulseCount = 7␍␊
[07:48:32:677] DRINKpulseCount = 8␍␊
[07:48:32:711] DRINKpulseCount = 9␍␊
[07:48:32:743] erver␍␊
[07:48:32:743] DDRINKpulseCount = 10␍␊
[07:48:32:743] DRINKpulseCount = 11␍␊
[07:48:32:789] DRINKpulseCount = 12␍␊
[07:48:32:832] rinkDRINKpulseCount = 13␍␊
[07:48:32:868] DRINKpulseCount = 14␍␊
[07:48:32:868] DRINKpulseCount = 15␍␊
[07:48:32:921] ing DRINKpulseCount = 16␍␊
[07:48:32:921] DRINKpulseCount = 17␍␊
[07:48:32:970] DRINKpulseCount = 18␍␊
[07:48:32:970] WateDRINKpulseCount = 19␍␊
[07:48:33:012] DRINKpulseCount = 20␍␊
[07:48:33:012] DRINKpulseCount = 21␍␊
[07:48:33:012] r = DRINKpulseCount = 22␍␊
[07:48:33:047] DRINKpulseCount = 23␍␊
[07:48:33:076] DRINKpulseCount = 24␍␊
[07:48:33:110] 34.9DRINKpulseCount = 25␍␊
[07:48:33:110] DRINKpulseCount = 26␍␊
[07:48:33:143] DRINKpulseCount = 27␍␊
[07:48:33:177] 5␍␊
[07:48:33:177] WaDRINKpulseCount = 28␍␊
[07:48:33:211] DRINKpulseCount = 29␍␊
[07:48:33:211] DRINKpulseCount = 30␍␊
[07:48:33:243] sh WaDRINKpulseCount = 31␍␊
[07:48:33:277] DRINKpulseCount = 32␍␊
[07:48:33:310] DRINKpulseCount = 33␍␊
[07:48:33:310] ter =DRINKpulseCount = 34␍␊
[07:48:33:344] DRINKpulseCount = 35␍␊
[07:48:33:376] DRINKpulseCount = 36␍␊
[07:48:33:376]  22.DRINKpulseCount = 37␍␊
[07:48:33:410] DRINKpulseCount = 38␍␊
[07:48:33:443] DRINKpulseCount = 39␍␊
[07:48:33:477] 47␍␊
[07:48:33:477] DRINKpulseCount = 40␍␊
[07:48:33:477] DRINKpulseCount = 41␍␊
[07:48:33:511] DRINKpulseCount = 42␍␊
[07:48:33:543] DRINKpulseCount = 43␍␊
[07:48:33:543] DRINKpulseCount = 44␍␊
[07:48:33:577] DRINKpulseCount = 45␍␊
[07:48:33:610] DRINKpulseCount = 46␍␊
[07:48:33:644] DRINKpulseCount = 47␍␊
[07:48:33:644] DRINKpulseCount = 48␍␊
[07:48:33:676] DRINKpulseCount = 49␍␊
[07:48:33:710] DRINKpulseCount = 50␍␊
[07:48:33:710] DRINKpulseCount = 51␍␊
[07:48:33:743] DRINKpulseCount = 52␍␊
[07:48:33:776] DRINKpulseCount = 53␍␊
[07:48:33:776] DRINKpulseCount = 54␍␊
[07:48:33:810] Flowing: 2.1L/min␍␊
[07:48:33:843] Flowing: 35mL/Sec␍␊
[07:48:33:843] Drinking Water Remaining: 34.92L␍␊
[07:48:33:877] SendiDRINKpulseCount = 1␍␊
[07:48:33:910] DRINKpulseCount = 2␍␊
[07:48:33:944] DRINKpulseCount = 3␍␊
[07:48:33:944] ng ValuDRINKpulseCount = 4␍␊
[07:48:33:978] DRINKpulseCount = 5␍␊
[07:48:34:010] DRINKpulseCount = 6␍␊
[07:48:34:043] es to SeDRINKpulseCount = 7␍␊
[07:48:34:076] DRINKpulseCount = 8␍␊
[07:48:34:076] DRINKpulseCount = 9␍␊
[07:48:34:110] rver␍␊
[07:48:34:110] DrDRINKpulseCount = 10␍␊
[07:48:34:143] DRINKpulseCount = 11␍␊
[07:48:34:143] DRINKpulseCount = 12␍␊
[07:48:34:177] inkiDRINKpulseCount = 13␍␊
[07:48:34:209] DRINKpulseCount = 14␍␊
[07:48:34:243] DRINKpulseCount = 15␍␊
[07:48:34:243] ng WaDRINKpulseCount = 16␍␊
[07:48:34:276] DRINKpulseCount = 17␍␊
[07:48:34:310] DRINKpulseCount = 18␍␊
[07:48:34:344] ter =DRINKpulseCount = 19␍␊
[07:48:34:344] DRINKpulseCount = 20␍␊
[07:48:34:377] DRINKpulseCount = 21␍␊
[07:48:34:411]  34.DRINKpulseCount = 22␍␊
[07:48:34:443] DRINKpulseCount = 23␍␊
[07:48:34:443] DRINKpulseCount = 24␍␊
[07:48:34:477] 92␍␊
[07:48:34:477] WDRINKpulseCount = 25␍␊
[07:48:34:510] DRINKpulseCount = 26␍␊
[07:48:34:510] DRINKpulseCount = 27␍␊
[07:48:34:544] ash WaDRINKpulseCount = 28␍␊
[07:48:34:576] DRINKpulseCount = 29␍␊
[07:48:34:610] DRINKpulseCount = 30␍␊
[07:48:34:610] ter DRINKpulseCount = 31␍␊
[07:48:34:643] DRINKpulseCount = 32␍␊
[07:48:34:677] DRINKpulseCount = 33␍␊
[07:48:34:711] = 22.DRINKpulseCount = 34␍␊
[07:48:34:711] DRINKpulseCount = 35␍␊
[07:48:34:743] DRINKpulseCount = 36␍␊
[07:48:34:777] 47␍␊
[07:48:34:777] DRINKpulseCount = 37␍␊
[07:48:34:810] DRINKpulseCount = 38␍␊
[07:48:34:810] DRINKpulseCount = 39␍␊
[07:48:34:844] DRINKpulseCount = 40␍␊
[07:48:34:876] DRINKpulseCount = 41␍␊
[07:48:34:876] DRINKpulseCount = 42␍␊
[07:48:34:910] DRINKpulseCount = 43␍␊
[07:48:34:943] DRINKpulseCount = 44␍␊
[07:48:34:943] DRINKpulseCount = 45␍␊
[07:48:34:977] DRINKpulseCount = 46␍␊
[07:48:35:010] DRINKpulseCount = 47␍␊
[07:48:35:043] DRINKpulseCount = 48␍␊
[07:48:35:043] DRINKpulseCount = 49␍␊
[07:48:35:077] DRINKpulseCount = 50␍␊
[07:48:35:110] DRINKpulseCount = 51␍␊
[07:48:35:110] Flowing: 2.1L/min␍␊
[07:48:35:144] Flowing: 35mL/Sec␍␊
[07:48:35:144] Drinking Water Remaining: 34.88L␍␊
[07:48:35:210] SendinDRINKpulseCount = 1␍␊
[07:48:35:210] DRINKpulseCount = 2␍␊
[07:48:35:243] DRINKpulseCount = 3␍␊
[07:48:35:277] DRINKpulseCount = 4␍␊
[07:48:35:277] g ValDRINKpulseCount = 5␍␊
[07:48:35:309] DRINKpulseCount = 6␍␊
[07:48:35:343] DRINKpulseCount = 7␍␊
[07:48:35:343] ues to SDRINKpulseCount = 8␍␊
[07:48:35:377] DRINKpulseCount = 9␍␊
[07:48:35:410] DRINKpulseCount = 10␍␊
[07:48:35:444] erver␍␊
[07:48:35:444] DRINKpulseCount = 11␍␊
[07:48:35:476] DRINKpulseCount = 12␍␊
[07:48:35:476] DRINKpulseCount = 13␍␊
[07:48:35:510] DrinkDRINKpulseCount = 14␍␊
[07:48:35:543] DRINKpulseCount = 15␍␊
[07:48:35:577] DRINKpulseCount = 16␍␊
[07:48:35:577] ing WDRINKpulseCount = 17␍␊
[07:48:35:609] DRINKpulseCount = 18␍␊
[07:48:35:643] DRINKpulseCount = 19␍␊
[07:48:35:643] ater DRINKpulseCount = 20␍␊
[07:48:35:677] DRINKpulseCount = 21␍␊
[07:48:35:710] DRINKpulseCount = 22␍␊
[07:48:35:744] = 34.DRINKpulseCount = 23␍␊
[07:48:35:744] DRINKpulseCount = 24␍␊
[07:48:35:776] DRINKpulseCount = 25␍␊
[07:48:35:810] 88␍␊
[07:48:35:810] WDRINKpulseCount = 26␍␊
[07:48:35:843] DRINKpulseCount = 27␍␊
[07:48:35:843] DRINKpulseCount = 28␍␊
[07:48:35:876] ash WDRINKpulseCount = 29␍␊
[07:48:35:909] DRINKpulseCount = 30␍␊
[07:48:35:943] DRINKpulseCount = 31␍␊
[07:48:35:943] aterDRINKpulseCount = 32␍␊
[07:48:35:977] DRINKpulseCount = 33␍␊
[07:48:36:010] DRINKpulseCount = 34␍␊
[07:48:36:010]  = 22DRINKpulseCount = 35␍␊
[07:48:36:043] DRINKpulseCount = 36␍␊
[07:48:36:076] DRINKpulseCount = 37␍␊
[07:48:36:110] .47␍␊
[07:48:36:110] DRINKpulseCount = 38␍␊
[07:48:36:143] DRINKpulseCount = 39␍␊
[07:48:36:143] DRINKpulseCount = 40␍␊
[07:48:36:177] DRINKpulseCount = 41␍␊
[07:48:36:209] DRINKpulseCount = 42␍␊
[07:48:36:209] DRINKpulseCount = 43␍␊
[07:48:36:243] DRINKpulseCount = 44␍␊
[07:48:36:277] DRINKpulseCount = 45␍␊
[07:48:36:277] DRINKpulseCount = 46␍␊
[07:48:36:310] DRINKpulseCount = 47␍␊
[07:48:36:343] DRINKpulseCount = 48␍␊
[07:48:36:343] DRINKpulseCount = 49␍␊
[07:48:36:377] DRINKpulseCount = 50␍␊
[07:48:36:409] DRINKpulseCount = 51␍␊
[07:48:36:409] DRINKpulseCount = 52␍␊
[07:48:36:443] Flowing: 2.1L/min␍␊
[07:48:36:476] Flowing: 35mL/Sec␍␊
[07:48:36:476] Drinking Water Remaining: 34.85L␍␊
[07:48:36:515] SendiDRINKpulseCount = 1␍␊
[07:48:36:543] DRINKpulseCount = 2␍␊
[07:48:36:576] DRINKpulseCount = 3␍␊
[07:48:36:610] ng ValueDRINKpulseCount = 4␍␊
[07:48:36:610] DRINKpulseCount = 5␍␊
[07:48:36:643] DRINKpulseCount = 6␍␊
[07:48:36:677] s to SeDRINKpulseCount = 7␍␊
[07:48:36:715] DRINKpulseCount = 8␍␊
[07:48:36:715] DRINKpulseCount = 9␍␊
[07:48:36:743] rver␍␊
[07:48:36:743] DrDRINKpulseCount = 10␍␊
[07:48:36:776] DRINKpulseCount = 11␍␊
[07:48:36:810] DRINKpulseCount = 12␍␊
[07:48:36:810] inkinDRINKpulseCount = 13␍␊
[07:48:36:844] DRINKpulseCount = 14␍␊
[07:48:36:876] DRINKpulseCount = 15␍␊
[07:48:36:876] g WatDRINKpulseCount = 16␍␊
[07:48:36:911] DRINKpulseCount = 17␍␊
[07:48:36:944] DRINKpulseCount = 18␍␊
[07:48:36:976] er = DRINKpulseCount = 19␍␊
[07:48:37:010] DRINKpulseCount = 20␍␊
[07:48:37:010] DRINKpulseCount = 21␍␊
[07:48:37:043] 34.85␍DRINKpulseCount = 22␍␊
[07:48:37:077] DRINKpulseCount = 23␍␊
[07:48:37:077] DRINKpulseCount = 24␍␊
[07:48:37:109] ␊
[07:48:37:109] WasDRINKpulseCount = 25␍␊
[07:48:37:143] DRINKpulseCount = 26␍␊
[07:48:37:176] DRINKpulseCount = 27␍␊
[07:48:37:176] h WatDRINKpulseCount = 28␍␊
[07:48:37:210] DRINKpulseCount = 29␍␊
[07:48:37:244] DRINKpulseCount = 30␍␊
[07:48:37:276] er = DRINKpulseCount = 31␍␊
[07:48:37:276] DRINKpulseCount = 32␍␊
[07:48:37:310] DRINKpulseCount = 33␍␊
[07:48:37:343] 22.47DRINKpulseCount = 34␍␊
[07:48:37:377] DRINKpulseCount = 35␍␊
[07:48:37:377] DRINKpulseCount = 36␍␊
[07:48:37:409] ␍␊
[07:48:37:409] DRINKpulseCount = 37␍␊
[07:48:37:443] DRINKpulseCount = 38␍␊
[07:48:37:443] DRINKpulseCount = 39␍␊
[07:48:37:477] DRINKpulseCount = 40␍␊
[07:48:37:510] DRINKpulseCount = 41␍␊
[07:48:37:544] DRINKpulseCount = 42␍␊
[07:48:37:544] DRINKpulseCount = 43␍␊
[07:48:37:576] DRINKpulseCount = 44␍␊
[07:48:37:610] DRINKpulseCount = 45␍␊
[07:48:37:610] DRINKpulseCount = 46␍␊
[07:48:37:643] DRINKpulseCount = 47␍␊
[07:48:37:677] DRINKpulseCount = 48␍␊
[07:48:37:677] DRINKpulseCount = 49␍␊
[07:48:37:710] DRINKpulseCount = 50␍␊
[07:48:37:743] DRINKpulseCount = 51␍␊
[07:48:37:743] DRINKpulseCount = 52␍␊
[07:48:37:776] Flowing: 2.1L/min␍␊
[07:48:37:810] Flowing: 35mL/Sec␍␊
[07:48:37:810] Drinking Water Remaining: 34.81L␍␊
[07:48:37:844] SendDRINKpulseCount = 1␍␊
[07:48:37:876] DRINKpulseCount = 2␍␊
[07:48:37:910] DRINKpulseCount = 3␍␊
[07:48:37:910] ing ValuDRINKpulseCount = 4␍␊
[07:48:37:943] DRINKpulseCount = 5␍␊
[07:48:37:977] DRINKpulseCount = 6␍␊
[07:48:38:009] es to SeDRINKpulseCount = 7␍␊
[07:48:38:043] DRINKpulseCount = 8␍␊
[07:48:38:043] DRINKpulseCount = 9␍␊
[07:48:38:077] rver␍␊
[07:48:38:077] DrDRINKpulseCount = 10␍␊
[07:48:38:110] DRINKpulseCount = 11␍␊
[07:48:38:110] DRINKpulseCount = 12␍␊
[07:48:38:144] inking WDRINKpulseCount = 13␍␊
[07:48:38:176] DRINKpulseCount = 14␍␊
[07:48:38:210] DRINKpulseCount = 15␍␊
[07:48:38:210] ater DRINKpulseCount = 16␍␊
[07:48:38:243] = 34.8DRINKpulseCount = 17␍␊
[07:48:38:277] 1␍␊
[07:48:38:277] Wash WDRINKpulseCount = 18␍␊
[07:48:38:309] ater = 22.47␍␊
[07:48:38:343] DRINKpulseCount = 19␍␊
[07:48:38:343] DRINKpulseCount = 20␍␊
[07:48:38:377] DRINKpulseCount = 21␍␊
[07:48:38:410] DRINKpulseCount = 22␍␊
[07:48:38:410] DRINKpulseCount = 23␍␊
[07:48:38:502] DRINKpulseCount = 24␍␊
[07:48:38:589] Sending Values to Server␍␊
[07:48:38:589] Drinking Water = 34.81␍␊
[07:48:38:623] Wash Water = 22.47␍␊
[07:48:38:654] DRINKpulseCount = 25␍␊
[07:48:38:736] DRINKpulseCount = 26␍␊
[07:48:38:792] Flowing: 1.2L/min␍␊
[07:48:38:792] Flowing: 21mL/Sec␍␊
[07:48:38:825] Drinking Water Remaining: 34.79L␍␊
[07:48:38:917] DRINKpulseCount = 1␍␊
[07:48:39:589] Sending Values to Server␍␊
[07:48:39:589] Drinking Water = 34.79␍␊
[07:48:39:622] Wash Water = 22.47␍␊
[07:48:39:995] Flowing: 0.0L/min␍␊
[07:48:39:995] Flowing: 0mL/Sec␍␊
[07:48:40:028] Drinking Water Remaining: 34.79L␍␊
[07:48:40:590] Sending Values to Server␍␊
[07:48:40:590] Drinking Water = 34.79␍␊
[07:48:40:622] Wash Water = 22.47␍␊
[08:01:19:091] [76060541] Connecting to 192.168.10.100:8080␍␊
[08:01:19:125] [76060550] Ready (ping: 5ms).␍␊
[08:01:19:239] Retriving levels from server␍␊
[08:01:19:239] 34.79␍␊
[08:01:19:255] 22.47␍␊
[08:02:24:823] [76126271] Connecting to 192.168.10.100:8080␍␊
[08:02:24:857] [76126280] Ready (ping: 5ms).␍␊
[08:02:24:971] Retriving levels from server␍␊
[08:02:24:971] 33.82␍␊
[08:02:24:999] 21.43␍␊
[08:26:45:636] [77587045] Connecting to 192.168.10.100:8080␍␊
[08:26:45:663] [77587080] Ready (ping: 21ms).␍␊
[08:26:45:804] Retriving levels from server␍␊
[08:26:45:804] 32.85␍␊
[08:26:45:823] 20.40␍␊
[08:32:21:319] [77922726] Connecting to 192.168.10.100:8080␍␊
[08:32:21:353] [77922738] Ready (ping: 6ms).␍␊
[08:32:21:469] Retriving levels from server␍␊
[08:32:21:469] 31.89␍␊
[08:32:21:487] 19.37␍␊
[08:33:12:072] [77973478] Connecting to 192.168.10.100:8080␍␊
[08:33:12:106] [77973508] Ready (ping: 20ms).␍␊
[08:33:12:242] Retriving levels from server␍␊
[08:33:12:242] 30.92␍␊
[08:33:12:259] 18.34␍␊

Here is the current code:

/*
  Using Code modified from:
  Blynk Flow Sensor Water Meter- Calculates Total Water Consumption.
  Source: https://github.com/pkarun/Blynk-Flow-Sensor-Water-Meter
*/

#define BLYNK_PRINT Serial           // Uncomment for debugging

#include "settings.h"
#include "secret.h"   // <<--- UNCOMMENT this before you use and change values on config.h tab

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266mDNS.h>  // For OTA with ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

BlynkTimer timer;
bool BLYNKneedsZero = 0;
int topFloatTripped = 0;
int bottomFloatTripped = 0;
volatile long DRINKpulseCount = 0;
volatile long WASHpulseCount = 0;
float DRINKflowRate;
float WASHflowRate;
unsigned int DRINKflowMilliLitres;
unsigned int WASHflowMilliLitres;
unsigned long DRINKtotalMilliLitres;
unsigned long WASHtotalMilliLitres;
float DRINKtotalLitres;
float WASHtotalLitres;
float DRINKtotalLitresold;
float WASHtotalLitresold;
unsigned long DRINKoldTime;
unsigned long WASHoldTime;


BLYNK_CONNECTED() { // runs once at device startup, once connected to server.

  Blynk.syncVirtual(VPIN_TOTAL_LITERS_DRINK, VPIN_TOTAL_LITERS_WASH); //gets last know value of virtual pins
}

// Restores last known liter count values from the virtual pin on the Blynk server
BLYNK_WRITE(VPIN_TOTAL_LITERS_DRINK)
{
  DRINKtotalLitresold = param.asFloat();
  Serial.println("Retriving levels from server");
  Serial.println(DRINKtotalLitresold);

}

BLYNK_WRITE(VPIN_TOTAL_LITERS_WASH)
{
  WASHtotalLitresold = param.asFloat();
  Serial.println(WASHtotalLitresold);
}

BLYNK_WRITE(VPIN_SET_DRINK) {  // Set Water Level in PUSH mode on virtual pin V24
  int setLitersDrink = param.asInt();
  Serial.print("Setting Drinking Water Level to ");
  Serial.println(setLitersDrink);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, setLitersDrink);
  DRINKtotalLitres = setLitersDrink;
  DRINKtotalLitresold = setLitersDrink;
  Blynk.virtualWrite(VPIN_SET_DRINK, " ");
  topFloatTripped = 0;
  bottomFloatTripped = 0;
  Blynk.virtualWrite(VPIN_TOP_FLOAT, 0);
  Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 0);
  Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_BLUE);
}

BLYNK_WRITE(VPIN_SET_WASH) {  // Set Water Level in PUSH mode on virtual pin V24
  int setLitersWASH = param.asInt();
  Serial.print("Setting Washing Water Level to ");
  Serial.println(setLitersWASH);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, setLitersWASH);
  WASHtotalLitres = setLitersWASH;
  WASHtotalLitresold = setLitersWASH;
  Blynk.virtualWrite(VPIN_SET_WASH, " ");
}

void ICACHE_RAM_ATTR DRINKpulseCounter()
{
  DRINKpulseCount++;
  Serial.print("DRINKpulseCount = ");
  Serial.println(DRINKpulseCount);
}
void ICACHE_RAM_ATTR WASHpulseCounter()
{
  WASHpulseCount++;
  Serial.print("WASHpulseCount = ");
  Serial.println(WASHpulseCount);
}

void flow()
{
  if ((millis() - DRINKoldTime) > 1000)   // Only process counters once per second
  {
    detachInterrupt(PULSE_PIN_DRINK);
    DRINKflowRate = ((1000.0 / (millis() - DRINKoldTime)) * DRINKpulseCount) / FLOW_CALIBRATION;
    DRINKoldTime = millis();
    DRINKflowMilliLitres = (DRINKflowRate / 60) * 1000;
    DRINKtotalMilliLitres += DRINKflowMilliLitres;
    DRINKtotalLitres = DRINKtotalLitresold - DRINKtotalMilliLitres * 0.001; // CHANGED THIS TO SUBTRACT AS WE WANT TO COUNT DOWN
    unsigned int frac;

    if (DRINKflowRate > 0) {
      // Print the flow rate for this second in liters / minute
      Serial.print("Flowing: ");
      Serial.print(int(DRINKflowRate));  // Print the integer part of the variable

      Serial.print(".");             // Print the decimal point
      frac = (DRINKflowRate - int(DRINKflowRate)) * 10; // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
      Serial.print(frac, DEC) ;      // Print the fractional part of the variable
      Serial.println("L/min");

      Serial.print("Flowing: ");  // Print the number of liters flowed in this second
      Serial.print(DRINKflowMilliLitres);
      Serial.println("mL/Sec");

      Serial.print("Drinking Water Remaining: ");  // Print the cumulative total of liters flowed since starting
      Serial.print(DRINKtotalLitres);
      Serial.println("L");
    }

    DRINKpulseCount = 0;  // Reset the pulse counter so we can start incrementing again

    attachInterrupt(PULSE_PIN_DRINK, DRINKpulseCounter, FALLING);    // Enable the interrupt again now that we've finished sending output

    detachInterrupt(PULSE_PIN_WASH);
    WASHflowRate = ((1000.0 / (millis() - WASHoldTime)) * WASHpulseCount) / FLOW_CALIBRATION;
    WASHoldTime = millis();
    WASHflowMilliLitres = (WASHflowRate / 60) * 1000;
    WASHtotalMilliLitres += WASHflowMilliLitres;
    WASHtotalLitres = WASHtotalLitresold - WASHtotalMilliLitres * 0.001; // CHANGED THIS TO SUBTRACT AS WE WANT TO COUNT DOWN

    if (WASHflowRate > 0) {

      // Print the flow rate for this second in liters/minute
      Serial.print("Flowing: ");
      Serial.print(int(WASHflowRate));  // Print the integer part of the variable

      Serial.print(".");             // Print the decimal point
      frac = (WASHflowRate - int(WASHflowRate)) * 10; // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
      Serial.print(frac, DEC) ;      // Print the fractional part of the variable
      Serial.println("L/min");

      Serial.print("Flowing: ");  // Print the number of liters flowed in this second
      Serial.print(WASHflowMilliLitres);
      Serial.println("mL/Sec");

      Serial.print("Washing Water Remaining: ");  // Print the cumulative total of liters flowed since starting
      Serial.print(WASHtotalLitres);
      Serial.println("L");
    }

    WASHpulseCount = 0;  // Reset the pulse counter so we can start incrementing again
    attachInterrupt(PULSE_PIN_WASH, WASHpulseCounter, FALLING);    // Enable the interrupt again now that we've finished sending output
  }
}

void sendtoBlynk()  // In this function we are sending values to blynk server
{
  if (digitalRead(PIN_TOP_FLOAT) == 0 && topFloatTripped == 0) //When the Top float trips for the first time.
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 255);
    Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_YELLOW);
    DRINKtotalLitres = 19;
    DRINKtotalLitresold = 19;
    topFloatTripped = 1;
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);          //update new water level
    Blynk.notify("30% Water Level Float Tripped");
    Serial.print("30% Water Level Float Tripped at ");  // Print the cumulative total of liters flowed since starting
  }
  else if (digitalRead(PIN_TOP_FLOAT) == 1 && topFloatTripped == 1) // When it Un-Trips, ie; goes back up or sloshes
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 0);
  }
  else if (digitalRead(PIN_TOP_FLOAT) == 0 && topFloatTripped == 1) // Then It goes down again...
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 255);
  }

  if (digitalRead(PIN_BOTTOM_FLOAT) == 0 && bottomFloatTripped == 0)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 255);
    digitalWrite(BLUE_LED, LOW); // LED On - Stupid LED is inverted
    Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_RED);
    DRINKtotalLitres = 10;
    DRINKtotalLitresold = 10;
    bottomFloatTripped = 1;
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);   //update new water level
    Blynk.notify("15% Water Level Float Tripped");
    Serial.print("15% Water Level Float Tripped at ");  // Print the liters it thought was remaining when the float tripped.
    Serial.println(DRINKtotalLitres);
  }
  else if (digitalRead(PIN_BOTTOM_FLOAT) == 1 && bottomFloatTripped == 1)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 0);
    digitalWrite(BLUE_LED, HIGH); // LED Off - Stupid LED is inverted
  }
  else if (digitalRead(PIN_BOTTOM_FLOAT) == 0 && bottomFloatTripped == 1)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 255);
    digitalWrite(BLUE_LED, LOW); // LED On - Stupid LED is inverted
  }

  if (WASHflowRate != 0 || DRINKflowRate != 0) {
    Serial.println("Sending Values to Server");
    Serial.print("Drinking Water = ");
    Serial.println(DRINKtotalLitres);
    Serial.print("Wash Water = ");
    Serial.println(WASHtotalLitres);
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);  // Total water consumption in liters (L)
    Blynk.virtualWrite(VPIN_FLOW_RATE_DRINK, DRINKflowRate);     // Displays the flow rate for this second in liters / minute (L/min)
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, WASHtotalLitres); // Total water consumption in liters (L)
    Blynk.virtualWrite(VPIN_FLOW_RATE_WASH, WASHflowRate);  // Displays the flow rate for this second in liters / minute (L/min)
    BLYNKneedsZero = 1;
  }
  if (WASHflowRate == 0 && DRINKflowRate == 0 && BLYNKneedsZero == 1) {
    Blynk.virtualWrite(VPIN_FLOW_RATE_DRINK, DRINKflowRate);   // Sends Zeros for the flow rates to make the interface nice.
    Blynk.virtualWrite(VPIN_FLOW_RATE_WASH, WASHflowRate);
    BLYNKneedsZero = 0;
  }
}

void CronJob1Min()
{
  float BatteryVoltage = (analogRead(PIN_CHASSIS_VOLTAGE)) * 0.01554955;
  Blynk.virtualWrite(V10, BatteryVoltage);
//  if (BatteryVoltage < 12); {
//    //Blynk.notify("Chassis Battery Below 12 Volts");
//    //Blynk.notify(BatteryVoltage);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres); //Updating server once a minute to keep the chart nice
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, WASHtotalLitres); //Updating server once a minute to keep the chart nice
}

void setup()
{
  Serial.begin(9600);
  Blynk.begin(AUTH, WIFI_SSID, WIFI_PASS, SERVER, PORT);
  ArduinoOTA.setHostname(OTA_HOSTNAME);  // For OTA - Use your own device identifying name
  ArduinoOTA.begin();  // For OTA

  pinMode(BLUE_LED, OUTPUT);
  digitalWrite(BLUE_LED, HIGH); // LED Off - Stupid LED is inverted
  pinMode(PULSE_PIN_DRINK, INPUT_PULLUP);  // Initialization of the variable "PULSE_PIN_DRINK" as INPUT
  pinMode(PULSE_PIN_WASH, INPUT_PULLUP);  // Initialization of the variable "PULSE_PIN_DRINK" as INPUT

  pinMode(PIN_TOP_FLOAT, INPUT_PULLUP);  // Initialization of the variable "PIN_TOP_FLOAT" as INPUT
  pinMode(PIN_BOTTOM_FLOAT, INPUT_PULLUP);  // Initialization of the variable "PIN_BOTTOM_FLOAT" as INPUT

  attachInterrupt(PULSE_PIN_DRINK, DRINKpulseCounter, FALLING);
  attachInterrupt(PULSE_PIN_WASH, WASHpulseCounter, FALLING);

  timer.setInterval(1000L, sendtoBlynk); // send values blynk server every sec (if it needs updating)
  timer.setInterval(60000L, CronJob1Min); // send values blynk server every 60 sec

}


void loop()
{

  Blynk.run();
  ArduinoOTA.handle();  // For OTA
  timer.run();
  flow();

}

I just tested repeatedly pressing the reset button, watching it boot, connect and get the values from the server correctly 50+ times. It must be whatever is causing it to disconnect in the first place.

I’m not really keen on your flow() function being called from your void loop. As I said before, i think it ought to be called by a timer. I think you could also simplify the logic by always writing the current values to Blynk when flow() executes.

I’m also unhappy about the way that you’re disabling and re-enabling the interrupts in flow().
The idea is that you don’t want the code execution to be diverted away from flow() by having an interrupt firing. So, to do this correctly you should be disabling both interrupts at the beginning, then reinstating them at the end of the function.

You could do this in a simpletway by using noInterrupts(); and Interrupts();

  noInterrupts();
    // your critical, time-sensitive code here
  interrupts();

Have you checked for a correlation between battery voltage and disconnections?

Pete.

I generally learn best by example and thus kept the flow() function as it was in the original code at GitHub - pkarun/Blynk-Flow-Sensor-Water-Meter: Blynk flow sensor water meter to measure water consumption using Blynk, NodeMCU and Water Flow Sensor (I used YF-S201B).

But I think I’ve made all the changes you’ve suggested now in the below code and we’ll see if that has any effect of this issue.

Handy! Implemented!

I had it writing serial debugs for a while but it cluttered it up, so I’ve commented it out for now.

If you’d be so kind as to confirm I’ve made these changes correctly as you suggested and I hope to come back with a good report soon.

/*
  Using Code now heavily modified, but based on:
  Blynk Flow Sensor Water Meter- Calculates Total Water Consumption.
  Source: https://github.com/pkarun/Blynk-Flow-Sensor-Water-Meter
*/

#define BLYNK_PRINT Serial           // Uncomment for debugging

#include "settings.h"
#include "secret.h"   // <<--- This file contains the secret Blynk Auth code and WiFi Credentials

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266mDNS.h>  // For OTA with ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

BlynkTimer timer;
bool BLYNKneedsZero = 0;
bool topFloatTripped = 0;
bool bottomFloatTripped = 0;
float DRINKflowRate;
float WASHflowRate;
float DRINKtotalLitres;
float WASHtotalLitres;
float DRINKtotalLitresold;
float WASHtotalLitresold;
unsigned int frac;
unsigned int DRINKflowMilliLitres;
unsigned int WASHflowMilliLitres;
unsigned long DRINKtotalMilliLitres;
unsigned long WASHtotalMilliLitres;
unsigned long DRINKoldTime;
unsigned long WASHoldTime;
volatile long DRINKpulseCount = 0;
volatile long WASHpulseCount = 0;

BLYNK_CONNECTED() { // runs once at device startup, once connected to server.

  Blynk.syncVirtual(VPIN_TOTAL_LITERS_DRINK, VPIN_TOTAL_LITERS_WASH); //gets last known value of virtual pins
}

// Restores last known liter count values from the virtual pin on the Blynk server
BLYNK_WRITE(VPIN_TOTAL_LITERS_DRINK)
{
  DRINKtotalLitresold = param.asFloat();
  Serial.println("Retrieving levels from server");
  Serial.println(DRINKtotalLitresold);

}

BLYNK_WRITE(VPIN_TOTAL_LITERS_WASH)
{
  WASHtotalLitresold = param.asFloat();
  Serial.println(WASHtotalLitresold);
}

BLYNK_WRITE(VPIN_SET_DRINK) {  // Set Water Level in PUSH mode on virtual pin V24
  int setLitersDrink = param.asInt();
  Serial.print("Setting Drinking Water Level to ");
  Serial.println(setLitersDrink);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, setLitersDrink);
  DRINKtotalLitres = setLitersDrink;
  DRINKtotalLitresold = setLitersDrink;
  Blynk.virtualWrite(VPIN_SET_DRINK, " ");
  topFloatTripped = 0;
  bottomFloatTripped = 0;
  Blynk.virtualWrite(VPIN_TOP_FLOAT, 0);
  Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 0);
  Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_BLUE);
}

BLYNK_WRITE(VPIN_SET_WASH) {  // Set Water Level in PUSH mode on virtual pin V24
  int setLitersWASH = param.asInt();
  Serial.print("Setting Washing Water Level to ");
  Serial.println(setLitersWASH);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, setLitersWASH);
  WASHtotalLitres = setLitersWASH;
  WASHtotalLitresold = setLitersWASH;
  Blynk.virtualWrite(VPIN_SET_WASH, " ");
}

void ICACHE_RAM_ATTR DRINKpulseCounter()
{
  DRINKpulseCount++;
  Serial.print("DRINKpulseCount = ");
  Serial.println(DRINKpulseCount);
}
void ICACHE_RAM_ATTR WASHpulseCounter()
{
  WASHpulseCount++;
  Serial.print("WASHpulseCount = ");
  Serial.println(WASHpulseCount);
}

void sendtoBlynk()
{
  noInterrupts(); // Disable the interrupts for a scoach....
  DRINKflowRate = ((1000.0 / (millis() - DRINKoldTime)) * DRINKpulseCount) / FLOW_CALIBRATION;
  DRINKoldTime = millis();
  DRINKflowMilliLitres = (DRINKflowRate / 60) * 1000;
  DRINKtotalMilliLitres += DRINKflowMilliLitres;
  DRINKtotalLitres = DRINKtotalLitresold - DRINKtotalMilliLitres * 0.001;

  if (DRINKflowRate > 0) {
    Serial.print("Flowing: ");     // Print the flow rate for this second in liters / minute
    Serial.print(int(DRINKflowRate));  // Print the integer part of the variable
    Serial.print(".");             // Print the decimal point
    frac = (DRINKflowRate - int(DRINKflowRate)) * 10; // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    Serial.print(frac, DEC) ;      // Print the fractional part of the variable
    Serial.println("L/min");
    Serial.print("Flowing: ");  // Print the number of mL flowed in this second
    Serial.print(DRINKflowMilliLitres);
    Serial.println("mL/Sec");
    Serial.print("Drinking Water Remaining: ");  // Print the drinking water remaining
    Serial.print(DRINKtotalLitres);
    Serial.println("L");
  }
  DRINKpulseCount = 0;  // Reset the pulse counter so we can start incrementing again


  // Now we check if the wash water is flowing...
  WASHflowRate = ((1000.0 / (millis() - WASHoldTime)) * WASHpulseCount) / FLOW_CALIBRATION;
  WASHoldTime = millis();
  WASHflowMilliLitres = (WASHflowRate / 60) * 1000;
  WASHtotalMilliLitres += WASHflowMilliLitres;
  WASHtotalLitres = WASHtotalLitresold - WASHtotalMilliLitres * 0.001;

  if (WASHflowRate > 0) {
    Serial.print("Flowing: ");     // Print the flow rate for this second in liters/minute
    Serial.print(int(WASHflowRate));  // Print the integer part of the variable
    Serial.print(".");             // Print the decimal point
    frac = (WASHflowRate - int(WASHflowRate)) * 10; // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    Serial.print(frac, DEC) ;      // Print the fractional part of the variable
    Serial.println("L/min");
    Serial.print("Flowing: ");     // Print the number of mL flowed in this second
    Serial.print(WASHflowMilliLitres);
    Serial.println("mL/Sec");
    Serial.print("Washing Water Remaining: ");  // Print the wash water remaining
    Serial.print(WASHtotalLitres);
    Serial.println("L");
  }

  WASHpulseCount = 0;  // Reset the pulse counter so we can start incrementing again

  interrupts();  //Re-enable the interrupts

  // Here we check if either of the level floats have tripped and adjust the measured water levels if true.
  if (digitalRead(PIN_TOP_FLOAT) == 0 && topFloatTripped == 0) //When the Top float trips for the first time.
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 255);
    Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_YELLOW);
    Serial.print("30% Water Level Float Tripped at ");  // Print the cumulative total measured liters remaining when the top float tripped.
    Serial.println(DRINKtotalLitres);
    Blynk.notify("30% Water Level Float Tripped");
    DRINKtotalLitres = 19;
    DRINKtotalLitresold = 19;
    topFloatTripped = 1;
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);          //update new water level
  }
  else if (digitalRead(PIN_TOP_FLOAT) == 1 && topFloatTripped == 1) // When it Un-Trips, ie; goes back up or sloshes
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 0);
  }
  else if (digitalRead(PIN_TOP_FLOAT) == 0 && topFloatTripped == 1) // Then It goes down again...
  {
    Blynk.virtualWrite(VPIN_TOP_FLOAT, 255);
  }

  if (digitalRead(PIN_BOTTOM_FLOAT) == 0 && bottomFloatTripped == 0)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 255);
    digitalWrite(BLUE_LED, LOW); // LED On - Stupid LED is inverted
    Blynk.setProperty(VPIN_TOTAL_LITERS_DRINK, "color", BLYNK_RED);
    Blynk.notify("15% Water Level Float Tripped");
    Serial.print("15% Water Level Float Tripped at ");   // Print the cumulative total measured liters remaining when the bottom float tripped.
    Serial.println(DRINKtotalLitres);
    DRINKtotalLitres = 10;
    DRINKtotalLitresold = 10;
    bottomFloatTripped = 1;
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);   //update new water level
  }
  else if (digitalRead(PIN_BOTTOM_FLOAT) == 1 && bottomFloatTripped == 1)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 0);
    digitalWrite(BLUE_LED, HIGH); // LED Off - Stupid LED is inverted
  }
  else if (digitalRead(PIN_BOTTOM_FLOAT) == 0 && bottomFloatTripped == 1)
  {
    Blynk.virtualWrite(VPIN_BOTTOM_FLOAT, 255);
    digitalWrite(BLUE_LED, LOW); // LED On - Stupid LED is inverted
  }

  if (WASHflowRate != 0 || DRINKflowRate != 0) {
    Serial.println("Sending Values to Server");
    Serial.print("Drinking Water = ");
    Serial.println(DRINKtotalLitres);
    Serial.print("Wash Water = ");
    Serial.println(WASHtotalLitres);
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres);  // Total water consumption in liters (L)
    Blynk.virtualWrite(VPIN_FLOW_RATE_DRINK, DRINKflowRate);     // Displays the flow rate for this second in liters / minute (L/min)
    Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, WASHtotalLitres); // Total water consumption in liters (L)
    Blynk.virtualWrite(VPIN_FLOW_RATE_WASH, WASHflowRate);  // Displays the flow rate for this second in liters / minute (L/min)
    BLYNKneedsZero = 1;
  }
  if (WASHflowRate == 0 && DRINKflowRate == 0 && BLYNKneedsZero == 1) {
    Blynk.virtualWrite(VPIN_FLOW_RATE_DRINK, DRINKflowRate);   // Sends Zeros for the flow rates to make the interface nice.
    Blynk.virtualWrite(VPIN_FLOW_RATE_WASH, WASHflowRate);
    BLYNKneedsZero = 0;
  }
}

void CronJob1Min()
{
  //float BatteryVoltage = (analogRead(PIN_CHASSIS_VOLTAGE)) * 0.01554955;
  //Blynk.virtualWrite(V10, BatteryVoltage);
  //  if (BatteryVoltage < 12); {
  //    //Blynk.notify("Chassis Battery Below 12 Volts");
  //    //Blynk.notify(BatteryVoltage);
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_DRINK, DRINKtotalLitres); //Updating server once a minute to keep the chart nice
  Blynk.virtualWrite(VPIN_TOTAL_LITERS_WASH, WASHtotalLitres); //Updating server once a minute to keep the chart nice
}

void setup()
{
  Serial.begin(9600);
  Blynk.begin(AUTH, WIFI_SSID, WIFI_PASS, SERVER, PORT);
  ArduinoOTA.setHostname(OTA_HOSTNAME);  // For OTA - Use your own device identifying name
  ArduinoOTA.begin();  // For OTA

  pinMode(BLUE_LED, OUTPUT);
  digitalWrite(BLUE_LED, HIGH); // LED Off - Stupid LED is inverted
  pinMode(PULSE_PIN_DRINK, INPUT_PULLUP);  // Initialization of the variable "PULSE_PIN_DRINK" as INPUT
  pinMode(PULSE_PIN_WASH, INPUT_PULLUP);  // Initialization of the variable "PULSE_PIN_DRINK" as INPUT

  pinMode(PIN_TOP_FLOAT, INPUT_PULLUP);  // Initialization of the variable "PIN_TOP_FLOAT" as INPUT
  pinMode(PIN_BOTTOM_FLOAT, INPUT_PULLUP);  // Initialization of the variable "PIN_BOTTOM_FLOAT" as INPUT

  attachInterrupt(PULSE_PIN_DRINK, DRINKpulseCounter, FALLING);
  attachInterrupt(PULSE_PIN_WASH, WASHpulseCounter, FALLING);

  timer.setInterval(1000L, sendtoBlynk); // send values blynk server every sec (if it needs updating)
  timer.setInterval(60000L, CronJob1Min); // send values blynk server every 60 sec to keep the charts nice
}

void loop()
{
  Blynk.run();
  ArduinoOTA.handle();  // For OTA Updates
  timer.run();
}

Personally, I’d put the line that re-enables interrupts right at the bottom of the sendtoBlynk function, otherwise an interrupt could err… interrupt the execution of that function and your values might not get written to the server.

Pete.

Done!

It’s still losing several liters every time this glitch reconnect happens.

In the below log you can see the tail end of valid water use and WASHpulseCount at 15:00, then at 15:56 it reconnects and retrieves the last known water levels. I’ve noticed that it seems the first reconnection event, it retrieves the correct values. (15.20 and 9.85) - But on subsequent reconnects it loses 2.69 liters of drinking water and 1.3 liters of wash water. Note it loses the same amount on each reconnect, and both counts are affected… at 8:13 this morning, valid pulses counting again.

I’m at a total loss…

[15:00:56:796] Sending Values to Server␍␊
[15:00:56:830] Drinking Water = 15.20␍␊
[15:00:56:830] Wash Water = 9.85␍␊
[15:00:56:864] WASHpulseCount = 1␍␊
[15:00:57:730] Flowing: 0.0L/min␍␊
[15:00:57:730] Flowing: 0mL/Sec␍␊
[15:00:57:764] Washing Water Remaining: 9.85L␍␊
[15:00:57:797] Sending Values to Server␍␊
[15:00:57:797] Drinking Water = 15.20␍␊
[15:00:57:832] Wash Water = 9.85␍␊
[15:56:09:513] [178186516] Connecting to 192.168.10.100:8080␍␊
[15:56:09:545] [178186528] Ready (ping: 8ms).␍␊
[15:56:09:663] Retrieving levels from server␍␊
[15:56:09:663] 15.20␍␊
[15:56:09:684] 9.85␍␊
[16:37:30:275] [180667215] Connecting to 192.168.10.100:8080␍␊
[16:37:30:308] [180667222] Ready (ping: 4ms).␍␊
[16:37:30:419] Retrieving levels from server␍␊
[16:37:30:419] 12.51␍␊
[16:37:30:440] 8.55␍␊
[21:24:06:254] [197862755] Connecting to 192.168.10.100:8080␍␊
[21:24:06:286] [197862763] Ready (ping: 5ms).␍␊
[21:24:06:399] Retrieving levels from server␍␊
[21:24:06:399] 9.81␍␊
[21:24:06:420] 7.25␍␊
[08:13:26:477] DRINKpulseCount = 1␍␊
[08:13:26:511] DRINKpulseCount = 2␍␊
[08:13:26:511] DRINKpulseCount = 3␍␊

Interestingly, I just did the math on the losses logged on my post from Sept 11, and the losses are the same on every reconnect. 0.97L of drinking water and 1.03L of wash water.

To clarify,

  1. The first re-connection event it retrieves the correct values.
  2. Then, the losses are the same on every reconnection event in that set.
  3. The losses vary from set to set… It seems like about 2 days between sets.

Both these pins will pulse HIGH then LOW at device boot… perhaps that is being interpreted as flow count? I do know (while testing another button sync sketch) that even when the code is timed out with something else (a Blynk.connect() timeout in my case),any triggered interrupts during the timeout did process later after the code started running again.

If so, perhaps some form of timeout timer that delays attaching the interrupts and/or any flow reading until a second or two after boot.

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.