---
# System prepended metadata

title: Environmental Monitoring and Fan Automation Project

---

Made by: Fredrik Fischer ff222nv - July 2023 

# Overview
**Short project overview**
This project is made to monitor indoor environmental conditions in real-time as well as to control the operation of a fan. Depending of the temperature and the chosen threshold value given by the user, the fan will automaticaly switch on or off. The system uses temperature and humidity sensors, which data is sent to a feed which displays the statistical data. The user can via an interface change the threshold value to decide the desired threshold temperature.

**Why I chose this project?**
I live in an older appartment building which has no modern ventilation system. As the weather turns warmer in the summer, there can be a problem with a lack of air flow in the appartment.

**What purpose does the project it serve?**
The project serves the purpose of monitoring as well as improving the indoor climate, by increasing airflow while the temperature in the appartment is uncomfortably high. This will hopefully create a better overview of the indoor climate as well as improved living conditions for the user of the system.

**How much time it might take to do?**
Depending on your previous experience, this project will approximatly take 2-5 hours.

**What insights you think it will give?**
This system will give the user a better understanding of the indoor climate. 

# **Material**
All IoT-products (microcontroller, sensor, wires etc.) came in the "LNU – 1DT305 Standard Kit (2023)" available at Electrokit.com. The whole kit was in total 399 sek. 

| Product  | Specifications | Price   |   Supplier  |
| -------- | -------- | -------- | --------
|1x Raspberry Pi Pico WH     | Microcontroller     | 109 sek     |    Electrokit |
|1x USB cable, A male – micro B 5p male.      | USB cable     | 39 sek     |    Electrokit |
|1x DHT11     | Temperature & Humidity Sensor    |   49 sek   |    Electrokit |
|1x Breadboard     |  420 dots     |  49 sek   |    Electrokit |
|6x Wire male-female     |  30 cm     |  ~7 sek  |    Electrokit |
|3x Wire male-male     |  30 cm     |  ~7 sek  |    Electrokit |
|1x USB-fan      |  14cm, 5 volt     |  99 sek  |    Clas Ohlson |
|1x 5V Dual-Channel Relay Module     |  To switch electricity to the fan on/off. For this project you only *need* a single channel module      |  ~50 sek   | Second hand, but similar can be found new at Electrokit |
|1x Plastic box     |  Food delivery box     |  ~5 sek   |    Some Thai Restaurant |
|Tape     |  Tape     |  ~1 sek   |    Any store that has tape |
|   |       |  **Total**    |     |
|   |       |  ~ 415 sek    |     |

# Computer setup
## Setting up the pico
Micropython is used as the programming language. To flash the hardware:

1 Press and hold the BOOTSEL button on your Raspberry Pi Pico and insert the USB into your computer.

2 Download the [UF2 firmware](https://micropython.org/download/rp2-pico-w/rp2-pico-w-latest.uf2)  and copy or cut the file onto the picos storage space

## IDE
The chosen IDE is Thonny which I installed from the flatpak package manager (in Linux).

To make Thonny recognise the pico, go to `Run > "Configure interpreter..."`. Choose the options as the image shows. ![](https://hackmd.io/_uploads/Byk6eO2uh.png). 
## Problems finding the port?
At first i could not find the Pico which was available at the `/dev/tty/ACM0 port`. If you have the same problem try following these steps:

1. Run `ls /dev/tty*` to see if it appears.
2. Run `lsmod | grep cdc_acm` to see if drivers are available and `sudo modprobe cdc_acm` to install them if needed.
3. Run `sudo usermod -a -G dialout <your_username>` to get the right permissions
4. Restart your computer and the Pico (unplug and plug in the Picos USB port )

Now it should work and should look something like the image below. The purple arrows `>>>` indicates success. A tip is to enable `Views > Files` to view your files. Try if it works by entering `Print("hello world")` after the arrows and press F5 (Run)

**Tip:**  The pico has an internal programmable led light. The port reference to the internal LED is **Not** "25", but "LED". This caused me some trouble in the beginning.

![](https://hackmd.io/_uploads/HJrKVOnd3.png)




To install any needed packages in Thonny, go to `Tools > Manage Packages`.


![](https://hackmd.io/_uploads/HJb57_h_3.png)

# Putting everything together

## Circuit diagram 

![](https://hackmd.io/_uploads/ByUInV2uh.png)
**IMPORTANT**: This is a overview model. The colors of the wires does not represent the colors of the wires in the accual project

Since the Pico is powered by 5 Volt, the VBUS port will output 5 Volts. This is perfect since this means that we wont need an external power supply to power the fan. However, the VBUS port cannot be switched on or off from within the pico itself. We therefor need to use a relay. By connecting the pico to the relay, the fan can safely and easily be switched on or off. 

You need to attach the wires to the usb port. To do this, you might want to buy a dedicated adaptor. I however, used some good old tape to attach the wires. Looking at the the USB port with the "fat side" facing down and "open side" facing up, you will see 4 pins. The GND is furthest to the left (Pin 1) and and the VCC is furthest to the right (Pin 4).   

Everything else is quite straight forward. Follow the instructions of the circut diagram. Just make sure that you connect the wires with the pico unplugged.

## Platform
Since this was my first project, I wanted the platform to be as simple as possible. I wanted to start with a cloud based alternative. At first I tried Datacake, but I failed to make it work correctly. Also, I later found that using MQTT was a paid alternative. I later found a tutorial from LNU, made by @ryantal, on how to set up Adafruit which can be found [here](https://hackmd.io/@lnu-iot/r1yEtcs55). It was helpful so I decided to go with that alternative! :)

Adafruit is a website/platform that has a wide range of features for IoT enthusiasts. It is a cloud based service that is free of charge for basic features, but paid alternatives for extended features exist as well. I will more specificaly use Adafruit IO, which is a platform for managing data feeds, communication between devices, dashboards, visualisation, automatisation and more. The Adafruit free version supports both MQTT and REST APIs. With Adafruit I will via my pico send data via MQTT that gets stored in a feed. I am via Adafruit able to, via a dashboard, modify values in feeds. My pico will fetch data from an Adafruit feed API.

In the future, I would like to try to make a project that is fully self hosted, since I think that is how technology really should be used.

## Package everything
When everything is connected, you can procees to put it in the plastic box. You will need to make a hole in the box and allow the wires to run through it. **Remember:** DHT11 sensor will need to be **outside** the box.


# Code

I will not show all of the code, but the basic functionallity. Some comments and print statements been removed for simplicities sake. 

1. Import all the nessesary packages like "network", "time", "dht", "umqtt.robust" or "umqtt.robust" or "mqtt.simple" etc.
2. Define variables like "ssid", "password", "adafruit_mqtt_port" etc. 
3. Define the functions: 

``` = python
def connect_wifi():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)
    while not wlan.isconnected():
        time.sleep(1)

def send_adafruit_mqtt_data(feed_name, value):
    client = mqtt.MQTTClient("pico", adafruit_mqtt_host, port=adafruit_mqtt_port,
                            user=adafruit_username, password=adafruit_key, ssl=False)
    client.connect()
    topic = "{}/feeds/{}/json".format(adafruit_username, feed_name)
    payload = ujson.dumps({"value": value})
    client.publish(topic, payload)
    client.disconnect()
       
def get_temperature_threshold():
    api_url = temperature_threshold_api_url
    headers = {"X-AIO-Key": adafruit_key}
    response = urequests.get(api_url, headers=headers)
    data = ujson.loads(response.text)
    return int(data["last_value"])
```

3. The main code of the program. 
``` =python
try:
    connect_wifi() #function to connect to wifi
except KeyboardInterrupt:
    machine.reset() # If device cannot connect to wifi, it will reset

relay_pin = Pin(16, Pin.OUT) # Relay that controls the fan
sensor = dht.DHT11(Pin(15))  # Temperature & Humidity sensor

# The loop will iterate forever
while True: 
    sensor.measure()
    temp = sensor.temperature()
    humidity = sensor.humidity()
    temperature_threshold_value = get_temperature_threshold()
    
    # Control relay based on Adafruit value
    if temperature_threshold_value < temp:
        relay_pin.value(0)  # Switch on the relay
    else:
        relay_pin.value(1)  # Switch off the relay
    
    send_adafruit_mqtt_data("humidity-feed", humidity)
    send_adafruit_mqtt_data("temperature-feed", temp)

    time.sleep(10)  # Delay for 10 second before the next iteration
```

## Transmitting the data / connectivity

The data is sent and recieved every 10 seconds. 

The data collected from the sensors are sent with MQTT. MQTT is good since it is lightweight protocol often used with IoT devices. I had one problem though with recieving data with MQTT. I worked, but it could only recieve data when activly sending data from Adafruit to my device. When the program ran the line "client.wait_msg()" (wait for the mqtt message), it made it impossible to simultaneously publish data to adafruit (without any async programming). I knew it could be done with asyncronous methods, but I never got it to function correctly. I instead chose to use API calls. It will use more energy, but it's fine since the device will not be powered by any portable powersupply (e.g a battery). It will be used at home with a stable power supply.

I will use WIFi for this project since the device will be used indoors in my own appartment. Since the Pico can access the WIFI from anywhere within the appartment, I'm not in need of any LoRa technology.  



# Presenting the data

The temperature and humidity data is send via MQTT to two different feeds in Adafruit. When the Adafruit feed recieves the data from the pico (which happens every 10 seconds), it is saved in a database and displayed in a the feed.  The feeds are then connected to the dashboard. 

The temperature threshold decides the threshold value of which the fan should turn on or off. I the temperature is higher than 23 degrees celsius, the fan will spin. If it is 23 degrees or lower, the fan will turn off. When the slide is modified, the data will be saved in the "temperature-threshold" feed. The previously showed `get_temperature_threshold():` method will get the most resent data of which position the slide currently has.

In the free version of Adafruit IO the data in the feeds are stored for 30 days. After 30 days, the data is removed.

## Dashboard
![](https://hackmd.io/_uploads/HJEz3K3d3.png)
The Adafruit dashboard

## Feed
![](https://hackmd.io/_uploads/SyEB0YnO2.png)
A example from the "temperature-feed"

# The final project

Here is the final product

![](https://hackmd.io/_uploads/Byt7vc2u3.jpg)

Video of the project can be found [here](https://youtube.com/shorts/y1yx4rJ7RJA?feature=share )

I am happy with the final product, however some thing could be improved for the next project.

1. Both send and recieve data with mqtt. To make this work, I'll have to learn to use async programming
2. Although I'm quite happy with Adafruit IO, I think a self hosted alternative is better, more free as well as more rewarding. For my next project, I would like to take that route!
3. Better connectivity: Although tape works to connect the usb, a better solution would be a dedicated adapter.
4. More fans, with more power: Since i have a two relays, I do have the opportunity to connect more fans (or other devices). I could also connect fans more powerful than 5 Volt to improve air flow. 
5. Improved casing: Although the plastic box works fine, it will not win any design competition. It would be fun to try to make a 3D printed box in the future :)




