:::info Most of us have plants in our homes and I know I tend to forget to give them their essentials: water and a pleasant living area.
This tutorial aims to get you through building a plant monitoring system with additional temperature and humidity monitoring. The sensors are connected to a LoPy4 who then communicates through MQTT. The data can be presented on a dashboard using Adafruit or using Grafana and storing the data on InfluxDB for further analysing (on a Raspberry Pi). :::
Depending on your experience: Part 1 takes approx. 2-3 hours to complete. Part 2 takes approx. 3-5 hours
[TOC]
I chose to make this project because I want to be able to monitor my six plants, collect data from them and get notifications when they need water. Adding a temperature and humidity sensor creates extra value for further analysing. I also wanted something I can control remotely. Having fun making something practical and learn more about transport protocols. The purpose of this project is to gather data and monitor your plants soil moisture, room temperature and humidity. Visualizing this with some awesome graphs. By adding a database and collecting sensordata we can learn about the environment our plant-babies live in. In the end, through the data, we will learn what conditions might be the best for a specific plant.
The main components you need for configuring are a PC or laptop, a monitor, keyboard, mouse, MicroSD card reader and a Wi-Fi connection. Also, two extra mobile phone charger – bricks.
Devices | Link | Description | Price |
---|---|---|---|
LoPy4* | link | Quadruple network development board, runs micropython | 34,95€ |
Expansion board 3.0 | link | For using GPIO, connecting sensors etc | 16€ |
Sensors | |||
FC-28 ** | link | Measures voltage between to capacitors, giving us soil humidity | 2,8€ *6 |
DHT11 | link | Measures temperature and air humidity | 4,7€ |
Essentials | |||
Micro USB cable | link | 3,5€ | |
Breadboard | link | For connecting sensors and the LoPy4 | 7€ |
Jumper wires M/M | link | To connect components | 3€ |
Jumper wires F/M | link | To connect components / extend soil sensors | 3€ |
~90€ | |||
*Can also be WiPy or the Node MCU, depending on your budget and knowledge | |||
** If you have a higher budget I recommend getting capacitive sensors, which have a longer lifespan |
Devices | Link | Description | Price |
---|---|---|---|
Raspberry Pi Zero with essentials | link | Minicomputer, runs backend components and triggers | 19€ |
Essentials | |||
Micro SD Card | link | For installing software on the RPi | 9,9€ |
Micro USB cable | link | For powering the device | 3,5€ |
~125€ |
To be able to communicate with the devices you need some software on your computer. I used atom for writing the code. The Atom pymakr plugin will also help us upload the code to the LoPy4. You can also use Visual Studio code if you prefer it. If you want to use a Raspberry Pi it is preferable to download a SSH client for coding and configuring.
- Installing Atom and the Pymakr plugin
- If on windows: Installing PuTTY This tool makes it possible to communicate with the Raspberry Pi without connecting peripherals. If you’re on mac or Linux, you don’t need any extra software for SSH.
- Installing extra drivers for windows/linux/macOS
Before we get started, we should update the firmware of the expansion board to prevent any bugs from messing with our project. It is recommended but not mandatory. Follow this guide After we have flashed the board, we connect the LoPy4 to the expansion board like this: ![](https://i.imgur.com/EKTw4bF.png =300x280) Now we can connect the device to our computer using a Micro USB cable. Make sure we are not running atom at this point
- Create an account over at pybytes and log in
- Continue by adding the Pycom device to pybytes
- Provisioning and flashing your device via USB This guide will also get us through the very important part of updating the firmware of the LoPy4
- After the firmware update is done, I recommend following this RGB Blink Example to make sure everything went fine and Atom can communicate with our Pycom device.
- Make sure to try the last step in the example in step 4 since this is how we will upload the project to the pycom device later.
If you're not familiar with the Raspberry Pi devices, check this out. For our backend services we are using the Raspberry Pi Zero. It runs everything off of the Micro SD card. To get started we need to download the Raspberry Pi Imager and then the Raspberry Pi OS Lite image and follow the full installation guide.
After the Micro SD card is flashed, we can insert it to the device and then connect your peripherals and connect the power cable ![](https://i.imgur.com/j37hkjt.png =450x280)
- Set up the device so it connects to our Wi-Fi.
- Since we want to be able to use the devices simultaneously we need to configure the device with SSH . After this we can go back to our main PC and fiddle on When we use SSH we can copy and paste the code and commands directly to the raspberry pi.
- Sign up for a free account over at Adafruit IO
- If you’re doing 6 soil moisture sensors, set up some feeds with the names of the pins, to keep track of which plant is which and their respective values.
- Like this:
- Grab the Adafruit KEY
- Copy the Active key and store it somewhere for the moment. We will add it in the code later.
After a lot of testing I found that connecting the soil moisture sensors individually worked best. Since they are not capacitive this will help the durability because we will only power one sensor at a time. The LoPy4 has some restrictions to which pins we can use, but the pins mentioned in the table below worked for me
The breadboard is used to connect the ground cables together and help us put the rest of the components together a bit easily. The circuit board of the soil moisture sensors and the DHT11 sensor connect to the breadboard and are then extended with the Male/Male jumper wires into the pycom device.
The Male/Female wires are used between the soil moisture circuit board and the "legs". Here we could add a few extra to enable them to reach plants further away than 20cm, just make sure we got + and - right I chose to make my build a bit more compact using a smaller breadboard but it's the same idea as the circuit diagram, only folded together. I also dug up my soldering iron and some wires that I used to extend the soil sensor board and "legs" to 120cm.
Here are my results and a video of me struggling with all the wires
<iframe width="560" height="315" src="https://www.youtube.com/embed/SX3KGmY5pao" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>If you don’t need/want to use 6 moisture sensors, you can just connect the pins respectively and match it with the list in main.py
Both the LoPy4 and the Raspberry pi are not power-hungry devices. I will not be discussing the Raspberry Pi's consumption since this device is always meant to be powered on at home. I chose the LoPy4 since I plan to experiment and take this project outdoors, communicating with LoRa and running off a battery. Right now, it runs off a direct power connection. I skipped a few classes on physics and electricity but with the current conditions we have some values to play with in theory:
Running off a 10000mAh power bank, only measuring once an hour and deep sleeping the rest, it could run for around two months
There are a bunch of different platforms available. Some who might be free but lack configurability and some that cost more and are configurable to the bone. In this project we are using:
- Adafruit IO For their easy dashboard and MQTT broker
- Grafana Open source with endless configurability, easy to set up alerts, notifications to various channels and easy connection to:
- InfluxDB. Open source time series database, simple and not too complicated to configure to collect MQTT data All of them are free to use and right now they fulfil all requirements. There are no subscription fees in this project. I found that Adafruit IO was enough for the purpose of this project, the Pycom documentation mentions Adafruit a few times and refers to handy guides. They offer a nice layer of security for MQTT communication. Grafana and InfluxDB have been buddies for a while. It is easy to set up the InfluxDB against Grafana and configuring alerts for your dataflow. They are also available to install on the Raspberry Pi.
If I would’ve put more time into research I would have found that a Raspberry Pi 4 would have been more suitable for this project, because it supports the TIG-stack and running docker, which makes things a bit easier.
I looked in to Balena Cloud, thethingsio, Ubidots and they all have their perks, but it often led to needing to pay for a subscription in the long run. The Balena Cloud is an interesting platform but has a higher learning curve.
If we want to add more sensors in the future, we need to reconsider the use of Adafruit, since it limits the amount of topics/feeds we can pub/sub to.
If you're not that interested in running your own database you could build only the first part, and if you have the cash, you can pay for Adafruit IO plus, which adds alerts/triggers to the relevant topics.
- Download the code from the Github Repository
- Make sure your Pycom device is recognized in Atom, RGB Blink Example
- Before we start sending values through to the Adafruit broker it would be awesome to see some values, right?
- Choose the test run folder as the project folder by choosing the menu item File > Open Folder and select a directory from the dialog.
- Upload the project to your device
- Run test.py to see if you are getting some values from the sensors, these will be shown in the terminal
- Example:
- The soil sensor values are between ~250-999 mV, where the lowest value means they are moist and 999 is absolutely dry
- You can follow the process by looking at the sensors circuit board which lights up during the measuring. The DHT11 sensor does not light up.
- If everything looks alright, delete the "test run" as project folder and replace it with the pycom folder
- Choose the pycom folder as the project folder. Choose the menu item File > Open Folder and select a directory from the dialog.
Configurations and explanations – main.py
import time # Allows use of time.sleep() for delays
import ubinascii # Following Adafruit MQTT configure
import machine # Interfaces with hardware components
from dht import DHT # Library for the DHT11 Sensor
from machine import Pin # Pin object to configure pins
from machine import ADC # ADC object to configure reading values
from umqtt import MQTTClient # For use of MQTT protocol to talk to Adafruit IO
Here are the pins we are using
# Pins we want to read from
ao_pins = ['P20', 'P19', 'P18', 'P17', 'P16', 'P15']
# Pins we want to turn on/off
vcc_pins = ['P4', 'P5', 'P9', 'P10', 'P11', 'P12']
In this section we need to add our credentials. Replacing: user_name with the adafruit io username you chose adafruit_key with your Adafruit Active key This configuration makes it possible to send data using MQTT
# Adafruit details
AIO_SERVER = "io.adafruit.com"
AIO_PORT = 1883
AIO_USER = "user_name"
AIO_KEY = "adafruit_key"
AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id())
AIO_TEMPERATURE_FEED = "temperature"
AIO_HUMIDITY_FEED = "humidity"
AIO_SOIL_FEED = "soil"
#Here we set up the ao_pins as in-”put” to read the values
for p in ao_pins:
set = Pin(p, mode=Pin.IN)
Creating an ADC object makes it possible for the LoPy4 to convert the analog signal that the soil moisture sensor sends to a digital signal so we can read the value.
def moist_sensor(p_in, p_out):
adc = ADC()
apin = adc.channel(pin=p_in, attn=ADC.ATTN_11DB)
p_out = Pin(p_out, mode=Pin.OUT, pull=Pin.PULL_DOWN)
p_out.value(1)
time.sleep(2)
volts = apin.value()
p_out.value(0)
time.sleep(2)
return volts
The DHT11 has its own library to help read the measurements. We are just making sure to read the values as long as they are valid, then sending them back in a variable
def humid_temp_sensor(read):
th = DHT('P23', 0)
time.sleep(2)
while read:
result = th.read()
while not result.is_valid():
time.sleep(.5)
result = th.read()
temperature = result.temperature
humidity = result.humidity
read = False
return (temperature, humidity)
In the main section we configure an MQTT client, connect it and then we Iterate over the soil sensor pins and publish the values to their respective feed which is "soil" + "pin number". The feed we are publishing to will be printed in the terminal The only data conversion we need to do is making sure we are sending string values, since this is one acceptable data format to publish.
def main():
client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY)
client.connect()
for ao, vcc in zip(ao_pins, vcc_pins):
feed = "feed_id" + ao
print(feed)
volts = (moist_sensor(ao, vcc) / 4.096)
client.publish(feed, str(volts))
time.sleep(1)
humid = int(humid_temp_sensor(True)[1])
client.publish(AIO_HUMIDITY_FEED, str(humid))
temp = int(humid_temp_sensor(True)[0])
client.publish(AIO_TEMPERATURE_FEED, str(temp))
client.disconnect()
while True:
main()
time.sleep(60 * 10)
In the last few rows, we set up the main function to run every 10 minutes. While you are testing you might want to change time.sleep(seconds) to whatever suits you.
There are some additional files besides main.py. To use MQTT we need a specific library which is the umqtt.py file from the Adafruit_IO Python Library. The DHT11 sensor also uses a library which is located at lib/dht.py Don't forget to save your changes Now we can upload the project to the Pycom device. Example
After this part you can create a dashboard in adafruit io and check to see that your MQTT client is publishing values.
Basic configurations Since we are running buster lite we need some things that aren't automatically there.
sudo apt install python3 # Installing python
sudo apt-get install python3-pip # Installing pip for python modules
sudo apt-get install libfontconfig # Necessary for running Grafana
sudo apt update && sudo apt upgrade -y # Make sure we are fully updated
Moving on to installing InfluxDB and Grafana. I wanted to write this part myself, but the length of this report would greatly exceed the recommendation. So I will give full credit to diyi0t and refer you to following their guide on Installing InfluxDB and Grafana on Raspbery Pi Note: We will use a customized MQTTToInfluxDBBridge.py available at the github repository Make sure to update the code with your credentials
If you want to see your Grafana graphs while you are not connected to your home network, you can easily install dataplicity and run a web server on the raspberry pi. Register at https://www.dataplicity.com/ and follow the steps to connect your device to dataplicity.
sudo apt-get install nginx
sudo netstat -an | grep LISTEN | grep :80
The output should look something like this:
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp6 0 0 :::80 :::* LISTEN
If it does not, run:
sudo service nginx restart
sudo nano /etc/nginx/sites-available/default
Add the following to the server block:
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm;
location / {
proxy_pass http://localhost:3000/;
}
}
After this is done, you go to https://www.dataplicity.com/ , click on your device and enable wormhole. Now you get access to the same content you would get if you were to connect to raspberrypi:3000 in your browser.
We are sending data over WiFi, the LoPy4 is connected to the same WiFi as the Raspberry Pi Zero. Since they are both in my home. The opportunity to use LoRa is always there, making the project transferable outdoors.
The frequency of the data being sent can be tweaked, right now it sends data every tenth minute. Since we are using a free Adafruit IO account, it is limited to 30 data points per minute. Meaning we are not allowed to send data that often (note: this can lead to a ban).
The way the transferring works is using the Adafruit IO MQTT broker that is configured using our Adafruit active key and username, adding a layer of security to prevent anybody from publishing or subscribing to our feeds. The Pycom device publishes data to a feed and both the Raspberry Pi and Adafruit dashboard are subscribed to the feed/topic.
MQTT in IoT is almost a must, it is a simple transfer protocol, and everybody should try it out at some point. Using Adafruit's broker makes it possible to keep the current settings on the Raspberry Pi and just moving the LoPy4 and sensors to another location. The Pi will always be able to receive the data. If we set up the LoPy4 to communicate through another wireless protocol, we need to consider some slight power consumption changes.
My initial thought was to set up my own MQTT broker and thus running it locally, preventing any other external connections for security reasons.
Running InfluxDB and Grafana locally on the raspberry pi makes it possible to run your own MQTT broker or other wireless communication protocols such as webhooks, sockets etc.
As for now, both devices are wall-powered and connected to my home wifi, no need to worry about battery-life just yet.
The data is easily accessible through https://io.adafruit.com/user-name/dashboards
or via Grafana at http://raspberrypi:3000/ or http://dataplicity-device-link.io/
The data is saved in InfluxDB as soon as it is received through MQTT. Almost instantly after the LoPy4 publishes the data the MQTTToInfluxDBBridge.py script handles storing the received data in our sensor_data database. This is then easily accessible using Grafana who connects to InfluxDB within a few clicks in the UI.
Adafruit and dataplicity are accessible from anywhere, with the small difference that adafruit only stores data for 30 days (free account) and through our Raspberry Pi, we can gather data for 600 years before it is full. Not considering the durability of the device and MicroSD card.
Running two weeks, sending data every five minutes for this project I've stored 660 KB in the database, meaning we can send data every five minutes for a hundred years without getting up to 2GB
Both the dashboards are showing the data received in real-time. Grafana gives us the opportunity to browse all the stored data.
Adding a panel Then choosing Add Query
I set up individual panels for every plant, giving them relevant names.
You can then duplicate them, changing the measurement and names
I also set up one for all the plants It is noticable when I watered my Chillies and Avocado no.5 The reason Avocado no.1 has such high values is simply because it has a bigger pot. Meaning the water runs through it faster and the topsoil is relatively dryer. Exciting!
You can then click and drag to put the panels anywhere you like.
Grafana makes it really easy to enable alerts for our data flow. I chose alerts through Discord and Google Chat. If you want something else, check this documentation
Save your changes and go to the main dashboard Select Notification channels and add a New channel For discord, you need a server, I created one called Soil Monitor Server, In the server settings you can create a webhook and just copy it into Grafana. Discord: how to create a webhook
Now test the notification by pressing Send Test.
Now we can go back to the panels we want to enable alerts for. The value of 950 means the plant is extremely dry. That is when I want a notification to water since that would mean I completely forgot.
And testing this by pulling the soil moisture sensor out of the plant.
Using InfluxDB was an obvious choice because it is simple since it is based on time series. It is open source and available for most devices. It was easy to install on the Raspberry Pi and the connection to Grafana was really easy. You just choose InfluxDB as a data source and fill out your credentials. I have no previous knowledge of databases and the option to just choose queries using a drop-down menu really made it simple.
To complete this DIY project, I found a plastic container, cut some holes in it and threw all the electronics inside, holding them together with some double-sided tape.
The clear plastic is obviously optional, but I like to see the messy-ness to keep the DIY spirit shining through. But it keeps everything as contained as possible.
Put the soil sensors in the plants
Now, convienently the RPi zero fits just perfectly in one of the plastic boxes that contained the LoPy4 or the Expansion board. I just cut a hole through one of them and used some double-sided tape to hold the pi in place.
Throw the Pi wherever it has WiFi access and power
Overall, the project build went alright, there were some things I should've thought of. For example, the possibility to use a Raspberry Pi 4 instead of a Zero, enabling easier use of docker and the full TIG-stack.
My initial plan was to use the RPi as an actuator, connecting pumps to it, but the delivery time of the pumps was over 5 weeks. This is a possible improvement to be made. The RPi's GPIO pins are easy to program and given the script we're already running; it shouldn't be so hard to implement.
It would also be logical to install a light sensor for measuring the amount of light for the plants.
My main issues were:
- Finding a reliable guide for installing grafana and influxdb on the RPi zero, this was the most time consuming. Configuring the LoPy4 itself was straight forward once I read the ADC and Pin in the pycom documentation.
- Finding an appropriate micropython library for MQTT communication for the LoPy4. Initially I tried the paho library but ran in to quite a few issues.
- Overall MQTT formatting, but that is easily solved by doing proper research. I rushed into it thinking paho projects from earlier assignments was enough.
And also, next summer, this project will go outdoors, and I will have the opportunity to experiment further with LoRa to measure plants and temperature inside of a greenhouse.
<iframe width="560" height="315" src="https://www.youtube.com/embed/KFwPk6DpuYY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>