So, you could either answer my question, or wait until I have the time to do a side-by-side comparison between this and the code that I posted earlier.
Pete.
So, you could either answer my question, or wait until I have the time to do a side-by-side comparison between this and the code that I posted earlier.
Pete.
I used your code. I put my SSID, password and token in. I decommented the Lora Library. I added:
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);
to the void take_a_reading()
Since my last post to you I moved
int packetSize = LoRa.parsePacket();
int reading = LoRa.parseInt();
to the void take_a_reading()
as well.
The program seems to be working okay now. Iāll test it out over the next few hours and get back to you. Thanks for your help. Here is the program as it stands now:
/*
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 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[] = "kuggle's_condo_2"; //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(1000L, take_a_reading); // Existing timer
timer.setInterval(60000L, check_connections); // Check that we have a WiFi connection every 1 minute
timer.setInterval(180000L, 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");
}
}
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 <<<<<<<<<<<<"));
}
}
Everything seems to be working now! One question. I took out the LED alarm section before we started trying to fix the problems.
//Alarm LED on receiving unit for tank 3
if (reading <= warning_level )
{
digitalWrite(ledPin,LOW);
}
else
{
digitalWrite(ledPin,HIGH);
}
if I want to reintroduce it in the program where do you think it should go?
Jeff
In take_a_reading
but you need to use adjusted_reading
Pete.
Okay. Thanks again. It took a lot of effort on your part. Much appreciated.
Jeff
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 <<<<<<<<<<<<"));
}
}
You can move them to a separate void function.
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?
Pete.
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.
More details here:
Pete.
As always thanks Pete. Iāll buy the plus. I hope it wonāt be too difficult to migrate the existing project to the new platform.
It should be fairly easy.
The only thing thatās significantly different is notifications. Have a read of this to get more infoā¦
Pete.
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.
Pete.
thanks
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?
Is this battery connected to your ESP8266 device, or Nano sensor device?
Also, is it the voltage that itās supplying to the board, or the actual battery voltage (assuming that they are different)?
Pete.
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
You didnāt really answer my questions.
Pete.