Join Les Pounder as he works on his IoT Garden! Watch him integrate technology into his garden and maintain the health of his favorite plants.
|All Raspberry Pi Projects|
Gardening is a delightful hobby, but it can be a chore and one particularly bothersome job is watering the garden. Water it too often and the plants can die, too little and they can also die! But surely technology can offer a solution to this age old problem? Well yes it can, and in this tutorial we shall be using the Raspberry Pi Zero W, the lower power Pi with added Bluetooth and WiFi, along with two sensors, a soil moisture sensor to check if our garden needs water and an Adafruit Flora UV sensor to measure the ultraviolet index of the sun. This data is then emailed to our preferred inbox via a Gmail account that we can use to send the messages on demand.
Our soil moisture sensor sensor will need an analog to digital converter to convert the analog voltage from our soil moisture sensor into something that the Pi can understand. In this case we shall be using the MCP3008 via an add on board from Rasp.IO called Analog Zero.
So let's get started by looking at the bill of materials for this project.
- Pi Zero W
- Rasp.IO Analog Zero board or
- Adafruit Flora UV sensor
- Vellemen Soil Moisture Sensor
- A transparent waterproof box
- USB battery
- Jumper jerky (Dupont connections)
All of the code, and a detailed circuit diagram can be found on the Github page for this project. (Zip Download link)
Building the hardware
Aside from our Pi Zero W, the main player in this project is the Rasp.IO Analog Zero board, which provides us with an analog to digital converter, the MCP3008. Yes you can buy the chip on its own for only a few dollars / pounds, but the Analog Zero board is a convenient form factor that offers a “less wires” alternative.
The two sensors that we are using are a simple soil moisture sensor from Velleman, and an Adafruit Flora UV sensor based upon the SI1145 IC. The moisture sensor is a simple analog sensor, hence the use of the Analog Zero, but the Flora UV sensor uses I2C so we need to have access to those GPIO pins, which luckily the Analog Zero provides.
The Analog Zero will take a little time to solder, and we shall also need to solder the pins for I2C and solder the 3V and GND pins for later. We will also need to solder wires from the Flora UV sensor to attach to our Analog Zero.
Once soldered, attach the Analog Zero to all 40 pins of the GPIO and then connect the sensors as per the diagram.
Now connect up your keyboard, mouse, HDMI, micro SD card, and finally power up the Pi Zero W to the desktop. You will need to setup WiFi on your Pi Zero W, and make a note of the IP address for future use. Now open a terminal and enter the following command to configure SPI and I2C connections.
Yes we can use the GUI “Raspberry Pi Configuration” tool found in the Preferences menu, but having raspi-config available to us over an SSH connection is rather handy should we need it.
Once inside raspi-config, we need to navigate to “Interfacing Options” then once inside this new menu go to the SPI option and press Enter, then select “Yes” to enable SPI. Then do the same for the I2C interface.
While not strictly necessary, now would be a great time to reboot to ensure that the changes have been made correctly. Then return to the Raspbian desktop. With the hardware installed and configured, we can now move on to installing the software library for this project.
Getting started with the software
We only have one software library to install for this project, and that is a Python library for working with the SI1145 sensor present on the Flora UV sensor. But before we install that library we need to ensure that our Pi Zero W has the latest system software installed. So open a terminal and type the following to update the list of installable software, and then install the latest software.
sudo apt update && sudo apt upgrade -y
With the software updated we now need to run another command in the terminal, and this command will install the Python library for our UV sensor.
git clone https://github.com/THP-JOE/Python_SI1145
Now change directory to that of the library we have just downloaded.
Now we need to run an install script so that the library will be available for later use. In the terminal type.
sudo python3 setup.py install
This library was designed to work with Python 2 but it installs cleanly and works with Python 3. But if you try out the built in examples you will need to add parentheses around the print statements, in line with Python 3 usage.
We can now close the terminal and instead let's open the Python editor, Thonny, found in the main menu under the Programming sub menu.
Once Thonny opens, immediately save your work as soil-uv-sensor.py
As ever with Python, we start by importing the libraries that we shall be using.
The first library is GPIO Zero, the easy to use Python library for working with the GPIO. From this library we import the MCP3008 class that will enable us to use the Analog Zero. Our second library is time, and we shall use that to add delays to our code, otherwise the project will spam our mailboxes with emails! Our third library is the SI1145 library that we shall use to read the data from our UV sensor. The fourth, fifth and sixth libraries are used to send emails, the smtplib enables Python to send an email, and the email.mime libraries are used to construct an email.
from gpiozero import MCP3008 import time import SI1145.SI1145 as SI1145 import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText
So we now move on and create two objects, one that is used to create a connection to the Flora UV sensor, called “sensor”. The other object is called “soil” and here we make a connection to the soil moisture sensor that is currently connected to A0 (Channel 0 of the MCP3008) via the Analog Zero.
sensor = SI1145.SI1145() soil = MCP3008(channel=0)
Our main body of code is a while True loop that will ensure that our code runs continuously. Our first few lines in this loop will read the UV sensor and store the value into a variable, UV, which is then divided by 100 to give us a UV index value, which is then printed to the Python shell for debug purposes.
while True: UV = sensor.readUV() uvIndex = UV / 100.0 print('UV Index: ' + str(uvIndex))
In order to get the reading from our soil moisture sensor, we first need to make a new variable called soil_check and in this variable we store the value that is being sent A0 / Channel 0 of the MCP3008. Typically this would be read as a voltage, with 100% conductivity providing 3.3V But in this case the MCP3008 class from GPIO Zero returns a float value between 0.0 and 1.0 With 0.0 being no conductivity, so dry soil, and 1.0 meaning we have perfect conductivity and probably an over watered garden. You will also notice that we round the figure to two decimal places, as the value returned from the soil moisture sensor is quite precise and goes to many decimal places. We then print this value to the Python shell before sleeping for a second. Now for the purposes of testing the delay between checks is rather small, but in real life this delay would be measured in hours.
soil_check = round(soil.value,2) print('The wetness of the soil is',soil_check) time.sleep(1)
So now that we have the data, let's use it. For this we need an if condition to check the value stored in soil_check against a hard coded value. In my case I used 0.1, but you are free to alter this to suit the plants / garden that you have. In my case I wanted to know if the soil became really dry, so any value equalling or lower than 0.1 will trigger the alert.
if soil_check <= 0.1:
Now we start to construct the email that will be sent should the alert be raised. The first part of any email is to say who the email is from and who it is being sent to.
fromaddr = "YOUR EMAIL ADDRESS" toaddr = "EMAIL ADDRESS TO SEND TO"
Next we construct our email as a MIME multipart message, in other words we can add more content to our email than a standard email. For this project we use multipart to enable the use of a subject line. But this could also be used with attachments such as video / images. Here we set up with our from and to email addresses, and then we set up the subject of the email.
msg = MIMEMultipart() msg['From'] = fromaddr msg['To'] = toaddr msg['Subject'] = 'Garden requires water'
The next line we come across forms the body of our email, and it is made up from the readings taken by our sensors. These values are stored as floats in the variables soil_check and uvIndex and we then use concatenation to add them to a string readings which is then stored in the body.
readings = 'Soil is '+str(soil_check)+'wet and the UV index is '+str(uvIndex) body = readings
Then we attach all of the email contents ready to be sent.
In order to send the message we need to have a connection to the Gmail server.
server = smtplib.SMTP('smtp.gmail.com', 587)
So we now need to ensure that our connection is secure, so we use Transport Layer Security.
Now let's login to our Gmail account obviously you will need to use your own account.
Our next step is to create a new variable text which will contain our email message converted to a string.
text = msg.as_string()
We can now finally send the email using our email address, the address of the recipient, and the text that we have just converted.
server.sendmail(fromaddr, toaddr, text)
Our last two lines of code close the connection to the Gmail server, and then instructs the project to wait, in this case for 10 seconds, but in reality this value will be much longer, otherwise you will receive lots of email spam!
So that’s it, we have now built and coded the project and it is ready to be tested. To test the code in Thonny, click on the “play” button located in the menu, or press F5. Now as there is no conductivity between the prongs of the soil moisture sensor the code will trigger it to send an email. So check your inbox to see if it has arrived. Once checked, place something conductive between the two prongs and you will see that the output is just printed to the Python shell and no email is triggered. When you are finished press the red stop button to halt the code.
So now that we have code, how can we make it executable? In order to do this there are two steps to take. First we need to add a line to the top of our Python code which instructs Python where to find the interpreter.
With that complete, we now need to go back to the terminal, and we need to issue a command to make the Python file executable from the terminal. The command is.
sudo chmod +x soil_uv.py
Now in the same terminal, launch the project by typing
Now the project will run in the terminal, printing output to the shell, and the emails should start to be sent as there is no connection between the two prongs of the sensor.
So how can we have the code run on boot? Well this is quite easy really. In the terminal we need to issue a command to edit our crontab, a file that contains a list of applications to be run at a specific time/date/occasion. To edit the crontab, issue the following command in the terminal.
sudo crontab -e
If this is the first time that you have used the crontab, then it will ask you to select a text editor, for this tutorial we used nano, but everyone has their favourite editor!
With crontab open, navigate to the bottom of the file and add the following line.
Then press Ctrl + X to exit, you will be asked to save the file, select Yes.
Now reboot the Pi Zero W and for now ensure the soil moisture sensor has no connection between the prongs. After a about a minute, the project should be running, and your inbox should start to receive emails.
Power down the Pi Zero W, place it in a waterproof container along with a USB battery power source, ensure the soil sensor is out of the box, but keep the UV sensor inside the box, oh and make sure the container is transparent! Place the project in your garden, and make sure the soil moisture sensor is firmly in the ground. Power up the Pi Zero W, and now you can wait for your garden to tell you when it needs watering.
In the next blog post in this series, we shall build a system to automatically water our garden when an alert is triggered.