It’s been a few months since I’ve reported in. Again a BIG thanks to Pete for all the help. I finally made it up to the cottage last week and had a chance to try out the water monitoring system for real. And of course what worked on the bench didn’t quite work in the field. Pete’s sketch above worked fine. However my minor tinkering caused some problems. I wanted to add a notification widget which would notify me if the water dropped below a certain level. Shouldn’t be a problem. However, the problem was the notification (where I put it in the sketch) somehow interferes with the four tank display. After I added that to the program I only see the basic depth… That is the depth displayed in Tank One. If I choose any of the other tanks I still see only that depth. Here’s is the program. Any suggestions on where to move the notification section so it doesn’t interfere with displaying the correct value for each of the tanks?
Jeff
/*
For this example you'll need the following library:
* *
1) Arduino-LiquidCrystal-I2C-library: https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
2) Blynk Library 0.6.1 (if usimg Legacy or latest if using IoT): https://github.com/blynkkk/blynk-library
Conncetions:
D0 (GPIO16) -> RST Pin on LoRa Rx module
D1 (GPIO5) -> LED on U3 connector?
D2 (GPIO4) -> DIO0 Pin on LoRa Rx Module
D3 (GPIO0) -> SDA Pin on OLED Display
D4 (GPIO2) -> SCL Pin on OLED Display
D5 (GPIO14) -> SCK pin on LoRA Rx module
D6 (GPIO12) -> MISO pin on LoRA Rx module
D7 (GPIO13) -> MOSI pin on LoRA Rx module
D8 (GPIO15) -> nSS pin on LoRA Rx module
*/
#include <LoRa.h>
#define BLYNK_PRINT Serial
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define I2C_SDA 0 // GPIO0 = D3 - redefining I2C pins as D1 is needed by LoRa unit
#define I2C_SCL 2 // GPIO2 = D4
#define ss 15 // GPIO15 = D1
#define rst 16 // GPIO16 = D0
#define dio0 4 // GPIO4 = D2
int LEDPin=5; //Relay and LED pin
int adjustment;
int adjusted_reading;
int tank_to_read;
const int ledPin = 5; // GPIO5 = D1 - warning light that water has dropped beyond preset level
char auth[] = "ZFiawkv0a-UnC_tXeO3Ir0n_FRhEXy1v"; //Enter the Auth code which was send by Blink
char ssid[] = "fernhill2"; //Enter your WIFI Name
char pass[] = "jakesnak"; //Enter your WIFI Password
int wifi_connect_count = 0; // Keep track of how many times we've tried to connect to the WiFi
int wifi_connect_max_retries = 20; // Specify how many attempts we will have at connecting to the WiFi
bool sync_completed = false; // Flag to track when BLYNK_WRITE(V1) has completed
BlynkTimer timer;
void setup()
{
pinMode(ledPin, OUTPUT);
Wire.begin(I2C_SDA, I2C_SCL); // Updated from deprecated wire.pins(sda,scl) command
Serial.begin(74880); // Native baud rate for the NodemCU
lcd.begin(); // iInit the LCD for 16 chars 2 lines
lcd.backlight(); // Turn on the backligt (try lcd.noBaklight() to turn it off)
delay (1000);
Serial.println("LoRa Receiver ");
LoRa.setPins(ss, rst, dio0);
if (!LoRa.begin(433E6))
{
Serial.println("Starting LoRa failed!");
delay(2000);
Serial.println("Restarting ESP...");
ESP.restart(); // Restart the ESP
}
Serial.println("LoRa Started");
lcd.clear();
lcd.print("Waiting");
LoRa.setSpreadingFactor(10);
LoRa.setSignalBandwidth(62.5E3);
LoRa.crc();
WiFi_Connect();
Blynk.config(auth);
send_to_blynk(); // Connect to Blynk then sync the segmented switch at startup
timer.setInterval( 1 * 1000L, take_a_reading); // Existing timer
timer.setInterval(1 * 60 * 1000L, check_connections); // Check that we have a WiFi connection every 1 minute
timer.setInterval(3 * 60 * 1000L, send_to_blynk); // send data to Blynk every 3 minutes (180,000 m/s)
}
void loop()
{
timer.run();
}
void take_a_reading()
{
int packetSize = LoRa.parsePacket();
int reading = LoRa.parseInt();
if (packetSize)
{
adjusted_reading = (reading - adjustment);
Serial.print("Selected tank = ");
Serial.println(tank_to_read);
Serial.print("Actual reading = ");
Serial.println(reading);
Serial.print("Adjustment factor = ");
Serial.println(adjustment);
Serial.print("Adjusted reading = ");
Serial.println(adjusted_reading);
lcd.setCursor(0, 0); //First line
lcd.print("water is down");
lcd.setCursor(0, 1); //Second line
lcd.print(adjusted_reading);
lcd.print(" inches");
}
if (adjusted_reading >=28 ) //ALARM
{
digitalWrite(LEDPin,HIGH); //ALARM
if(adjusted_reading >=28)
{
Blynk.notify("water level has dropped below 28 inches");
}
timer.setTimeout(1600L, [](){
Blynk.email("jgroberm@shaw.ca", "water level has dropped below 28 inches");
});
}
else {
digitalWrite(LEDPin,LOW); // play tone of 400Hz for 500 ms
}
}
void send_to_blynk()
{
if (WiFi.status() == WL_CONNECTED)
{
Serial.println ("Connecting to Blynk");
Blynk.connect();
if (Blynk.connected())
{
Serial.println ("Connected");
sync_completed = false;
Blynk.syncVirtual(V1); // force the server to send the latest value for the segmented switch
while (!sync_completed) // Wait until BLYNK_WRITE(V1) has completed
{
Blynk.run();
}
take_a_reading(); // take a reading from the tank indicated by the segmented switch
Blynk.virtualWrite(V0, adjusted_reading); // To Display Widget
Blynk.run();
Blynk.disconnect();
Serial.println ("Blynk Disconnected");
}
else
{
Serial.println (">>>>>>>>>>>> Unable to connect to Blynk <<<<<<<<<<<<");
}
}
else
{
// we get here if we there is no WiFi connection
Serial.println (">>>>>>>>>>>> No WiFi Connection, so Blynk connection not attempted <<<<<<<<<<<<");
}
}
BLYNK_WRITE(V1) // Segmented switch to select tank
{
Serial.println("BLYNK_WRITE(V1) Executed");
tank_to_read = param.asInt();
switch (tank_to_read)
{
case 1:
{
adjustment = 0;
sync_completed = true;
break;
}
case 2:
{
adjustment = 4;
sync_completed = true;
break;
}
case 3:
{
adjustment = 8;
sync_completed = true;
break;
}
case 4:
{
adjustment = 12;
sync_completed = true;
break;
}
}
}
void check_connections()
{
if (WiFi.status() != WL_CONNECTED)
{
WiFi_Connect();
}
else
{
Serial.println(F(">>>> WiFi checked - all good <<<<"));
}
}
void WiFi_Connect() // New functon to handle the connectuon to the WiFi network
{
wifi_connect_count=0; // reset the counter
Serial.println(F("Connecting to WiFi"));
if (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(ssid, pass); // connect to the network
}
while (WiFi.status() != WL_CONNECTED && wifi_connect_count < wifi_connect_max_retries) // Loop until we've connected, or reached the maximum number of attemps allowed
{
delay(500);
wifi_connect_count++;
Serial.print(F("WiFi connection - attempt number "));
Serial.println(wifi_connect_count);
}
if (WiFi.status() == WL_CONNECTED)
{
WiFi.mode(WIFI_STA);
Serial.println(F("Wi-Fi CONNECTED"));
Serial.println();
}
else
{
Serial.println(F(">>>>>>>>>>>> Unable to connect to WiFi <<<<<<<<<<<<"));
}
}
First of all, your notification and email code needs to be executed when the device is connected to Blynk. As this only occurs when your send_to_Blynk function is executed, this is where your notification and email code should go.
I’m not sure why you’ve added a non-blocking timeout timer between the notification and email, it serves no purpose.
Also, the way that your notification code is written, you’ll get a notification and email every 3 minutes while the alarm condition exists.
You really need to add a flag which indicates that a notification has been sent for that alarm condition then don’t send another notification until the alarm condition has been cleared.
More on that here (this is written for Blynk IoT, which does notifications in a very different way, but the flag variable process is exactly the same)…
Secondly, your sketch is now very difficult to follow, especially when it comes to your if statements, as you’ve not followed any sort of formatting protocol when it comes to indenting your code. If you take a look at the code examples I provided, you’ll see that it’s easy which if statements are nested inside each other, and which are free standing.
But, your indents are all over the place with your other code too, which makes it extremely difficult to read.
Also, I’m not clear from this comment…
whether you’re referring to your LCD display, or the Blynk app, or both. Also, you’ve not really confirmed that this functionality worked as required before your code changes. Did you do sufficient testing to prove that it worked as required before making your changes?
As always thank you, Pete, for your insightful analysis. I have tried the sketch referenced in the December 21st post above and it appears to work. One thing I’m not clear on is the LCD readings. I’m not sure if they reflect the adjustment levels (referenced in the cases, or the actual level transmitted from the well.
Given I’d like to get the unit operational as soon as possible I’ll hold off using sketch with notifications .
Best
Jeff
An update and a couple of questions.
Thanks to your help the water monitoring device works well (pardon the pun) and at least once this summer saved our water supply. However now with the phasing out of the legacy Blynk I’m faced with having to migrate it to the new blynk which raises a couple of questions. The current device uses a segmented switch. I don’t see that option available on the new blynk (in the free version). Am I missing it somehow? Also in the legacy blynk it was possible to share the app (for an energy “fee”) I don’t see that option available here - which I need as I share the app with a few neighbours who also share our water supply.
Jeff
That’s correct, it’s only available with a Plus or Pro subscription.
You can add users to your organisation. Maximum 5 users in total (including yourself) for the free version, 10 for the Plus version.
However, you can’t change the permissions for the users in either the free or Plus version, a Pro subscription is needed for that.
HI Pete:
One question. In the program (May 28th above) We check that we have a wifi connection every minute. What is the maximum time that one minute could be expanded to? Does that checking actually check to see if the wifi connection is connected to the internet? I’m still trying to cut back on actual internet useage.
Thanks
Jeff
The if (WiFi.status() != WL_CONNECTED) test simply checks if the board is connected to the router.
Try unplugging the router from the internet and watching the serial monitor. You’ll se that the board is still connected to the WiFi network.
Well the tank monitor has been working at the cottage for the summer and it’s performed very well. It alerted us of a leak and we were able to get to the problem without losing all our water. The neighbours were very impressed and grateful. So thanks to all who helped - Particulary Pete.
One problem did occur at the end of summer. The sensor suddenly went offline. We deduced the problem was due to a battery or solar controller problem. Not to difficult to fix. The battery was old to begin with. However that did bring up the possibility of being able to monitor the voltage at the same time. That would probably mean using a second device like a 1NA219 to monitor the voltage. I’m wondering how difficult would it be to add that second device into the master program (above). So that when the program sends the depth info it would also send the voltage?
Hi Pete:
Thanks for the answer and advice. The sensor unit at the well is quite simple. It’s a Nano connected to a Ra-02. It’s powered by a 12v sealed battery that’s powered by a solar panel that is connected to the battery through a solar controller.
The unit transmits to the ESP8266 unit at the cottage that transmits the data from the sensor unit to Blynk.
Jeff
Um… I think I answered the first question… The battery IS connected to the Nano device at the well
The battery 12 volts goes through a step down to 5volts that is connected to board. So the voltage supplied to the board is 5v. It would be ideal to know what the battery voltage is. Does this help?
That could be taken to mean that you want to monitor the voltage at the sender end, but I don’t like to jump to conclusions.
Yes, it answers both of my questions.
The easiest solution would be to use a simple two resistor voltage divider to allow you to measure the battery voltage with one of the available analog pins on the Nano.
As these two resistors will be in series across the positive and negative terminals of the battery you’ll need to choose high resistances so that you don’t drain the battery or fry the resistors.