# Tutorial on how to build a temperature and humidity sensor This project is designed for you who wants to keep an eye of your plants, without having to actually keep an eye of them physically. #### Authors David Agerberg (da222uc) Joel Klingberg (jk223sk) Edvin Hellsing (eh224ax) ## Save your plants! This project lets your plants live longer by making sure the soil is moist enough, which the soil moisture sensor keeps track of. The sensor sends soil moisture data via Wi-Fi to PyBytes where it is visualized. It is also possible to keep track of the soil moisture level by looking at red, yellow and green LED lights mounted on the breadboard, connected to the Pycom board. The LED lights has the function of a trafic light, the green LED means the moisture level is alright, the yellow that it has been watered too much, and the red LED that it needs water. ### Estimated time for the project This project takes approximately 120 hours to complete if you are completely new to playing around with IoT, like the authors of this article. ## Objectives ### Why choose this project The authors aim has been to develop a device that is convenient in the everyday life. The outcome of this project is a useful device with the purpose of monitoring soil moisture level in plants. The device will facilitate the maintenance of plants by visually notyfing its owners when it is time to add more water. Since caring for plants can by tricky, one might argue that this is a suitable device for the digital home. ### Purpose of the project By collecting and displaying the data in a dashboard a user can analyze the soil moisture level and compare different surrounding factors like temperature, exposure to sunlight and amount of water added. Ultimately, the data provides insights regarding a plant's best conditions. ### Project insights This project gives a brief insight of the exciting world of Internet of Things in general, and programming, collecting and visualizing plant's soil moisture level in particular. ## Material This project has been done using Pycom LoPy4, a device programmed by MicroPython. The material needed for this project is: - Pycom lopy4 (specifications can be read in this product datasheet: https://pycom.io/wp-content/uploads/2018/08/lopy4-specsheet.pdf) - Pycom Expansion board - Breadboard - Soil hygrometer module FC-28 - Wires - Resistors - 1 x red LED light - 1 x yellow LED light - 1 x green LED light - Micro USB cable ### Where the material was bought All parts listed above can be bought from Electrokit (https://www.electrokit.com/en/), worth mentioning is that package below includes more parts than needed. - LNU - 1DT305 Tillämpad IoT - LoPy4 and sensors bundle (https://www.electrokit.com/en/product/lnu-1dt305-tillampad-iot-lopy4-and-sensors-bundle/), 995.00 SEK - Soil hygrometer module FC-28 (https://www.electrokit.com/en/product/soil-hygrometer-module/), 29.00 SEK <b>Total material cost: </b>1 024.00 SEK ## Computer setup <b>How the firmware on the Pycom Expansion board was updated: </b> No update of the Pycom Expansion board was needed on Mac since it had 3.1 straight out of the box. But an update was ran with dfu-util tools via homebrew in the Terminal, the file with the latest firmware – `expansion31_0.0.11.dfu` – were downloaded from Pycom's website (https://docs.pycom.io/pytrackpysense/installation/firmware/). <b>The Pycom Lopy4 firmware: </b>The firmware for the Pycom Lopy4 was downloaded from https://pycom.io/downloads/. The firmware upgrade tool was used to make it possible to send data from the sensor connected to the Pycom board via Wi-Fi to Pybytes. <b>Chosen IDE:</b> Visual Studio Code with the Pymakr-plugin. ### How the code was uploaded <b>How the code was uploaded:</b> via Github. (<a href="https://github.com/joelklingberg/applied-iot-lnu">https://github.com/joelklingberg/applied-iot-lnu</a>) <b>Chosen IDE:</b> Visual Studio Code with the Pymakr-plugin. ### Circuit diagram <b>How the wiring was connected:</b> ![](https://i.imgur.com/HqU3CVC.png) ### The Pybytes Platform Pybytes is a cloud-based platform. The free version of Pybytes will be sufficient for this project. If the project would be on a bigger scale, AWS IoT could be an option to consider. By using the Pycom updater, it was possible to force update Pybytes registration and follow the instructions given when running the firmware updater tool. The authors Wi-Fi were added to Pybytes (where a free account is needed), and the Pycom device added, and connected to the Wi-Fi in the Pybytes account. The Activation code given in *Provisioning* at Pybytes were pasted in the Pymakr terminal in Visual Studio Code to make it possible to send data from the program ran in Visual Studio Code to Pybytes, and visualize it in a created dashboard. ## The platform in terms of functionality ### The code ### The project's code is presented below, explanation of every vital step is commented with '#' in the code. ``` import machine # Import of library "machine" which it used to read data from A0 and pins on the pycom board from time import sleep # Sleep when that is used, e.g. between every loop from machine import Pin # Pins that are being used for the LED lights adc = machine.ADC() # ADC are being used with machine, to read data from A0 sensor = adc.channel(pin='P15', attn=machine.ADC.ATTN_11DB) # Reads from pin 15 on the pycom board p_out_green = Pin('P9', mode=Pin.OUT) # P9 where the green LED light is connected to the pycom board p_out_orange = Pin('P10', mode=Pin.OUT) # P10 where the orange LED light is connected to the pycom board p_out_red = Pin('P11', mode=Pin.OUT) # P11 where the red LED light is connected to the pycom board def blink(): # 10 loops (blinks) if else is reached, then all LED:s blinks with 1 sec pause between blinks for _ in range(10): p_out_green.value(1) p_out_orange.value(1) p_out_red.value(1) sleep(1) p_out_green.value(0) p_out_orange.value(0) p_out_red.value(0) sleep(1) def read_sensor(sensor): # Take multiple readings and take the average to get a more reliable reading print("Moisture value: {0}" .format(sensor())) # 0 is being replaced with the sensor value READING_DELAY_IN_S = 1 # Reading delay in one second NUM_READINGS = 10 # Number of readings (10) total = 0 # The sum of all readings for i in range(0, NUM_READINGS): # Do 10 sensor readings, return the average value sleep(READING_DELAY_IN_S) # One second sleep between every reading sensor_reading = sensor() # Grabs the sensor value print('Moisture value: {0}'.format(sensor())) #Prints every sensor value in the loop total += sensor_reading # Total variable (first 0), then sum with its pre value average_reading = int(total/NUM_READINGS) # All read values divided by number of readings (i.e 10) print("Average moisture: {0}" .format(sensor())) # Prints average read sensor value return average_reading # Returns the average reading def check_plant(sensor_reading): # Defintions of break points values from the soil moist sensor LOW_VALUE = 1000 HIGH_VALUE = 2000 if sensor_reading >= LOW_VALUE and sensor_reading <= HIGH_VALUE: # If value is between 1000-2500, print text below and activate green LED print("Woooa! Perfect, between {0}-{1} is the target range, you have green fingers my old friend!".format(LOW_VALUE, HIGH_VALUE)) p_out_green.value(1) p_out_orange.value(0) p_out_red.value(0) elif LOW_VALUE > sensor_reading: # If value is below 1000, print text below and activate yellow LED print("Hmm! Below {0} is too wet, drink the water instead of poring it over your flowers, else you will get blisters on your fingers.".format(LOW_VALUE)) p_out_orange.value(1) p_out_red.value(0) p_out_green.value(0) elif HIGH_VALUE < sensor_reading: # If value is over 2500, print text below and activate red LED print("Ooof! Over {0} is perhaps too dry, you should water your poor flowers.".format(HIGH_VALUE)) p_out_red.value(1) p_out_green.value(0) p_out_orange.value(0) else: # If an error is suspected, blink all LED lights and print text below print("Man, This is a tricky one, it might be a bit too dry or a bit too wet, or something spooky's happening. I have no idea what you should do.") blink() while True: # Continue as long as true, with 5 seconds paus between every loop average_reading = read_sensor(sensor) pybytes.send_signal(2, average_reading) check_plant(average_reading) #Check plant average reading sleep(5) ``` ## Explanation of the code A description of the code is given below. Description of the code has been given inline throughout the code with explaning comments on allmost every part. What it basically does is importing a few libraries, "Machine" and its "Pin" and "Sleep" from "Time". "ADC" is being used to make it possible to read data from A0 on the soil moisture sensor, and P15 as it is the contact on the pycom board where the calbe from A0 is connected. P9, P10 and P11 are the contacts on the pycom board to which the cables from the LED lights (red, yellow and green) are connected via ground. After that, there is a `def blink():` for loop which has the purpose to blink the three LED lights ten (10) times if the elif statement reaches the else part, which indicates some sort of error. The `def read_sensor(sensor):` part takes the sum of ten sensor readings, divides them by ten and prints the average value in the console with a message, and sends them via Wi-Fi to Pybytes where it is presented in a main table, and visualized in a line chart aswell as a bar chart. The `def check_plant(sensor_reading):` part defines the range of soil moisture values, and holds an elif statement for the different scenarios. In the end, there is a `while True:` which keeps the elif statement going until it is prompted to stop in the Pymakr terminal. ## Finalizing the design Below, the final results of the project are listed. ### Project results The project results is prestended with images below. ### Pictures In moisture soil, where the sensor values are between 1000-2000, the green lamp will be active: ![](https://i.imgur.com/15vzGfT.jpg) In air the red lamp will be activated since the sensor values will be over 2000 (too dry): ![](https://i.imgur.com/8uhxQcI.jpg) In water the orange lamp will be activated since the sensor values will be under 1000 (too wet): ![](https://i.imgur.com/N8MbKHk.jpg) The screenshot shows the pybytes dashboard where the data collected with the soil moisture sensor is visualized. ![](https://i.imgur.com/B5ggPqy.png) ### Final thoughts The values collected by the soil moist sensor are substantially higher than a reseller (https://protosupplies.com/product/soil-moisture-sensor-module/) of a similar sensor to the one used in this project, which at a first glance might be confusing. A tested of their Soil Moisture Sensor Module gave the following readings: > Dry enough that the plant should have already been watered was up around 850 – 950 > Just right was in the 600 – 700 range > Too wet was down in the 200 - 400 range Therefore they programmed following ranges: > Under 500 is too wet > 500-750 is the target range > Over 750 is dry enough that we should water the poor thing. Based on that, this project initially tried a range similar to written above. However their equipment has a range between 0-2013, while the one used from Electrokit (Electrokit, 2020) has a range from 0-4095 why the programmed was written as followed: > Bellow 1000 is considered as a low value, which means the plant has been watered too much, that basically means "Stop watering your plants!" and the red LED light starts to shine. > > A value that is higher than 2000 is considered as a high value, which in opposit to a low value means the plant has not been watered enough much, the plant is too dry which in in other words can be put as "Poor lots of water on your plant if you want them to live!" and the yellow LED light starts to shine. > > If the readings holds a value in the range from 1000-2000, the plant lives a happy life, and the green LED lights starts to shine and you will receive a friendly message that you have green fingers. One might wonder if the values is a bit reverse, and that would have been more logic that a high value means that the moisture is high, not that it is low. But since other similar sensors seems to be configured in the same way, what really would have been confusing was if the values should have been reveresed just in this project. Overall, the project went well since the goal was reached. It is easily to sat the project was really challenging in the beginning, but became more and more clear down the road since the authors of this report gathered more experince for each week. ### Possible improvements One of the main improvements would be to send data via LoRa and TTN and display the values in, e.g. Ubidots. This would have added extra value at the same time as it had made the project more comprehensive. In the current setup a local Wi-Fi is used to send the values directly to Pybytes for visualization. By using LoRa and TTN it would have connected to an existing TTN gateway and benefit from the open networks provided. Additionally, this project has opportunities to scale up in several ways. Several possible improvements were identified, like programming either text message or email notifications when the plants moisture level is either too high or low. Email notifications would have been possible using either a local SMTP server or through any service provided by a company. Regarding text messages a possible solution could include integrating an API. The project in this state needs personal monitoring while notifications could assist any plant owner even more, e.g. when away from home. Another possible improvement could be to attach a light sensor module and measure exposure to sunlight. In addition to this a temperature sensor (e.g. MCP9700) could have been attached. By using any of these or in combination more insight could have been gained regarding physical placement and surrounding factors when caring for plants. This project is adapted for indoor use. It is also limited to a power supply via USB connection to a computer. However, several improvements could have been done taking this project further with opportunities scaling up. A battery power source would have removed the physical restriction to a computer. For outdoor use a waterproof chassis would be needed ensure an operative device. Finally, the possible improvements are many but if allowed to be creative, a self-watering system could have been integrated. Of course, such a project would need considerably more experience and knowledge.