That sketch was old I don’t remember if it worked here is one that is kind of working now. There is one problem that I am trouble shooting is that the water 0’s at midnight the last couple of nights. Not sure if it is a network issue or if it is some how calling my V2 function. Or maybe its just a gremlin somewhere in the clouds… It isn’t my timed reset because then it would call the notify. I added a notify in the V2 function to see if that will give me any info tonight.
#define BLYNK_PRINT Serial // Defines the object that is used for printing
#define BLYNK_DEBUG // Optional, this enables more detailed prints
/* Comment this out to disable prints and save space */
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ArduinoOTA.h>
#include <WidgetRTC.h>
#include <ESP8266mDNS.h> //for OTA
#include <WiFiUdp.h> //for OTA
//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 = 0;
bool flowNotifyFlage = 0;
unsigned long oldTime;
String strsetHostname;
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
litersResetFlag = doc["litersResetFlag"];
Blynk.virtualWrite(V1, totalLitres);
return true;
}
bool saveData() {
StaticJsonDocument<100> doc;
doc["totalMilliLitres"] = totalMilliLitres;
doc["yesterDate"] = yesterDate; ////Note: but to save does not work to load as<String>..
doc["litersResetFlag"] = litersResetFlag;
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 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);
}
void setup()
{
Serial.begin(115200);
pinMode(D3, OUTPUT);
digitalWrite(D3, HIGH);
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, LOW);
WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
WiFi.begin(ssid,pass);
if (WiFi.waitForConnectResult() != WL_CONNECTED) //was while loop
{
Serial.println("Connection Failed! Rebooting...");
delay(1000); //was 5s
ESP.restart();
}
ArduinoOTA.setHostname("flowmeter_v7");
ArduinoOTA.begin();
Blynk.config(auth);
Blynk.connect();
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(V7);
timer.setTimeout(5000L,[](){ //Lambda "Reconnection" timer function
terminal1.println(" ");
terminal1.println(String ("Connected ") + currentTime + " " + currentDate);
//terminal1.println(String ("Yesterdate ") + yesterDate);
terminal1.flush();
if (!loadData())
{
terminal1.println("Failed to load on Connect");
terminal1.flush();
}
else
{
terminal1.println("Loaded on Connect");
terminal1.flush();
}
Blynk.syncVirtual(V12);
});
}
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(600000L,[](){ //Lambda "Reconnection" every 10 minutes
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
{
terminal1.println("Failed to load on Send values");
terminal1.flush();
}
else
{
Serial.println("Data saved");
}
}
void checkcounterReset() //time input
{
if(hour() == SThour)
{ //daily clear total liters
if(minute() >= STmin)
{
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(String ("Changeflag ") + currentTime + " " + currentDate);
terminal1.println(" ");
terminal1.flush();
Blynk.notify("ChangeFlag");
if (!saveData()) //save mL to little FS
{
Serial.println("Failed to save Data");
}
else
{
Serial.println("Data saved");
}
}
}
}
BLYNK_WRITE(V0)
{
totalMilliLitres = param.asInt();
}
BLYNK_WRITE(V2)
{
if (param.asInt())
{ //manual reset Liters
totalMilliLitres = 0;
Blynk.virtualWrite(V1, totalLitres);
Blynk.notify("Reset counter");
}
}
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);
}
}
BLYNK_WRITE(V15)
{
if (param.asInt())
{
digitalWrite(D3,LOW);
timer.setTimeout(900L,[]()
{
digitalWrite(D3,HIGH);
Blynk.virtualWrite(V15,0);
});
}
}