--- tags: School --- # Monitor your plants and their environment Pierre Lantz Söderlund (pl222zv) In this tutorial a step by step guide will be provided on connecting a microcontroller to the internet through MQTT which will send and visualize data. The current tutorial should take approximately 2-3 hours to follow and complete. ## Objective Due to the fact that I find taking care of my plants difficult (such as giving them water and placing them in an environment where they can thrive), I decided to use IoT, as an aid in attending to the above described objectives. Hence, the current tutorial seeks to remedy this issue by using a ESP8266 microcontroller which can monitor the 1) humidity 2) temperature of a plant’s environment and 3) the moisture of its soil. Moreover, a major objective of the project was to use a MQTT transport protocol in order to gain a better understanding of its functions. By completing the project one shall gain an understanding of using a microcontroller with micropython and sending data through MQTT. ## Material In what follows, Table 1 will provide a list of the material needed to complete the project. You will also need a laptop or computer to upload your program to the microcontroller. | Product | Where to buy | Description | Price | | ------- | ------------ | ----------- | ----- | | NodeMCU ESP8266* | [Link](https://www.kjell.com/se/produkter/el-verktyg/arduino/utvecklingskort/nodemcu-utvecklingskort-p87091) | Microcontroller that can run micropython. | 249 SEK | | DHT22 | [Link](https://www.electrokit.com/produkt/temp-fuktsensor-rht03/) | Measures the temperature and humidity. | 99 SEK | | Soil moisture sensor | [Link](https://www.electrokit.com/produkt/jordfuktighetssensor/) | Measures resistance between probes. | 29 SEK | | Breadboard | [Link](https://www.electrokit.com/produkt/kopplingsdack-400-anslutningar/) | For connecting everything together. | 59 SEK | | Jumper wires | [Link](https://www.kjell.com/se/produkter/el-verktyg/arduino/arduino-tillbehor/kopplingskablar-hane-hane-65-pack-p87212) | Connect the sensors to the microcontroller. | 90 SEK | | Phone charger with Micro-USB cable | [Link](https://www.kjell.com/se/produkter/dator/kablar-adaptrar/usb/usb-kablar/micro-usb-kabel-1-m-p68687) | To upload your code to the microcontroller and then to power it afterwards. | 209 SEK | | | | Total: | 735 SEK | | *Can be another microcontroller like LoPy4, ESP32, etc | | | | ![](https://i.imgur.com/UeJxcRw.jpg) For this task the NodeMCU ESP8266 microcontroller was used. It is a cheap and nifty little device with WiFi built in and is therefore suitable for the objective of this project. ## Computer and Device Setup ### Flashing the NodeMCU ESP8266 The NodeMCU ESP8266 does not come with MicroPython by default, therefore we have to flash it with MicroPython firmware in order to be able to program it. Below I provide a step by step guide on how to flash the MicroPython firmware on the NodeMCU ESP8266 to be able to use it with MicroPython. * Install the latest version of python from pythons website [here](https://www.python.org/downloads/). * Install the latest stable version of esptool.py with pip by opening a Terminal window and type ``` python -m pip install esptool ``` * Go to the folder where esptool.py is installed by typing: ``` cd C:\Users\USERNAME\AppData\Local\Programs\Python\Python39\Lib\site-packages ``` Do not forget to change USERNAME to your computer's username. * Run esptool.py by typing: ``` esptool.py ``` in the command line. ![](https://i.imgur.com/rATF3ro.png) * Download the latest firmware of micropython for the ESP8266 board by going to the [MicroPython Downloads page](https://micropython.org/download/esp8266/). * Add the .bin file to the site-packages folder. * Now you need to erase the ESP8266 flash memory to be able to flash it with the MicroPython firmware. Do so by holding the **BOOT/FLASH** button while running the following command ``` esptool.py --chip esp8266 erase_flash ``` When the process has begun you can release the button. After a while the memory will be erased. ![](https://i.imgur.com/Yc7qqBz.jpg) * You need to know the COM port of the device beforehand. To find that out you can go to the Device Manager in Windows and look under ports. If you can not see it you might not have the drivers. In that case download the drivers from [Silicon Labs website](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers) and install it. * Knowing the COM port of the board and the flash memory erased, you are now ready to flash the board. Do so by typing ``` “esptool.py --chip esp8266 --port <YOUR_COM_PORT> write_flash --flash_mode dio --flash_size detect 0x0 <YOUR_BIN_FILE> ``` Do not forget to change the com port and name of your bin file. Hold down the **BOOT/FLASH** button before running the command. Now you have the MicroPython firmware on the NodeMCU. ### Installing the IDE with Pymakr extension I chose to use Visual Studio Code with the pymakr plugin to program the microcontroller. IDE was chosen as it is very versatile and you can use it for a lot of programming languages without the need of several programs. * Install [Node.js](https://nodejs.org/en/download/) on your computer by downloading it from their website and run the .exe file. Then follow the instructions. ![](https://i.imgur.com/w8x8v7o.png) * Install [Visual Studio Code](https://code.visualstudio.com/) by doing the same as for Node.js. ![](https://i.imgur.com/z2z7TvL.png) * Open up VS Code and click on the Extensions page. Search for Pymakr and install it. The Pymakr extension should be installed and the Pymakr Console will open. * Press All Commands in the bottom of the screen and then press Pymakr > Global Setting. * This opens up the pymakr.json file. Under manufacturers we have to add ``` “Silicon Labs” ``` for it to recognize our board. ![](https://i.imgur.com/unpBT6p.png) * You are now ready to upload code to the NodeMCU ESP8266 with Visual Studio Code. ### Uploading code Uploading code with Visual Studio Code is straightforward. You can create a folder to store the code (1 in picture below) and then press the upload button (2 in picture below). ![](https://i.imgur.com/ryk8Dgp.png) ## Putting everything together The circuit diagram for the project can be seen below: ![](https://i.imgur.com/cVMcmcU.png) * The red lines are positive cables powering the sensors from the 3v3 pin on the NodeMCU through the positive rail on the breadboard. * The black lines are ground cables from the GND pin going to the sensors through the negative rail on the breadboard. * The yellow lines are data cables from the respective sensor. The DHT sensor is connected to D5 and the soil sensor is connected to A0. When everything is connected together it will look like this: ![](https://i.imgur.com/Bv7UOoH.jpg) This is only connected with jumper wires for development. With a 3D printed enclosure and by soldering these components on a perforated board, this could be used in production. This could be a step to take this project to a more advanced level in the future. ## Platform In this project the Adafruit IO was uses as the platform. It is a cloud platform with MQTT broker and an easy to understand dashboard, hence a perfect fit for this simple project. To start using it you need to create a free Adafruit IO account [here](https://accounts.adafruit.com/users/sign_in) at Adafruit's website. Although the free account only allows you to have 10 feeds to publish to, it is suitable for the needs of this project. In the future I would like to add a local platform to this project in the means of a MQTT broker and TIG-stack installed on a Raspberry Pi. Such additions to the project would provide more control and functionality. Moreover, this would also make it possible to scale the project up with adding more devices. ## The code In the following section the code used for this project can be found. For this code you need to download the umqttsimple library from [github](https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/MQTT/umqttsimple.py). Santos' (nd) code served as a foundation for the code used in the current project. Modifications to Santos' code were made, such as adding the soil moisture sensor to the code. ``` # Importing libraries for the project. import time from umqttsimple import MQTTClient import ubinascii import machine from machine import Pin, ADC import micropython import network import esp import dht esp.osdebug(None) import gc gc.collect() # Variables for the WiFi connection and IP Adress/Hostname for the MQTT broker. # Do not forget to change it to your needs. ssid = 'YOUR_SSID' password = 'YOUR_PASSWORD' mqtt_server = 'io.adafruit.com' # Give the device an unique ID and save it to client_id. client_id = ubinascii.hexlify(machine.unique_id()) # This will publish temperature, humidity and soilhumidity data to separate topics. topic_pub_temp = b'Zaikool/feeds/sensor.temperature' topic_pub_hum = b'Zaikool/feeds/sensor.humidity' topic_pub_soilhum = b'Zaikool/feeds/sensor.soilhumidity' # The last_message variable will hold the last time a message was sent. # The message_interval is the time between the message, set to 10 minutes (60 * 10 seconds). last_message = 0 message_interval = 60 * 10 # Connect the device to WiFi. station = network.WLAN(network.STA_IF) station.active(True) station.connect(ssid, password) while station.isconnected() == False: pass print('WiFi connection successful.') # Initialize the DHT22 and soil sensor on GPIO 14 and A0. sensor = dht.DHT22(Pin(14)) soilsensor = ADC(0) # Connect to MQTT Broker. def connect_mqtt(): global client_id, mqtt_server # Enter Adafruit username and key below. client = MQTTClient(client_id, mqtt_server, user="ADAFRUIT_USERNAME", password="ADAFRUIT_KEY") client.connect() print('Connected to %s MQTT broker' % (mqtt_server)) return client # This function resets the device if it can not publish the readings via MQTT. def restart_and_reconnect(): print('Failed to connect to MQTT broker. Reconnecting...') time.sleep(10) machine.reset() #Function to read the DHT sensor, it returns temperature and humidity values. def read_sensor(): try: sensor.measure() temp = sensor.temperature() hum = sensor.humidity() if (isinstance(temp, float) and isinstance(hum, float)) or (isinstance(temp, int) and isinstance(hum, int)): temp = (b'{0:3.1f},'.format(temp)) hum = (b'{0:3.1f},'.format(hum)) return temp, hum else: return('Invalid sensor readings.') except OSError as e: return('Failed to read sensor.') # Function to read the soil moisture sensor. def moist_sensor(): soil = soilsensor.read() return soil try: client = connect_mqtt() except OSError as e: restart_and_reconnect() while True: try: if (time.time() - last_message) > message_interval: # Get readings. temp, hum = read_sensor() soil = moist_sensor() # Print readings to serial. print(temp) print(hum) print(soil) # Publish readings to topics. client.publish(topic_pub_temp, temp) client.publish(topic_pub_hum, hum) client.publish(topic_pub_soilhum, str(soil)) # Update the time when the last readings was sent. last_message = time.time() except OSError as e: restart_and_reconnect() ``` ## Transmitting the data ### Wireless Protocol The device used for this project only has WiFi hence WiFi is being used to transmit the data. WiFi does not have long range and high power consumption, nonetheless, is perfect for the project as it aims for home use (such as monitoring your house plants). If one would want to make this project portable with a battery, an option would be to instead use a device with other wireless protocols (like the LoPy4 which have LoRa and SigFox). ### Transport Protocol The NodeMCU ESP8266 device transfers the data with MQTT to the Adafruit IO MQTT broker with the credentials entered in the code. This gives security while sending through MQTT and prevents others from publishing and subscribing to your topics (feeds in this case). The device sends the data every 10 minutes as specified in the code. While the free Adafruit IO account limits you to 30 data points I chose to send the data every 10 minutes. This allows you to still be able to upscale the project with additional devices. ## Create the dashboard To create a dashboard you go to the **Dashboard** tab when logged in to Adafruit IO and press the cog on the right side of the page as shown below. ![](https://i.imgur.com/KzrJzww.png) Here you press **Create New Block**. There are many different blocks to choose from. For the soil humidity and humidity i chose **Gauge** to present the humidity and **Line Chart** for the temperature. ![](https://i.imgur.com/mHKZgjV.png) Finally you choose which feed (topic) to be connected to the corresponding block. ![](https://i.imgur.com/xyBWXmF.png) You are then ready to see your data. ## Presenting the data The data is being presented on Adafruit IO dashboard. ![](https://i.imgur.com/lzPoc0k.png) You can send up to 30 data points per minute. The data is then saved to Adafruit IO as soon as it is received from the device (in case of the current project every 10 minutes). Adafruit IO stores the data for 30 days. ![](https://i.imgur.com/S1M26gH.png) The picture above illustrates the value of the soil moisture sensor, presented as a graph. ## Finalizing the design After assembling the project and putting the soil moisture sensor in a plant by the window, the project is completed. ![](https://i.imgur.com/So2JXsY.jpg) It is important to mention that the finalised project is only a prototype and not ready for deployment. To be able to use it in production, in the future, I would like to create an enclosure and solder the cables for more durability. Additionally, using a microcontroller with several analog inputs (in order to be able to add more soil moisture sensors) could be another possible option. Such steps would allow one microcontroller to monitor several plants. ![](https://i.imgur.com/5W6j6ex.jpg) ![](https://i.imgur.com/S4uE1o9.jpg) ### Final Thoughts As far as I am concerned, the outcome of the project is satisfactory, however some minor problems were possible to identify. Hence, I would like to comment on the most pressing issue and propose a change for future development: During the research state of this task, I found out a disadvantage with the soil moisture sensor being used in the project. Although, it is a cheap device it comes with an disadvantage. The constant current flowing through the sensor probes - inserted in the soil - leads to elctrolytic breakdown. This corrodes the thin layer on the PCB and renders the sensor useless. To prevent such issue, I would replace the sensors for capacitive soil moisture sensors, which would not encounter the same problem. While capacitive soil moisture sensors are more expensive, they are also more durable, thus more suitable in the long run. Having no prior experience with programming I found writing my own code challenging. Nevertheless, I came across a pedagogical tutorial (ref 3) by Rui Santos which became a great aid in programming the device. All in all, I was able to execute my original plan and even add the moisture sensor. ## References 1. Santos, R. (nd). Flashing MicroPython Firmware with esptool.py on ESP32 and ESP8266. Randomnerdtutorials.com. Avaialble at: https://randomnerdtutorials.com/flashing-micropython-firmware-esptool-py-esp32-esp8266/ 2. Santos, R. (nd). MicroPython: MQTT – Publish DHT11/DHT22 Sensor Readings (ESP32/ESP8266). Randomnerdtutorials.com. Avaialble at:https://randomnerdtutorials.com/micropython-mqtt-publish-dht11-dht22-esp32-esp8266/ 3. Santos, R. (nd). MicroPython: Program ESP32/ESP8266 using VS Code and Pymakr. Randomnerdtutorials.com. Avaialble at: https://randomnerdtutorials.com/micropython-esp32-esp8266-vs-code-pymakr/