Introduction: Future Sight Greenhouse System - Predictive Plants on the Cloud!
Fuelled by the Green Planet hype, I decided to start gardening, only to find that I really lack a green thumb, mainly because of all the soldering gun burns, so I thought it would be a good idea to give my plants a green thumb of their own! If there is something like a plant thumb.....
PS : I've entered this project into a few competitions, if you like it, please do vote for it in the top right corner of the post.
Thanks a lot!
Step 1: Project Overview
My project revolves around how to make a plant understand when it needs water and then water itself, and notify me, if possible.
I used a Moisture Sensor to detect the moisture level of the soil, an Intel Edison to acquire the data and forward it to the cloud over TCP/IP or RESTful API depending on the choice of Cloud Platform.
There are many cloud based services available to use for data logging, but I've used my own Cloud Connected Platform based on a Raspberry Pi.
This solution makes it easier for me to access and process data while maintaining privacy and reducing delay times due to data limits. Alternatively, you could use something like Thingspeak or DeviceHub, which utilize RESTful APIs and are compatible with most hardware devices.
The flow of this system is chalked out as follows.
Step 2: Gathering Materials
The materials I've used mainly come from the Grove Environmental Starter pack for the Intel Edison, but homebrew sensors will work equally well, provided they measure the same parameters.
- Intel Edison (SoC + Arduino Breakout Board) : This is the endpoint for our greenhouse sensor system, it acquires the readings from peripheral sensors, filters and processes them and connects to the gateway to forward the sensor values to the cloud.
- Raspberry Pi (optional) : This is the cloud server that I will be using to log my data, and to access and process it. I will be using a MySQL backend to do so. All data will be stored in a dedicated database with reading index and timestamp.
- Grove Moisture Sensor : This sensor gauges the moisture value of the soil by measuring change in resistivity via a change in voltage. This voltage is fed to the 10-bit ADC of the Edison to gain a measure of the moisture level of the soil.
- Grove Relay Module : Powering a pump motor isn't something a microcontroller can handle on its own, owing to higher power consumption. A relay is used to transfer that power consumption over to a power supp while still maintaining control within the Edison.
- Grove 6v Water Pump : A water pump is essentially a DC motor with a volute attached to its shaft instead of a wheel. This causes a suction of water and pumps it out the other end to the plant
Step 3: Interfacing the Sensors and Actuators
Interfacing the moisture sensors to the Edison is a relatively easy job, as the moisture sensor operates on ADC, it has only 3 terminals including the signal, and the ADC read is one line of code using the MRAA library for the Edison.
The relay is connected to one of the Digital outputs of the Edison as the relay can only be in an on or off state. It is powered using a 6V power supply operating at a constant current of 1 Amp.
The pump is connected to the outputs of the relay. care should be taken to ensure that the terminals are connected in the configuration to ensure suction at the inlet port.
I will also run the listen_ed.py file in the background, as I will be listening for TCP messages from the Raspberry Pi. This is not required if you are using a commercial service.
Step 4: Connecting the System to the Cloud
Now that the moisture sensor, relay and pump are connected to the Edison, we can focus on the software side of things, where we look at connecting this system to the cloud and sending data to it.
There are two ways of connecting to the cloud, as described before, and I'll go over both of them here.
Using a commerical Cloud Service (Thingspeak)
Thingspeak uses HTTP to send and receive data, via the REST API. The REST API makes it easy for hardware systems to perform operations such as GET, POST or DELETE data from a web server. The general syntax of a REST command to Thingspeak is as follows
GET <a href="https://api.thingspeak.com/update?api_key=*API_key_of_Thingspeak_Channel*&field1=0"> https://api.thingspeak.com/update?api_key=*API_ke...</a>
Your Thingspeak is divided into channels, which represent each of your devices, and each channel consists of up to 10 fields which can be updated simultaneously through one REST command.
You will also be provided a security key for your channel when you sign up. This key is used as a parameter within the REST command to verify access to the channel.
Over here, our channel would be the Edison and the field would be the moisture sensor.
Using basic string processing, we append the ADC reading of the moisture sensor to the Edison to send to Thingspeak, and then call the HTTP request.
Once you've uploaded a significant amount of data, the dashboard should look like the dashboard above.
Using the Raspberry Pi IoT Platform
Firstly, we will have to create a database within the Raspberry Pi to store data in. This can be done by opening MYSQL and executing the command;
CREATE TABLE Moisture(Sr INT(50) auto_increment primary key, Value INT,Time TIMESTAMP)
After this, the Raspberry Pi must be configured to listen for datagrams over the TCP/IP port, which is done by executing the listen.py file in the background by running the following in the terminal
sudo python listen.py &
Now, the Raspberry Pi is up and running. It will listen for packets over TCP/IP, deconstruct the datagram and update the database in the background.
Step 5: Predicitive Algorithm
Now, for the fun part. Future Sight!
To implement the predictive algorithm, we will be using a Machine Learning technique called Linear Regression. It estimates the future values of a dataset by running a line through all the data points, and determining the best fit using the Least Squares Method. In simple terms, it cycles through all possible line values in the space, and decides that the one with the least error or deviation in readings is the best fit. This line is then extrapolated to find the next value of the dataset. As our dataset is a time series set, the next point corresponds to the next reading in time!
So now that we have the dataset of points in our database, we can use the numpy and matplotlib packages in Python to plot this data and extrapolate the line to find the next possible value. Once this predicted value is found, the Raspberry Pi sends it to the Intel Edison, where it is compared with the existing value. If the existing value falls below the predicted value, the Edison switches on the pump to water the plant.
You can implement this algorithm in MatLab as well using the attached sample. Download your values from Thingspeak as a CSV file and copy them to the folder where your MatLab executable is. On execution, you should get a linear fit line as shown.
Step 6: Results
I took the predicted value, and compared it to the next value that was sensed by the Edison to get a measure of error every hour. I've been running this setup for about a day, and I've collected results at regular intervals. And fortunately, they look pretty promising!
Step 7: Improvements and Future Scope
As you can see in the graph, we do have a noise spike, and while one moderate spike of that size in say 100 samples doesn't harm the output much, frequent such spikes or one large spike in a smaller number of samples will.
So, in order to maintain consistency and continuity of the readings, a sample will be compared with previous and next samples before processing, and if the difference is above a certain threshold, that reading will be discarded.
Another flavour of regression can be used, known as non-linear regression, which maps the dataset to a polynomial curve, which gives a much more accurate reading. Beware of overfitting, though!
There you have it! Your own smart plant that's actually smart! Using machine learning to predict whether or not it will have enough water later on!
We have a be nice policy.
Please be positive and constructive.