---
# System prepended metadata

title: Temperature and humidity sensor using an ESP32-WROOM-32 and Adafruit IO

---

# Temperature and humidity sensor using an ESP32-WROOM-32 and Adafruit IO
[TOC]

## Overview
* Name: **Jimmy Atterstig**
* Student ID: **ja225hx**
* Operating system: **Linux Mint 20.2 Cinnamon**
* Approximate time: **2 hours**
* Approximate cost: **300 kr, or roughly $29 at the time of writing**


This project shows how to build a basic system for monitoring temperature and humidity in an area, whether that be for your home or for a greenhouse. Using the MQTT protocol we send the information onto an Adafruit IO dashboard to visualize the data. A time estimation is hard, and depends heavily on your previous knowledge. As I have previous experience in electronics and wiring, the building of the project with wiring and connecting sensors took maybe 10 minutes to get working. All in all, I would estimate the project to take roughly 2 hours with previous knowledge, if you don't run into any problems. This project was done for the summer course at Linnaeus University *1DT305*, or, *Introduction to Applied Internet of Things*.




## Objective

I chose this project for two main reasons, the first being time. I already have quite a lot of experience in electronics and sensoring systems, but no experience at all with IoT. Thus: my objective was to learn about connecting the devices and transferring the data to the web without use of a cable transfer. This led to me choosing a quite simple system consisting of just one sensor - so that I could get on to the part I cared about.

The second reason being that I have asthma, and have long wondered how much the humidity in my room is affecting my ability to get proper sleep. Thus I would like to see if I could find a connection between the humidity and my asthmatic symptoms at night. This will be a long project though, since I need to look at it over a longer period of time to be able to draw any sort of conclusion.




## Material


|                                                     Component                                                      | Price (SEK)  |
|:------------------------------------------------------------------------------------------------------------------:|:------------:|
|                                 [ESP32-WROOM-32](https://sizable.se/P.CE9S1/ESP32)                                 |    94 kr     |
|           [DHT11](https://www.electrokit.com/en/product/digital-temperature-and-humidity-sensor-dht11/)            |    49 kr     |
|            [Micro USB cable](https://www.electrokit.com/en/product/usb-kabel-a-hane-micro-b-hane-15cm/)            |    19 kr     |
|   [Jumper wires male to male](https://www.electrokit.com/en/product/jumper-wires-1-pin-male-male-150mm-10-pack/)   |     29kr     |
| [Breadboard](https://www.mouser.se/ProductDetail/BusBoard-Prototype-Systems/BB830?qs=VEfmQw3KOauhPeTwYxNCaA%3D%3D) | 30kr - 100kr |

Note that most of these items can be bought anywhere, and their specifications don't really matter. The linked breadboard for example - I prefer having a robust breadboard that I know will hold up for a very long time, which is why I used the BB830 (BusBoard), since they are known for being high-quality. But really, any breadboard works. 

The ESP32 and DHT11 can both have specifications that matter however. The DHT11 linked is one which has a built-in resistor, omitting the need for a resistor when wiring the sensor to the controller. It doesn't really matter if the sensor has this resistor or not, as long as you pay attention. The ESP32 seem to come in a variety of different specifications and models. There are a lot of different pinouts and data sheets available online so it might be a hassle finding the right one. 

#### ESP32
The ESP32 is a low-cost, low-power microcontroller that has integrated wifi and blueooth capabilities.
#### DHT11
The DHT11 is a very basic (and cheap) temperature and humidity sensor, with a relatively bad accuracy (± 2 degrees celsius).
#### Micro USB cable
Simply used to connect the ESP32 to a computer to upload code and power the controller.
#### Jumper wires
Basic wires for connecting the sensor to the controller on a breadboard.
#### Breadboard
A board which is designed for electrical applications, where you can easily connect different components together.



## Computer setup

Since I'm using Linux Mint, which is a distro based on Ubuntu, I could follow the Ubuntu installations, and this should work for any OS based on Ubuntu. 

### IDE

Atom was the recommended IDE, and so I chose to use it. We begin by updating our system, by updating installed packages. We also install *npm*, which is a package manager for javascript, which we will need later for *Node.js*.

```
    sudo apt -y update
    sudo apt -y upgrade
    sudo apt install -y npm
```
We then download the *.deb* file from [atom.io](https://atom.io) and run it using any software manager. We then need to install the *pymakr* plugin to *Atom*, which needs *Node.js* installed. For me, this was simply done by running 
```
    sudo apt install -y nodejs
```
but there might be some more prerequisites that I'm unaware of, since I already have quite a lot of development tools and packages installed. Then we open *Atom* and find the package manager under *settings*. Search for *pymakr* and install it! 

### Flashing the microcontroller

We then need to flash the ESP32, which is done by following the [tutorial](https://hackmd.io/@lnu-iot/SyZ2diUOq#Linux-OS-(Ubuntu-22.04)) given by TA's in the course. 

We start off by running some commands to remove access conflict. *Brltty* is a process which provides access for blind people, using a braille display, so we don't need it.

```
    sudo systemctl stop brltty-udev.service
    sudo systemctl mask brltty-udev.service
    sudo systemctl stop brltty.service
    sudo systemctl disable brltty.service
```

We then need to connect the ESP32 to our computer via cable. After this, we run the following command to check if it connected properly.

```
    sudo dmesg | grep ttyUSB0
```

We then need to download [this file](https://micropython.org/resources/firmware/esp32-20220117-v1.18.bin), which is a bin we need to flash the ESP32. We also need to modify port permissions, so that we can properly write to the board. ***NOTE:*** you **need** to run these commands every time you reconnect the ESP32 to your computer. 

```
    ls -l /dev/ttyUSB0
    sudo usermod -a -G dialout [Your username]
    sudo chmod a+rw /dev/ttyUSB0
    ls -l /dev/ttyUSB0
```
The first and last command simply checks if it worked, so they are not 100% necessary, but good to use. Then we need to open the [ESP web-flasher](https://nabucasa.github.io/esp-web-flasher/). Make sure your board is connected, and on some boards you also need to keep the *boot* button on the ESP during the entire flashing process, so I recommend that you do if you're unsure. 

Make sure the device is connected, and connect it on the website. Choose the right port (ttyUSB0 if instructions above followed). Then press erase to delete all files from the board. Then you enter an offset of *1000*, and choose the *bin* file downloaded earlier in the process, and press *program*.

The flash is now complete! All that is left to do is to connect the board in *Atom*. Open *Atom*, and then at the bottom open the *pymakr* plugin. Choose *global settings*, and remove the check box from safe-boot. Then enter the device port that you chose into the device address field. This should be ttyUSB0 if following along. Then click on connect device in *pymakr* and choose the device address. 


## Putting everything together
The following figure shows the basic circuit connection. Note that there are four pins on the DHT11, where I only use three. This is because the third pin is not connected to anything. I use a DHT11 breakout board that only has 3 pins, and a built-in resistor, but I could not finding a fritzing part for it. This is also not the exact model of ESP32 board I use, but it is close enough.
![](https://i.imgur.com/152U69i.jpg)

The red line is connected from the first pin on the DHT11 to *VIN* on the ESP32, to power the sensor. The white line is what sends the sensor data to the controller, and is connected from the second pin on the DHT11 to GPIO14 on the microcontroller, which seems to have different positioning depending on board. Here it's called D14. The black wire connects the fourth pin on the DHT11 to the *GND* on the controller. Not really necessary to use breadboards for this, but I like it because it makes it more controlled. 

Important here is to check that you don't power your microcontroller which too high a voltage, since this is what is sent out through the *VIN* pin back to the sensor, which could damage the sensor. If you're unsure, the *3V3* should also work, since the DHT11 can run on 3-5 volts. 


## Platform

For platform I chose to use the Adafruit IO. It's a relatively straight-forward and user friendly platform. We use the MQTT protocol to send data over the web to the Adafruit database, which then stores it. From there it is quite easy to visualize the data in different ways, in different graphs and formats. One thing that disturbed me was that there did not seem to be any way to remove singular data points, as I had one where I accidentally sent the wrong data which I would have liked to remove. You can also only choose between specific time periods to showcase in the dashboard, even though you can filter it with complete control if you just look at the feed of data.

Adafruit IO is a cloud-based platform, which can be both free and paid. The free version can do everything the paid can, it just has some limitations. The data doesn't get stored for quite as long, and the amount of data points you can send per minute are more limited. There is also a limit to the amount of feeds and dashboards you can create, but that is not a problem for a project such as this.

I would have liked to use a TIG-stack, to have more control and use (in my opinion) a better looking dashboard and graphs, but I didn't have the time. I took on quite a lot of summer courses, where I planned to be able to start in time with this one, but alas, there was the problem with hardware acquisition. So - this is what I had time to do.

## The code

Much of the code used is taken from the courses [github repository](https://github.com/iot-lnu/applied-iot) which goes under the GNU GPL-3 license, and thus free to use. Most of the code is not taken straight from there though, and instead from different tutorials provided to us.

All code I'm using can be seen at [this github repo](https://github.com/hundgog/IoTSummerCourse).

For starters, to connect to the wifi, I followed the [wifi tutorial](https://hackmd.io/@lnu-iot/SJ8TGsUd5). Not much to say about this, except to remember to change both the SSID and password for your wifi. I put this code into *boot.py*, to ensure that it runs every time you reset the board.

Then we need libraries. One for the DHT11 and one "library" for the [MQTT code](https://hackmd.io/@lnu-iot/ByPRkQTF9), again, gotten from tutorials. The DHT11 library is entirely gotten from the course github.

And then all that is left is a main script to control the system and send the data. 

```*.py
def send_data():
    global last_random_sent_ticks
    global RANDOMS_INTERVAL

    if ((time.ticks_ms() - last_random_sent_ticks) < RANDOMS_INTERVAL):
        return; # Too soon since last one sent.

    print("Publishing: {0} to {1} ... ".format(temp, AIO_TEMPERATURE_FEED), end='')
    print("Publishing: {0} to {1} ... ".format(hum, AIO_HUMIDITY_FEED), end='')
    try:
        client.publish(topic=AIO_TEMPERATURE_FEED, msg=str(temp))
        client.publish(topic=AIO_HUMIDITY_FEED, msg=str(hum))
        print("DONE")
    except Exception as e:
        print("FAILED")
    finally:
        last_random_sent_ticks = time.ticks_ms()
```

This above code handles the actual sending of the data to the Adafruit IO, and is one of the most important parts of the code. It publishes the data through the MQTT if possible, and prints to console to see status. The most important part of the code however, comes below. It handes the actual sensor measurements, where *sensor* is the pin allocated to the sensor, and as said earlier, is set to GPIO14. This measures both temperature and humidity, and then calls on the above function to send the data to the broker.

```*.py
    while 1:
        sleep(2)
        sensor.measure()
        temp = sensor.temperature()
        hum = sensor.humidity()
        print('Temperature: %3.1f C' %temp)
        print('Humidity: %3.1f %%' %hum)           # Repeat this loop forever
        client.check_msg()# Action a message if one is received. Non-blocking.
        send_data()  
```


## Transmitting the data / connectivity

The data is sent every 10 seconds, meaning we send 12 data points every minute (since we are sending two different things). This falls below the 30 points per minute that a free user can use. 

The wireless protocol used here is simple WiFi. This is both because this project was made for indoors-use, which is guaranteed to have WiFi, and because there are no LoRa access points near me. I did not check this early enough to get equipment to set up one myself, as stable as I would have liked, anyway. 

The data is transmitted using the MQTT protocol, which is an extremely lightweight protocol designed for situations with limited bandwitdh or resource constraints. 



## Presenting the data

![](https://i.imgur.com/qT7IjID.png)

This shows how the dashboard looks, a bit zoomed in, showing time graphs for both the temperature and the humidity values. This shows the values over a period of what Adafruit IO calls "2 days", but seems to be 29 hours? Data was recorded continously for 3 days straight. The first data point seen in the graph is from June 27th. I definitely had more than 29 hours of data in a row stored in the feeds, so I'm not quite sure why this would be the result. The next option was 7 days, which included a nasty spike from the start when I sent one data point that was extremely wrong (roughly a value of 80 on temp scale), so I wasn't too fond of using that.

The data is stored in the Adafruit IO feeds for 30 days before being removed.

I also experimented some with a webhook to send information/alerts to my Discord. I set it up but didn't see much use for it so I later removed it.



## Finalizing the design

All in all, the project went good. I wish that I had more time so I could have played around with other options, especially for the data presentation and handling, since I wasn't too fond of Adafruit IO, even though it was easy to use. I would have wanted to experiment with setting up a self-hosted solution for visualizing the data, such as a TIG-stack or Node-red. Maybe try an entirely local setup with the help of other microcontrollers, maybe a Raspberry Pi.

I also could have chosen a more intricate project in terms of sensors, or, even some actuating function. I was pondering making some sort of door opener with relays, and maybe RFID tagging where it connects to a server to check if the specific RFID tag is allowed in. But - I had no time to ponder as I needed to order the parts. 

I also wanted to 3D print a case for the ESP32. I also should have probably added some sort of battery, to make it more wireless, because what's the point of have wireless uploading if you still need it plugged in for the power?

Another fun thing to do could be to use more accurate sensors - maybe the DHT22, or something even more accurate to see how mismatched the DHT11 actually is.


Here follows a picture of the finalized project on the board!

<img src="https://i.imgur.com/niXFfFA.jpghttps://i.imgur.com/niXFfFA.jpg" width="500" height="500" />

*Note that I am using two BB830 breadboards connected together, this is not necessary at all. 