Display only one sensor (of several) attached to one device

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

1 Like

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?

1 Like

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.

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.

Pete.

Thank you Pete, my main thoughts are how to be integrate a sensor into my existing Blynk program.
Jeff

It rather depends on what you do at the Nano end as far as taking the voltage readings and sending them via LoRa is concerned.

You’d then need to extract the voltage readings and send them to a virtual pin in Blynk along with your existing data. You could then add some notification functionality to warn you when the voltage drops below a certain level.

Pete.

Thanks Pete:
I was thinking of sending the data (water depth, voltage) as an array from the well to ESp8266. Hopefully I can figure out how to have sketch parse the array and send it to the Blynk server.

I’d send it as either a string, with delimiters between the fields, or as a JSON object.

Pete.

Hi Pete:
It’s been a while since we chatted. I hope you had a good winter. It’s spring and I’m planning on going up to the cabin. The program you helped my with (December 2021 above) worked really well last summer and actually saved us from a water break - so thanks. At the end of last year I mentioned that I thought I’d like to add a sensor to measure the voltage of the battery at the tank - as it began to fail towards the end of the season. I took your advice and learned about voltage dividers. I created one and attached it to the transmitter at the well head. The transmitter sketch works okay and displays the water depth and voltage. The problem is on the receiving end. I’ve tried to add code to receive, parse and display the voltage. But it doesn’t work I just get a reading of “0”. I have avoided having to rewrite the code to send and receive the data as an array or structure as I’m not quite comfortable with them - so I thought I’d try a simple solution. Obviously it didn’t work. Is there a way of getting the voltage to display along with the water depth and send it along to Blynk2? I’ll attach the transmitter sketch followed by the receiver sketch.
TRANSMITTER SKETCH

/* 
 * Credits to VDEngineering video for the Kalman filter algorithm:
 * https://www.youtube.com/watch?v=ruB917YmtgE
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <LoRa.h>
#include <SPI.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);

const int echo = 8;
const int trig = 7;
const int maxdist = 450;
const float mindist = 2.5;


//const int R1 = 30000;
//const int R2 = 7500;

double kalman(double U);

double kalman(double U) {
  static const double R = 60;
  static const double H = 1.00;
  static double Q = 10;
  static double P = 0;
  static double U_hat = 0;
  static double K = 0;
  K = P * H / (H * P * H + R);
  U_hat += +K * (U - H * U_hat);
  P = (1 - K * H) * P + Q;
  return U_hat;
}

double distance, duration, voltage;

void setup() {
  lcd.begin();
  lcd.backlight();
  delay(1000);

  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(A0, INPUT);

  while (!Serial)
    ;
  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1)
      ;
  }

  LoRa.setSpreadingFactor(10);
  LoRa.setSignalBandwidth(62.5E3);
  LoRa.crc();
}

void loop() {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  duration = pulseIn(echo, HIGH);
  distance = (duration * .0133) / 2;

  // Define voltage divider resistors
  int value = 0;
  float R1 = 30000.0;
  float R2 = 7500.0;
  //Read voltate - may have to adjust 5.00 to input voltage on Vin
  value = analogRead(A0);
  voltage = value * (5.10 / 1024) * ((R1 + R2) / R2);  // should be 5 volts, but adjusted for voltage reading at nano 5v pin

  // Kalman filter for distance measurement
  double fildist = kalman(distance);

  Serial.print("Water is down: ");
  Serial.print(fildist);
  Serial.print(" inches, Voltage is: ");
  Serial.print(voltage);
  Serial.println(" V");

  delay(500);

  // Send packet
  LoRa.beginPacket();
  LoRa.print(fildist);
  LoRa.print(",");
  LoRa.print(voltage);
  LoRa.endPacket();

  delay(200);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Water:");
  lcd.print(fildist);
  lcd.print(" in");
  lcd.setCursor(0, 1);
  lcd.print("Voltage:");
  lcd.print(voltage);
  lcd.print(" V");

  if (fildist <= 25) {
    digitalWrite(5, LOW);
  } else {
    digitalWrite(5, HIGH);
  }
}

RECEIVER SKETCH

/*
   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;
int voltage;

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[] = "XXXXXXXXXXXXX";  //Enter your WIFI Name kuggle's_condo_2
char pass[] = "XXXXXXXXXXXXXX";  //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(9600); // 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(2 * 60 * 1000L, send_to_blynk); // send data to Blynk every 2 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);
Serial.print("Voltage = ");
    Serial.println(voltage);

  
    lcd.setCursor(0, 0); //First line
    lcd.print(adjusted_reading);
    lcd.print(" inches");
    lcd.setCursor(0, 1); //Second line
    lcd.print(voltage);
  }

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.virtualWrite(V1, voltage); // send voltage to Blynk
      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 = 13;
        sync_completed = true;
        break;
      }

    case 3:
      {
        adjustment = 15;
        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 <<<<<<<<<<<<"));
  }
}