Soil moisture sensor readings on Blynk

Hii,
I have been facing an issue of opposite readings of soil moisture sensors on a gauge in blynk. So, I checked the forum for similar problems and tried making some amends but I couldn’t resolve the issue. Any help would be really appreciated. Here’s my code -

#define BLYNK_PRINT Serial
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#define BLYNK_PRINT Serial
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS D2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

char auth[] = "4pd1tQr1dAilNauRpvQQR0--wfNMaoDW";
char ssid[] = "KUMAR";
char pass[] = "SRAVENKY@861614";

#define sensorPin D3
int sensorState = 0;
int lastState = 0;
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;
void sendSensor()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Blynk.virtualWrite(V5, h);  //V5 is for Humidity
  Blynk.virtualWrite(V6, t);  //V6 is for Temperature
}
void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  pinMode(sensorPin, INPUT);
  dht.begin();

  timer.setInterval(10000L, sendSensor);
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  sensors.begin();
}
int sensor = A0;
void sendTemps()
{
  sensor = analogRead(A0);
  sensor = map (sensor, 0,1023,1023,0);
  sensor = (sensor / 1023) * 100; 
  sensors.requestTemperatures();
  float temp = sensors.getTempCByIndex(0);
  Serial.println(temp);
  Serial.println(sensor);
  Blynk.virtualWrite(V1, temp);
  Blynk.virtualWrite(V2, sensor);
  delay(1000);
}
void loop()
{
  Blynk.run();
  timer.run();
  sendTemps();
  sensorState = digitalRead(sensorPin);
  Serial.println(sensorState);

  if (sensorState == 1 && lastState == 0) {
    Serial.println("needs water, send notification");
    Blynk.notify("Water has been detected in the soil");
    lastState = 1;
    delay(1000);

  }
  else if (sensorState == 1 && lastState == 1) {
    //do nothing, has not been watered yet
    Serial.println("has not been watered yet");
    delay(1000);
  }
  else {
    //st
    Serial.println("does not need water");
    lastState = 0;
    delay(1000);
  }

  delay(100);
}


This is the circuit diagram

Hey there,
First of all you should read this
https://docs.blynk.io/en/legacy-platform/legacy-articles/keep-your-void-loop-clean

Maybe explaining what this means, with some info about how your gauge widget is configured, would be a good starting point?
Details of what you see in the serial monitor at the same time might also be helpful.

Pete.

So, what I mean is that when my sensor is under DRY conditions it shows 1024 or values near to that and when I put the sensor in WET conditions the value drops to 600 or nearer so that’s my issue. I am using a normal gauge V2 pin with a reading rate of 1 second.
Serial Monitor readings -
image

What is this code supposed to do?

sensor = map (sensor, 0,1023,1023,0);
sensor = (sensor / 1023) * 100;

I believe this will make sensor value almost always be 0.
Since sensor is int.

Jonas

The purpose of that part of the code is to get the correct values for the conditions i.e. If the sensor is in wet conditions, then the reading should be higher (since in wet conditions the moisture is also high) and if the moisture is in dry conditions then the readings should be lower (since moisture is lesser). But that part I checked from another similar question on the forum. Later I deleted that part and had my original and present code as -

#define BLYNK_PRINT Serial
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#define BLYNK_PRINT Serial
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS D2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

char auth[] = "4pd1tQr1dAilNauRpvQQR0--wfNMaoDW";
char ssid[] = "KUMAR";
char pass[] = "SRAVENKY@861614";

#define sensorPin D3
int sensorState = 0;
int lastState = 0;
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;
void sendSensor()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Blynk.virtualWrite(V5, h);  //V5 is for Humidity
  Blynk.virtualWrite(V6, t);  //V6 is for Temperature
}
void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  pinMode(sensorPin, INPUT);
  dht.begin();

  timer.setInterval(10000L, sendSensor);
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  sensors.begin();
}
int sensor = A0;
void sendTemps()
{
  sensor = analogRead(A0);
  sensors.requestTemperatures();
  float temp = sensors.getTempCByIndex(0);
  Serial.println(temp);
  Serial.println(sensor);
  Blynk.virtualWrite(V1, temp);
  Blynk.virtualWrite(V2, sensor);
  delay(1000);
}
void loop()
{
  Blynk.run();
  timer.run();
  sendTemps();
  sensorState = digitalRead(sensorPin);
  Serial.println(sensorState);

  if (sensorState == 1 && lastState == 0) {
    Serial.println("needs water, send notification");
    Blynk.notify("Water has been detected in the soil");
    lastState = 1;
    delay(1000);

  }
  else if (sensorState == 1 && lastState == 1) {
    //do nothing, has not been watered yet
    Serial.println("has not been watered yet");
    delay(1000);
  }
  else {
    //st
    Serial.println("does not need water");
    lastState = 0;
    delay(1000);
  }

  delay(1000);
}

Now with this code, I’m getting the readings as:
For DRY conditions - readings above 1000 till 1024.
For WET conditions- readings between 300 and 700.
Which I know are the default readings of the moisture sensor.
But it is more useful if we have the intuitive readings like if more moisture then more the reading and if less moisture then lesser the reading. So the problem is - I’m not able to figure it out.
Please help me out. :sweat_smile: :upside_down_face:

First off, it’s better if you copy/paste from the serial monitor rather than taking a screenshot.

Also, these numbers mean nothing without some commentary, or information about what is displayed on the gauge widget for each of the serial monitor readings. Had you coped and pasted the text then you could have added this info.

That’s why I said…

I think you’d be better printing the un-mapped (raw|) values to your serial monitor, followed by the mapped values.
It’s also possible to set-up mappings in the widget, and we need to know if you’ve done this - but despite me asking…

Pete.

What is not working for you? What is the very first observation masking you say it does not work (as expected)?

Some things we can note:

  1. In your setup you are initialising serial port 2 times. 1 is enough.
  2. In your setup you are initialising blynk (begin) 2 times. 1 is enough. (2 times maybe also cause your problems?)

You are using a timer to read your dht11 once every 10 secs. Good.
But when you read your other sensors, you do that In the main Loop with a 1 sec delay. This would mean you try to send that every second to blynk. Not sure, but this might be to often for blynk restriction. Better to also read these and send to blynk in your timer routine running every 10 secs.

Then, as Pete states, use statements like this:

Serial.print (" sensor: ");
Serial.println(sensor);

So you can debug your code.

Oh, I understand Pete. Thank you so much for your time. I’m actually a bit new to blynk so can you tell me about the widget configuration you were referring to cause I am using the legacy app and there’s just very little configuration for the widget.

Thank you Jonas. So shall I delay the conditionals in my main loop to 10 seconds too?

You shouldn’t use delay with blynk, and you should clean your void loop as well

There more configuration options for the gauge widget in Legacy than in IoT.

Just post a screenshot of the widget configuration screen.

Pete.

These are the screenshots, Pete. The 1024 is the reading cause the moisture sensor is in the air i.e. dry condition.

The updated code with changes looks something like this -

#define BLYNK_PRINT Serial
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#define BLYNK_PRINT Serial
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS D2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

char auth[] = "4pd1tQr1dAilNauRpvQQR0--wfNMaoDW";
char ssid[] = "KUMAR";
char pass[] = "SRAVENKY@861614";

#define sensorPin D3
int sensorState = 0;
int lastState = 0;
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;
void sendSensor()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Blynk.virtualWrite(V5, h);  //V5 is for Humidity
  Blynk.virtualWrite(V6, t);  //V6 is for Temperature
}
void setup()
{
  Blynk.begin(auth, ssid, pass);
  pinMode(sensorPin, INPUT);
  dht.begin();

  timer.setInterval(10000L, sendSensor);
  Serial.begin(115200);
  sensors.begin();
}
int sensor = A0;
void sendTemps()
{
  sensor = analogRead(A0);
  sensors.requestTemperatures();
  float temp = sensors.getTempCByIndex(0);
  Serial.println(temp);
  Serial.println(sensor);
  Blynk.virtualWrite(V1, temp);
  Blynk.virtualWrite(V2, sensor);
  delay(1000);
}
void loop()
{
  Blynk.run();
  timer.run();
  sendTemps();
  sensorState = digitalRead(sensorPin);
  Serial.println(sensorState);

  if (sensorState == 1 && lastState == 0) {
    Serial.println("needs water, send notification");
    Blynk.notify("Water has been detected in the soil");
    lastState = 1;
    delay(1000);

  }
  else if (sensorState == 1 && lastState == 1) {
    //do nothing, has not been watered yet
    Serial.println("has not been watered yet");
    delay(1000);
  }
  else {
    //st
    Serial.println("does not need water");
    lastState = 0;
    delay(1000);
  }

  delay(10000);
}

I just have no idea how to further clean my void loop.

Avoid DELAY. It is easy to use - BUT it prevents other code to be run. SOmetimes this causes problems. So you should in general avoid delays.

Instead - use timers to call functions on regular basis.
You have already done so for reading DHT11 but not for the other sensors.

This code you use:

  timer.setInterval(10000L, sendSensor);

Actually tells the system to “run the function ‘sendSensor’ once every 10 secs”. (10000L = 10000 msecs = 10 secs). HOwever, you must also use the code:

   timer.run();

in your loop().

But you already do this for your DHT11 sensor - why not just do the same for other sensors?

=>
Either just add the code for other sensors into your “sendSensor” code, or create a new one.
If you create a new one, you also need to set the time interval like this:

  timer.setInterval(60000L, handleMyOtherSensor);

And then you write the function:

void handleMyOtherSensor()
{
   // place your code here
}

In the example I set the time to 60000L (= 60 secs) just to show that you that easy can set any other time you want.
And - for these type of sensors you really don’t need to read them more often than once per minute. (I never read temp sensors more often than once per 5 mins.)

I hope this clarifies.

Jonas

1 Like

So can I use the timer in place of delay in the if-else statements also?

Because I made the changes to the delay in the main loop after the if-else statements.

The main problem is that as of now for dry conditions, the readings are 1024 which is very high but it should be somewhere between 300 to 600. Is there any way I can do that?

I dont know what your if-else statements really do.

But it seem to me your:

  • function sendTemps could be called by time every 10 or 60 secs instead of being called from loop().
  • The if-else statements in the loop could PROBABLY be part of the sendTemps function. (but i havent really analyzed what they are for .)

In general your loop could be like this:

void loop()
{
  Blynk.run();
  timer.run();
}

and then you have all your sensor reading in functions which you call using a timer.
Once you have understood this concept - it is much simpler and easier to maintain.

Other thing
In your last code examples you read wet-sensor from A0 which I think will return a value 0-1023.
You then send this to blynk V2 which seems to be set 0-100.
If the wet sensor normally returns 200-400 or 800-1000 I guess that will mean the blynk V2 always will display 100.
You will need to map the 0-1023 to 0-100.
(In a previous code example you did this in a bad way causing a “round-off” or “cut-off” by using an integer so it would most often return the value 0. If I’m not wrong.)

1 Like

Another quite boring answer.

I suggest you run your moisture sensor a bit to test its functionality.

  • Let it be dry, read every 1 mins and display the value (A0) in a serial monitor.
  • Let if be wet -"-
  • Put it in dry soil -"-
  • Put it in wet/humid soil -"-

Repeat this test for a few hours and probably also next day and next day.

=>
If you now feel the moisture sensor is working as expected - THEN you continue to make it work with BLYNK.

It seems to me you are as well struggling to understand if the wet/humid sensors really works as well as trying to get the data to blynk.

1 Like