Lawn irrigation with pop up sprinklers controlled with Arduino/Blynk

Hello
Have an ongoing project, where I stuck to the end …

Have all the hardware built to irrigate my lawn. it is installed and works fine.

Now the problem, I would like to control the solenoid valves to the pop-up sprinklers with my Arduino Uno.

Have connected it to blynk and tried to push buttons to test the valves, all ok.

The function of the program that I need is the following

Push button starts a sequence of ten steps (I have 10 solenoid valves) each step must be active for 1 h before the program ladders to the next step.
When the last step is done, it must be possible to start again.

The sequence must also go to Stann middle of the ongoing irrigation.

What would be nice to have the triggers to a moisture sensor that starts the sequence of herself.

Have tried to build this in blynk but not come to a solution, it is possible to do this in blynk, what do you think? and if so, how?

or has anyone of you a code that could work?

If someone is doing something similar, I have some information about the design of valves, water flows etc.

Very grateful for the help

4 Likes

Wow I LOVE that water solenoid distributor!! Did you make it youself?

I’m working on a similar system with only 4 valves. It’s a working work-in-progress.
I havn’t made any changes to it since August.

It’s made up of a brain and also solar powered sensors.

The brain and sensors all run on ESP8266 Dev boards (WeMos, NodeMCU etc).
The brain controls 4 solenoid valves by switching the power on and off via a relay bank.

Here is the code for the brain then the sensors. (the sensors are not finished for solar use but will give you the idea)

/*
  Virtual Ports:
  --------------
  V0 = Terminal
  V1 = RTC
  V2 = Manual Mode Button
  V3 = Wifi Signal (Value Widget)
  V4 = Time (Value Widget)
  V5 = Date (Value Widget)
  V6 =
  V7 =
  V8 = Relay1 State LED
  V9 = Relay2 State LED
  V10 = Relay3 State LED
  V11 =
  V12 = Moisture Threshold
  V13 = Moisture Reset
  V14 = Moisture Threshold Display
  V15 = Moisture Reset Display
  V16 =
  V17 = Daily Water Usage (Value)
  V18 =
  V19 =
  V20 = Sensor: Zone 1 Moisture
  V21 = Sensor: Zone 1 Wifi
  V22 = 
  V23 = Sensor: Zone 2 Moisture
  V24 = Sensor: Zone 2 Wifi
  V25 = 
  V26 = Sensor: Zone 3 Moisture
  V27 = Sensor: Zone 3 Wifi
  V28 = 
  V29 =
  V30 =
  V31 =
*/
/****************************************************************************/
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
/****************************************************************************/
char auth[] = "xxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxxx";
/****************************************************************************/
#define RELAY1 14 // D5
#define RELAY2 12 // D6
#define RELAY3 13 // D7
#define RELAY4 4  // D2
#define BLYNK_MSG_LIMIT 200
/****************************************************************************/
#define TERMINAL_vPIN                 0
#define RTC_vPIN                      1
#define MANUAL_MODE_vPIN              2
#define WIFI_vPIN                     3
#define TIME_vPIN                     4
#define DATE_vPIN                     5

#define LED1_vPIN                     8
#define LED2_vPIN                     9
#define LED3_vPIN                     10

#define MOIST_THRESHOLD_vPIN          12
#define MOIST_RESET_vPIN              13
#define MOIST_THRESHOLD_DISPLAY_vPIN  14
#define MOIST_RESET_DISPLAY_vPIN      15

#define DAILY_WATER_vPIN              17

#define MOIST_SENS1_vPIN              20
#define MOIST_SENS2_vPIN              23
#define MOIST_SENS3_vPIN              26
/****************************************************************************/
SimpleTimer timer;
SimpleTimer timer_relayStates;
SimpleTimer timer_getMoistureUpdates;
WidgetTerminal terminal(TERMINAL_vPIN);
WidgetRTC rtc;
BLYNK_ATTACH_WIDGET(rtc, RTC_vPIN);
/****************************************************************************/
String extraZeroH;
String extraZeroM;
String extraZeroS;
/****************************************************************************/
int manualMode;
int manualModePrev;
int moistureThreshold;
int moistureThreshold1;
int moistureThreshold2;
int moistureThreshold3;
int moistureThresholdReset1;
int moistureThresholdReset2;
int moistureThresholdReset3;
/****************************************************************************/
boolean RelayOneStatePrev;
boolean RelayTwoStatePrev;
boolean RelayThreeStatePrev;
boolean RelayFourStatePrev;
/****************************************************************************/
int moistureSensor1;
int moistureSensor2;
int moistureSensor3;
String signalStrength;
/****************************************************************************/
void sendUptime() {
  extraZeroH = "";
  extraZeroM = "";
  extraZeroS = "";

  if (hour() < 10) {
    extraZeroH = '0';
  }
  if (minute() < 10) {
    extraZeroM = '0';
  }
  if (second() < 10) {
    extraZeroS = '0';
  }
  String currentTime = String(extraZeroH + hour()) + ':' + extraZeroM + minute() + ':' + extraZeroS + second();
  String currentDate = String(day()) + '-' + monthShortStr(month()) + '-' + year();
  Blynk.virtualWrite(DATE_vPIN, currentDate);
  Blynk.virtualWrite(TIME_vPIN, currentTime);
  signalStrength = map(WiFi.RSSI(), -125, -42, 0, 100);
  signalStrength += '%';
  Blynk.virtualWrite(WIFI_vPIN, signalStrength);
}
/****************************************************************************/
void sendRelayStates() {
  if (RelayOneStatePrev != digitalRead(RELAY1)) {
    Blynk.virtualWrite(LED1_vPIN, map(!digitalRead(RELAY1), 0, 1, 0, 255));
    RelayOneStatePrev = digitalRead(RELAY1);
  }
  if (RelayTwoStatePrev != digitalRead(RELAY2)) {
    Blynk.virtualWrite(LED2_vPIN, map(!digitalRead(RELAY2), 0, 1, 0, 255));
    RelayTwoStatePrev = digitalRead(RELAY2);
  }
  if (RelayThreeStatePrev != digitalRead(RELAY3)) {
    Blynk.virtualWrite(LED3_vPIN, map(!digitalRead(RELAY3), 0, 1, 0, 255));
    RelayThreeStatePrev = digitalRead(RELAY3);
  }
}
/****************************************************************************/
void getMoistureUpdates() {
  Blynk.syncVirtual(MOIST_SENS1_vPIN); 
  //Blynk.syncVirtual(MOIST_SENS2_vPIN); 
  //Blynk.syncVirtual(MOIST_SENS3_vPIN); 
}
/****************************************************************************/
BLYNK_CONNECTED() {
  terminal.println("Reconnecting... Updating vPINs");
  terminal.flush();
  Blynk.syncVirtual(MANUAL_MODE_vPIN);
  Blynk.syncVirtual(MOIST_THRESHOLD_vPIN);
  Blynk.syncVirtual(MOIST_RESET_vPIN);
  //Blynk.syncVirtual(MOIST_SENS1_vPIN);
  //Blynk.syncVirtual(MOIST_SENS2_vPIN);
  //Blynk.syncVirtual(MOIST_SENS3_vPIN);
}
BLYNK_WRITE(MANUAL_MODE_vPIN) {
  manualOverride(param.asInt());
  terminal.print("Manual Mode:");
  terminal.println(param.asInt());
  terminal.flush();
}
BLYNK_WRITE(MOIST_THRESHOLD_vPIN) {
  moistureThreshold = param.asInt();
  Blynk.virtualWrite(MOIST_THRESHOLD_DISPLAY_vPIN,param.asInt());
  terminal.print("Moisture Threshold: ");
  terminal.print(moistureThreshold);
  terminal.println("%");
  terminal.flush();
}
BLYNK_WRITE(MOIST_RESET_vPIN) {
  moistureThresholdReset1 = param.asInt();
  moistureThresholdReset2 = param.asInt();
  moistureThresholdReset3 = param.asInt();
  Blynk.virtualWrite(MOIST_RESET_DISPLAY_vPIN,param.asInt());
  terminal.print("Moisture Reset: ");
  terminal.print(param.asInt());
  terminal.println("%");
  terminal.flush();
}
BLYNK_WRITE(MOIST_SENS1_vPIN) {
  if (!param.asInt()) {
    moistureSensor1 = (int)999;
  } else {
    moistureSensor1 = param.asInt();
  }
}
BLYNK_WRITE(MOIST_SENS2_vPIN) {
  if (!param.asInt()) {
    moistureSensor2 = (int)999;
  } else {
    moistureSensor2 = param.asInt();
  }
}
BLYNK_WRITE(MOIST_SENS3_vPIN) {
 if (!param.asInt()) {
    moistureSensor3 = (int)999;
  } else {
    moistureSensor3 = param.asInt();
  }
}
/****************************************************************************/
void setup() {
  // PINMODS
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  // SET RELAYS OFF
  digitalWrite(RELAY1, HIGH);
  digitalWrite(RELAY2, HIGH);
  digitalWrite(RELAY3, HIGH);
  digitalWrite(RELAY4, HIGH);
  // COMMS
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  Blynk.begin(auth, ssid, pass, IPAddress(192, 168, 1, 2));
  while (Blynk.connect() == false) {}
  ArduinoOTA.setHostname("gArduino-Base"); // OPTIONAL
  ArduinoOTA.begin();
  // RTC
  rtc.begin();
  // TIMERS
  timer.setInterval(1000L, sendUptime);
  timer_relayStates.setInterval(250L, sendRelayStates);
  timer_getMoistureUpdates.setInterval(1000L, getMoistureUpdates);
  // READY
  terminal.println("### Garduino Base - Device started");
  terminal.flush();
}
/****************************************************************************/
void manualOverride(int state) {
  if (state == 1) {
    digitalWrite(RELAY4, LOW);
    digitalWrite(RELAY1, HIGH);
    digitalWrite(RELAY2, HIGH);
    digitalWrite(RELAY3, HIGH);
    manualMode = 1;
  } else if (state == 0) {
    digitalWrite(RELAY4, HIGH);
    manualMode = 0;
  }
}
/****************************************************************************/

/****************************************************************************/

/****************************************************************************/
void loop() {
  Blynk.run();
  ArduinoOTA.handle();
  timer.run();
  timer_relayStates.run();
  timer_getMoistureUpdates.run();

  if (manualMode == 0) {

    if (moistureSensor1 < moistureThreshold && digitalRead(RELAY1)) {
      digitalWrite(RELAY1, LOW);
    }
    if (moistureSensor1 > moistureThresholdReset1 && !digitalRead(RELAY1) ) {
      digitalWrite(RELAY1, HIGH);
    }

    if (moistureSensor2 < moistureThreshold && digitalRead(RELAY2)) {
      digitalWrite(RELAY2, LOW);
    }
    if (moistureSensor2 > moistureThresholdReset2 && !digitalRead(RELAY2) ) {
      digitalWrite(RELAY2, HIGH);
    }

    if (moistureSensor3 < moistureThreshold && digitalRead(RELAY3)) {
      digitalWrite(RELAY3, LOW);
    }
    if (moistureSensor3 > moistureThresholdReset3 && !digitalRead(RELAY3) ) {
      digitalWrite(RELAY3, HIGH);
    }


  }
}
/****************************************************************************/

Sensor Code:

/*
  Virtual Ports:
  V0 = Hue (Slider 0-255)
  V1 = Saturation (Slider 0-255)
  V2 = Brightness (Slider 0-255)
*/
/****************************************************************************/
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
char auth[] = "xxxxxxxxx";
ADC_MODE(ADC_VCC); 
SimpleTimer timer;
/****************************************************************************/
void setup()
{
  WiFi.mode(WIFI_STA);
  Blynk.begin(auth, "xxxxxxx", "xxxxxxxxxxx", IPAddress(192, 168, 1, 2));
  while (Blynk.connect() == false) {}
  /*********** OTA *************/
  ArduinoOTA.setHostname("Tester-02-ESP8266");
  ArduinoOTA.begin();
  /******** READY **************/
  
  timer.setInterval(1000L, sendUptime);
}
/****************************************************************************/
void sendUptime() {
  Blynk.virtualWrite(1, millis() / 1000 );
  Blynk.virtualWrite(2, map(WiFi.RSSI(), -105, -40, 0, 100) + String('%') );
  Blynk.virtualWrite(3, ESP.getVcc() );
  //Blynk.virtualWrite(4, analogRead(A0) );
}
/****************************************************************************/
void loop()
{
  Blynk.run();
  ArduinoOTA.handle();
  timer.run();
}


6 Likes

Hi

Thanks,yes the water distributor is built by me:)

Really nice project !

Your project looks really nice, I am grateful that you shared your project to me.
I will look deeper into it as soon as possible and try to understand how it is built.

Thanks !

2 Likes

hi @Jamin - cool project ; how did you get the cool icons in the water readout and temperature ? Is it available for iOS or just Android

@mars, He’s using the labelled value indicator widget, and entered an emoticon :bulb: :slight_smile: . That’s a neat workaround @jasmin !

1 Like

very cool !

To Jamin.
Hi. Very good project.
I have one question: how You inserted pictograms of the thermometer and drops onto widgets TEMP,
HUMIDITY and WATER USAGE TODAY?
Thank You.

Hello @Jamin
Really awesome project.
I am working on similar project .i have used water flow sensor as you shown in pics.
Have you got good accuracy for counting
Water usage with this sensore??
From where you buy this solenoid valves??

Use emojis from your smartphone keyboard.
For labeling widget.
Like this :droplet::sweat_drops:

Hi, I found this and had it working on my UNO (+ ESP Serial). Yet to get it working on the ESP standalone.


http://diyhacking.com/projects/FlowMeterDIY.ino

Bingo!

Hello, Great project! It is possible that you generate QR Code for this project?
Thanks
Maciej

1 Like

Thank you @Jamin for the great project.
I’m having problems compiling. Can you help me.
I am using Arduino IDE 1.8.1 Install, library Blynk 0.4.7, NodeMCU 8266 v1

In file included from C:\Users\GioLangLe\Documents\Arduino\libraries\Blynk\src/WidgetLED.h:13:0,

                 from C:\Users\GioLangLe\Documents\Arduino\libraries\Blynk\src/BlynkWidgets.h:10,

                 from C:\Users\GioLangLe\Documents\Arduino\libraries\Blynk\src/BlynkSimpleEsp8266.h:94,

                 from C:\Users\GioLangLe\Desktop\SPI\SPI.ino:41:

C:\Users\GioLangLe\Desktop\SPI\SPI.ino: In function 'void BlynkWidgetWrite1(BlynkReq&, const BlynkParam&)':

C:\Users\GioLangLe\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkWidgetBase.h:50:33: error: 'class WidgetRTC' has no member named 'onWrite'

     BLYNK_WRITE(pin) { (widget).onWrite(request, param); }

                                 ^

C:\Users\GioLangLe\Desktop\SPI\SPI.ino:83:1: note: in expansion of macro 'BLYNK_ATTACH_WIDGET'

 BLYNK_ATTACH_WIDGET(rtc, RTC_vPIN);

 ^

C:\Users\GioLangLe\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkWidgetBase.h: In instantiation of 'BlynkAttachWidgetHelper::BlynkAttachWidgetHelper(T&, uint8_t) [with T = WidgetRTC; uint8_t = unsigned char]':

C:\Users\GioLangLe\Desktop\SPI\SPI.ino:83:1:   required from here

C:\Users\GioLangLe\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkWidgetBase.h:43:9: error: 'class WidgetRTC' has no member named 'setVPin'

         widget.setVPin(vPin);

         ^

exit status 1

Those errors are not related to my project, but instead your local setup.

Check all your libraries are correct and up to date. You also need to troubleshoot in steps by removing portions until it works.

Sorry I cant help more.

1 Like

What versions are you using?

Not latest… haha – actually not sure what I have installed at home.

However the code you would have copied above is quite old… back when I had only been writing arduino/c++ a few months.

Check out my Github repo for the project that the above code evolved in to. Its more complete but might be slightly different to whats you’re wanting. Either way its probably a better stating point.

and here is the community thread:

1 Like

Dear Jamin,
please explain to me if you want what does the simpletimer shorthand, like this:

timer.setInterval( 1000, []() { ... } )

Thanks a lot

It’s the same as using simpletimer but without the hassle of having to write a callback function.

Thanks a lot for your answer.
So to ensure that I understood your reply, that means that we can have ( using the shorthand way ) at setup section, both the simpletimer definition as well as the required function ( the callback function ). Is that correct.

Thanks and Best regards,
Mike Kranidis

For a little light reading :stuck_out_tongue: Google “Lambda Expressions C++

2 Likes