Try   HackMD

Overview

Author: Cajsa Schoultz (cs224mj)

This tutorial will guide you through the process of building a temperature and humidity monitoring system using IoT technology. By the end of this tutorial, you will be able to measure and display real-time temperature and humidity data.

This project will take approximately 4-6 hours to complete.

Objective

By building a beginner-level weather station, individuals can gain hands-on experience in combining hardware components, programming, and cloud connectivity to create a practical IoT solution.

The objective of this tutorial is to empower beginners with the knowledge and skills to create their own weather station that measures temperature and humidity. By using sensors, we can accurately capture real-time data from the environment. The collected data is then transmitted wirelessly to a cloud-based platform, allowing users to remotely access and monitor the weather conditions from anywhere in the world.

Through this tutorial, the aim is to provide a step-by-step guide that simplifies the process of building an IoT weather station for beginners. By combining hardware setup, coding, connectivity, and data presentation, users will gain a comprehensive understanding of how different components interact to create a functional and practical IoT solution. This project serves as a foundation for individuals interested in exploring IoT applications.

Material

List of materials

Item Description Cost
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Raspberry Pi Pico WH Microcontroller 109 sek
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Breadboard Microcontroller board 39 sek
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
DS18B20 Digital temperature sensor 42 sek
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
DHT11 Digital temperature and humidity sensor 49 sek
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
USB-cable A-male – micro B 5p male 1.8m Connection between microcontroller and computer 130 sek
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
USB-A female to USB-C male For computers with only USB-C 249 sek
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →
Jumper Wires x8 29 sek

The reason why two different temperature sensors are used for this project is to get a more accurate measurement of the surrounding environment. Each temperature sensor has its own strengths and limitations, and by combining their readings, we can obtain a more reliable and precise measurement. At first, I planned on only including the DHT11 to measure temperature and humidity; however, upon doing some research it revealed that there is an accuracy for ±2%. Therefore I chose to include DS18B20 which has an accuracy of ±0,5%.

Everything is bought through Electrokit, where I purchased their LNU starter kit.

Computer Setup

This project was developed on a MacBook updated with macOS Ventura 13.4.1. Therefore, there might be differences for other computing systems for the installation and setup process.

1. Install Visual Studio Code

For this project, I have chosen to use Visual Studio Code (VS Code). VS Code is a free IDE and open-source code editor developed by Microsoft. VS Code provides a lightweight and customizable environment that offers a rich set of features, making it the preferred choice for this beginner project.

Initial to the project, you have to install VS Code. This can be done through downloading VS Code and download and install the IDE on the preferred operating system. VS Code is available for Windows, macOS, and Linux. Thus, making it accessible to many users.

Once installed, launch VS Code by opening it from your applications or using the desktop shortcut.

2. Install Node.js

The next step is to install Node.js to be able to proceed to the next step due to the dependability of using PyMakr.

3. PyMakr Plugin

The third step is to install the plugin Pymakr. In VS Code, click on the Extensions icon on the left sidebar (or use the keyboard shortcut Ctrl+Shift+X / Cmd+Shift+X). In the search bar, type "Pymakr" and press Enter. Look for the "Pymakr" extension in the search results, and click the Install button. Wait for the installation process to complete.

4. Updating the firmware on microcontroller

When the software and plugin is installed, it is time to unpack the microcontroller and attach it to the breadboard. Make sure that the microcontroller is appropriately attached, that is vertically aligned with the board.

Afterward, it is time to plug in the USB cable into the Raspberry Pi. Note that the port that is attached to the microcontroller is fragile, so it is recommended that the USB-port that is plugged into the computer is attached/removed during development and setup of sensors.

At the same time as you are connecting the USB cable to the computer, press down the BOOTSEL button on the microcontroller. By doing this, the microcontroller will appear as a file named RP1-RP2 in your system.

The next step is to download the micropython firmware, which you should make sure is the latest release. After downloading, drag this file onto the RPI-RP2 file.

The board will automatically disconnect and reconnect again. However, it may not always reconnect again depending on your computer software. In this case where a Macbook is used, it did not reconnect.

Now you are up and running and ready to start developing the project!

Putting everything together

Before putting everything together, please note that no power source is connected to the board. This can be ensured by deattaching the USB-cable from the computer.

Below, a step-by-step guide for this will be presented with a circuit diagram at the end:

Gather the necessary components:

  • Raspberry Pi Pico WH
  • Breadboard
  • DHT11 temperature and humidity sensor
  • DS18B20 temperature sensor
  • Male-to-male jumper wires

Set up the Raspberry Pi and Breadboard

  • Ensure your Raspberry Pi is powered off.
  • Connect the Raspberry Pi to the breadboard. Make sure the pins are aligned correctly, allowing the GPIO pins to connect with the breadboard.

Wiring the DHT11 Sensor
Connect the DHT11 sensor to the Raspberry Pi GPIO pins using jumper wires as follows:

  • Connect a jumper wire from the positive power rail on the breadboard to any available 3.3V pin on the Raspberry Pi.
  • Connect a jumper wire from the ground (GND) rail on the breadboard to any available ground (GND) pin on the Raspberry Pi.
  • Connect a jumper wire from the breadboard row where the DHT11 DATA pin is connected to any GPIO pin on the Raspberry Pi. Remember the GPIO pin number for later use.

Wiring the DS18B20 Sensor
Connect the DS18B20 sensor to the Raspberry Pi GPIO pins using jumper wires as follows:

  • Connect a jumper wire from the positive power rail on the breadboard to any available 3.3V pin on the Raspberry Pi.
  • Connect a jumper wire from the ground (GND) rail on the breadboard to any available ground (GND) pin on the Raspberry Pi.
  • Connect a jumper wire from the breadboard row where the DS18B20 DATA pin is connected to any GPIO pin on the Raspberry Pi. Remember the GPIO pin number for later use in the code.

If it looks like this you are all set!

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

The circuit diagram is done through Fritzing.

IMPORTANT NOTE!
Verify the connections:

  • Double-check that all the connections are secure and correctly placed. This is crucial to ensure proper communication between the sensors and the Raspberry Pi.

You are now set to plug in your breadboard to the computer and start coding!

Platform

Initial to this project, it was difficult to select the appropriate platform. I wanted the platform to be suitable for not only myself but also considering other people that may use this tutorial. The ease of use, the cost or subscription fee, and the documentation was therefore taken into consideration.

After carefully evaluating the available options, it was determined that MQTT utilizing Adafruit.io emerged as the most optimal selection. Adafruit.io offers a comprehensive platform for efficiently managing, analyzing, and visually representing data obtained from IoT devices. One notable advantage is that it is freely accessible to all users upon creating an account, further enhancing its appeal.

You must create an account to be able to connect your device to the platform.

The Code

In order to simplify the process and ease of understanding the presentation of the code is divided into smaller parts.

We then start with the boot.py file in order to connect the device to the internet. Instructions can be found here. Note that I have imported the Wi-Fi name and passwords from secrets. This file has been added to protect the Wi-Fi credentials.

# boot.py -- run on boot-up def do_connect(): import network from time import sleep from secrets import secrets import machine 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(secrets["ssid"], secrets["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 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) # Receve response print(rec_bytes) # Print the response s.close() # Close connection # WiFi Connection try: ip = do_connect() except KeyboardInterrupt: print("Keyboard interrupt") # HTTP request try: http_get() except Exception as err: print("Exception", err)

As we are using a MQTT protocol to transmit the data, we first need to add a new folder which we name mqtt.py. Here, we insert this code. More information can be found here.

When we have established an internet connection and our MQTT is up and running, we can start creating the code for the project. This code is inserted into main.py. See code below:

# main.py -- put your code here! import time # Allows use of time.sleep() for delays from 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 import micropython # Needed to run any MicroPython code import random # Random number generator from machine import Pin # Define pin import dht # import the builtin library import onewire import ds18x20 oneWire_pin = machine.Pin(26) # DS18x20 connected to pin 27 # Initailize pin with Dallas Semiconductor temperature sensor DS18X20 oneWire_sensor = ds18x20.DS18X20(onewire.OneWire(oneWire_pin)) # Scan and print the address of all sensors connected to pin 27 sensors = oneWire_sensor.scan() print('Found devices: ', sensors) # BEGIN SETTINGS # These need to be change to suit your environment # Wireless network WIFI_SSID = "" WIFI_PASS = "" # No this is not our regular password. :) # Adafruit IO (AIO) configuration AIO_SERVER = "io.adafruit.com" AIO_PORT = 1883 AIO_USER = "cajsaschoultz" AIO_KEY = "aio_ymwt41OwzxI9zQHVjpm1uxkIwsdJ" AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id()) # Can be anything AIO_TEMPERATURE_FEED = "cajsaschoultz/feeds/temperature" AIO_HUMIDITY_FEED = "cajsaschoultz/feeds/humidity" AIO_TEMPERATUREDS_FEED = "cajsaschoultz/feeds/temperature-2" # END SETTINGS # FUNCTIONS # Function to connect Pico to the WiFi def do_connect(): import network from time import sleep import machine 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_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 # Try WiFi Connection try: ip = do_connect() except KeyboardInterrupt: print("Keyboard interrupt") # 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.connect() print("Connected to %s, subscribed to %s and %s topics" % (AIO_SERVER, AIO_TEMPERATURE_FEED, AIO_HUMIDITY_FEED)) tempSensor = dht.DHT11(Pin(27)) # DHT11 Constructor try: while True: try: tempSensor.measure() temperature = tempSensor.temperature() humidity = tempSensor.humidity() oneWire_sensor.convert_temp() time.sleep_ms(750) print("Temperature is {} degrees Celsius".format(oneWire_sensor.read_temp(sensors[0]))) client.publish(topic=AIO_TEMPERATURE_FEED, msg=str(temperature)) client.publish(topic=AIO_HUMIDITY_FEED, msg=str(humidity)) client.publish(topic=AIO_TEMPERATUREDS_FEED, msg=str(oneWire_sensor.read_temp(sensors[0]))) print("Temperature is {} degrees Celsius and Humidity is {}%".format(temperature, humidity)) except: print("Error in reading sensor values") time.sleep(300) finally: # If an exception is thrown ... client.disconnect() # ... disconnect the client and clean up. client = None print("Disconnected from Adafruit IO.")

The code in itself is pretty straightforward and simple. Note that I have removed my Wi-Fi credentials in this code on line 75 and 76, where they would normally be stated.

If you have followed all the previous steps in this tutorial you should be able to recreate this project.

Transmitting the data / connectivity

The sensor data is transmitted to Adafruit on a five minute interval. The reason for choosing a five minute interval is that temperature changes typically occur at a slower pace, and frequent updates may not be necessary for most applications. By using a five-minute interval, we can strike a balance between timely updates and efficient use of network resources. This interval allows for periodic monitoring of temperature changes while minimizing unnecessary data transfers.

However, it's important to evaluate the specific needs of your application. If your environment experiences rapid temperature fluctuations or if real-time monitoring is critical, you may need to adjust the transmission interval to a shorter duration. On the other hand, if temperature changes occur slowly and real-time updates are not vital, you can consider extending the interval to conserve network bandwidth and reduce power consumption.

Wi-Fi is used as the wireless protocol for this project. As this is an indoor project, it does make sense to use the Wi-Fi available. The data is sent through a MQTT protocol.

Presenting the data

When using Adafruit.io, it is possible to add blocks which best illustrates the desired presentation of the data. For this project, I wanted to visualize the data in two ways - trough gauges and line charts. This not only allowed for a clear understanding of the current data, but also illustrating how it has changed over time. Essentially, you can add any widget that you find suitable.

Every five minutes, data is transmitted to Adafruit.io, and the values are presented in the span of 24 hours. Furthermore, I chose to use the value span of -60 to 130°C for illustration and as it captures the values of both sensors.
Note that the DHT11 can only measure temperature between 0 and 50°C, while DS18B20 can measure temperature between -55 to 125°C. When you are using the free version of Adafruit.io, the data feeds are stored for 30 days.

Below, the data is presented from this project. The gauges and line charts are specified with the sensor used.




I also chose to include an additional line chart, presenting temperature data from both sensors side by side for illustration (the green line represents DS18B20 and the blue line represent DTH11):

Based on the accuracy levels of the temperature sensors, we can calculate the mean value of both sensors (e.g. 25+26/2=25,5). However, as the accuracy of DS18B20 is somewhat more accurate than DHT11, we will use the value of the former twice (e.g. 25+25+26/3=25,33).

Finalizing the design

Final Thoughts

As this was my first ever project within IoT, I am very satisfied with the results I have gotten. It was truly a great beginners project to learn and understand the basics. For future projects, I am eager to create something more advanced or even level up this project. For example, I was interested in monitoring soil as well, but did not have the time to gather the sufficient sensor. This will most likely be the next project I pursue.

The actual device is currently very fragile, as I did not prioritize any design in this particular project. This would have been helpful to greate a more enduring device that would last longer. In addition to this, I have now only used my computer for powering the device. It would be useful to include another type of power distibutor, such as a powerbank. Additionally, as seen in the final design, the jumper wires are somewhat messy due to the length, and I would therefore switch these to shorter ones.

In conclusion, it was a fun (although sometimes challenging) project. Considering the above mentioned final notes, I am aware of the natural steps going forward to improve the device and design.