element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Open Arduino
  • Challenges & Projects
  • Project14
  • Open Arduino
  • More
  • Cancel
Open Arduino
Blog Arduino and ESP-01 based irrigation system
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Open Arduino to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: urkraft
  • Date Created: 26 Apr 2018 5:22 PM Date Created
  • Views 6092 views
  • Likes 10 likes
  • Comments 22 comments
  • ardintermediate
  • arduino_projects
  • openarduinoch
Related
Recommended

Arduino and ESP-01 based irrigation system

urkraft
urkraft
26 Apr 2018

General description

The purpose of this project is to create an automated irrigation system based on an Arduino Uno and ESP-01. It will need to automatically detect when irrigation is required and if there is water in the reservoir so that irrigation can initiated. If the reservoir is empty, then an e-mail must be sent to inform of this so that the situation can be remedied. If irrigation is required and water is available (and all the safety requirements are met), then irrigation should be initiated.

 

The system includes a soil hygrometer sensor for detecting the dryness of the soil, a water reservoir (a bucket of water), a water level switch for detecting if the water reservoir is empty, a peristaltic water pump used to irrigate the soil, and an OLED graphical display and a rotary encoder which are used to adjust humidity thresholds at which irrigation should be started and stopped.

 

As mentioned earlier, the system also includes a set of safety requirements which have to be met.

 

Project specification:

 

The main components of the system are:

 

  • An Arduino Uno (hereafter referred to as “Uno”) which controls everything
  • A 9V DC 1A power adapter for the Uno
  • An ESP-01 WiFi module which is used to facilitate messaging
  • A FC-28 soil hygrometer (moisture sensor) for detecting humidity in soil
  • A water level switch NC mounted on a float for detecting when the water reservoir is empty
  • A Keyes KY-040 rotary encoder is used to adjust threshold values used by the sketch
  • A 0.96" 128 x 64 pixel OLED graphical display used to display status information
  • A peristaltic water pump to pump water from the water reservoir to the soil
  • A 12V DC 1A power adapter for the water pump
  • A 10 gallon bucket of water (water reservoir)
  • A potted plant to water

 

Operation:

 

The two sensors (soil hygrometer and water level switch) are connected to inputs of the Uno (A0 and D11 respectively) and the water pump is controlled by an output signal (D10) from  the Uno. Two LED’s are controlled by output signals from the Uno and are used as status indicators:

 

  • Red  : (D13) Lit to indicate that the soil is dry enough to warrant watering
  • Blue : (D12) Lit to indicate that the water reservoir is empty (requires a refill of water)

 

A 0.96" 128 x 64 piksel OLED graphical display is also used to display status information and to adjust threshold levels for turning the water pump on and off. It uses the Uno's I2C interface (A5(SCL) and A4(SDA)).

 

A Keyes KY-040 rotary encoder is used together with the OLED display to adjust the threshold values used by the script. It uses the D2 through D5 pins as input. The system goes into adjustment modus when the knob is depressed. The user can then scroll through the items which can be adjusted. The item to calibrate is choosen by depressing the switch once more when it displayed. This causes the system to display the current value being used for that item. The user can then increase the value by turning the knob clockwise (whereupon the displayed value increases) or counter clockwise (whereupon the displayed value decreases). To choose the displayed value the user must depress the knob - whereupon the system also exits adjustment mode and commenses to use the new values.

 

There are three criteria which all have to be met in order to turn on the pump (and water the plant):

 

  1. There must be water in the reservoir
  2. The soil moisture reading in the soil must be greater than a specified high threshold value (indicating the soil is too dry)
  3. A specified minimum amount of time must have elapsed since the pump was last turned off while watering (but not if this was due to entering adjustment modus).

 

Any one of the following criteria will cause the pump to be turned off:

 

  • No water left in the water reservoir
  • The moisture reading of the soil is lower than a specified low threshold value (indicating the soil has been irrigated sufficiently. This criteria also triggers the timer which keeps track of the amount of time that has elapsed since the pump was turned off).
  • the pump has been on continually for at least MAX_PUMP_ON_TIME milliseconds.
  • (only temporarily) entering adjustment mode

 

Basically, the Uno just goes in a loop checking the criteria above and taking action when necessary. Each loop iteration takes approximately 20-30 seconds to complete. If, however the knob of the rotary encoder is depressed and this is detected, the function for adjustment modus is called and normal operation is not resumed until after returning from the function. Before the adjustment function is called the water pump and on time timer are both stopped if the pump is on. Both are then resumed upon returning from the adjustment function.

 

Notes:

 

GPIO ESP_WATER_EMPTY is used to signal to the ESP-01 that the water reservoir is empty (via the GP0 pin of the ESP-01). The ESP-01 is configured to use its GPIO0 as an input. A LOW signal on this pin will trigger the sendMessage(FILL_RESERVOIR_URL) function on the ESP-01. This function invokes a PHP script on my Raspberry Pi server via a HTTP GET request. The parameter it uses indicates which script to invoke. This one (FILL_RESERVOIR_URL) results in an e-mail being sent to me informing me that the water reservoir is empty. The ESP-01 also calls this function with CONNECT_SUCCESS_URL as the parameter from its setup() function. The resulting e-mail informs me that the the ESP-01 has successfully connected to the WiFi and it also reminds me that any custom thresholds need to be re-entered (since this e-mail will only be sent whenever the ESP-01 restarts => the Uno has also been restarted.

 

Future features to implement:

 

  • replace Uno with custom design (with ability to reprogram by attaching adequate IO interface)

 

Schematic:

 

image

 

Breadboard Layout:

 

image

 

ESP-01 Sketch:

 

/******************************************************************************************************** 
 * Program for ESP-01 used in semi-automated irrigation system 
 * =========================================================== 
 *  
 * Summary: 
 * -------- 
 *  
 *  This sketch is used to sends emails by running appropriate PHP scripts (the URL parameter used)  
 *  triggered via HTTP GET requests to a HOST. 
 *   
 *  One script is triggered by the setup() function after  
 *  the ESP-01 establishes a WiFi connection to MY_SSID. That e-mail informs the recipient that it has 
 *  successfully established the WiFi connection and that the default threshold values are being used  
 *  by the Arduino Uno to control the water pump. 
 *   
 *  The other script is triggered by a LOW signal on the GPIO0 pin (which is configured as an input). 
 *  The e-mail that this script sends informs the recipient that the water reservoir is empty. After 
 *  triggering the script the sketch waits for PAUSE_AFTER_RESERVOIS_EMPTY_EMAIL_SENT before continuing. 
 *   
 *  The sketch uses the onboard blue LED (GPIO2) to indicate status during the WiFi connection process. 
 *  It flashes the LED until a connection is made. If no connection is made after MAX_CONNECT_ATTEMPTS 
 *  it turns the LED on for 10 seconds before exiting the script. 
 */  
  
  
#include   
  
  
const char* MY_SSID = "********"; // replace with the SSID you would like to connect to  
const char* PASSWORD = "********"; // replace with the SSID password  
  
  
IPAddress staticIP(192, 168, 1, 46); // replace with static IP address to use for ESP-01 device  
IPAddress gateway(192, 168, 1, 1); // replace with gateway IP address for the SSID  
IPAddress subnet(255, 255, 255, 0);  
  
  
const int MAX_CONNECT_ATTEMPTS = 5; // maximum attempts to make to connect the ESP-01 to the wifi PA  
const int MAX_WAIT_FOR_CONNECT_CYCLES = 40; // 2 cycles = approx. 1 sec  
const unsigned long PAUSE_AFTER_RESERVOIS_EMPTY_EMAIL_SENT = 1000UL * 60UL * 60UL * 24UL; // one day  
  
  
const String HOST = "192.168.1.45";  // replace with your server IP address  
const int HTTP_PORT = 80;  
const String FILL_RESERVOIR_URL = "/fillReservoir.php";  // script that sends me email warning that water reservoir is empty  
const String CONNECT_SUCCESS_URL = "/connectSuccess.php"; // script that sends me email informing of successful wifi connect  
  
  
const int RESERVOIR = 0;  // IO pin to use as input for signalling that the the water reservori is empty (LOW => empty)  
const int BLUE_LED = 2;   // IO pin to use for blinking the blue onboard LED to signal status (HIGH => off)  
  
  
int reservoirLevel = HIGH;  // used to store water reservoir status (LOW => empty)  
int ledStatus = HIGH; // used to store onboard blue LED status (HIGH => off)  
bool wifiIsConnected = false; // used to store wifi connection status (false => not connected)  
  
  
void setup() {  
  delay(10000);   // long delay here to make sure signals have stabilized before continuing  
  Serial.begin(115200);    
  Serial.println();  
  delay(100);    
  
  
  pinMode(BLUE_LED, OUTPUT);  
  digitalWrite(BLUE_LED, ledStatus);  
    
  WiFi.mode(WIFI_STA);  // configure ESP-01 to operate as a wifi station  
  wifiConnect();  
  for (int i = MAX_CONNECT_ATTEMPTS; i > 0; i--) {  
    if (wifiIsConnected = wifiConnect()) {  // connected! => no need to continue trying to connect  
      break;  
    }  
  }  
  if (!wifiIsConnected) {  
    digitalWrite(BLUE_LED, LOW);  
    delay(10000);  
    exit(1);  
  }  
    
  delay(100);    
  sendMessage(CONNECT_SUCCESS_URL);  
  delay(500);    
  pinMode(RESERVOIR, INPUT);  
  delay(100);  
}    
    
void loop() {  
  if (LOW == (reservoirLevel = digitalRead(RESERVOIR))) {  
    sendMessage(FILL_RESERVOIR_URL);  
    delay(PAUSE_AFTER_RESERVOIS_EMPTY_EMAIL_SENT);  
  } else {  
    delay(5000);  
  }  
}  
  
  
void sendMessage(String URL) {  
  WiFiClient client;    
      
  if (!client.connect(HOST, HTTP_PORT)) {    
    //Serial.println("connection failed");    
    return;    
  }    
      
  client.print(String("GET ") + URL + " HTTP/1.1\r\n" +    
               "Host: " + HOST + "\r\n" +     
               "Connection: close\r\n\r\n");    
  delay(500);    
}  
  
  
bool wifiConnect() {  
  bool wifiConnected = false;  
  
  
  WiFi.begin(MY_SSID, PASSWORD, 13, ap_mac, true);  
  WiFi.config(staticIP, gateway, subnet);  
  for (int i = MAX_WAIT_FOR_CONNECT_CYCLES; i > 0 ; i--) { // wait for 20 seconds to be connected  
    Serial.print("Connection status: ");  
    Serial.println(WiFi.status());  
    if (wifiConnected = (WiFi.status() == 3)) {  //WL_CONNECTED)) {  
      wifiConnected = true;  
      break;  
    }  
    delay(500);  
    if (ledStatus == HIGH) {  
      ledStatus = LOW;  
    } else {  
      ledStatus = HIGH;   
    }  
    digitalWrite(BLUE_LED, ledStatus);  
  }  
  ledStatus = HIGH;  
  digitalWrite(BLUE_LED, ledStatus);  
  WiFi.printDiag(Serial);  
  return wifiConnected;  
}

 

Arduino Uno Sketch:

 

/********************************************************************************************** 
* Program for semi-automated irrigation using Arduino Uno 
* ======================================================= 
*  
 
#include   
#include   
#include <adafruit_gfx.h>  
#include <adafruit_ssd1306.h>  
  
  
#define OLED_RESET 4  
Adafruit_SSD1306 display(OLED_RESET);  
  
  
#define NUMFLAKES 10  
#define XPOS 0  
#define YPOS 1  
#define DELTAY 2  
  
  
  
  
#define LOGO16_GLCD_HEIGHT 16   
#define LOGO16_GLCD_WIDTH  16   
#if (SSD1306_LCDHEIGHT != 32)  
#error("Height incorrect, please fix Adafruit_SSD1306.h!");  
#endif  
  
  
//==============  
// encoder stuff  
//==============  
#define ENCODER_CLK 2  
#define ENCODER_DT 3  
#define ENCODER_SW 4  
   
int encoderCounter = 0;   
int encoderClkState;  
int encoderClkLastState;    
int encoderSwLastState;  
int encoderSwState;  
int encoderPosition = 0;  
  
  
// I/O  
const int DRY_LED = 13;  // (Output) used to indicate what pump status should be ON (set HIGH) when the pump should be on  
const int PUMP = 10; // (Output) used to turn the pump on (set HIGH) and off (set LOW)  
const int WATER_EMPTY_LED = 12;  // (Output) used to indicate if the reservoir is empty (set HIGH => ON)  
const int WATER_LEVEL = 11;  // (Input) used to detect if there is water in the reservoir (HIGH) or if it is empty (LOW)  
const int ESP_WATER_EMPTY = 9;  // (Output) used to signal the ESP-01 that the water reservoir is empty (set LOW => empty)  
  
  
// A0 : ADC (Analog Input) used to read soil humidity: high value => dry, low value => wet   
// Max value is approx. 1018 - bone dry  
// Min value is approx. 530 - drowning in water  
const unsigned long MINIMUM_TIME = 1000UL * 60UL * 60UL * 24UL; // minimum time that must transpire between irrigation (1 day)  
//const unsigned long MINIMUM_TIME = 60UL * 1000UL; // minimum time that must transpire between irrigation (only for testing)  
const unsigned long MAX_PUMP_ON_TIME = 1000UL * 60UL * 15UL; // maximum time pump can be turned on for (15 minutes)  
//const unsigned long MAX_PUMP_ON_TIME = 60UL * 1000UL; // maximum time pump can be turned on for (only for testing)  
  
  
//==========  
// VARIABLES  
//==========  
  
  
// timing  
unsigned long lastIrrMillis = 0UL;  
unsigned long currentMillis = 0UL;  
unsigned long pumpOnMillis = 0UL;  
  
  
// soil moisture reading  
int pumpOnThresh = 200;  // Turn on the pump when ADC input value >= this value  
int pumpOffThresh = 190; // Turn off the pump when ADC input value <= this value (and do not trun on again for at least a day)  
bool pumpIsOn = false;  
int moisture = 800; // previous  
int waterLevel;  
  
  
//int tmpMoisture = 0;  //  new (temporary)  
  
  
int displayLine = 0;  
const int DISPLAY_LINE_INCREASE = 8;  
const int DISPLAY_LINE_MAX = 32;  
  
  
//======  
// SETUP  
//======  
  
  
void setup() {  
  // initialize Serial  
  Serial.begin(9600);  
  delay(100);  
  
  
  Serial.println("Soil moisture sensor");  
  
  
  // initialize IO  
  pinMode(WATER_LEVEL, INPUT_PULLUP);  
    
  pinMode(PUMP, OUTPUT);  
  digitalWrite(PUMP, LOW);  
  pumpIsOn = false;  
    
  pinMode(DRY_LED, OUTPUT);  
  digitalWrite(DRY_LED, LOW);  
    
  pinMode(WATER_EMPTY_LED, OUTPUT);  
  digitalWrite(WATER_EMPTY_LED, LOW);  
  
  
  pinMode(ENCODER_CLK, INPUT);  
  pinMode(ENCODER_DT, INPUT);  
  pinMode(ENCODER_SW, INPUT);  
    
  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)  
  // init done  
    
  display.setTextSize(1);  
  display.setTextColor(WHITE);  
  
  
  pinMode(ESP_WATER_EMPTY, OUTPUT);  
  digitalWrite(ESP_WATER_EMPTY, HIGH);  
}  
  
  
void loop() {  
  // rotary encoder stuff  
  encoderSwState = digitalRead(ENCODER_SW);  
  if ((encoderSwLastState == encoderSwState) and (encoderSwState == false)) {  
    unsigned long deltaTime;  
    if (pumpIsOn) {  
      deltaTime = millis() - pumpOnMillis;  
      digitalWrite(PUMP, LOW);  
    }  
    chooseMenu();  
    if (pumpIsOn) {  
      pumpOnMillis = millis() - deltaTime;  
      digitalWrite(PUMP, HIGH);  
    }  
    delay(1000);  
  }  
  
  
  //irrigation stuff  
  waterLevel = readInput(WATER_LEVEL);  // read water level  
  if (waterLevel == LOW) {  // water reservoir is empty  
    digitalWrite(PUMP, LOW); // turn off pump  
    pumpIsOn = false;  
    digitalWrite(WATER_EMPTY_LED, HIGH); // turn on LED indicator  
    digitalWrite(ESP_WATER_EMPTY, LOW);  // signal ESP-01 to send e-mail informing water reservoir is empty  
    // Serial.println("The water reservoir is empty => fill it up!");  
  } else {  
    digitalWrite(WATER_EMPTY_LED, LOW); // turn off LED indicator  
    digitalWrite(ESP_WATER_EMPTY, HIGH);  // signal ESP-01 that water reservoir contains water  
  }  
    
  moisture = analogRead(A0);  
  if (moisture >= pumpOnThresh) {  
    digitalWrite(DRY_LED, HIGH);  // turn on LED indicator  
    if (pumpIsOn) {  
      currentMillis = millis();  
      if ((pumpOnMillis == 0) or ((currentMillis - pumpOnMillis) >= MAX_PUMP_ON_TIME) or (currentMillis < pumpOnMillis)) {  
        digitalWrite(PUMP, LOW); // turn pump off  
        pumpIsOn = false;  
        lastIrrMillis = millis();  
      }  
    } else {  // pump is off  
      currentMillis = millis();  
      if ((lastIrrMillis == 0) or (currentMillis - lastIrrMillis >= MINIMUM_TIME)) {  
        if (waterLevel == HIGH) {  
          digitalWrite(PUMP, HIGH);  // turn on pump  
          pumpIsOn = true;  
          pumpOnMillis = millis();  
        } else {  
          // Serial.println("but no water in reservoir!");  
        }  
      } else {  
        // Serial.println("but not enough time has passed since last irrigation.");  
      }  
    }  
  } else if (moisture <= pumpOffThresh) {  
    digitalWrite(DRY_LED, LOW); // turn off LED indicator  
    if (pumpIsOn) {  
      digitalWrite(PUMP, LOW); // turn off pump  
      pumpIsOn = false;  
      lastIrrMillis = millis();  // update lastIrrMillis in preparation for MINIMUM_TIME criteria calculation  
    } else {  
      // Serial.println("The soil moisture level is high and the water pump is already off.");  
    }  
  } else {  
    // Serial.println("The soil moisture level is adequate => no action needed.");  
  }  
  display.clearDisplay();  
  display.setCursor(0, 0);  
  display.print("PumpOnTres: ");  
  display.print(pumpOnThresh);  
  display.setCursor(0, 8);  
  display.print("Value: ");  
  display.print(moisture);  
  if (pumpIsOn) {  
    display.print(" (ON)");  
  } else {  
    display.print(" (OFF)");  
  }  
  display.setCursor(0, 16);  
  display.print("PumpOffTres: ");  
  display.print(pumpOffThresh);  
  display.setCursor(0, 24);  
  if (waterLevel == LOW) {  
    display.print("Bucket is empty.");  
  } else {  
    display.print("Bucket has water.");  
  }  
  display.display();  
}  
  
  
int readInput(int input) {  
  int millisStep = 20;  
  int reading;  
  for(int readings = 3; readings; readings--) {  
    reading = debounce(digitalRead(input));  
    delay(millisStep);  
  }  
  return reading;  
}  
  
  
int debounce (int SampleA) {  
  static int SampleB = 0;  
  static int SampleC = 0;  
  static int LastDebounceResult = 0;  
  LastDebounceResult = LastDebounceResult & (SampleA | SampleB | SampleC) | (SampleA & SampleB & SampleC);  
  SampleC = SampleB;  
  SampleB = SampleA;  
  return LastDebounceResult;  
}  
  
  
void chooseMenu() {  
  char* menu[] = {"Change PumpOnTres", "Change PumpOffTres"};  
  int menuLen = 2;  
  bool skipIt = true;  
  int pos = 0;  
  
  
  display.clearDisplay();  
  display.setCursor(0, 0);  
  display.print("Choose menu:");  
  display.setCursor(0, 8);  
  display.print(menu[pos]);  
  display.setCursor(0, 16);  
  display.print("press dial");  
  display.setCursor(0, 24);  
  display.print("to set.");  
  display.display();  
  delay(200);  
    
  // Reads the initial state of the ENCODER_SW  
  encoderSwLastState = false;  
  //delay(80);  
  encoderSwState = digitalRead(ENCODER_SW);  
  
  
  while (!((encoderSwLastState == encoderSwState) and (encoderSwState == false))) {  
    encoderSwLastState = encoderSwState;  
    encoderSwState = digitalRead(ENCODER_SW);  
      
    encoderClkState = digitalRead(ENCODER_CLK);  
    if (encoderClkState != encoderClkLastState) {  
      if (!skipIt) {  
        if (digitalRead(ENCODER_DT) != encoderClkState) {  
          pos++;  
          pos %= menuLen;  
        } else {  
          pos--;  
          if (pos < 0) {  
            pos = menuLen - 1;  
          }  
        }  
        display.clearDisplay();  
        display.setCursor(0, 0);  
        display.print("Choose menu:");  
        display.setCursor(0, 8);  
        display.print(menu[pos]);  
        display.setCursor(0, 16);  
        display.print("press dial");  
        display.setCursor(0, 24);  
        display.print("to set.");  
        display.display();  
      }  
      skipIt = !skipIt;  
    }  
    encoderClkLastState = encoderClkState;  
  }  
  display.clearDisplay();  
  display.setCursor(0, 0);  
  display.print("Choose menu:");  
  display.setCursor(0, 8);  
  display.print(menu[pos]);  
  display.setCursor(0, 16);  
  display.print("menu chosen.");  
  // display.setCursor(0, 24);  
  // display.print(onThresh);  
  display.display();  
  delay(1000);  
  if (pos == 0) {  
    pumpOnThresh = getEncoderData("PumpOnTres", pumpOnThresh);  
  } else if (pos == 1) {  
    pumpOffThresh = getEncoderData("PumpOffTres", pumpOffThresh);  
    // pumpOffThresh = setLowThresh();  
  }  
}  
  
  
int getEncoderData(char* theParam, int startPos) {  
  bool skipIt = true;  
  // int onThresh = pumpOnThresh;  
  
  
  display.clearDisplay();  
  display.setCursor(0, 0);  
  display.print("Change ");  
  display.print(theParam);  
  display.print(":");  
  display.setCursor(0, 8);  
  display.print(startPos);  
  display.setCursor(0, 16);  
  display.print("press dial");  
  display.setCursor(0, 24);  
  display.print("to set.");  
  display.display();  
  delay(200);  
    
  // Reads the initial state of the ENCODER_SW  
  encoderSwLastState = false;  
  encoderSwState = digitalRead(ENCODER_SW);  
  
  
  while (!((encoderSwLastState == encoderSwState) and (encoderSwState == false))) {  
    encoderSwLastState = encoderSwState;  
    encoderSwState = digitalRead(ENCODER_SW);  
      
    encoderClkState = digitalRead(ENCODER_CLK);  
    if (encoderClkState != encoderClkLastState) {  
      if (!skipIt) {  
        if (digitalRead(ENCODER_DT) != encoderClkState) {  
          if (startPos < 1023) {  
            startPos++;  
          }  
        } else {  
          if (startPos > 0) {  
            startPos--;  
          }  
        }  
        display.clearDisplay();  
        display.setCursor(0, 0);  
        display.print("Change ");  
        display.print(theParam);  
        display.print(":");  
        display.setCursor(0, 8);  
        display.print(startPos);  
        display.setCursor(0, 16);  
        display.print("press dial");  
        display.setCursor(0, 24);  
        display.print("to set.");  
        display.display();  
      }  
      skipIt = !skipIt;  
    }  
    encoderClkLastState = encoderClkState;  
  }  
  display.clearDisplay();  
  display.setCursor(0, 0);  
  display.print("Change ");  
  display.print(theParam);  
  display.print(":");  
  display.setCursor(0, 8);  
  display.print(startPos);  
  display.setCursor(0, 16);  
  display.print(theParam);  
  display.print(" set to");  
  display.setCursor(0, 24);  
  display.print(startPos);  
  display.display();  
  delay(1000);  
  return startPos;  
}

 

Arduino Uno IO Pin Use:

D0: -

D1: -

D2:In ENCODER_CLK

D3:In ENCODER_DT

D4:In ENCODER_SW

D5: -

D6: -

D7: -

D8: -

D9:Out ESP_WATER_EMPTY LOW: Send e-mail informing that water reservoir is empty

D10:Out PUMP HIGH: ON - Turn water pump on

D11:In WATER_LEVEL HIGH: Water reservoir has water (this pin is also connected to GP0 of the ESP-01)

D12:Out WATER_EMPTY_LED HIGH: ON  - Signal water reservoir is empty (Blue LED)

D13:Out DRY_LED HIGH: Lit - Signal pump should be on (Red LED)

 

 

A0:Analog In Soil hygrometer reading

A1: -

A2: -

A3: -

A4:SDA I2C (OLED display)

A5:SCL I2C (OLED display)

 

image

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

  • Sign in to reply

Top Comments

  • DAB
    DAB over 6 years ago in reply to urkraft +5
    You need to set up the soil sensor so that it works at less than 1v. If you use more than 1.25 volts you get electrolysis, which eats away the metal. DAB
  • urkraft
    urkraft over 7 years ago in reply to genebren +4
    Thank you Gene . I have actually taken it further and have a breadboard solution where i am just using a ATMega328P microcontroller with just the essential components necessary for the functionality i…
  • afmishaq
    afmishaq over 6 years ago in reply to urkraft +3
    No, you do not have to change the Vcc. The voltage across the two sensing electrodes has to be adjusted to 1V. I see a little pot on your sensor. May be that can be used to adjust the voltage. You have…
Parents
  • korn
    korn over 6 years ago

    That's a great project.....

     

    That bucket reminds me of my CO2 Laser water supply bucket..

     

     

     

    image

     

    theres a temp probe, float switch, flow sensor there along with the pump and filter..

     

    I 3D printed the odd ball pieces.

     

    the flow sensor was cheap. might be good for your project to catch a plugged intake  hose or stalled pump....

    image

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • urkraft
    urkraft over 6 years ago in reply to korn

    Wow - thanks Robert! Lots of cool stuff you have there!  Would love to use those ideas! And acquiring a 3D printer is certainly at the top of my wish list. I had a practice position for 4 months this summer at the Technical Museum in Oslo where i had access to Ultimaker 2+ 3D printers and that was a blast. They had their official opening of the new TeknoLab Maker Space room the week after i left - a fantastic room! There they have 16 Ultimaker 2+ 3D printers. I was responsible for implementing the printer servers for them. Each one has a Raspberry Pi 3 B+ with OctoPrint and a Raspberry Pi camera. I also created the surveillance system used by the instructor for remote monitoring of all 16 printers simultaneously. But, since they claimed that they did not have the resources to employ me, i had to move on and no longer have access to the printers. If i ever get a job with sufficient income i would like to purchase a Prusa i3 Mk3 printer. I also fantasize about acquiring a laser cutter. They had one at the Technical Museum as well, and i soon found out that they are amazing tools for all kinds of applications. An architect working there was very much into designing lamps and was able to make some really creative solutions with the laser cutter.

     

    Regards,

    raymond

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • korn
    korn over 6 years ago in reply to urkraft

    I volunteer at my local library. I just like talking to people at the demos...

     

    they offer cheap 3D Printing to patrons but if you do the demo you have to demo something.... could be your own item you get to keep.... too bad you're not local to me . we just lost our last 3d printer guy.....

     

    I got a new prusa clone, tronxy i think, 3D printer on ebay for $120.  added a $15 2.5 watt laser diode and  did  some paper cutting and wood engraving....

     

    not a bad way to go.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • urkraft
    urkraft over 6 years ago in reply to korn

    Robert,

     

    After the Technical Museum told me that they were unable to hire me i had to move on to somewhere with real prospects of employment. My unemployment supervisor found me a new practice place at a geo-technical company just a short walk from where i live. It is a lot of monotonous hard work, but the deal is that if they like my performance and abilities after 2 months of practice i will get a paid engagement for 3-6 months. They also said that they really liked my technical background and interests and if my performance was still good after that and they had more work for me then they may decide to hire me. Also, even though a lot of the work that i am doing now is very monotonous i find it interesting. I am able to learn new things all the time. I challenge myself to find better ways of getting the job done. It is a small company with some nice and talented people. And they use a lot of technologies that i am interested in as well. So i am hoping this works out. The 10th of October will mark completion of my first month of practice there.

     

    The past few years i had made many attempts trying to get a job or practice at the libraries in Oslo and around where i live. I tried to get them interested in creating maker spaces as well, but it was impossible to get in contact with the person who was in charge of these decisions. Then, they suddenly established a maker space at the central library in Oslo and had televised coverage with the Prime Minister at the opening. Then they started advertising maker space positions at a number of the branches in Oslo and around where i live. I applied to all of them, but was never called into an interview. Then, while i was at the Technical Museum, employees from the libraries who were hired to work in their maker spaces started coming to the courses at the Museum to learn about maker spaces and 3D printing. One of the library employees contacted me to learn more about the work i had done there so that they could use it at the libraries. I gave him a link to an edited copy of the documentation that i made for the project (i removed all of the security sensitive material), but i found it strange that i was deemed not worth calling in to be interviewed for a position at the libraries but the people who got the jobs needed to consult me about technical solutions for the maker spaces.

     

    -raymond

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • urkraft
    urkraft over 6 years ago in reply to korn

    Robert,

     

    After the Technical Museum told me that they were unable to hire me i had to move on to somewhere with real prospects of employment. My unemployment supervisor found me a new practice place at a geo-technical company just a short walk from where i live. It is a lot of monotonous hard work, but the deal is that if they like my performance and abilities after 2 months of practice i will get a paid engagement for 3-6 months. They also said that they really liked my technical background and interests and if my performance was still good after that and they had more work for me then they may decide to hire me. Also, even though a lot of the work that i am doing now is very monotonous i find it interesting. I am able to learn new things all the time. I challenge myself to find better ways of getting the job done. It is a small company with some nice and talented people. And they use a lot of technologies that i am interested in as well. So i am hoping this works out. The 10th of October will mark completion of my first month of practice there.

     

    The past few years i had made many attempts trying to get a job or practice at the libraries in Oslo and around where i live. I tried to get them interested in creating maker spaces as well, but it was impossible to get in contact with the person who was in charge of these decisions. Then, they suddenly established a maker space at the central library in Oslo and had televised coverage with the Prime Minister at the opening. Then they started advertising maker space positions at a number of the branches in Oslo and around where i live. I applied to all of them, but was never called into an interview. Then, while i was at the Technical Museum, employees from the libraries who were hired to work in their maker spaces started coming to the courses at the Museum to learn about maker spaces and 3D printing. One of the library employees contacted me to learn more about the work i had done there so that they could use it at the libraries. I gave him a link to an edited copy of the documentation that i made for the project (i removed all of the security sensitive material), but i found it strange that i was deemed not worth calling in to be interviewed for a position at the libraries but the people who got the jobs needed to consult me about technical solutions for the maker spaces.

     

    -raymond

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • korn
    korn over 6 years ago in reply to urkraft

    Congratulations on your first month, you're half way there...

     

    I've had a few similar situations where my work is dismissed by someone who suddenly promotes it later as his own project. They soon come back to me for more details on how to move forward..... At first its infuriating then I find myself laughing about it. I've moved on from those places and never looked back.

     

    Don't let it bother you, it simply proves your knowledge is valuable.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • urkraft
    urkraft over 6 years ago in reply to korn

    Thank you for your words of wisdom Robert. Experience has taught me that anger and bitterness have no positive effects whatsoever, but rather are like a poison which is very damaging to anyone who allows them to take root and fester. Unfortunately though, i have not been successful in blocking them out - and they are taking their toll on me. I am trying to focus on other things, but occasionally i experience a relapse - as was the case in my previous post. Your comment has been very helpful - thank you!

     

    Regards,

    raymond

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube