In this tutorial, we will learn to create a Raspberry Pi Pico DHT22 web server using MicroPython. In the DHT web server, we will see how to display temperature and humidity values on the web page which will be accessible through an IP address. All devices which are connected to the same router to which the Raspberry Pi Pico is connected can access this web page using an IP address.
Raspberry Pi Pico does not support Wi-Fi capabilities hence we have to use a separate Wi-Fi module to enable Wi-Fi connectivity. Therefore, we will interface and program ESP-01 Wi-Fi module with Raspberry Pi Pico to enable Wi-Fi features. We will use Thonny IDE to program Raspberry Pi Pico with ESP-01 and DHT22 in MircoPython. We will use AT commands through the serial port that is UART to configure the ESP-01 Wi-Fi module.
Prerequisites
Before we start this lesson make sure you are familiar with and have the latest version Python 3 in your system, have set up MicoPython in Raspberry Pi Pico, and have a running Integrated Development Environment(IDE) in which we will be doing the programming. We will be using the same Thonny IDE as we have done previously when we learned how to blink and chase LEDs in micro-python. If you have not followed our previous tutorial, you check here:
If you are using uPyCraft IDE, you can check this getting started guide:
Recommended Readings:
- Interface ESP8266 WiFi Module with Raspberry Pi Pico
- DHT11 DHT22 with Raspberry Pi Pico using MicroPython
DHT11/DHT22 Introduction
The DHT11/DHT22 is a sensor which measures relative humidity and temperature sensor. It provides a calibrated digital output with a 1-wire protocol. Both sensors are inexpensive. They are quite similar to each other with some differences in specifications.
DHT22 is almost similar to the DHT11 but the former measures temperature and humidity with higher accuracy and supports a wider range.
DHT11 vs DHT22
The following table lists the comparison of both DHT sensors.
DHT22 | DHT11 | |
Temperature | -40 to 80 ºC +/- 0.5ºC | 0 to 50 ºC +/-2 ºC |
Humidity | 0 to 100% +/-2% | 20 to 90% +/-5% |
Resolution | Humidity: 0.1%Temperature: 0.1ºC | Humidity: 1%Temperature: 1ºC |
Operating Voltage | 3- 6 V DC( directly power able from Raspberry Pi Pico) | 3-5.5 V DC( directly power able from Raspberry Pi Pico) |
Sampling time | 2 seconds | 1 second |
Current rating | $4 to $10 | $1 to $5 |
Output data type | float | int |
Pinout | 4-pin (same as DHT11) | 4-pin (same as DHT22) |
Price | 5 | 2 |
As you can see from the above comparison table that DHT22 offers wider temperature range and resolution for temperature and humidity. But it is more expensive than DHT11. However, DHT11 has a better sampling period. Furthermore, the operating voltage range for both sensors is almost and we can directly power these sensors from power pins of Raspberry Pi Pico.
Regardless of above differences, both DHT sensors have the same working principle and same pinout. We can use the same MicroPython script to read temperature and humidity readings by selecting DHT type inside the code.
DHT sensors are pre-calibrated. We can directly connect them with Raspberry Pi Pico to obtain sensor output reading. They are internally composed of a humidity sensing sensor and a thermistor. These two components measure humidity and temperature.
DHT11/DHT22 Pinout
This following figure shows the pinout diagram of DHT sensors. DHT sensor consists of four pins. But on DHT modules only three pins are exposed to the pinout of the module and10k ohm pull-up resistor is internally connected to pin 2.
Pin Description
The following lists the pinout of the DHT sensor and their brief description. Pin number starts from left to right when you hold the sensor from the front end.
DHT11/DHT22 Pin | Connection with Raspberry Pi Pico |
1 ( VCC) | 3.3V |
2 (Data Out) | Any GPIO pins of Raspberry Pi Pico along with 10k ohm pull-up resistor |
3 (NC) | Not used |
4 (GND) | Ground |
- Vcc is the power supply pin. Apply voltage in a range of 3.3 V to 5.0 V to this pin
- Data Out is the digital output pin. It sends out the value of measured temperature and humidity in the form of serial data
- N/C is not connected
- GND: Connect the GND pin
Interfacing Raspberry Pi Pico with DHT22 and ESP-01
This section shows how to connect Raspberry Pi Pico with DHT22 sensor and ESP-01.
Parts Required
We will require the following components:
- Raspberry Pi Pico
- DHT22 Sensor
- 10K ohm resistor (not required if using the module version of the sensor)
- ESP-01 Module
- Connecting Wires
- Breadboard
Raspberry Pi Pico with DHT22
Connect the DHT22 to Raspberry Pi Pico along with a 10K ohm pull-up resistor.
- The first pin for both sensors is a power supply(Vcc) pin. Connect it with the 3.3 volt pin of Raspberry Pi Pico.
- Data out is the pin through which we get temperature and humidity samples from the DHT sensor. Connect this pin with GP16 of Raspberry Pi Pico and also connect the data pin with a 10k pull-up resistor. But you can also use any digital pin of Raspberry Pi Pico as well.
A Pull-up resistor is used to keep the data pin high for proper communication between the microcontroller and sensor. You can check the datasheet of DHT11 and DHT22 to get more information about it. DHT22 is also known by the name of AM2302.
- Third pin is not used
- Connect the fourth pin (GND) to the ground pin of the board
The connections between the two devices which we are using can be seen below.
DHT22 | Raspberry Pi Pico |
VCC | 3.3V |
Data Out | GP16 along with 10k ohm resistor |
NC | – |
GND | GND |
We have used the same connections as specified in the table above.
Raspberry Pi Pico with ESP-01
The ESP-01 module consists of 8 pins. However we will use 5 pins to connect with the Pi Pico board. These include the VCC, EN, GND, RX and TX pins. RX and TX pins of the module will be connected with the UART pins of the Pi Pico board. Let us first have a look at the Raspberry Pi Pi UART Pins.
Raspberry Pi Pico UART Pins
Raspberry Pi Pico contains two identical UART peripherals with separate 32×8 Tx and 32×12 Rx FIFOs.
The following table lists the GPIO pins for both UART peripherals which are exposed on Raspberry Pi Pico development board pinouts.
UART Pins | GPIO Pins |
UART0-TX | GP0/GP12/GP16 |
UART0-RX | GP1/GP13/GP17 |
UART1-TX | GP4/GP8 |
UART1-RX | GP5/GP9 |
For this guide, we will use UART0-TX and RX pins.
Follow the connection diagram below to connect the two devices.
Raspberry Pi Pico | ESP-01 |
3.3V | VCC |
3.3V | EN |
GND | GND |
GP1 (UART0 RX) | TX |
GP0 (UART0 TX) | RX |
Connection Diagram Raspberry Pi Pico with DHT22 and ESP-01
We have used the same connections as given in the two tables above. All three devices will be commonly grounded and will be powered with the same 3.3V pin of Raspberry Pi Pico.
The diagram below shows the connection diagram of Raspberry Pi Pico with DHT22 and ESP-01.
MicroPython Script Raspberry Pi Pico DHT22 Web Server with ESP-01 (Display Temperature and Humidity)
import uos
import utime
from machine import Pin, I2C
import dht
recv_buf="" # receive buffer global variable
print()
print("Machine: \t" + uos.uname()[4])
print("MicroPython: \t" + uos.uname()[3])
sensor = dht.DHT22(Pin(16))
uart0 = machine.UART(0, baudrate=115200)
print(uart0)
def Rx_ESP_Data():
recv=bytes()
while uart0.any()>0:
recv+=uart0.read(1)
res=recv.decode('utf-8')
return res
def Connect_WiFi(cmd, uart=uart0, timeout=3000):
print("CMD: " + cmd)
uart.write(cmd)
utime.sleep(7.0)
Wait_ESP_Rsp(uart, timeout)
print()
def Send_AT_Cmd(cmd, uart=uart0, timeout=3000):
print("CMD: " + cmd)
uart.write(cmd)
Wait_ESP_Rsp(uart, timeout)
print()
def Wait_ESP_Rsp(uart=uart0, timeout=3000):
prvMills = utime.ticks_ms()
resp = b""
while (utime.ticks_ms()-prvMills)<timeout:
if uart.any():
resp = b"".join([resp, uart.read(1)])
print("resp:")
try:
print(resp.decode())
except UnicodeError:
print(resp)
Send_AT_Cmd('AT\r\n') #Test AT startup
Send_AT_Cmd('AT+GMR\r\n') #Check version information
Send_AT_Cmd('AT+CIPSERVER=0\r\n') #Check version information
Send_AT_Cmd('AT+RST\r\n') #Check version information
Send_AT_Cmd('AT+RESTORE\r\n') #Restore Factory Default Settings
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the Wi-Fi mode
Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the Wi-Fi mode = Station mode
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the Wi-Fi mode again
Connect_WiFi('AT+CWJAP="PTCL-BB","44332211"\r\n', timeout=5000) #Connect to AP
Send_AT_Cmd('AT+CIFSR\r\n',timeout=5000) #Obtain the Local IP Address
Send_AT_Cmd('AT+CIPMUX=1\r\n') #Obtain the Local IP Address
utime.sleep(1.0)
Send_AT_Cmd('AT+CIPSERVER=1,80\r\n') #Obtain the Local IP Address
utime.sleep(1.0)
print ('Starting connection to ESP8266...')
while True:
res =""
res=Rx_ESP_Data()
utime.sleep(2.0)
if '+IPD' in res: # if the buffer contains IPD(a connection), then respond with HTML handshake
sensor.measure()
temp = str(sensor.temperature())
hum = str(sensor.humidity())
print(temp)
print( hum)
print('__________________')
utime.sleep(3)
id_index = res.find('+IPD')
print("resp:")
print(res)
connection_id = res[id_index+5]
print("connectionId:" + connection_id)
print ('! Incoming connection - sending webpage')
uart0.write('AT+CIPSEND='+connection_id+',1569'+'\r\n') #Send a HTTP response then a webpage as bytes the 108 is the amount of bytes you are sending, change this if you change the data sent below
utime.sleep(1.0)
uart0.write('HTTP/1.1 200 OK'+'\r\n')
uart0.write('Content-Type: text/html'+'\r\n')
uart0.write('Connection: close'+'\r\n')
uart0.write(''+'\r\n')
uart0.write('<!DOCTYPE HTML>'+'\r\n')
html ='<html> <head> <meta http-equiv=\"refresh\" content=\"10\"> <title>Raspberry Pi Pico Web Server</title> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> <link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.7.2/css/all.css\" integrity=\"sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr\" crossorigin=\"anonymous\"> <link rel=\"icon\" href=\"data:,\"> <style> html {font-family: Arial; display: inline-block; text-align: center;} p { font-size: 1.2rem;} body { margin: 0;} .top_nav { overflow: hidden; background-color: #da0a0a; color: white; font-size: 1rem; } .content { padding: 30px; } .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); } .cards { max-width: 800px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } .value { font-size: 3rem; } .symbol { font-size: 2rem; } </style> </head> <body> <div class=\"top_nav\"> <h1>Raspberry Pi Pico DHT22 Web Server</h1> </div> <div class=\"content\"> <div class=\"cards\"> <div class=\"card\"> <p><i class=\"fas fa-thermometer-half fa-3x\" style=\"color:#da0a0a;\"></i><span class=\"symbol\">Temperature</span></p><p><span class=\"value\"><span id=\"temperature_Celsius\">' + temp + '</span> °C</span></p> </div> <div class=\"card\"> <p><i class=\"fas fa-tint\" style=\"color:#da0a0a;\"></i> <span class=\"symbol\">Humidity</span></p><p><span class=\"value\"><span id=\"humidity\">' + hum + '</span> %</span></p> </div> </div> </div> </body> </html>'
uart0.write(html +'\r\n')
utime.sleep(4.0)
Send_AT_Cmd('AT+CIPCLOSE='+ connection_id+'\r\n') # once file sent, close connection
utime.sleep(4.0)
res="" #reset buffer
print ('Waiting For connection...')
How the Code Works?
We will start by importing the uos module. We also import the utime module so that we will be able to add a delay of 10 seconds in between our readings. Moreover, we import Pin, dht and I2C module so that we will be able to access its methods through its defined classes.
import uos
import utime
from machine import Pin, I2C
import dht
Then, we will print the information about our current operating system in the Thonny shell terminal. We will uos.uname() and print the operating system version and release.
print()
print("Machine: \t" + uos.uname()[4])
print("MicroPython: \t" + uos.uname()[3])
Next, we will define a dht object named ‘sensor’ and assign the data pin to it. Here we are using DHT22 sensor with data pin connected at GP16. If using DHT11 replace ‘DHT22’ with ‘DHT11’ and change the pin number appropriately.
sensor = dht.DHT22(Pin(16))
Initialize UART Communication
Then we will create an uart object by using UART() and specify the UART channel as the first parameter and the baud rate as the second parameter. We are using UART0 in this case with baud rate of 115200 for the uart communication. ESP8266 has a default baud rate of 115200 hence we will use the same baud rate here for Raspberry Pi Pico UART communication in order to create synchronization. Moreover, we will also print the UART details in the shell terminal.
uart0 = machine.UART(0, baudrate=115200)
print(uart0)
This Connect_WiFi() function is used to connect ESP8266 with WiFi.
def Connect_WiFi(cmd, uart=uart0, timeout=3000):
print("CMD: " + cmd)
uart.write(cmd)
utime.sleep(7.0)
Wait_ESP_Rsp(uart, timeout)
print()
Next, we will define three functions. The first one is Rx_ESP_Data(). This reads the serial data being received. This data is decoded from UTF-8 format and returned.
def Rx_ESP_Data():
recv=bytes()
while uart0.any()>0:
recv+=uart0.read(1)
res=recv.decode('utf-8')
return res
The second function is Send_AT_Cmd(cmd, uart=uart0, timeout=3000). It takes in three parameters, the AT command, the UART channel and the response time. This function will be used to it send an AT command to ESP8266 via uart0. The response time is set to 3 seconds.
def Send_AT_Cmd(cmd, uart=uart0, timeout=3000):
print("CMD: " + cmd)
uart.write(cmd)
Wait_ESP_Rsp(uart, timeout)
print()
The Wait_ESP_Rsp(uart=uart0, timeout=3000) function waits for 3 seconds to get the response from ESP8266. After receiving the data from ESP8266 it concatenates the received bytes and prints them on the shell terminal.
def Wait_ESP_Rsp(uart=uart0, timeout=3000):
prvMills = utime.ticks_ms()
resp = b""
while (utime.ticks_ms()-prvMills)<timeout:
if uart.any():
resp = b"".join([resp, uart.read(1)])
print("resp:")
try:
print(resp.decode())
except UnicodeError:
print(resp)
AT Commands
Now let us look at the series of AT commands that we will send through UART0 to ESP8266.
Send_AT_Cmd('AT\r\n') #Test AT startup
Send_AT_Cmd('AT+GMR\r\n') #Check version information
Send_AT_Cmd('AT+CIPSERVER=0\r\n') #Check version information
Send_AT_Cmd('AT+RST\r\n') #Check version information
Send_AT_Cmd('AT+RESTORE\r\n') #Restore Factory Default Settings
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the Wi-Fi mode
Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the Wi-Fi mode = Station mode
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the Wi-Fi mode again
Connect_WiFi('AT+CWJAP="YOUR_SSID","YOUR_PASSWORD"\r\n', timeout=5000) #Connect to AP
Send_AT_Cmd('AT+CIFSR\r\n',timeout=5000) #Obtain the Local IP Address
Send_AT_Cmd('AT+CIPMUX=1\r\n') #Obtain the Local IP Address
utime.sleep(1.0)
Send_AT_Cmd('AT+CIPSERVER=1,80\r\n') #Obtain the Local IP Address
utime.sleep(1.0)
AT: This type of command is used to test the startup function of WiFi module. The response would be ok, against this command if everything is ok.
Send_AT_Cmd('AT\r\n') #Test AT startup
AT+GMR : This type of AT command is used to check the version of AT command and we used SDK version of AT command in this type of WIFI module.
Send_AT_Cmd('AT+GMR\r\n') #Check version information
AT+CIPSERVER=0: This configures the ESP8266 as server and sets the mode as 0 which means delete server (need to follow by restart)
Send_AT_Cmd('AT+CIPSERVER=0\r\n')
AT+RST: This type of command is used for reset the WiFi module when it is in working condition. The response would be ok, when reset the module.
Send_AT_Cmd('AT+RST\r\n')
AT+RESTORE: This type of command is used to restore factory settings means, when this command is entered then all the parameters are reset automatically to default one’s.
Send_AT_Cmd('AT+RESTORE\r\n') #Restore Factory Default Settings
AT+CWMODE? : This type of command is used to query the WiFi mode of ESP8266.
Send_AT_Cmd('AT+CWMODE?\r\n') #Query the WiFi mode
AT+CWMODE=1 : This sets the WiFi mode of ESP8266 in this case in station mode.
Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the WiFi mode = Station mode
AT+CWJAP=”SSID”,”PASSWORD”\r\n’, timeout=TIME_ms : This connects the ESP8266 with an AP whose SSID and password are given, The timeout here is the reconnection time.
Connect_WiFi('AT+CWJAP="YOUR_SSID","YOUR_PASSWORD"\r\n', timeout=5000) #Connect to AP
AT+CIFSR: This command obtains the local IP address.
Send_AT_Cmd('AT+CIFSR\r\n')
AT+CIPMUX=1:This command is used to enable multiple connections (maximum 4)
Send_AT_Cmd('AT+CIPMUX=1\r\n')
AT+CIPSERVER=1: This command configures ESP8266 as server.
Send_AT_Cmd('AT+CIPSERVER=1,80\r\n')
while loop
Inside the while loop, we will first call Rx_ESP_Data() which returns the data that the ESP8266 receives. This is saved in the variable ‘res.’
Add a delay of 2 seconds before proceeding further.
res =""
res=Rx_ESP_Data()
utime.sleep(2.0)
Next, we will check if the buffer contains an IPD connection or not. If it does then, respond with an HTML handshake.
We will obtain the temperature and humidity reading and save it in ‘temp’ and ‘hum’ respectively. These will be printed in the shell console after a delay of 3 seconds. We use the sensor object on the appropriate method e.g. temperature() to get the temperature reading in Celsius and humidity to get the humidity value in percentage. Additionally, we also convert them to string values as we will display them on cards in the web server
The response will also be printed in the shell terminal. Additionally, we obtain the connection ID and print it as well.
if '+IPD' in res: # if the buffer contains IPD(a connection), then respond with HTML handshake
sensor.measure()
temp = str(sensor.temperature())
hum = str(sensor.humidity())
print(temp)
print( hum)
print('__________________')
utime.sleep(3)
id_index = res.find('+IPD')
print("resp:")
print(res)
connection_id = res[id_index+5]
print("connectionId:" + connection_id)
Then by using the uart object on the write() method, we will send the bytes to the UART. First, we are writing the AT command: AT+CIPSEND=’ID’, ‘LENGTH’ This will set the length of the data that will be sent. Next after a delay of 1 second, we will write the HTML script that will build the web page to the serial port. After that, we will close the multiple connections as we are sending the AT command: AT+CIPCLOSE=’ID’. Then we will reset the buffer and wait for the connection.
print ('! Incoming connection - sending webpage')
uart0.write('AT+CIPSEND='+connection_id+',1569'+'\r\n') #Send a HTTP response then a webpage as bytes the 108 is the amount of bytes you are sending, change this if you change the data sent below
utime.sleep(1.0)
uart0.write('HTTP/1.1 200 OK'+'\r\n')
uart0.write('Content-Type: text/html'+'\r\n')
uart0.write('Connection: close'+'\r\n')
uart0.write(''+'\r\n')
uart0.write('<!DOCTYPE HTML>'+'\r\n')
html ='<html> <head> <meta http-equiv=\"refresh\" content=\"10\"> <title>Raspberry Pi Pico Web Server</title> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> <link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.7.2/css/all.css\" integrity=\"sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr\" crossorigin=\"anonymous\"> <link rel=\"icon\" href=\"data:,\"> <style> html {font-family: Arial; display: inline-block; text-align: center;} p { font-size: 1.2rem;} body { margin: 0;} .top_nav { overflow: hidden; background-color: #da0a0a; color: white; font-size: 1rem; } .content { padding: 30px; } .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); } .cards { max-width: 800px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } .value { font-size: 3rem; } .symbol { font-size: 2rem; } </style> </head> <body> <div class=\"top_nav\"> <h1>Raspberry Pi Pico DHT22 Web Server</h1> </div> <div class=\"content\"> <div class=\"cards\"> <div class=\"card\"> <p><i class=\"fas fa-thermometer-half fa-3x\" style=\"color:#da0a0a;\"></i><span class=\"symbol\">Temperature</span></p><p><span class=\"value\"><span id=\"temperature_Celsius\">' + temp + '</span> °C</span></p> </div> <div class=\"card\"> <p><i class=\"fas fa-tint\" style=\"color:#da0a0a;\"></i> <span class=\"symbol\">Humidity</span></p><p><span class=\"value\"><span id=\"humidity\">' + hum + '</span> %</span></p> </div> </div> </div> </body> </html>'
uart0.write(html +'\r\n')
utime.sleep(4.0)
Send_AT_Cmd('AT+CIPCLOSE='+ connection_id+'\r\n') # once file sent, close connection
utime.sleep(4.0)
res="" #reset buffer
print ('Waiting For connection...')
Create Web page (HTML+CSS)
To build the web page, we will add HTML code and for styling we will add CSS script.
Now let’s go through each line of HTML code to understand how it builds the web page.
In this HTML document, we use cards, paragraphs, headings, icons and title tags to create a web page. This web page displays temperature and humidity readings of DHT22 sensor.
HTML is a hypertext markup language which is used to build web pages. All web browsers understand this language and can read web pages which are based on HTML language.
In HTML, we place all the content of a web page between <html> and </html> tags. The <html> tag shows the beginning of a web page and the </html> indicates the end of a web page.
HTML code mainly includes two parts such as head and body. The head part contains CSS, scripts, meta tags, links of external resources and styling codes. It is placed between <head> and </head> tags.
'<html> <head> <meta http-equiv=\"refresh\" content=\"10\"> <title>Raspberry Pi Pico Web Server</title> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> <link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.7.2/css/all.css\" integrity=\"sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr\" crossorigin=\"anonymous\"> <link rel=\"icon\" href=\"data:,\"> <style> html {font-family: Arial; display: inline-block; text-align: center;} p { font-size: 1.2rem;} body { margin: 0;} .top_nav { overflow: hidden; background-color: #da0a0a; color: white; font-size: 1rem; } .content { padding: 30px; } .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); } .cards { max-width: 800px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } .value { font-size: 3rem; } .symbol { font-size: 2rem; } </style> </head>
Title, Icons and HTTP header
We will start with the title of the web page. The <title> tag will indicate the beginning of the title and the </title> tag will indicate the ending. In between these tags, we will specify “Raspberry Pi Pico Web Server” which will be displayed in the browser’s title bar.
<title>Raspberry Pi Pico Web Server</title>
This meta-tag http-equiv provides attributes to HTTP header. The http-equiv attribute takes many values or information to simulate header response. In this example, we use the http-equiv attribute to refresh the content of the web page after every specified time interval. Users aren’t required to refresh the web page to get updated sensor values. This line forces the HTML page to refresh itself after every 10 seconds. Moreover, this meta tag will make sure our web server is available for all browsers e.g., smartphones, laptops, computers etc.
<meta http-equiv=\"refresh\" content=\"10\">
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
On our web page, we will also display icons. This link tag loads the icons used in the webpage from fontawesome.
<link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.7.2/css/all.css\" integrity=\"sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr\" crossorigin=\"anonymous\">
Styling Web Page with CSS
CSS is used to give styles to a web page. To add CSS files in head tags, we use <style></style> tags. This CSS code styles the cards and web page by specifying the colors, font, font size etc.
This CSS code sets text alignment, padding, margin, and width of body tags of HTML documents along with the font size, color of the cards etc. We use cards to display Temperature and Humidity readings from DHT22. In HTML, a card is a bordered box that has features such as padding. Content. Header, footers, colors, etc.
<style> html {font-family: Arial; display: inline-block; text-align: center;} p { font-size: 1.2rem;} body { margin: 0;} .top_nav { overflow: hidden; background-color: #da0a0a; color: white; font-size: 1rem; } .content { padding: 30px; } .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); } .cards { max-width: 800px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } .value { font-size: 3rem; } .symbol { font-size: 2rem; } </style>
HTML Web Page Body
The second most important part of an HTML document is the body which goes inside the tags <body> and </body>. The body part includes the main content of the web page such as headings, images, buttons, icons, tables, charts, etc. For example, in this Raspberry Pi Pico DHT22 MicroPython based web server, the body part includes a heading and two cards to display the sensor readings.
<body> <div class=\"top_nav\"> <h1>Raspberry Pi Pico DHT22 Web Server</h1> </div> <div class=\"content\"> <div class=\"cards\"> <div class=\"card\"> <p><i class=\"fas fa-thermometer-half fa-3x\" style=\"color:#da0a0a;\"></i><span class=\"symbol\">Temperature</span></p><p><span class=\"value\"><span id=\"temperature_Celsius\">' + temp + '</span> °C</span></p> </div> <div class=\"card\"> <p><i class=\"fas fa-tint\" style=\"color:#da0a0a;\"></i> <span class=\"symbol\">Humidity</span></p><p><span class=\"value\"><span id=\"humidity\">' + hum + '</span> %</span></p> </div> </div> </div> </body> </html>'
We will include the heading of our webpage inside the <h1></h1> tags and it will be “Raspberry Pi Pico DHT22 Web Server”.
<h1>Raspberry Pi Pico DHT22 Web Server</h1>
Next, we will include the following lines of code to display texts and cards for temperature and humidity readings along with the units and icons.
<div class=\"top_nav\"> <h1>Raspberry Pi Pico DHT22 Web Server</h1> </div> <div class=\"content\"> <div class=\"cards\"> <div class=\"card\"> <p><i class=\"fas fa-thermometer-half fa-3x\" style=\"color:#da0a0a;\"></i><span class=\"symbol\">Temperature</span></p><p><span class=\"value\"><span id=\"temperature_Celsius\">' + temp + '</span> °C</span></p> </div> <div class=\"card\"> <p><i class=\"fas fa-tint\" style=\"color:#da0a0a;\"></i> <span class=\"symbol\">Humidity</span></p><p><span class=\"value\"><span id=\"humidity\">' + hum + '</span> %</span></p> </div> </div> </div>
Demonstration
After you have copied the following code onto a new file, click the ‘Save’ icon to save your program code on your PC.
After you have saved the code press the Run button to upload the code to your board. Before uploading code make sure the correct board is selected.
In the shell terminal of your IDE, you will be able to view the IP address after a successful connection gets established:
Now, open your web browser either on your laptop or mobile and type the IP address which we have found in the last step. As soon as you type the IP address on your web browser and hit enter, the Raspberry Pi Pico web server will receive an HTTP request.
You will see the web page with the latest temperature values in your web browser:
The web page viewed from a cell phone will look like this:
Video Demo:
- Raspberry Pi Pico Web Server with BME280 (Weather Station)
- Interface ESP8266 WiFi Module with Raspberry Pi Pico
- Raspberry Pi Pico BME680 Web Server with MicroPython
- Raspberry Pi Pico DS18B20 Web Server (Weather Station)
You may also like to read other DHT11 and DHT22 tutorials:
- DHT11/DHT22 Web Server ESP8266 NodeMCU using Arduino IDE
- ESP32 DHT11 and DHT22 Web Server using Arduino IDE
- DHT11 DHT22 with Arduino – Display Readings on OLED
- DHT11 DHT22 with ESP8266 NodeMCU – Display Readings on OLED
- DHT22 Data Logger with Arduino and Micro SD Card
- DHT11 DHT22 with ESP32 – Display Readings on OLED
- MicroPython: DHT11/DHT22 Web Server with ESP32/ESP8266 (Weather Station)
Where do I get the dht module, which needs to be imported, from?
How would you need to change the code to do this project with a Raspberry Pi Pico W?
You can modify this one:
https://microcontrollerslab.com/raspberry-pi-pico-w-wireless-bme280-web-server/
We are planning to convert all Pico articles for Pico W.