# ESP32 Home Weather Station for Houseplants ## Introduction *Project by: Rikard Kloth (rk222tq)* This tutorial will explain how to setup an IoT home weather station using a Heltec ESP32 microcontroller for temperature and humidity control and webhook push notifications to Discord. - Estimateted time of setup: 5h ## Project Objective The main objective behind the project was to be able to measure the best weather conditions for our houseplants, in order to create the optimal environment for our plants. The IoT device will help fulfill this objective by outputting sensor data that can be acted on by increasing humidity (with a humidifier) and lower temperature (by opening adjacent windows). The idea behind the project was to react on weather conditions that were causing our houseplants to wilt and die during the summer. The device should help with insights on when and how the houseplants needs attention. ## Materials | Hardware | Amount | Description |Retailer, Cost | | ---------------- | ------ | ------------------------------------------ | --- | | Heltec lora32 v2 | x1 | Microcontroller | amazon.se, ca 350:- SEK | | Breadboard | x1 | Base for connecting circuit |electrokit.com, ca 60:- SEK | | Jumper cable | x5 | Male to male cables for circuit connection | electrokit.com, ca 30:- SEK | | DHT11 sensor | x1 | Digital temperature and humidity sensor |electrokit.com, ca 50:- SEK | | Micro USB cable | x1 | For uploading code and power supply | amazon.se, ca 30:- SEK | | USB wall adapter | x1 | For power supply | amazon.se, ca 30:- SEK | The Heltec lora32 v2 is an affordable and versatile microcontroller development board that supports LoRa connectivity and is easy to learn for a first IoT project. ## Computer and Device Setup For this project I used Atom IDE supported by the Pymakr plugin through which the code is uploaded. In addition to Atom and Pymakr, Node.js software needs to be installed. Circuit connection shown in image below. *Image 1: Schematic over device circuit on breadboad* ![](https://i.imgur.com/izbaCZn.jpg) The white wire connects to the ground, the red connects the power. The DHT11 digital sensor works with both 3.3 volts or 5 volts. For this project I went with 3.3 volts. The blue wire connects the signal pin to the Heltec board. Since im using a digital sensor, no extra resistors are needed. ## IoT Platform I'm using Adafruit IO as a data visualization platform. Adafruit is webservice platform that can be set up for a free account with limited functionalities (which I did for this project). ## The Code This section includes code snippets of the main parts of the code. The following libraries were used but are not shown here: time, ubinascii and micropython. Also, the snippets do not show how to set up the sensors or how to configure Adafruit IO, as these were deemed to be of lower priority to show. A dht.py library and a mqtt.py library needs to be imported as well. #### Libraries ```python= from network import WLAN # For operation of WiFi network from mqtt import MQTTClient # For use of MQTT protocol to talk to Adafruit IO from dht import DHT #importing DHT class from machine import Pin,ADC #Pin allows for control of I/O Pins, ADC allows for analog to digital data conversion ``` #### Connection to WiFi Setup for beeing able to connect to the internet. For this project a WiFi connection was best suited. ```python= # WIFI # We need to have a connection to WiFi for Internet access wlan = WLAN(mode=WLAN.STA) wlan.connect(WIFI_SSID, auth=(WLAN.WPA2, WIFI_PASS), timeout=5000) while not wlan.isconnected(): # Code waits here until WiFi connects machine.idle() ``` #### Functions The first function helps make sure that the user gets feedback on current statuts which would lead to an improved user experience. additionaly, this could be expanded into a mobile application where users might want to recieve feedback about their plants health when on vacation. The second function helps send data to Adafruit IO. ```python= # Function to respond to control messages from Adafruit IO def sub_cb(topic, msg): # sub_cb means "callback subroutine" print((topic, msg)) # Outputs the message that was received. Debugging use. if msg == b"ON": # If message is "ON" blink once (triggered by flick of switch on Adafruit IO) led.value(1) time.sleep(0.2) led.value(0) time.sleep(0.2) elif msg == b"OFF": # If message is "OFF" blink twice (triggered by flick of switch on Adafruit IO) led.value(1) time.sleep(0.2) led.value(0) time.sleep(0.2) led.value(1) time.sleep(0.2) led.value(0) time.sleep(0.2) else: # If any other message is received ... print("Unknown message") # ... do nothing but output that it happened. # Function to send sensor data to Adafruit IO def send_sensor_data(): global last_data_sent_ticks global TEMPERATURE_INTERVAL if ((time.ticks_ms() - last_data_sent_ticks) < TEMPERATURE_INTERVAL): # Check if 60 seconds have passed return; # Too soon since last one sent. try: #publish temp and humidity data to respective topics client.publish(topic=AIO_TEMPERATURE_FEED, msg=str(result.temperature)) client.publish(topic=AIO_HUMIDITY_FEED, msg=str(result.humidity)) print("DONE") except Exception as e: print("FAILED") finally: last_data_sent_ticks = time.ticks_ms() #reset time since data was sent ``` #### MQTT Messaging Protocol The messaging between the device and the Adafruit IO server is setup using the MQTT protocol. ```python= # Use the MQTT protocol to connect to Adafruit IO client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY) # Subscribed messages will be delivered to this callback client.set_callback(sub_cb) client.connect() client.subscribe(AIO_TEMPERATURE_FEED) client.subscribe(AIO_HUMIDITY_FEED) client.subscribe(AIO_LEDS_FEED) ``` #### Check Message and Send Data - Disconnect if Needed The second function checks recieved messages and sends the sensor data to Adagruit IO. ```python= try: # Code between try: and finally: may cause an error # so ensure the client disconnects the server if # that happens. while 1: # Repeat this loop forever client.check_msg()# Action a message if one is received. Non-blocking. send_sensor_data() # Send data to Adafruit IO if it's time. finally: # If an exception is thrown ... client.disconnect() # ... disconnect the client, dicsonnect from wifi and print a message to communicate this client = None wlan.disconnect() wlan = None print("Disconnected from Adafruit IO.") ``` ## Data Transmission and Presentation Both data on humidity and tempeture are sent once every 60 seconds. The data is sent over WiFi since the device doesn't need to move outside of the house. For this project I chose Adafruit.io as a web service for data visualization. The dashboard is made up by two line charts and the control switch for status check (Shown in image 2 bellow). The control function triggers an LED on the Heltec board. A quick blink if it is switched "ON" and two quick blinks if switched "OFF". The data is shown in Adafruit.io for the past 24 hours. Comunication between the device and Adafruit.io is based on the MQTT protocol. *Image 2: Adafruit.io Temperature and humidity dashboard* ![](https://i.imgur.com/FxiL8DP.png) Two actions are set in Adafruit.io that are triggered by the data. When the humidity and/or temperature reach a certain level a notification indicationg which data and its value is sent to a discord server using the webhooks protocol (Discord notification shown in image 3 bellow). *Image 3: Notification sent shown in Discord* ![](https://i.imgur.com/zurRPJP.png) ## Final Thoughts This was a fun little project for a beginner which can serve as a great introduction both to setting up a device but also to programming in (Micro)Python :smile:. ![](https://i.imgur.com/UB2Z0JM.jpg)