---
# System prepended metadata

title: Tutorial on how to Build a Temperature and Humidity Sensor

---

# Tutorial on how to Build a Temperature and Humidity Sensor


### Author: 
Hao Chen, hc222ig

## Overview
This project involves building an IoT device using a Raspberry Pi Pico to measure and report temperature and humidity data. The data is collected using a DHT11 sensor and sent to the Datacake platform for visualization. The device is programmed in MicroPython and connected to the internet via Wi-Fi.

Time to complete: Approximately 5-6 hours

## Objective
I chose this project to gain hands-on experience with IoT development, specifically focusing on environmental monitoring. The project provides practical insights into sensor integration, data transmission, and cloud-based data visualization.

The device serves as a simple environmental monitoring system that can be used in various applications, such as home automation, greenhouse monitoring, or office environment tracking.

This project will provide insights into real-time data collection and analysis, the process of connecting devices to the cloud, and how to visualize data for better understanding and decision-making.

## Material

The following list of used material was purchased within the Start Kit - Applied IoT at Linnaeus University (2024) from electro:kit for 399kr.



| Item                                     | Image                                                                                                       |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Raspberry Pi Pico WH                     | <img src="https://www.electrokit.com/cache/ba/999x999-product_41019_41019114_PICO-WH-HERO.jpg" width="100"> |
| DHT11 Temperature and Humidity sensor                                         | <img src="https://www.electrokit.com/upload/product/41015/41015728/41015728.jpg" width="100">                                                                                                             |
| Breadboard with 840 connections          | <img src="https://www.electrokit.com/upload/product/10160/10160840/10160840.jpg" width="100">               |
| USB cable A male - micro B 5p male 1.8m  | <img src="https://www.electrokit.com/upload/quick/36/bf/5f05_41022181.jpg" width="100">                     |
| Jumper wires (male/male and female/male) | <img src="https://www.electrokit.com/cache/24/700x700-product_41012_41012684_41012684.jpg" width="100">     |


## Computer Setup/Chosen IDE
Visual Studio Code with the Pymakr plugin.

Steps for Setup:
1. **Install VS Code:** Download and install from the [VS Code website](https://code.visualstudio.com/).
2. **Install Pymakr Plugin:** Go to Extensions in VS Code, search for Pymakr, and install it.
3. **Install Additional Software:** Install Node.js from [Node.js website](https://nodejs.org/en).
4. **Update the RPi Pico Firmware:** Download the MicroPython firmware from [here](https://micropython.org/download/RPI_PICO_W/). Download the latest **.uf2** file from the Releases category.
5. **Connect the RPi Pico:**
*  Connect the micro-USB end of your cable into the Raspberry Pi Pico.
* Hold the BOOTSEL button down on the board.
* Connect the USB type A end of your cable into your computer's USB port.
* Release the BOOTSEL button after connecting it to your computer.
6. **Copy Firmware:**

* A new drive named RPI-RP2 will appear in your file system.
* Copy the downloaded .uf2 file to this drive.
* Wait until the board automatically disconnects from your computer.
7. **Reconnect the Board:** Unplug and plug back the USB cable to confirm the board is ready.


## Putting Everything Together

**Electrical Connections**
Follow the wiring diagram below to connect the DHT11 sensor to the Raspberry Pi Pico:
![DHT11_bb](https://hackmd.io/_uploads/SJcmuqMPR.jpg)


**DHT11 Sensor**
* VCC to Pico 3.3V (red wire)
* GND to Pico GND (black wire)
* Data to Pico GPIO27 (yellow/blue wire, with a pull-up resistor if necessary)

Ensure all connections are secure and double-check the pin mappings to avoid any damage to the components.

**Electrical Calculations**
Ensure that the power supply (5V via USB) is sufficient for all connected components. Calculate the total current draw to avoid overloading the Pico's power supply.

## Platform
**Chosen Platform**
Datacake: A cloud-based platform for IoT data visualization.

**Functionality:** Datacake offers easy setup for IoT devices, real-time data visualization, and configurable dashboards.
**Why Chosen:** It provides a free tier for the first five created devices suitable for small projects, easy integration, and robust features for data analysis.

## The Code
**Project Structure**
The project is organized with the following files and folders:
![Skärmavbild 2024-07-01 kl. 14.19.04](https://hackmd.io/_uploads/HJgD_cGDC.jpg)

Root:
* boot.py
* main.py
* pymakr.conf
* .gitignore

lib/ folder
* datacake_keys.py
* dht.py
* keys.py
* wifiConnection.py

**lib/datacake_keys.py**
This file contains the Datacake API URL and token:
```
# datacake_keys.py
API_URL = 'https://api.datacake.co/v1/devices/YOUR_DEVICE_ID/data'
API_KEY = 'YOUR_API_KEY'
```
**lib/dht.py**
This file contains the DHT11/DHT22 driver code:
```
# DHT11/DHT22 driver for MicroPython on ESP8266
# MIT license; Copyright (c) 2016 Damien P. George

import sys
import machine

if hasattr(machine, "dht_readinto"):
    from machine import dht_readinto
elif sys.platform.startswith("esp"):
    from esp import dht_readinto
elif sys.platform == "pyboard":
    from pyb import dht_readinto
else:
    dht_readinto = __import__(sys.platform).dht_readinto

del machine

class DHTBase:
    def __init__(self, pin):
        self.pin = pin
        self.buf = bytearray(5)

    def measure(self):
        buf = self.buf
        dht_readinto(self.pin, buf)
        if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]:
            raise Exception("checksum error")

class DHT11(DHTBase):
    def humidity(self):
        return self.buf[0]

    def temperature(self):
        return self.buf[2]

class DHT22(DHTBase):
    def humidity(self):
        return (self.buf[0] << 8 | self.buf[1]) * 0.1

    def temperature(self):
        t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1
        if self.buf[2] & 0x80:
            t = -t
        return t
```

**lib/keys.py**
This file contains the Wi-Fi credentials:
```
# keys.py
WIFI_SSID = 'your_wifi_ssid'
WIFI_PASS = 'your_wifi_password'
```

**lib/wifiConnection.py**
This file contains the Wi-Fi connection code:
```
# wifiConnection.py
import keys
import network
from time import sleep

def 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(keys.WIFI_SSID, keys.WIFI_PASS)  # 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

def disconnect():
    wlan = network.WLAN(network.STA_IF)         # Put modem on Station mode
    wlan.disconnect()
    wlan = None
```

**boot.py**
This file initializes the Wi-Fi connection and performs an HTTP GET request to test the connection:
```
# boot.py
import lib.wifiConnection as wifiConnection

def http_get(url = 'http://detectportal.firefox.com/'):
    import socket                           # Used by HTML get request
    import time                             # Used for delay
    _, _, host, path = url.split('/', 3)    # Separate URL request
    addr = socket.getaddrinfo(host, 80)[0][-1]  # Get IP address of host
    s = socket.socket()                     # Initialise the socket
    s.connect(addr)                         # Try connecting to host address
    # Send HTTP request to the host with specific path
    s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))    
    time.sleep(1)                           # Sleep for a second
    rec_bytes = s.recv(10000)               # Receive response
    print(rec_bytes)                        # Print the response
    s.close()                               # Close connection

# WiFi Connection
try:
    ip = wifiConnection.connect()
except KeyboardInterrupt:
    print("Keyboard interrupt")

# HTTP request
try:
    http_get()
except (Exception, KeyboardInterrupt) as err:
    print("No Internet", err)

# WiFi Disconnect
# wifiConnection.disconnect()
```

**main.py**
This is the main file that ties everything together:
```
import sys
sys.path.append('lib')

import lib.dht as dht
import machine
import time
import urequests
import lib.wifiConnection as wifiConnection
import lib.datacake_keys as datacake_keys

# DHT11 Sensor
tempSensor = dht.DHT11(machine.Pin(27)) # DHT11 Constructor 

# WiFi Connection
ip = wifiConnection.connect()
print("Device IP:", ip)

# Check Internet Connection
try:
    response = urequests.get("http://www.google.com")
    print("Internet connection verified")
    response.close()
except Exception as e:
    print("No internet connection:", e)

while True:
    try:
        tempSensor.measure()
        temperature = tempSensor.temperature()
        humidity = tempSensor.humidity()
        print("Temperature is {} degrees Celsius and Humidity is {}%".format(temperature, humidity))

        # Send data to Datacake
        headers = {
            'Authorization': 'Token {}'.format(datacake_keys.DATACAKE_TOKEN),
            'Content-Type': 'application/json'
        }
        payload = {
            'device': '644972db-76c1-402d-a784-83a6c456cd84', # Device Serial Number
            'temperature': temperature,
            'humidity': humidity
        }
        try:
            response = urequests.post(datacake_keys.DATACAKE_API_URL, headers=headers, json=payload)
            response.close()
        except Exception as e:
            print("Error while sending data:", e)
    except Exception as error:
        print("Exception occurred:", error)
    time.sleep(600)  # Send updates every 10 minutes
```
**Explanation**
WiFi Connection: Connects the device to a Wi-Fi network using credentials stored in lib/wifiConnection.py.

**Data Reading:** Reads temperature and humidity from the DHT11 sensor every 10 minutes.

**Data Transmission:** Sends the data to Datacake using an HTTP POST request.

## Transmitting the Data:

Interval: Data is sent every 10 minutes.
Wireless Protocol: Wi-Fi is used to connect to the internet.
Transport Protocol: HTTP is used to send data to Datacake's API.
Design Choices:

Wi-Fi: Chosen for its simplicity and availability in most environments.
HTTP: Easy to implement and supported by Datacake.


## Presenting the Data
**Datacake Dashboard:** The dashboard is built to display real-time temperature and humidity data using configurable widgets such as charts and values. The data is displayed in an easy-to-understand format, allowing for quick insights into environmental conditions.

**Data Preservation:** The data is stored in Datacake's cloud database and is preserved for a minimum duration as per Datacake's free tier policy. This typically includes historical data retention for a certain period, enabling users to analyze trends over time.

**Visual Examples:**
Here are some examples of how the Datacake dashboard might look:

![Skärmavbild 2024-06-19 kl. 15.55.56](https://hackmd.io/_uploads/HyDPOe5LC.png)
![Skärmavbild 2024-06-26 kl. 22.20.34](https://hackmd.io/_uploads/rJzudgqLA.png)




**Data Saving Frequency:** Data is sent to the Datacake database every 10 minutes, ensuring that the dashboard is updated with near real-time information.

**Database Choice**
Datacake's cloud storage was chosen for its ease of integration, real-time data visualization capabilities, and support for multiple IoT devices. The platform also offers a free tier, making it suitable for small-scale projects and prototypes.

**Automation and Triggers**
Datacake allows setting up alerts and triggers based on specific data conditions. For example, users can configure alerts to notify them when temperature or humidity exceeds a certain threshold. This is useful for applications such as monitoring server rooms, greenhouses, or residential environments.

**Triggers:** Custom triggers can be set to perform actions such as sending notifications, triggering other IoT devices, or logging events based on the data received.



## Finalizing the Design
**Final Results:**
The device successfully reads and transmits temperature and humidity data to Datacake. Visuals data is displayed on a desired custom dashboard, allowing for easy monitoring and analysis of the environmental conditions.

The final product was used indoors close to a window in a bedroom:
![IMG_3235](https://hackmd.io/_uploads/Bkrfqlq8A.jpg)



**Final Thoughts**

Improvements:
* Additional Sensors: Incorporating more sensors, for air quality detection, or motion sensors, could provide a more comprehensive environmental monitoring system.
* Power Management: Implementing power-saving features and exploring alternative power sources (e.g., battery) to make the device more versatile and portable.

Successes:
* Hardware Integration: The project achieved seamless integration of the DHT11 sensor with the Raspberry Pi Pico, ensuring accurate data collection.
* Cloud Platform: Utilizing Datacake for data visualization proved to be effective and user-friendly. The platform's real-time data updates and customizable dashboards enhanced the overall user experience.
* Learning Experience: The project provided valuable hands-on experience, for first time building in IoT development that included sensor integration, data transmission, and cloud-based data visualization.