Dear Blynkers
I am busy adapting the “Water Tank Level Indicator with Low Level Warning Notifications” project by GG07 (thank you, GG07, your project proves incredibly helpful). I want to incorporate an adjustable flow-rate alarm, for notifying the user when the drain rate exceeds an adjustable limit. For this, I have tied a numeric input on V1, the variable named drainAlert, into the app.
I calculate the flowrate by reading the volume over time. To achieve a good average over a longer timeframe, I store both the volume and time in a two-dimensional array. Somehow, the second-last time value, stored as (levelChange[1][2]), overwrites what I’m trying to read from V1. I cannot make sense of it!
I’m using a cheap knock-off of the Node MCU V3 ver 0.1, Android 8.0.0, on the Blynk server with Blynk 0.4.10.
Below, the trimmed code:
//****Virtual Pin Assignments****
// V1 - Numeric Widget - Drain Rate, 0 to disable
// V8 - Terminal
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#define filterSamples 15 //odd number, not smaller than 3
char auth[] = "***";
char ssid[] = "***";
char pass[] = "***";
int maximumRange;
int flowStep = 0;
int volume;
int percent;
int drainAlert = 0;
int levelChange[9][2];
int flowSampling = 1.0; //interval in minutes over which flowrate is calculated. There are 9 datapoints spread over this interval
int flowRate;
unsigned long prevTime = 0;
int smoothDistance; //variables for sensor1 data
const int waterTankDia = 2830; //Water Tank Diameter (mm)
const int waterTankHt = 1890; //ie. installed Sensor Height (mm)
const int minDistance = 300; //At this distance, tank is full
long duration, distance; //Duration used to calculate distance
BlynkTimer timer;
WidgetTerminal terminal(V8);
//**********************************************************************
BLYNK_CONNECTED() { // runs once at device startup, once connected to server.
//Blynk.syncVirtual(V1);
Serial.println("Connected to Blynk");
}
//**********************************************************************
//Switch drain rate alert off if V1 == 0
BLYNK_WRITE(V1) {
drainAlert = param.asInt();
}
//**********************************************************************
void MeasureCmForSmoothing() {
// Measures ultrasonic distance in *mm*!
smoothDistance = 300+flowStep;
flowStep++;
// if ((millis() - prevTime)>(flowSampling*4000)){
prevTime = millis();
for( int a = 8; a >= 1; a-- ) {
levelChange[a+1][1] = levelChange[a][1];
levelChange[a+1][2] = levelChange[a][2];
}
levelChange[1][2] = prevTime/1000;
levelChange[1][1] = ((waterTankHt*(PI*(sq(waterTankDia/2))))-(smoothDistance*(PI*(sq(waterTankDia/2)))))/1000000;
for (int a = 1; a <= 9; a++){
Serial.print (a);
Serial.print ("=");
Serial.print (levelChange[a][1]);
Serial.print ("/");
Serial.print (levelChange[a][2]);
Serial.print (":");
}
Serial.println ();
if (levelChange[9][1] != 0){
flowRate = ((levelChange[1][1] - levelChange[9][1])*3600)/(levelChange[1][2] - levelChange[9][2]); //result in l/h
}
volume = levelChange[1][1];
percent = ((float)volume/maximumRange)*100;
Serial.print("distance=");
Serial.print(smoothDistance);
Serial.print("; volume=");
Serial.print(volume);
Serial.print("; percent=");
Serial.print(percent);
Serial.print("; time=");
Serial.print(millis());
Serial.print("; flowrate=");
Serial.print(flowRate);
Serial.print("; DrainAlert=");
Serial.println(drainAlert);
Serial.println();
// }
}
//**********************************************************************
void UploadMeasurements() {
if (drainAlert != 0){
terminal.print("FLOW RATE ALERT");
terminal.println(flowRate);
terminal.flush();
}
}
//**********************************************************************
void setup() {
Serial.begin(74880);
for(int a = 1; a < 10; a++) { //Initialize array with zeroes
levelChange[a][1] = 0;
}
//determine the tank volume, which is waterTankHt minus minDistance, rounded to the nearest 10
maximumRange = ((waterTankHt*(PI*(sq(waterTankDia/2))))-(minDistance*(PI*(sq(waterTankDia/2)))))/1000000;
maximumRange = maximumRange/10;
maximumRange = maximumRange*10;
Blynk.begin(auth, ssid, pass);
timer.setTimeout(400, [](){
timer.setInterval(10000L, UploadMeasurements);
});
timer.setTimeout(700, [](){
timer.setInterval(5000L, MeasureCmForSmoothing);
});
}
//**********************************************************************
void loop() {
Blynk.run(); // Initiates Blynk
timer.run(); // Initiates SimpleTimer
}