**Author:** Pranav Patel (pp222gm) ## Introduction This is a tutorial on how to build a temperature monitoring device as well as setting up an automation script to turn on and off a fan based on the temperature reading. **Time Requirement:** 4-8 h ## Project Objective The project idea came to fruition during a hot summer day where getting up to start the fan felt too much. The idea is that the fan will be able to automatically start itself up based on the temperature readings. The initial idea was to use weather station readings. However, as that was a vague and general reading of the temperature of a city, it would not fluctuate and the reading would not be as effective. Thus the final idea was to use a sensor device and read the temperature of a room as well as use a buzzer to notify the room of the fan activation. This would allow fluctuations based on the variables in the room to change the reading over time. MQTT protocol will be used to transmit the data over to a home automation system where scripts will be run to automate the fan. The main objective of this project is to learn and create such a device using IoT. Taking on this challenge would teach how IoT devices work and what applications of the data are possible. ## Material | Item| Description |Link| Price| |----------------- |----------------------- |-------|----------------------- | | Raspberry Pi Pico WH |The microcontroller which will run the program | [Pico WH](https://www.electrokit.com/en/product/raspberry-pi-pico-wh/) |109 SEK | Breadboard |The extension to connect the Pico WH with the sensors without soldering | [Elektrokit](https://www.electrokit.com/en/product/solderless-breadboard-400-tie-points/) |49 SEK | Digital temperature and humidity sensor DHT11| The Temperature and Humidity Sensor | [Electrokit](https://www.electrokit.com/en/product/digital-temperature-and-humidity-sensor-dht11/) | 49 SEK | Piezo alarm passive|Buzzer which makes sound upon activation | [Electrokit](https://www.electrokit.com/en/product/piezo-alarm-passive/) | 36 SEK |Jumper cables male-male x3|Male to Male cables for connecting the parts|[Electrokit](https://www.electrokit.com/produkt/labbsladd-20-pin-15cm-hane-hane/)|29 SEK |Jumper cables male-female x10|Male to female cables to connect the parts|[Electrokit](https://www.electrokit.com/produkt/labbsladd-40-pin-30cm-hona-hane/)|29 SEK |IKEA Gateway*|Bridge and network mesh to connect and group IKEA products|[SellPy](https://www.sellpy.se/item/yxrVrBLCzy?utm_source=google&utm_medium=cpc&utm_campaign=18297600463&gad=1&gclid=CjwKCAjw44mlBhAQEiwAqP3eVjdvqdbVJJwCLJMM70O42cdxEg7RScWgPllW84BtBLCqKO55BxnbvxoCi7AQAvD_BwE)| 180 SEK |IKEA Trådlöst uttag|Smart plug from IKEA which can be remotely controlled|[IKEA](https://www.ikea.com/se/sv/p/tradfri-tradloest-uttag-smart-90356166/)| 149 SEK | | || **Total** | | ||| **630 SEK****| >Note: Items marked with asterisk(*) are not in production anymore and thus could be out of stock. Total marked with double asterisk(**) can vary due to harder to find materials. >IMPORTANT: IKEA Gateway not to be confused with newer model Dirigera hub. Dirigera has not yet seen support with Home Assistant. ## Computer Setup This project was developed on a computer with [Windows 10](https://www.microsoft.com/sv-se/software-download/windows10). Due to this, the instructions could vary on other Operating systems. A Virtual environment was run for the Home Assistant and mosquitto broker for the MQTT protocol between the Pico WH and Home Assistant. A connection to AdaFruit IO was also established to monitor the data of the temperature and humidity from the sensor. For the IDE, I used [Visual Studio Code](https://code.visualstudio.com) due to experience working with it before. It has great extensions that help editing and also good support for using microcontrollers. Here below are two lists of software which need to be installed to setup the development environment and server. **Development Software** * Python 3.7 or newer * [MicroPython Firmware](https://micropython.org/download/rp2-pico-w/) * [Visual Studio Code](https://code.visualstudio.com) * [Node.js](https://nodejs.org/en) **Server Software** * Mosquitto * VirtualBox (For Home Assistant) * Ikea Home Smart 1(Android/iOS) ### Pico WH Setup The Pico WH must be flashed with a new firmware in order to work with MicroPython. This firmware is found [here](https://micropython.org/download/rp2-pico-w/). >Note: If any problems occur during the usage of the microcontroller and you wish to reset the Pico W, use the [flash-nuke](https://github.com/dwelch67/raspberrypi-pico/blob/main/flash_nuke.uf2) given here. #### Step 1: Flash Firmware Connect the microUSB (small side) cable end into the Pico WH first. After that, press and HOLD in the BOOTSEL button on the Pico and connect the USB end into your computer. For extra safety, avoid usb hubs and prefer the ports on your computer/laptop. Wait until a new drive name RPI-RP2 opens in your file system. When you see the drive open, copy the Micropython firmware uf2 file in this storage. Wait until your board automatically disconnects from your computer and reconnects. #### Step 2: Test Microcontroller Connection Open up Visual Studio code and search for PyMakr extension in the extensions. Download it and wait for it to install. Once finished you can create a project in the PyMakr extension and connect your Microcontroller to it. The device should show up as shown in Figure 1. ![](https://i.imgur.com/xUQlLdh.png) *Figure 1. PyMakr Devices check* If PyMakr doesn't immediately start, do not worry and restart your Visual Studio Code which will reload PyMakr. Hover mouse over the device and see the options come up. Click on the lightning button to connect device and then the first option to view in terminal and you should see the terminal open as shown in Figure 2 and 3: ![](https://i.imgur.com/d95uP6F.png) *Figure 2. Microcontroller connection* ![](https://i.imgur.com/moID50L.png) *Figure 3. Test microcontroller response* type in the terminal ###### code ```Print("Hello World!")``` if the response from the microcontroller returns Hello World! then you have successfully connected to your Microcontroller. ### Setup Home Assistant The Home Assistant webpage has a comprehensive guide to download the Home Assistant Operating System on Virtual Box [here](https://www.home-assistant.io/installation/windows/). If followed correctly, Home Assistant OS will start up on your home screen as shown in Figure 4. ![](https://i.imgur.com/cVjVB2R.png) *Figure 4. Home Assistant OS CLI* From here you can go to your browser and type in: > http://YOUR.HOME.ASSISTANT.IPADDRESS:8123 Where ```YOUR.HOME.ASSISTANT.IPADDRESS``` is replaced with your the ipv4 address shown on your home assistant command line interface. After waiting for some time and completing the initial configuration, you will arrive upon the dashboard which should look similar to Figure 5: ![](https://i.imgur.com/fjELNvq.png) *Figure 5. Home Assistant Dashboard* Home Assistant has now been successfully connected. ### Setup AdaFruit First, sign up to AdaFruit IO and create an account. In the Home dashboard, you will see a yellow button on the top left with a key symbol. Clicking on that will give you your username and key which is to be used when making the connection to the MQTT Client in MicroPython. After that, in the Home page, you will see a tab called Feeds. Navigate to the tab and create 2 new feeds. One feed called "Temperature" and another called "Humidity". When you go into each feed, a button on the side which says "Feed info" will be present. Click on the button and make a point of the endpoint which says "MQTT by key". These are the topics that you can send the data to in the code. Navigate over to the Dashboards and create one dashboard which will present the temperature and humidity. Go into the dashboard and click the settings cogwheel on the top right. Click add block and make a block of your choice for temperature and a block for humidity. An example of such a dashboard is shown in Figure 6. ![](https://i.imgur.com/I0FUgE8.png) *Figure 6. AdaFruit IO Temp and Humidity Dashboard* ### Setup IKEA Gateway IKEA have their configuration setup manual included in their products. To setup the IKEA gateway and the Trådlöst outlet, please refer to the video [here](https://www.youtube.com/watch?v=5yzhOy1THPg) from IKEA official as a guide. ### Connect IKEA Gateway to Home Assistant. Underneath your gateway, there will be a sticker that will have a security code on it. Keep a picture of the code for future use. On your Home Assistant dashboard, click on Settings on the left dash and then click on "Devices and Services". At the bottom right there will be a button which says "Add Integration". Click on that and search up IKEA. >IMPORTANT: Make sure that your IKEA gateway is connected to the same router and WiFi as your computer and your Home Assistant is or the Home Assistant will not be able to find your gateway. Input your security code when prompted and the search for your device will start. Once your gateway is found, all your devices in the gateway will be brought over to Home Assistant as entities. ### Setup Mosquitto Download mosquitto from their official page [here](https://mosquitto.org). After you have gone through the installation of mosquitto, go to the directory where you have mosquitto installed and open the ```mosquitto.conf``` file with any text editor of your choice. As shown in Figure 7 and 8 below, change the value of ```allow_anonymous``` to be ```True``` and the ```listener``` to be set to a port of your choice. ![](https://i.imgur.com/AU0HhsL.png) *Figure 7. Mosquitto Listener settings* ![](https://i.imgur.com/6Fba3PZ.png) *Figure 8. Allow external connections to broker* Once completed, save your mosquitto.conf file, open up command prompt and navigate to the directory where you downloaded mosquitto. Type in the command ```mosquitto --verbose -c mosquitto.conf``` and hit Enter. Your command prompt should look a little like Figure 9. ![](https://i.imgur.com/QYVWHz2.png) *Figure 9. Mosquitto connection successful* Mosquitto is now running and should be able to get your messages. If you want to test it out, use your browser and input your machines IP address and the port number you have mosquitto running on in the format ```http://IP_ADDRESS:PORT```, if you get a message similar to Figure 10, your mosquitto is configured correctly. ![](https://i.imgur.com/cVDKxf2.png) *Figure 10. Mosquitto connection testing* ### Network Architecture The connectivity architecture of the program is quite tough to perceive through the tutorial and with words. Figure 11 below explains the architecture of the whole project. ![](https://i.imgur.com/k6HFb6p.png) *Figure 11. Architecture of the device and communication* ## Pico WH and Sensors connection Figure 12 shows a detailed picture showing the connection of the Pico WH with the DHT11 Sensor and the Passive Piezo Buzzer. ![](https://i.imgur.com/dOGxpDC.png) *Figure 12. Connection of IoT Device* This layout can be changed to suit personal preferences. ## Code :::info The full code for the project can be viewed [**here**](https://github.com/Alacdoom97/temperature-controlled-fan) ::: For the program, the following libraries were used: ```python import time # Allows use of time.sleep() for delays from time import sleep # Allows use of time.sleep() for delays from lib.mqtt import MQTTClient # For use of MQTT protocol to talk to Adafruit IO import ubinascii # Conversions between binary data and various encodings import machine # Interfaces with hardware components from machine import Pin, PWM import random # Random number generator import dht import network from secrets import wifi_SSID, wifi_password ``` The DHT and MQTTClient library can be found in the code link above. These libraries are not self creations and are made by other developers. >Note: If the DHT Library does not work, there are various dht libraries online which can be copied. For connecting to WiFi and the MQTT brokers, the following code was used: ```python # These need to be change to suit your environment RANDOMS_INTERVAL = 20000 # milliseconds last_random_sent_ticks = 0 # milliseconds led = Pin("LED", Pin.OUT) # led pin initialization for Raspberry Pi Pico W tempSensor = dht.DHT11(Pin(27, Pin.IN)) buzzer = PWM(Pin(26)) # Adafruit IO (AIO) and Mosquito (MQ) configuration AIO_SERVER = "io.adafruit.com" MQ_SERVER = "MOSQUITTO_MACHINE_IP_ADDRESS" MQ_PORT = 3998 AIO_PORT = 1883 AIO_USER = "ADAFRUIT_USERNAME" AIO_KEY = "ADAFRUIT_KEY" AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id()) MQ_CLIENT_ID = ubinascii.hexlify(machine.unique_id()) # Can be anything MQ_BUZZER_TOPIC = "sensors/buzzer" AIO_RANDOMS_FEED = "pranav97/feeds/random" AIO_TEMP_FEED = "pranav97/feeds/temperature" AIO_HUMIDITY_FEED = "pranav97/feeds/humidity" MQ_TEMP_FEED = "sensors/temperature" MQ_HUMIDITY_FEED = "sensors/humidity" # Function to connect Pico to the WiFi def do_connect(): wlan = network.WLAN(network.STA_IF) # Put modem on Station mode if not wlan.isconnected(): # Check if already connected print('connecting to network...') wlan.active(True) # Activate network interface # set power mode to get WiFi power-saving off (if needed) wlan.config(pm = 0xa11140) wlan.connect(wifi_SSID, wifi_password) # Your WiFi Credential print('Waiting for connection...', end='') # Check if it is connected otherwise wait while not wlan.isconnected() and wlan.status() >= 0: print('.', end='') sleep(1) # Print the IP assigned by router ip = wlan.ifconfig()[0] print('\nConnected on {}'.format(ip)) return ip # Use the MQTT protocol to connect to Adafruit IO and Mosquitto MQclient = MQTTClient(AIO_CLIENT_ID, MQ_SERVER, MQ_PORT, keepalive=30) AIOclient = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY) led.off() # Subscribed messages will be delivered to this callback MQclient.connect() MQclient.set_callback(sub_cb) AIOclient.connect() MQclient.subscribe(MQ_BUZZER_TOPIC) print("Connected to %s, subscribed to %s topic" % (MQ_SERVER, MQ_BUZZER_TOPIC)) ``` The ```set_callback(sub_cb)``` function subscribes to a topic and gets all the incoming messages that arrive from the broker. This is useful for later when the automation scripts are made. The code for the ```sub_cb``` function are as shown below. ```python # Callback Function to respond to messages from Home Assistant 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 says "ON" but previous message says "OFF"... onNumber = random.randint(50,100) led.on() playsong(songStart) AIOclient.publish(topic=AIO_FAN_STATUS_FEED, msg=str(onNumber)) elif msg == b"OFF": # If message says "OFF" ... offNumber = random.randint(0,49) led.off() playsong(songStop) AIOclient.publish(topic=AIO_FAN_STATUS_FEED, msg=str(offNumber)) else: # If any other message is received ... print("Unknown message") # ... do nothing but output that it happened. ``` The playsong function is connected to the buzzer which plays a start tone and an end tone when the fan starts and stops. The code for it is shown below: ```python def playtone(frequency): buzzer.duty_u16(1000) buzzer.freq(frequency) def bequiet(): buzzer.duty_u16(0) def playsong(mysong): for i in range(len(mysong)): if (mysong[i] == "P"): bequiet() else: playtone(tones[mysong[i]]) time.sleep(0.3) bequiet() ``` The main running of the code is set in a while loop which runs continuously. The code first checks for any callback messages and then sends data over to the brokers. Once the loop is broken or interrupted, the brokers are disconnected from and the program stops running. ```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 MQclient.check_msg()# Action a message if one is received. Non-blocking. send_data() # Send a random number to Adafruit IO if it's time. finally: # If an exception is thrown ... MQclient.disconnect() AIOclient.disconnect() # ... disconnect the client and clean up. AIOclient = None MQclient = None print("Disconnected from Adafruit IO and Mosquitto.") ``` The send data code which is the main functionality is as below: ```python # Function to publish random number to Adafruit IO MQTT server at fixed interval def send_data(): global last_random_sent_ticks global RANDOMS_INTERVAL tempSensor.measure() temperature = tempSensor.temperature() humidity = tempSensor.humidity() if ((time.ticks_ms() - last_random_sent_ticks) < RANDOMS_INTERVAL): return; # Too soon since last one sent. some_number = random_integer(100) print("Publishing: {0} and {1} to {2} and {3} respectively ... ".format(temperature, humidity, MQ_TEMP_FEED, MQ_HUMIDITY_FEED), end='') try: AIOclient.publish(topic=AIO_TEMP_FEED, msg=str(temperature)) AIOclient.publish(topic=AIO_HUMIDITY_FEED, msg=str(humidity)) MQclient.publish(topic=MQ_TEMP_FEED, msg=str(temperature)) MQclient.publish(topic=MQ_HUMIDITY_FEED, msg=str(humidity)) time.sleep(2) print("DONE") except Exception as e: print("FAILED") finally: last_random_sent_ticks = time.ticks_ms() ``` ## Transmitting the data The data is sent over random intervals varying from 2 to 20 seconds. The reasoning for this was to see if there was a change between having normal interval times and having random timers. There was no significant change in the timing but since the random interval code was already in place, it was kept in the final code. The wireless protocol to connect the microcontroller was WiFi. This was easiest to get the data transmitted over to AdaFruit IO. LoRaWan was considered, however due to the lack of time and aspect of connectivity security, it is a thought for prospects. The transport protocol used for this project was MQTT. MQTT is lightweight and for small data sizes, it is efficient. It was setup to have two brokers which had different endpoints. The first broker is AdaFruit IO which was used for two reasons. The first reason was the ability to monitor the activity outside the house since I can use wireless data to access the webpage. The second reason is to make use of its Actions to send WebHook messages to my Discord server for notifications when I am outside. Initially the plan was to have the Home Assistant listen in to the topics of the AdaFruit IO broker but after a great deal of research, it was shown that Home Assistant has problems and compatability issues with brokers which are lacking certain QoS( Quality of Service) levels. For this reason, the microcontroller also connects to the local mosquitto broker on the machine. The temperature and humidity data from the DHT11 sensor is then sent over to the broker and Home Assistant will listen to the topics and pick up the data. ## Home Assistant MQTT setup The steps to setup MQTT receiving and publishing in Home Assistant are shown as below: #### Step 1 In Home Assistant, go to setting and click on "Devices and Services". In the bottom right, there will be a button saying "Add Integration" which you can click on. Search for MQTT and add the normal MQTT service. After adding it, you will see it appear on the services dashboard as seen in Figure 13. ![](https://i.imgur.com/EVXWLnL.png) *Figure 13. MQTT Service* #### Step 2 Clicking the MQTT setting button and in the intergration entries, configure the entry. Click on ```Re-Configure MQTT``` and then input the details of your mosquitto broker. In the broker aspect, you input the local machine IP address and and the port which you have chosen in the port field. The username and password can be kept blank as there is no user created for the local mosquitto broker. #### Step 3 At the bottom of the MQTT settings, you can listen to a topic and have it print the packet data. This is useful to test the connection to the broker and check if the packet is coming in the correct format. This is shown in Figure 14. ![](https://i.imgur.com/zHMk2u7.png) *Figure 14. MQTT Listen to topic* ## Automation triggering ### Home Assistant #### Step 1 First, download the Visual Studio Code extension by going to Settings, clicking on Add-ons and opening the Add-on Store using the button at the bottom right. In the Add-on store, search for ```Visual Studio Code``` and download the extension which is shown in Figure 15. ![](https://i.imgur.com/uyeRkCb.png) *Figure 15. Visual Studio Code add-on for Home Assistant* If you do not see Studio Code Server on the dash to the left, Try refreshing the Home Assistant web page to restart Visual Studio Code. #### Step 2 Click on Studio Code Server to open it and navigate over to the ```configuration.yaml``` file. In there paste in the following code: ``` mqtt: sensor: - state_topic: "YOUR_TOPIC_NAME" ``` then save the file. The file should look like the example in Figure 16. ![](https://i.imgur.com/CC0kCw9.png) *Figure 16. configuration.yaml file* If done correctly, a new entity should be available to use. Navigate to the Devices and Services tab and at the top, click on the entities button. Scroll down until you find an entity that has the entity ID ```sensor.mqtt_sensor```. An example of it is shown in Figure 17. ![](https://i.imgur.com/RioLjQr.png) *Figure 17. MQTT Sensor entity* #### Step 3 Click on Settings and then navigate to Automations and Scenes. There we want to create a new automation from scratch. Click the button on the bottom right to create a new automation and then an automation screen as shown in Figure 18 will appear. ![](https://i.imgur.com/G6IGDXf.png) *Figure 18. New Automation Screen* Triggers: In this section a trigger whose purpose is to activate the automation. This trigger happens when an MQTT message is recieved. Conditions: When selecting a condition, the automation will stop and check that the condition is fulfilled before continuing with the script. This stops the fan from turning on and off on every message received. The condition compares the value of an entity to a fixed value. It is for this reason that we turn the MQTT sensor into an entity. The condition can compare the entity value with a fixed value which is what the final automation will do. Actions: When the trigger and conditions are met, the program will initiate the action. This is usually to change the state of a device, play mediaor call services etc... For our script, the IKEA smart outlet's state will be changed on action. Figures 19, 20 and 21 show the Trigger, Condition and Action to turn on the Fan ![](https://i.imgur.com/t40Wpql.png) *Figure 19. Automation Trigger MQTT message receive* ![](https://i.imgur.com/Yct6Cih.png) *Figure 20. Automation Condition Temperature* ![](https://i.imgur.com/kTHHHXS.png) *Figure 21. Automation Action Fan On* Following the same procedure, an automation was created to turn off the fan which is shown in Figure 22. ![](https://i.imgur.com/4w4zZGf.png) *Figure 22. Automation to turn off fan* Another two automations were created which published messages back to the broker. These scripts are shown in Figures 23 and 24. ![](https://i.imgur.com/y5pt4du.png) *Figure 23. Fan Buzzer Start Sound Automation* ![](https://i.imgur.com/mLJo0np.png) *Figure 24. Fan Buzzer Stop Sound Automation* These automations will relay back to the broker. The microcontroller subscribes to the topic and with the callback function, it activates the passive piezo buzzer to notify the users in the room. ### Adafruit In AdaFruit, two automation triggers were created using Webhooks. In the AdaFruit IO, we navigate over to Actions and create a new Action. Here there are two actions which are created, these actions are: 1. If the value of Fan Status returns a value greater than or equal to 50, send a webhook message to my discord channel notifying that my fan has turned itself on. 2. If the value of Fan Status returns a value less than 50, send a webhook message to my discord channel notifying that the fan has turned itself off. Figure 25 shows the two actions. Figure 26 showcases the Discord messages which arrived notifying the status of the fan. ![](https://i.imgur.com/agNdGwk.png) *Figure 25. AdaFruit IO Actions* ![](https://i.imgur.com/cWRknKd.png) *Figure 26. Discord Notifications* The webhooks notification are created to monitor the activity of the fan while outside the house. ## Final Results I am pleased with the outcome of this project. It has been a learning experience in the realms of IoT, connections and data handling. ![](https://i.imgur.com/9xN1wLd.jpg) ![](https://i.imgur.com/KiewNnG.jpg) While the build of the device is simple and I would have preferred enclosing the breadboard and the microcontroller in a box and leaving a slit open for the DHT11 sensor and piezo buzzer to stay outside, I am pleased with the results that the device works and fulfills its core objective from my testing. ![](https://i.imgur.com/OOtSa4M.png) My testing showed the Piezo buzzer worked as intended with the code and the automation scripts. ##### Final Reflections While creating the project, I have found areas which can be improved upon even though my goal was successfully reached. These improvements are: * Cable Management * Monitor and optimize the power consumption * Add LCD Display to show temperature and humidity in room * Add voice capabilities by connecting a microphone to the device. * Change from webhook message going to discord into JSON message sending to Whatsapp number. My initial idea for this project was to try and create a humidity sensor which can be inserted into the soil to check for the humidity and send a notification if the soil is too dry. As it was summertime when I was working on this project, the need for the automated fan overrode the initial project idea. Another idea I had considered was to incorporate a microphone device which listened to sounds. The device would have a machine learning model which analyzes the sounds and compares to a database of random sounds. The workload was more intensive but the potential is there for so much more. This is a project that I look forward to developing. Overall I am satisfied with the project and it has been a learning experience that has been fun and engaging for me, other students and teachers.