Arduino Watering System Prototype - DIY Living Green Wall
November 13, 2016
This post is part of the series on DIY Living Green Wall:
- Living Green Wall Prototype
- Arduino Watering System Prototype
- 3D Printed Case for Living Green Wall project
To follow you need basic knowledge of Arduino circuits (do some tutorials first) and basic skills in programming.
Business requirements
This is an initial set of requirements for a DIY home irrigation system. I will dig into other possible evolution paths later on.
- We want to water our plants in intervals, for instance every 12 hours. Interval starts when watering starts.
- Watering process should take no longer then set amount of time, for instance 20 minutes
- We should be able to stop watering process manually
- We should be able to start watering process manually
Bill of Material
- Arduino Uno Rev 3 or compatible
- Prototyping Breadboard
- Pushbutton
- 5V Relay Module, LOW level triggered
- 10k Ohm resistor
- 12V DC, 1 Amp Power Supply
- 12V DC Pump motor
- Few colors of prototyping wires
Pump Controller
First of all lets develop and implement requirements 1) and 2). To turn the water pump on and off you need a switch. A relay is an electrically operated switch. Many relays use an electromagnet to mechanically operate the switch and provide electrical isolation between two circuits. In this project there is no real need to isolate one circuit from the other as I use 12V 1A power source. You cannot use the 5V from a USB to power up motor and relay module because USB ports usually deliver only 100mA, which is not enough. I used an Arduino UNO to control the relay. I developed a simple circuit to distinguish between the NO (Normally open) and NC (Normally closed) terminals of the relay.
Relays
For a great explanatory how relays work see this article: http://pcbheaven.com/wikipages/How_Relays_Work/
COM (Common connection) - is a center terminal where you connect positive wire of your device’s power supply.
NO (Normally open) - acts like a switch when it is open - there is no physical contact between COM and NO. When a relay module is triggered, NO connects to COM by the electromagnet inside the relay and supply to the load is provided. That powers up the motor. The circuit will stay closed until we trigger the state to LOW in relay.
NC (Normally closed) - is always in physical contact with COM, even when a relay is not powered. When a relay is triggered it opens the circuit and the connection is lost. It behaves just the opposite to NO.
A relay’s default state is the COM’s power off and connected to NC. (It is an equivalent of setting the Relay boards IN pin to HIGH; has +5v sent to it). It is actually a safety feature. If your Arduino lost power, it would automatically turn off all devices connected to the relay. When you connect a device to the relay’s NO (Normally Open) connector and you set the corresponding IN pin to LOW (0v), power will flow in from the COM connector and out of the NO connector powering your device (water pump in this case).
Power source
To run the 12V water pump motor, which should be enough for your DIY Green Wall project, you need the 12V power source. I took the power supply out of my broken scanner machine and I attached 2.1mm plug to it so it fitted in power plug of Arduino. Remember that the center pin must be positive otherwise you will fry your Arduino. I will drive 12V motor through my Arduino. Some other projects available online suggest separating Arduino and controlled device circuits. You can easily buy 12v 1A power supply online.
Circuit
First, try to build this circuit without the water pump motor connected and observe LEDs on Relay Module - green LED indicated the pump is working. Note how we print to serial output information how long watering will last or when it starts again.
Code
int motorPinOut = 10; //Pin starts water pump motor
const int wateringLedPin = 13; // the number of the LED pin
const double waterEveryMinutes=0.5; // Time Interval pump starts watering process. In minutes.
const double wateringTimeInMinutes=0.2; // Time Watering Process takes. In minutes.
boolean isWatering = false; //
//"ALWAYS use unsigned long for timers, not int"
unsigned long lastWateringTime=millis()-(waterEveryMinutes\*60\*1000); // Time of last watering. Milliseconds since Arduino program has started.
unsigned long wateringStartedTime=millis()-(wateringTimeInMinutes\*60\*1000); //"ALWAYS use unsigned long for timers, not int"
void setup() {
Serial.begin(9600);
pinMode(motorPinOut, OUTPUT);
// initialize the LED pin as an output:
pinMode(wateringLedPin, OUTPUT);
}
void loop() {
if(isWatering){
long timer=(wateringStartedTime+(wateringTimeInMinutes\*60\*1000))-millis();
digitalWrite(motorPinOut, LOW);
if(timer<=0){
stopWatering();
}else{
printOuput("Watering ends in "+millisToTime(timer)+"\\n");
}
}else{
digitalWrite(motorPinOut, HIGH);
long timer=(lastWateringTime+(waterEveryMinutes\*60\*1000))-millis();
if(timer<=0){
startWatering();
}else{
printOuput("Watering starts in "+millisToTime(timer)+"\\n");
}
}
}
void startWatering(){
isWatering=true;
printOuput("Watering starts\\n");
// start motor
digitalWrite(motorPinOut, LOW);
wateringStartedTime=millis();
lastWateringTime=millis();
}
void stopWatering(){
isWatering=false;
printOuput("Watering ends\\n");
// stop motor
digitalWrite(motorPinOut, HIGH);
}
String millisToTime(unsigned long milliseconds){
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000\*60)) % 60);
int hours = (int) ((milliseconds / (1000\*60\*60)) % 24);
String timeString="";
timeString=timeString+hours+":"+minutes+":"+seconds;
return timeString;
}
void printOuput(String msg){
Serial.print(msg);
}
Manual Control
Connect three wires to the board. The first two, red and black, connect to the two long vertical rows on the side of the breadboard to provide access to the 5 volt supply and ground. The third wire goes from digital pin 2 to one leg of the pushbutton. That corresponding leg of the button connects through a pull-down resistor (here 10K ohm) to ground. The other leg of the button connects to the 5 volt supply.
When the pushbutton is open (not pressed down) there is no connection between the two legs of the pushbutton, so the pin is connected to ground (through the pull-down resistor) and we read a LOW. When the button is closed (pressed down), it makes a connection between its two legs, connecting the pin to 5 volts, so that we read a HIGH.
An internal Arduino LED connected to PIN13 will be lit every time push button has been pressed.
int motorPinOut = 10; //Pin starts water pump motor
const int buttonPin = 2; // the number of the pushbutton pin
const int wateringLedPin = 13; // the number of the LED pin
const double waterEveryMinutes=0.5; // Time Interval pump starts watering process. In minutes.
const double wateringTimeInMinutes=0.2; // Time Watering Process takes. In minutes.
boolean isWatering = false; //
//"ALWAYS use unsigned long for timers, not int"
unsigned long lastWateringTime=millis()-(waterEveryMinutes\*60\*1000); // Time of last watering. Milliseconds since Arduino program has started.
unsigned long wateringStartedTime=millis()-(wateringTimeInMinutes\*60\*1000); //"ALWAYS use unsigned long for timers, not int"
boolean buttonState = false; //Button state, FALSE=unpressed, TRUE=pressed
int lastButtonState=buttonState; // Previous button state. Used to reduce state related signals spamming.
void setup() {
Serial.begin(9600);
pinMode(motorPinOut, OUTPUT);
// initialize the LED pin as an output:
pinMode(wateringLedPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop() {
if(isWatering){
long timer=(wateringStartedTime+(wateringTimeInMinutes\*60\*1000))-millis();
digitalWrite(motorPinOut, LOW);
if(timer<=0){
stopWatering();
}else{
printOuput("Watering ends in "+millisToTime(timer));
}
}else{
digitalWrite(motorPinOut, HIGH);
long timer=(lastWateringTime+(waterEveryMinutes\*60\*1000))-millis();
if(timer<=0){
startWatering();
}else{
printOuput("Watering starts in "+millisToTime(timer));
}
}
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH){
// turn LED on:
digitalWrite(wateringLedPin, HIGH);
}else{
// turn LED off:
digitalWrite(wateringLedPin, LOW);
}
// check if the pushbutton is pressed (buttonState is HIGH) AND if previous pushbutton state was different start or stop watering
if (buttonState == HIGH && lastButtonState == LOW && !isWatering) {
startWatering();
} else if(buttonState == HIGH && lastButtonState == LOW && isWatering){
stopWatering();
}
lastButtonState=buttonState;
}
void startWatering(){
isWatering=true;
printOuput("Watering starts");
// start motor
digitalWrite(motorPinOut, LOW);
wateringStartedTime=millis();
lastWateringTime=millis();
}
void stopWatering(){
isWatering=false;
printOuput("Watering ends");
// stop motor
digitalWrite(motorPinOut, HIGH);
}
String millisToTime(unsigned long milliseconds){
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000\*60)) % 60);
int hours = (int) ((milliseconds / (1000\*60\*60)) % 24);
String timeString="";
timeString=timeString+hours+":"+minutes+":"+seconds;
return timeString;
}
void printOuput(String msg){
Serial.print(msg+"\\n");
}
Working prototype
Here is a video presentation of working prototype of DIY Arduino Watering System. Enjoy.
https://www.youtube.com/watch?v=zV4oOTXU35M
Sources/Further read:
https://www.arduino.cc/en/Tutorial/Button
Soutces at Github: