# Build your own greenhouse monitor system ![](https://hackmd.io/_uploads/SyT-o17Yn.jpg) Karl Flysjö kf222qy ## Overview To help protect the crop yield in a greenhouse the temperature and humidity or the air and the moisture of the soil is measured at regular intervals to be able to send warnings to the end-user if for instance the temperature would be too high or too low. The estimated time this would take from start to finish is about 3 hours + troubleshooting. ## Objective If a greenhouse would be forgotten with it's doors closed, the temperature would rise quickly on a summer day. Tomato plants would start taking damage just above 40 degrees celsius, something that would be reached quickly with closed doors. Besides this soil moisture is also fundamental. Always having high humidity can damage the roots and promote fungal infections but after a certain threshold plasmolysis would occur, this damage is irreparable for the plants. By sending an alert to the user, the Greenhouse monitor is a low price way to help protect crops and crop yields for anyone that has a greenhouse. In excess of providing alerts the temperature and humidity is also logged. The logged values are displayed in graphs and can be analyzed to gain knowledge of the thermal behaviour and characteristics of one's own greenhouse. This is done by connecting a DHT22 and a soil moisture sensor to a Raspberry Pi Pico W and posting sensor readings to a server running the TIG-stack. By following this guide you will be able to get a Windows 11 computer and a Raspberry Pi Pico W setup to perform these tasks. This tutorial will show you how to configure a developmental device that with a few future amendments can become a permanent fixture in a home gardening environment. ## Bill of Materials - Raspberry Pi Pico W - DHT22 - Capacitive soil moisture sensor - Breadboard - 3xAA Battery-holder - Wires for connections ### Raspberry Pi Pico W ![](https://hackmd.io/_uploads/rJkw9k7Yn.jpg) General purpose microcontroller with both Wi-Fi and Bluetooth-connectivity. It has a good selection of different IO's as well as the previously mentioned connectivity, this makes it usable for IoT projects. For those interested: the Pi Pico W uses the RP2040 IC which is based on the ARM Cortex-M0+ processor core. This can be programmed in a multitude of languages and can even run Tensorflow Lite. The Pi Pico W can be bought at [electrokit](https://www.electrokit.com/produkt/raspberry-pi-pico-w/) for 98 SEK and can generally be found in better sorted electronic stores. Hereinafter this device will be simply referred to as Pico or the Pico. ### DHT22 ![](https://hackmd.io/_uploads/SJ-Y91Xt2.jpg) Temperature and humidity sensor with higher humidity range than the most basic ones, can also be called RHT03 or AM2302. If a humidity sensor that can't handle 100% relative humidity, shortened RH, is placed in an environment that has reached the dew-point, the humidity readings will remain unpredictable for a while even after returning to normal conditions. I learned this when building a Martha Tent for growing Lion's Mane mushrooms, i will write a tutorial on that project in the future and add a link here when I have written it. The sensor can be bought at [electrokit](https://www.electrokit.com/produkt/temp-fuktsensor-dht22/) for 129 SEK ### Capacitive soil moisture sensor ![](https://hackmd.io/_uploads/HJhockQYh.jpg) To measure the moisture of the soil, a PCB with a large surface area is placed in the soil. The PCB has two isolated copper areas and by running a known square wave signal through the positive side and seeing how its altered we can estimate the capacitance the PCB experiences. In a soil sample this will vary with the soil moisture content and therefore we can estimate it. Can be bought at [pchbutik](https://pchbutik.se/sv/kretskort/1237-jordfukt-sensor-kapacitiv-avkanning-analogt-utgang-passar-arduino.html) for 33 SEK. Hereinafter this device will be simply referred to as CSMS for short :::warning Do not get tempted to buy a resistive soil moisture sensor even though they are cheap. The exposed copper leads will go through electrolysis from their voltage difference, which leads to deterioration of the sensor as well as an unwanted leakage of copper into the soil. ::: ### Other material The other materials can be easily sourced by either the one of the listed sites or in any well sorted electronic store. Since we are running low voltages and very low currents there aren't any high requirements on these items. ## Computer setup The setup was done on a computer running Windows 11, using the Pymakr plugin for Visual Studio Code or VSC for short. I usually work with VSC because it alot of available plugins and I'm familiar with it. Pymakr was chosen because it provided adequate functionality. The first prerequisite is to have VSC installed on your computer, follow this link for instructions. After installing the next step is to install dependencies for Pymakr. To function, Pymakr requires node.js to be installed on the system, so for those that don't already have node.js they now need to install it. To do this you can follow the link [here](https://nodejs.org/en/download). Now you can start VSC and install Pymakr First go to extensions and enter "Pymakr" into the search bar. ![](https://hackmd.io/_uploads/rJoN2kQK2.jpg) Start the installation and let it finish, at this point I recommend restarting your computer. ### Flash with bootloader For the microcontroller to be able to run the Micropython source code we have to flash it with a bootloader, for this project version 1.20.0 was used and can be downloaded [here](https://micropython.org/download/rp2-pico-w/). Get your Pi Pico and USB-micro cable and follow the steps listed below: 1. While holding down the BOOTSEL button on your Pico, connect the USB-cable from the Pico to your computer. ![](https://hackmd.io/_uploads/ryS52yQYh.jpg) 2. After your computer has connected with the Pico you can let go of the button. 3. The Pico should now be read as a portable storage device called RPI-RP2 by your computer. 4. Simply copy the bootloader-file to the RPI-RP2 drive and the Pico will restart itself running the firmware. ### Creating a new Pymakr project Now you can create your first project in Pymakr by clicking the icon in the left toolbar and choosing "Create new project" ![](https://hackmd.io/_uploads/r1hV01XFn.jpg) Navigate to a folder of your choosing and click "Use this folder". Now you can name your project and you are ready to go. To be able to flash your project's source code to the Pico you have to first add the device to the project, and then click the connect button. For convenience you can start developer-mode which uploads the code to the Pico every time a file in the project is saved. ![](https://hackmd.io/_uploads/H1tsJlmt2.jpg) ## Circuitry :::danger When working with electronics only add or change connections with the power source disconnected, you risk damaging the components or injuring yourself otherwise. The next advice is to double-check every connection before plugging in the power-source, or the consequences would range from nothing working all the way to starting a fire, which could lead to the most dire of consequences. ::: Going forward the connections for this project are fairly uncomplicated. #### Fritzing The following is a diagram of the connections. Other pins could be chosen for the DHT22 and the CSMS but then the code would need to be updated. ![](https://hackmd.io/_uploads/BkWgVemt3.jpg) #### Calculations To calculate the power draw we need to calculate the consumption of each sensor and also the Pico itself, after that is done, the battery life can be estimated. The values for the power consumption are found in the pertaining data sheets. The power for the Pico was calculated from an estimation of being in sleep mode for 58 seconds drawing 25.4 mA, running normally for 1 second drawing 40 mA and transmitting over Wi-Fi for 1 second drawing about 72 mA every minute. This gives the calculation below: $I_{ave} = \frac{25.4 mA \cdot 58s + 40 mA \cdot 1s + 72 mA \cdot 1s}{60s}=26.42mA$ | Unit | Voltage | Power | | -------- | -------- | -------- | | Pi Pico | 4.5 V | 26.42 mA | | DHT22 | 3.3 V | 2.5 mA | | CSMS | 3.3 V | 5 mA | $P_{ave}=\Sigma_k (U_k \cdot I_k) = 4.5V \cdot 40mA + 3.3V \cdot 2.5mA + 3.3V \cdot 5mA = 143.64 mW$ Since I used high estimates for both the DHT and CSMS i will round this down to 140mW, now for the capacity of the batteries: $P_{stored} = \Sigma_k (U_k \cdot I_k) = 3 \cdot 1.5V \cdot 2700 mAh = 12150 mWh$ To get the battery life we simply divide the capacity with the average power consumption: $Hours=\dfrac{12150mWh}{140mW}=86.78h$ This is a limitation and in the last section I will mention possible ways to increase the battery life. ## Platform ### The chosen stack Now we have an assembled bundle of sensors and microcontroller, so how do we proceed from here? The next step is to establish a method to send data to a server where we can display the sensor readings and in our case, also provide alerts when the greenhouse is providing unfavorable conditions. It is possible to get a low-code solution up and running rather quickly, but we want to learn so we are going to host our own solution. For this project I have elected to use what is colloquially called the TIG-stack, TIG is an acronym for Telegraf, InfluxDB and Grafana. The architecture consists of the Pico sending the data using the MQTT-protocol via a Wi-Fi connection to the HiveMQ MQTT-broker, after this the TIG-stack comes into play. - Telegraf collects data from the MQTT-broker. - InfluxDB is a time series database that receives data from Telegraf and forwards it to Grafana. - Grafana queries the data entering InfluxDB and performs visualizations and sends out alerts. In the graphic seen below you can see how the tech-stack was ran, encircled in blue means that it's ran as a Docker container: ![](https://hackmd.io/_uploads/rySe5bVK2.jpg) There are of course many different platforms that can be used so it all boils down to picking one that suits your own needs. With that said there are a multitude of reasons behind me choosing to go with the TIG-stack. Telegraf is versatile in regards to what data sources could be used as inputs, this reduced the risk that I would have to alter my platform if I had to alter my setup. InfluxDB is well supported and provides strong real-time analytics. Finally Grafana integrates very well with InfluxDB while providing all the necessary functionality in regards to visualization and sending alerts. On a more philosophical level the elements of the TIG-stack are also open-source, which is something I personally appreciate. All in all this choice of platform is regarded as easy to set up, free and scales well with increased size. This is also a good place to mention my choice of MQTT-broker, where I went with HiveMQ. My choice in broker was more relaxed than the rest of my system. There were several solid options and HiveMQ edged the others out with a well-written documentation and honestly by having attracted some of the world's largest companies as customers. The downside is that the free version is limited to 100 connections, meaning that if the project would scale up, further considerations would have to be taken. There is still one major component that is yet to be mentioned, Docker. Docker is a virtualization software that helps guarantee portability of applications across different systems. As long as an application has a Docker-image, it should be able to run on any system that can run Docker. Docker creates something called containers when running it's images, with Docker-compose, these images can be bundled together with their dependencies, helping with the previously mentioned portability. ### Installation To get this running on your own Windows-machine you first need to download Docker, [follow this link](https://docs.docker.com/desktop/install/windows-install/) for instructions. Remember that these instructions are for someone running Windows 11 and if you are running a different system you will need to read the documentation. To set this up you need to create a folder in your computer and download and place [these files](https://github.com/kflysjo/greenhouse-monitor) in there. Before starting Docker-compose it is necessary to configure it for you personally. No files need editing for it to get up and running, but I recommend that you update the username and password for the MQTT communication in the file called telegraf.conf, this also needs to be updated in source code for the Pico to match. After getting to this stage start off by running Docker-desktop before navigating to the folder you placed the config files in. You should now be able to run the command "docker-compose up" in the terminal to get the entire stack up and running on your computer. The first time running this command, Docker will download the images for the applications that are used and it will take a bit longer than it will in the future. This is how it should look when it's up and running: ![](https://hackmd.io/_uploads/Hky4Vx7t2.png) ### Importing data to Grafana With the Docker-compose up and running we are now able to configure Grafana so it knows which data source we are after. Log into Grafana on any regular web browser using the following credentials: - URL: http://127.0.0.1:3000/login - Username: "king" - Password: "karl" :::info If you wish to change these credentials I recommend that you do so before running "docker-compose up" the first time. Changing the credentials in compose.yaml has no effect after the command has been run for the first time and would then need to be changed in the pertaining application. ::: After successfully logging in you can add a data source, follow the steps below for instructions: Go to the left toolbar and click "Data sources" under configuration. ![](https://hackmd.io/_uploads/BJfpNgQK3.png) Click "Add data source" ![](https://hackmd.io/_uploads/B1mGBe7t3.png) Select InfluxDB as the source. ![](https://hackmd.io/_uploads/H11UHlmF3.png) The address needs to match the configuration file and should be `http://influxdb:8086` In accordance with the configuration file the InfluxDB details are as follows: - Database : "iot" - User: "iotlnu" - Password: "micropython" Click the "Save & Test" button at the button and if everything worked you should get a notification saying `Data source is working` ![](https://hackmd.io/_uploads/S1faremt2.png) ::: info Now you should download the source code found in the next section and upload it to the Pico before continuing with the next step. ::: ### Setting up a dashboard in Grafana With the Pico flashed with the firmware, it should be left running so at least one data point is sent, for reasons that will soon be apparent. Once again go to the left toolbar and click "Dashboard" under "Create" ![](https://hackmd.io/_uploads/ryA-8emY3.png) Now click on "Add an empty panel" ![](https://hackmd.io/_uploads/BkUw8gmY2.png) Having sent data to the database you can now click-select which data you want to display on your newly created panel from dropdown-menus. ![](https://hackmd.io/_uploads/rylaLlQKh.png) I chose to put temperature and humidity on different panels, since I want different scales on the y-axis. Then I created one new panel for the soil moisture level and one new panel for the temperature prediction warnings. You can now create the necessary alerts, i followed the guide in found in this [link](https://hevodata.com/learn/grafana-webhooks-integration/) ## Source code The first step is to try to connect to a Wi-fi network of your choosing. Start off by updating the credentials in the login.py file by changing the dictionary called secrets. ```python= # Wireless network credentials secrets = { 'ssid' : 'wifi-ssid', 'password' : 'wifi-pass', } ``` You also need to update the MQTT credentials in main.py to your computer's local IP-adress as well as the username and password for the MQTT topic. ```python= # MQTT configurations MQTT_SERVER = "192.168.0.179" MQTT_PORT = 1883 MQTT_USER = "this" MQTT_KEY = "time" MQTT_CLIENT_ID = ubinascii.hexlify(machine.unique_id()) # Can be anything MQTT_DHT_FEED = "devices/greenhouse" ``` When actually running the code it starts off with running boot.py to connect to the chosen Wi-Fi. After this it runs main.py where it creates all the necessary variables and a MQTT-client object before entering a loop that reads the sensors and sends it to the broker. To give the reader an honest chance to amend the prediction warning code i will explain the code snippet here: ```python= FIFO_temp.append(temperature) if (len(FIFO_temp) > FULL_FIFO_LEN-1): FIFO_temp.pop(0) if (FIFO_temp[0] < FIFO_temp[-1]): temp_pred_one_h = temperature + (max(FIFO_temp) - min(FIFO_temp)) / len(FIFO_temp) * 60 else: temp_pred_one_h = temperature - (max(FIFO_temp) - min(FIFO_temp)) / len(FIFO_temp) * 60 ``` This code uses the assumption that the sensors are somewhat stable and will not provide faulty measurements that differ wildly from previous and forthcoming readings. I simply take the highest and lowest value of the previous 10 minutes and divide their difference by 10 to get an average change per minute, this gives the absolute value of the change which i now multiply by 60 go get the predicted temperature in an hour. To decide if it's going up or down I compare the value ten minutes ago to the most recent value and call that representative. If it's going up I add the change rate to the current temperature and if it's going down I subtract it. I admit this is a very crude way of predicting the future temperature but with stable enough sensors it has done the trick for me. But I will comment on this part in the final section of this tutorial on possible alterations of the prediction analysis. The project also includes an external library for the MQTT-functionality, the original source ca be found [here](https://github.com/iot-lnu/applied-iot/blob/master/Pycom%20Micropython%20(esp32)/network-examples/mqtt_ubidots/mqtt.py). It sends the necessery packets to establish connections. The full source code can be be found and downloaded [here](https://github.com/kflysjo/greenhouse-monitor/tree/main/main) ## Transmitting the data As of now in the developmental setup the data is sent once every minute. This interval could be increased a bit to save battery life, but i will elaborate on this in the last section of the tutorial. Initially i attempted to connect a Lora-module to a gateway but due to geographical reasons it was not possible to establish a connection with any Lora gateway from the greenhouse's geographical location. It was however possible to connect to an existing Wi-Fi network, so this became the method of my choosing. The semiconductor designers of the processor within the Pico did such a good job that the current draw is lower using the builtin Wi-Fi than the M5-Stack Lora module that i had. With Lora not being an option Wi-Fi was honestly the only convenient method of connectivity remaining. NB-IoT would have been my backup choice but since it doesn't use an ISM-band for communication it would require getting a SIM-card and some sort of subscription. The protocol of my choosing was MQTT and it was an easy choice. MQTT is lightweight and efficient which is great for resource constrained devices, it doesn't require maintaining a continuous connection which is great if we were to utilize sleep-mode, MQTT also scales well with an increased number of clients. There are of course many more good qualities of MQTT but the ones listed here are the ones that are central to this specific project. The way it works is that every client starts off by sending a connect package to a broker, after this they can either publish messages or request to subscribe to every message in a certain package. Every packet consists of a header with a fixed length as well as a payload with a variable length. The header contains something called control flags, package type and desired quality of service, which defines how many acknowledgments that are to be sent, if any. The payload, as you might have guessed, contains the actual information. Telegraf likes Json, that means that we like Json too. Json is a way to format data and is standard practice to use in a multitude of applications. Because of this we configure the payload to consist of a json-object. The data is packet together in a struct before being sent to the MQTT-broker ## Presenting the data As seen in the picture below and previously stated, i chose to display the temperature and humidity in different panels as well as soil moisture and prediction warnings also getting their own panels. ![](https://hackmd.io/_uploads/SkPCLxmYn.png) The data is saved in the database every time a reading is performed, which is every minute as of now. Since InfluxBD was chosen, we lack issues with real-time handling. It also lacks external dependencies. Within grafana i have configured alerts for five different events: - Temperature is above 40 celsius - Temperature is below 5 celsius - Temperature is predicted to rise above 40 celsius - Temperature is predicted to sink below 5 celsius - Soil moisture is below 20% These should be customized to fit the needs of your area and your selection of crops. The air humidity does not have any alerts connected to it, but it is still getting logged for future analytic reasons that will be mentioned in the next section. You might wonder why I don't do predictive analysis on the soil moisture level, that is simply because it takes time to dry up so having an early warning will give sufficient time to water the plants. My plan however is to include predictive analysis in the future. ## Finalizing the design This is how the Greenhouse monitor looks when installed in place. When installing a developmental product like this it is necessary to be wary with water or debris touching a sensitive part. ![](https://hackmd.io/_uploads/ByQE_lmt2.jpg) I also want to mention briefly that there are no perfectly isotropic antennas so how you orient the device will affect the link-budget between the Greenhouse monitor and the Wi-Fi router, so if you have a hard time establishing a connection testing different orientations could be a last resort solution. The project has been rewarding, making a project that has real life use for yourself is always more satisfying. The biggest drawback with the current design is the battery life, a battery life of less than 4 days is simply not economically, practically or environmentally feasible. My suggested way of getting around this is by flashing the Pico with a [custom bootloader that enables a function called picosleep](https://ghubcoder.github.io/posts/deep-sleeping-the-pico-micropython/). While in picosleep the current draw would only be 1.4mA and the sensors would draw no power during this time, leading to the following calculation: $I_{ave} = \frac{1.4 mA \cdot 598s + 40 mA \cdot 1s + 72 mA \cdot 1s}{600s}=1.58mA$ We can now update the table: | Unit | Voltage | Power | Time on| | -------- | -------- | -------- |--------| | Pi Pico | 4.5 V | 3.22 mA | 600 s | DHT22 | 3.3 V | 2.5 mA | 2 s | CSMS | 3.3 V | 5 mA | 2 s $P_{ave}=\frac{\Sigma_k (U_k \cdot I_k \cdot t_{on})}{60} = \frac{4.5V \cdot 3.22mA \cdot 600s + 3.3V \cdot 2.5mA \cdot 2s + 3.3V \cdot 5mA \cdot 2s}{60s}= 7.12 mW$ Since I once again used high estimates for both the DHT and CSMS i will round this down to 7 mW, the new lifetime of the batteries: $life_{battery}=\dfrac{12150mWh}{7mW}\approxeq1735h \approxeq 72 days$ This is still not as high as one perhaps would like but it's a harsh estimate so the real battery life would be better. My recommendation would be to get rechargeable batteries and change about once a month The main thing I would like to amend is the code for the prediction. Moving forward I'm going to set up another Greenhouse Monitor next to the existing one and run different firmware on it with updated prediction functionality to then be able to compare them and evaluate which model is the most suitable for our purpose. Also to use multivariable analysis to determine the rate of change of soil moisture. The model will use all three measured values to determine the rate of change of soil moisture by numerically solving a partial differential equation. I would also like to either 3D-print or buy a housing for the unit to have the Pico and the batteries in some sort of case. This is to protect against moisture and mechanical damage. The CSMS and DHT22 would be placed adequately and have wires running back to the Pico that would be in a case with the batteries. One thing to keep in mind however is that the case would attenuate the signal so the range of the Wi-Fi would be affected.