Advice for my project

Hello!

So far, in my “Growing Plant System” project, I’ve managed to display all the data from my sensors on my Blynk app. Now, I want to go a step further and add a button that will control a relay.
More exactly, I want to get a notification from my app when the value of my soil moisture sensor has fallen under a threshold, so I can know when to go and activate my water pump using a button inside the app or the web

  1. What do I need to do in Blynk.Console datastream / events.

What I did :

  1. What I need to do in my code.

What I have so far:

void setup()

{

  Serial.begin(9600);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initializare OLED cu adresa 0x3C

  display.clearDisplay();

  BlynkEdgent.begin();

  pinMode(DHTPin, INPUT);

  pinMode(SoilPin, OUTPUT);

  dht.begin();

}

void loop()

{

  BlynkEdgent.run();

  get_water_level();

  get_temperature();

  get_humidity();

  get_soil_humidity();

}

void get_water_level()

{

  if (millis() - sonic_counter > sonic_interval) // once every 2 sec

  {

    sonic_counter += sonic_interval;

    duration = sonar.ping_median(10);

    distance = (duration / 2) * 0.0343;

    if (distance >= 400 || distance <= 2)

    {

      //Serial.println("Out of range");

    }

    percent = constrain((map(distance, 12, 2, 0, 100)), 0, 100);

    Blynk.virtualWrite(V0, percent);

  }

}

void get_temperature()

{

  if (millis() - temperature_count > temperature_interval) // every 3secs

  {

    temperature_count += temperature_interval;

    t = dht.readTemperature();

    if (isnan(t)) // look into this

    {

      //Serial.println(F("Failed to read from DHT sensor!"));

    }

    Blynk.virtualWrite(V1, t);

  }

}

void get_humidity()

{

  if (millis() - humidity_count > humidity_interval) // every 3 secs

  {

    humidity_count += humidity_interval;

    h = dht.readHumidity();

    if (isnan(h)) // look into this

    {

      //Serial.println(F("Failed to read from DHT sensor!"));

    }

     Blynk.virtualWrite(V2,h);

  }

}

void get_soil_humidity()

{

  if (millis() - soil_humidity_count > soil_humidity_interval) // every 2 secs

  {

    soil_humidity_count += soil_humidity_interval;

    soilMoistureValue = analogRead(SoilPin);

    soilmoisturepercent = constrain((map(soilMoistureValue, AirValue, WaterValue, 0, 100)), 0, 100);

    Blynk.virtualWrite(V3, soilmoisturepercent);

  }

}

Put a tick in the “Available in Conditions” and “Available in Actions” checkboxes in the Automations part of the datastream. Do the same for your soil moisture datastream.

Nothing.

In the app, click on Automations (at the bottom) and create a new automation.
You can either set a condition of something equivalent to “if soil moisture < xxx send a notification” or “if soil moisture < xxx switch the Water Pump on”.

If you don’t need the water pump turning on automatically then it doesn’t need to be available in conditions/actions.

Here’s the docs…

Pete.

1 Like

He actually needs to make BLYNK_WRITE(Vx), where Vx is a relay pin. To handle the request from automation.

True! I missed that wasnt already there.

@Wicked You also need to sort-out your void loop with a timer to call these functions…

http://help.blynk.cc/getting-started-library-auth-token-code-examples/blynk-basics/keep-your-void-loop-clean

Pete.

Ok, I’ve done the automation part, really cool stuff ! And easy aswell.
Now I’m gonna try and implement my relay , and yes, I do plan to also have it fully automated ( to turn on by itself for an x amount of seconds of condition is met ) .

I am already. I’m using millis() and creating events once every x seconds. If you check each functions , all of them have conditions to only do stuff after x seconds have passed. It’s multi-tasking implementation

It still means thet the MCU has to process 4 functions, and do 4 sets of millis comparisons, every time the void loop executes.

Blynk/SimpleTimer does all of this from a single timer.run() command and is therefore much more efficient (and therefore better with Blynk).

No, it’s sequential processing on a singe-threaded processor.

Pete.

2 Likes

I dont understand why im getting an error regarding Wifi.h when im not even using it ?
Also , an error regarging BlynkTimer timer aswell.
What am I doing wrong ? Do I need or not to use #include <WiFi.h> and #include <WiFiClient.h> with the new Edgent library?

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "NewPing.h"
#include <DHT.h>

#define BLYNK_TEMPLATE_ID "TMPLTqt3bsNh"
#define BLYNK_DEVICE_NAME "Plant Automation"
#define BLYNK_FIRMWARE_VERSION "0.1.0"
#define BLYNK_PRINT Serial
#define APP_DEBUG


#include "BlynkEdgent.h"


#define DHTTYPE DHT22

#define echoPin 26 
#define trigPin 25 
#define max_distance 400

float distance, duration; // variable for the distance measurement
int percent;

float h, t;
uint8_t DHTPin = 27;

const int AirValue = 2500;  
const int WaterValue = 1150; 
const int SoilPin = 36;
int soilMoistureValue = 0;
int soilmoisturepercent = 0;


NewPing sonar(trigPin, echoPin, max_distance);
DHT dht(DHTPin, DHTTYPE);

BlynkTimer timer;

void get_temperature()
{
    t = dht.readTemperature();
    if (isnan(t)) // look into this
    {
      //Serial.println(F("Failed to read from DHT sensor!"));
    }
    Blynk.virtualWrite(V1,t);
  
}

void get_soil_humidity()
{
    soilMoistureValue = analogRead(SoilPin);
    soilmoisturepercent = constrain((map(soilMoistureValue, AirValue, WaterValue, 0, 100)), 0, 100);
    Blynk.virtualWrite(V3,soilmoisturepercent );
}

void setup()
{
  BlynkEdgent.begin();
  pinMode(DHTPin, INPUT);
  pinMode(SoilPin, OUTPUT);
  dht.begin();

  timer.setInterval(2000L, get_temperature);
  timer.setInterval(1000L, get_soil_humidity);
}


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

Erors:

Edgent_ESP32:40:12: error: redefinition of ‘BlynkTimer timer’
BlynkTimer timer;
^
In file included from C:\Users\filim\AppData\Local\Temp\arduino_modified_sketch_821966\Edgent_ESP32.ino:15:0:
sketch\BlynkEdgent.h:111:12: note: ‘BlynkTimer timer’ previously declared here
BlynkTimer timer;
^
Multiple libraries were found for “WiFi.h”
Used: C:\Users\filim\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFi
Not used: C:\Program Files (x86)\Arduino\libraries\WiFi
exit status 1
redefinition of ‘BlynkTimer timer’

There is an issue with the current Edgent examples.

If you replace “timer” with something else, mytimer for example, it should be fine.

I think it’s fixed in the next library release.

Pete.

1 Like

Another stupid question, but I cant figure it out. How can I set up my switch button ( both web and app) to send 1 when its OFF and 0 when ON? ( my relay is in normal open configuration , so I need to send 0 to to start it ).

I can of course set the ON value as 0 and OFF as 1, but then my switch button will turn on when I want to close my relay , and off when I want to start the relay, which is confusing as an interface

The app is the same as before, and the web very similar - set ON value to 0 and OFF value to 1.

But, personally I prefer to invert the value in the code.

Pete.

Damn, of course I have to do it in the code , how did I not think of that…

Thanks @PeteKnight . Now I will try to see if I can automate the pump . If I have more question , I will come back to this thread

My program has a weird behavior when I start my pump. The ultrasonic sensor that is used to read my water level is showing 100% everytime I enable the pump , and then goes back to normal .
Showing 100% level either means:

  • the sensor reads a distance of 2cm or less all of the sudden
  • the sensor gets disconnected
void get_water_level()

{

    duration = sonar.ping_median(10);

    distance = (duration / 2) * 0.0343;

    if (distance >= 400 || distance <= 2)

    {

      //Serial.println("Out of range");

    }

    percent = constrain((map(distance, 12, 2, 0, 100)), 0, 100);

    Blynk.virtualWrite(V0, percent);

  

}

Is it something you heard of it before ?

give us your timer.setInterval for get_water_level

mytimer.setInterval(3000L, get_water_level);

Full code:

BLYNK_WRITE(V4) // Button Widget writes to Virtual Pin V5 

{

  int val= param.asInt();

  digitalWrite(32, !val );

}

BLYNK_WRITE(V5)

{

  int led = param.asInt();

  ledcWrite(0, led);

  Blynk.virtualWrite(V5,led);

}

void get_temperature()

{

    t = dht.readTemperature();

    if (isnan(t)) // look into this

    {

      //Serial.println(F("Failed to read from DHT sensor!"));

    }

    Blynk.virtualWrite(V1,t);

  

}

void get_soil_humidity()

{

    soilMoistureValue = analogRead(SoilPin);

    soilmoisturepercent = constrain((map(soilMoistureValue, AirValue, WaterValue, 0, 100)), 0, 100);

    Blynk.virtualWrite(V3,soilmoisturepercent );

}

void get_water_level()

{

    duration = sonar.ping_median(10);

    distance = (duration / 2) * 0.0343;

    if (distance >= 400 || distance <= 2)

    {

      //Serial.println("Out of range");

    }

    percent = constrain((map(distance, 12, 2, 0, 100)), 0, 100);

    Blynk.virtualWrite(V0, percent);

  

}

void get_humidity()

{

    h = dht.readHumidity();

    if (isnan(h)) // look into this

    {

      //Serial.println(F("Failed to read from DHT sensor!"));

    }

     Blynk.virtualWrite(V2,h);

  

}

void setup()

{

  BlynkEdgent.begin();

  pinMode(DHTPin, INPUT);

  pinMode(SoilPin, OUTPUT);

  dht.begin();

  pinMode(32, OUTPUT);

  digitalWrite( 32, HIGH ) ;

  ledcAttachPin(33, 0);

  ledcSetup(0, 4000, 8);

  mytimer.setInterval(3000L, get_temperature);

  mytimer.setInterval(3000L, get_water_level);

  mytimer.setInterval(2000L, get_soil_humidity);

  mytimer.setInterval(3000L, get_humidity);

  

}

void loop()

{

  BlynkEdgent.run();

  mytimer.run();

}

First of all, you have to stage timers
You have 3 timers at same time
then, you should insert Serial.println(distance) before if condition , to see the results in your serial monitor.

What do you mean by I have 3 timers at the same time? And how can I stage them

mytimer.setInterval(3000L, get_temperature);
mytimer.setInterval(3000L, get_water_level);
mytimer.setInterval(3000L, get_humidity);

Read the “Staggering Timers” section of this…

Take care not to fall asleep before you get to the right bit! :laughing:

Pete.

3 Likes

Very nice post!
So let me know I understood it corectly. I should use different periods of time, but also be careful for them to not be combinations like 1 sec / 2 sec or 2 secs / 4 secs etc .
Of course, I dont plan to call my temperature/humidity sensor once every 3 seconds. I was doing this now just so I can test things out. I will definitely make those numbers higher , 30 secs ++++ .

I will ran some tests to check how long each function takes to also have an idea on the delay .

Thank you very much for the information ! I will come back here if I have further problems with this project, to not spam the forum with new posts

1 Like