Beginner coding for Automatic irrigation system

Good afternoon everyone. Apologies for being a beginner here (coding).

My project is as follows:

Ultimately a 16 zone plant watering system for my balcony plants. Reasons: I'm lazy, live in 40+ degrees heat, not so much time on my hands, not an experienced gardener, I love automation. :slight_smile:

I work in automotive technical, auto electrician, have built some small bespoke electronics projects on occasion, but not coding, this is where my knowledge dies off.

I am looking through the online training etc, but also looking at other similar projects that vary vastly in the coding (which i get confused about). I am a "learn on the job" kind of guy.

I want to use Mega 2560 R3, Capacitance Soil Moisture Sensor, Relay Module (to run solenoids), ESP8266 wifi as I would like to get this online. I will run solenoids from the relays on their own power supply. I have a central pump for all.

I will start with just one moisture sensor and 1 relay.

I built the circuit on circuito.io and got the following code. I assume just some basic formality of a code.

1st step/question for me is some info about the code i attached. is it relevant, necessary.

2nd step/question. How do i simply control the relay from the moisture sensor.

1 Like

// Include Libraries
#include "Arduino.h"
#include "ESP8266.h"
#include "GraphicLCD.h"
#include "SoilMoisture.h"


// Pin Definitions
#define GRAPHICLCD_PIN_TX 3
#define GRAPHICLCD_PIN_RX 2
#define RELAYMODULE4CH_PIN_IN1 4
#define RELAYMODULE4CH_PIN_IN2 5
#define RELAYMODULE4CH_PIN_IN4 7
#define RELAYMODULE4CH_PIN_IN3 6
#define SOILMOISTURE_5V1_1_PIN_SIG A10
#define SOILMOISTURE_5V2_2_PIN_SIG A0
#define SOILMOISTURE_5V3_3_PIN_SIG A3
#define SOILMOISTURE_5V4_4_PIN_SIG A13



// Global variables and defines
// ====================================================================
// vvvvvvvvvvvvvvvvvvvv ENTER YOUR WI-FI SETTINGS  vvvvvvvvvvvvvvvvvvvv
//
const char *SSID = "WIFI-SSID";     // CornishRes
const char *PASSWORD = "PASSWORD";  // Crabpeople2023!!
//
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// ====================================================================
char *const host = "www.google.com";
int hostPort = 80;
//define an array for the 4ch relay module pins
int RelayModule4chPins[] = { RELAYMODULE4CH_PIN_IN1, RELAYMODULE4CH_PIN_IN2, RELAYMODULE4CH_PIN_IN3, RELAYMODULE4CH_PIN_IN4 };
// object initialization
ESP8266 wifi;
GraphicLCD graphicLCD(GRAPHICLCD_PIN_RX, GRAPHICLCD_PIN_TX);
SoilMoisture soilMoisture_5v1_1(SOILMOISTURE_5V1_1_PIN_SIG);
SoilMoisture soilMoisture_5v2_2(SOILMOISTURE_5V2_2_PIN_SIG);
SoilMoisture soilMoisture_5v3_3(SOILMOISTURE_5V3_3_PIN_SIG);
SoilMoisture soilMoisture_5v4_4(SOILMOISTURE_5V4_4_PIN_SIG);


// define vars for testing menu
const int timeout = 10000;  //define timeout of 10 sec
char menuOption = 0;
long time0;

// Setup the essentials for your circuit to work. It runs first every time your circuit is powered with electricity.
void setup() {
  // Setup Serial which is useful for debugging
  // Use the Serial Monitor to view printed messages
  Serial.begin(9600);
  while (!Serial)
    ;  // wait for serial port to connect. Needed for native USB
  Serial.println("start");

  wifi.init(SSID, PASSWORD);
  pinMode(RELAYMODULE4CH_PIN_IN1, OUTPUT);
  pinMode(RELAYMODULE4CH_PIN_IN2, OUTPUT);
  pinMode(RELAYMODULE4CH_PIN_IN3, OUTPUT);
  pinMode(RELAYMODULE4CH_PIN_IN4, OUTPUT);
  menuOption = menu();
}

// Main logic of your circuit. It defines the interaction between the components you selected. After setup, it runs over and over again, in an eternal loop.
void loop() {


  if (menuOption == '1') {
    // Logic Level Converter - Bi-Directional - Test Code
    //Send request for www.google.com at port 80
    wifi.httpGet(host, hostPort);
    // get response buffer. Note that it is set to 250 bytes due to the Arduino low memory
    char *wifiBuf = wifi.getBuffer();
    //Comment out to print the buffer to Serial Monitor
    //for(int i=0; i< MAX_BUFFER_SIZE ; i++)
    //  Serial.print(wifiBuf[i]);
    //search buffer for the date and time and print it to the serial monitor. This is GMT time!
    char *wifiDateIdx = strstr(wifiBuf, "Date");
    for (int i = 0; wifiDateIdx[i] != '\n'; i++)
      Serial.print(wifiDateIdx[i]);

  } else if (menuOption == '2') {
    // Graphic LCD 160x128 Huge - Test Code
    // The LCD Screen will display the text of your choice at the location (30,50) on screen. Counting from the top left corner: 30 pixels to the right and 50 pixels down
    graphicLCD.setX(30);                     // 1. sets left-right indent for text to print. Change the value in the brackets (1 - left, 164 - right) for a different indent.
    graphicLCD.setY(50);                     // 2. sets top-bottom height for text to print. Change the value in the brackets (1 - top, 128 - bottom) for a different height.
    graphicLCD.print("Circuito.io Rocks!");  // 3. prints the text in the brackets. Modify the text to get your own unique print.
    delay(1000);                             // 4. waits 1000 milliseconds (1 sec). Change the value in the brackets (1000) for a longer or shorter delay in milliseconds.
    graphicLCD.clear();                      // 5. wipes the screen
    delay(1000);                             // 6. waits 1000 milliseconds (1 sec). Change the value in the brackets (1000) for a longer or shorter delay in milliseconds.
  } else if (menuOption == '3') {
    // Relay Module 4-Ch - Test Code
    //This loop will turn on and off each relay in the array for 0.5 sec
    for (int i = 0; i < 4; i++) {
      digitalWrite(RelayModule4chPins[i], HIGH);
      delay(500);
      digitalWrite(RelayModule4chPins[i], LOW);
      delay(500);
    }
  } else if (menuOption == '4') {
    // Soil Moisture Sensor #1 - Test Code
    int soilMoisture_5v1_1Val = soilMoisture_5v1_1.read();
    Serial.print(F("Val: "));
    Serial.println(soilMoisture_5v1_1Val);

  } else if (menuOption == '5') {
    // Soil Moisture Sensor #2 - Test Code
    int soilMoisture_5v2_2Val = soilMoisture_5v2_2.read();
    Serial.print(F("Val: "));
    Serial.println(soilMoisture_5v2_2Val);

  } else if (menuOption == '6') {
    // Soil Moisture Sensor #3 - Test Code
    int soilMoisture_5v3_3Val = soilMoisture_5v3_3.read();
    Serial.print(F("Val: "));
    Serial.println(soilMoisture_5v3_3Val);

  } else if (menuOption == '7') {
    // Soil Moisture Sensor #4 - Test Code
    int soilMoisture_5v4_4Val = soilMoisture_5v4_4.read();
    Serial.print(F("Val: "));
    Serial.println(soilMoisture_5v4_4Val);
  }

  if (millis() - time0 > timeout) {
    menuOption = menu();
  }
}



// Menu function for selecting the components to be tested
// Follow serial monitor for instrcutions
char menu() {

  Serial.println(F("\nWhich component would you like to test?"));
  Serial.println(F("(1) Logic Level Converter - Bi-Directional"));
  Serial.println(F("(2) Graphic LCD 160x128 Huge"));
  Serial.println(F("(3) Relay Module 4-Ch"));
  Serial.println(F("(4) Soil Moisture Sensor #1"));
  Serial.println(F("(5) Soil Moisture Sensor #2"));
  Serial.println(F("(6) Soil Moisture Sensor #3"));
  Serial.println(F("(7) Soil Moisture Sensor #4"));
  Serial.println(F("(menu) send anything else or press on board reset button\n"));
  while (!Serial.available())
    ;

  // Read data from serial monitor if received
  while (Serial.available()) {
    char c = Serial.read();
    if (isAlphaNumeric(c)) {

      if (c == '1')
        Serial.println(F("Now Testing Logic Level Converter - Bi-Directional"));
      else if (c == '2')
        Serial.println(F("Now Testing Graphic LCD 160x128 Huge"));
      else if (c == '3')
        Serial.println(F("Now Testing Relay Module 4-Ch"));
      else if (c == '4')
        Serial.println(F("Now Testing Soil Moisture Sensor #1"));
      else if (c == '5')
        Serial.println(F("Now Testing Soil Moisture Sensor #2"));
      else if (c == '6')
        Serial.println(F("Now Testing Soil Moisture Sensor #3"));
      else if (c == '7')
        Serial.println(F("Now Testing Soil Moisture Sensor #4"));
      else {
        Serial.println(F("illegal input!"));
        return 0;
      }
      time0 = millis();
      return c;
    }
  }
}

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

*    Circuito.io is an automatic generator of schematics and code for off
*    the shelf hardware combinations.

*    Copyright (C) 2016 Roboplan Technologies Ltd.

*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.

*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.

*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*    In addition, and without limitation, to the disclaimers of warranties 
*    stated above and in the GNU General Public License version 3 (or any 
*    later version), Roboplan Technologies Ltd. ("Roboplan") offers this 
*    program subject to the following warranty disclaimers and by using 
*    this program you acknowledge and agree to the following:
*    THIS PROGRAM IS PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS, AND 
*    WITHOUT WARRANTIES OF ANY KIND EITHER EXPRESS OR IMPLIED.  ROBOPLAN 
*    HEREBY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
*    NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, TITLE, FITNESS 
*    FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND THOSE ARISING BY 
*    STATUTE OR FROM A COURSE OF DEALING OR USAGE OF TRADE. 
*    YOUR RELIANCE ON, OR USE OF THIS PROGRAM IS AT YOUR SOLE RISK.
*    ROBOPLAN DOES NOT GUARANTEE THAT THE PROGRAM WILL BE FREE OF, OR NOT 
*    SUSCEPTIBLE TO, BUGS, SECURITY BREACHES, OR VIRUSES. ROBOPLAN DOES 
*    NOT WARRANT THAT YOUR USE OF THE PROGRAM, INCLUDING PURSUANT TO 
*    SCHEMATICS, INSTRUCTIONS OR RECOMMENDATIONS OF ROBOPLAN, WILL BE SAFE 
*    FOR PERSONAL USE OR FOR PRODUCTION OR COMMERCIAL USE, WILL NOT 
*    VIOLATE ANY THIRD PARTY RIGHTS, WILL PROVIDE THE INTENDED OR DESIRED
*    RESULTS, OR OPERATE AS YOU INTENDED OR AS MAY BE INDICATED BY ROBOPLAN. 
*    YOU HEREBY WAIVE, AGREE NOT TO ASSERT AGAINST, AND RELEASE ROBOPLAN, 
*    ITS LICENSORS AND AFFILIATES FROM, ANY CLAIMS IN CONNECTION WITH ANY OF 
*    THE ABOVE. 
********************************************************/

Welcome to the forum

Your topic has been moved to a more relevant forum category

If you do a bit of research you will find that moisture sensor mostly does not work. There are sensors that work that I just found out about, but they are 'professional' units. No idea re cost but suspect higher to much higher.

1 Like

Thanks. Ill stick to my original approach for now as its not costly. Further down the line I can upgrade.

For now some feedback on the hardware selection and guidance on code is what i need

Thanks

Mark

In that case, the Project Hub has 21 irrigation projects for you to learn from.

Nothing to apologise for, this forum is for beginners like you.

When you first started doing that did you start with trying to understand all the electrics of a complete car? (I suspect not). If not, then why are you trying to work with what looks like an attempt at complete code for the whole thing? You have Wifi, multple soil sensors and a display in there, and I guess you don't understand any of it. The code you posted is way too complex for a beginner. Start simple, go through the beginner examples in the IDE, the tutorials on this forum and elsewhere. The first trap to avoid is using delay. Note what it does (nothing for a time) then learn how time things without delay. Second trap is 'while' loops that wait for something to happen and stop anything else happening. Learn what a state machine is. But, before that, learn the basics of code, like you (I hope) learnt the basics of electricity before being let loose on the wiring of a whole car.

Why? I find this an odd thing to do. What is a relay other than a solenoid that operates some contacts? Skip the relay and operate the solenoids directly from a suitable MOSFET. Too soon for that with your current knowledge? Something to think about and come back to later.

Please keep us updated, I love seeing these kinds of project progress from 'I don't know how to do this' to 'look what I made :slight_smile: '.

1 Like

Ha. Yes your correct, the code is a blur. The code i attached was automatically generated from the circuito.io website after designing the physical system.

For now I want to leave the wifi, lcd out and just test 1 moisture sensor and 1 relay. I will use 12v solenoids so need seperate 12v supply, hence the relays. Unless you say otherwise? I can control 12v solenoid straight from Mega 2560? My understanding I cant.

I should probably not look at the coding created by circuito.io then and start from scratch.... help lol

Mark

btw, mosfets i can do. But for now the relay board is not expensive and just simplifies things for me for now while i get around the core problem of making it run and figuring out coding.

If you want to learn, yes, ignore it. Alternatively go thorough it line by line and learn what each line does. There are plenty of online C / C++ references to help you, for example https://cplusplus.com/doc/tutorial/, but I think ignoring it is the best option.

I don't see any need for relays for what you are trying to do, I don't see any need for isolation. One 12V power supply should be OK for the whole thing, especially if you know how to use MOSFETs. At the moment I suggest forgetting about the solenoids and just use LEDs in their place to show what is happening, add the solenoids later when you are happy that the LEDs go on and off at the right times.

1 Like

Ok i see. I have done the physical circuit with 12v solenoid and use of mosfet instead of relay. Ill do that at the end, will make a small pcb for that lot.

Back to coding...

Mark

Which watering theory will the code represent? Some flowers need more water, some need less. Some flowers like a bath every xx day...
"Code" doesn't know that.

I think at the moment you are trying to do the code equivalent of rewiring a whole car before you know how to connect a light bulb to a battery and a switch. Learn the basics first.

2 Likes

Firstly my hardware arrives today within next few hours.

Step one i need simple code just to check my "full dry" and "saturated" readings from the sensor

Step 2: Code - if moisture sensor reads below "x" activate "output" until moisture sensor reads "x"

Side note: power to external pump and the arduino will only be on at 5am-6am and 7pm-8pm. This is externally controlled and only for info purposes

Mark

I'd say it is not bad for an auto generated software.
For a quick start comment the wifi.init ( in the setup ), connect the relay board and a moisture sensor and you are good to test the circuit
Commands are sent trough the serial, so start the arduino serial monitor ( at 9600 baud ):

  • option 3 test the four relays
  • options 4-7 test one of the sensors

P.S.
option 1 is quite funny 'Logic level converter' ( in fact test wifi that you disabled before, so don't test it... or enable it before testing )

Step 1:

Please check code

This should allow me to read the sensor and activate output automatically depending on moisture.

Mark

// Define pins
#define SOIL_MOISTURE1_PIN A0
#define SOLENOID1_PIN 2

// Define threshold variable
int threshold = 500; // Change this value to adjust the threshold for activating the pump

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  
  // Set pump pin as output
  pinMode(SOLENOID1_PIN, OUTPUT);
}

void loop() {
  // Read soil moisture sensor data
  int soil_moisture = analogRead(SOIL_MOISTURE1_PIN);
  
  // Print sensor data to serial monitor
  Serial.print("Soil Moisture: ");
  Serial.println(soil_moisture);
  
  // Check if soil moisture is below threshold
  if (soil_moisture < threshold) {
    // Activate pump
    digitalWrite(SOLENOID1_PIN, HIGH);
    Serial.println("Solenoid1 activated!");
  } else {
    // Deactivate pump
    digitalWrite(SOLENOID_PIN1, LOW);
    Serial.println("sOLENOID1 deactivated.");
  }
  
  // Delay for 1 second
  delay(1000);
}

You can try how it works, but I have doubts you get good watering results.
Logic could be: ...until moisture sensor reads (x+ something). Results depend on distance between sensor and water drip valve.
Or time based:
if moisture sensor reads <x, irrigate 5 minutes, if <y, irrigate 10 minutes, else don't irrigate

It looks like it will work to test your hardware. You might consider making the delay a bit longer so you can more easily see what's going on.

The capitalization for "sOLENOID1 deactivated." isn't what you intended I suspect. It doesn't matter at all, but it does illustrate that you need to develop an eagle eye for spotting odd things in your code for those times when a similar error actually is important.

yes (x+ something) is a good point and will do that

Thanks

Mark

Yes, thank you. I had noticed after posting. Dont turn CAPS on is the solution there:)