Introduction
In this project, you will learn how to make a web server with a Raspberry Pi Pico board that streams data from a BME280 sensor. The BME280 is a temperature, humidity, and pressure sensor that is excellent for use in mini weather stations and other similar applications. The data from the sensor is displayed on a web page that is updated in real-time, and the web server can be accessed from any computer or mobile device on the same network.
Thank You, PCBWay:
This project is successfully completed because of the support and help from PCBWay. Guys if you have a PCB project, please see their website and get exciting bargains and coupons.
PCBway is the best prototype PCB company offering great PCB boards at lower prices If you sign-up using this link you will get beginner and sign-up coupon rewards. https://www.pcbway.com
Why NextPCB
- Most Efficient, Economic, Inventive PCB Solutions
- Higher Quality
- Lower Price
- Faster Delivery
Before moving with this tutorial you should have the Raspberry Pi Pico W add-on installed in your Thonny IDE. Follow one of the following tutorials to install the Pico W on the Thonny IDE, if you haven’t already. Raspberry Pi Pico W – Getting Started: Tutorials, Pinout
You might also enjoy reading other Webserver projects:
Required Material
Introducing the BME280 Sensor Module
The BME280 barometric pressure sensor is a great sensor for monitoring temperature, Humidity & Atmospheric Pressure. It is frequently used in weather stations and other applications where accurate atmospheric pressure measurements are needed. The BME280 sensor module is a low-cost, high-performance, digital humidity, pressure and temperature sensor.
The BME280 module is based on the Bosch BME280 sensor, which is a low-power, high-accuracy sensor. The module includes a built-in EEPROM for storing calibration data and an I2C interface for communication with the host system. Interface BME280 Temperature, Humidity & Pressure with Arduino
Wiring Diagram – Raspberry Pi Pico W Web Server With BME280
We will use I2C communication with the BME280 sensor module. For that, wire the sensor to the Raspberry Pi Pico W SDA and SCL pins, as shown in the following wiring diagram. Check Also Interface BME280 With Raspberry Pi Pico W Using MicroPython
As said before, BME280 works with the I2C Communication protocol. So we just require 4 connections. Refer to the connection list below:
Attach the VCC, GND, SCL & SDA pin of the BME280 Sensor to 3.3V, GND, GP21 & GP20 of Raspberry Pi Pico W respectively.
- VIN = 3.3v
- GND = GND
- SCL = GP21
- SDA = GP20
MicroPython Code: Raspberry Pi Pico W Web Server With BME280
MicroPython code to control a BME280 and a Pico W webserver. The MicroPython code to control a BME280 and Pico W webserver are as follows: Also see Getting Started With Raspberry Pi Pico With Thonny IDE
The code for the Raspberry Pi Pico W Web Server With BME280 is divided into two parts:
- bme280.py
- main.py
The main code requires a library for BME280. The library contains all the required modules and registers to extract the data from the Sensor.
bme280.py
Open your Thonny IDE and paste one of the codes below into the Thonny Editor. Save the file inside the Raspberry Pi Pico and name it bme280.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
import time from ustruct import unpack, unpack_from from array import array # BME280 default address. BME280_I2CADDR = 0x76 # Operating Modes BME280_OSAMPLE_1 = 1 BME280_OSAMPLE_2 = 2 BME280_OSAMPLE_4 = 3 BME280_OSAMPLE_8 = 4 BME280_OSAMPLE_16 = 5 BME280_REGISTER_CONTROL_HUM = 0xF2 BME280_REGISTER_CONTROL = 0xF4 class BME280: def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, i2c=None, **kwargs): # Check that mode is valid. if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, BME280_OSAMPLE_8, BME280_OSAMPLE_16]: raise ValueError( 'Unexpected mode value {0}. Set mode to one of ' 'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or ' 'BME280_ULTRAHIGHRES'.format(mode)) self._mode = mode self.address = address if i2c is None: raise ValueError('An I2C object is required.') self.i2c = i2c # load calibration data dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26) dig_e1_e7 = self.i2c.readfrom_mem(self.address, 0xE1, 7) self.dig_T1, self.dig_T2, self.dig_T3, self.dig_P1, \ self.dig_P2, self.dig_P3, self.dig_P4, self.dig_P5, \ self.dig_P6, self.dig_P7, self.dig_P8, self.dig_P9, \ _, self.dig_H1 = unpack("<HhhHhhhhhhhhBB", dig_88_a1) self.dig_H2, self.dig_H3 = unpack("<hB", dig_e1_e7) e4_sign = unpack_from("<b", dig_e1_e7, 3)[0] self.dig_H4 = (e4_sign << 4) | (dig_e1_e7[4] & 0xF) e6_sign = unpack_from("<b", dig_e1_e7, 5)[0] self.dig_H5 = (e6_sign << 4) | (dig_e1_e7[4] >> 4) self.dig_H6 = unpack_from("<b", dig_e1_e7, 6)[0] self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL, bytearray([0x3F])) self.t_fine = 0 # temporary data holders which stay allocated self._l1_barray = bytearray(1) self._l8_barray = bytearray(8) self._l3_resultarray = array("i", [0, 0, 0]) def read_raw_data(self, result): """ Reads the raw (uncompensated) data from the sensor. Args: result: array of length 3 or alike where the result will be stored, in temperature, pressure, humidity order Returns: None """ self._l1_barray[0] = self._mode self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL_HUM, self._l1_barray) self._l1_barray[0] = self._mode << 5 | self._mode << 2 | 1 self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL, self._l1_barray) sleep_time = 1250 + 2300 * (1 << self._mode) sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 time.sleep_us(sleep_time) # Wait the required time # burst readout from 0xF7 to 0xFE, recommended by datasheet self.i2c.readfrom_mem_into(self.address, 0xF7, self._l8_barray) readout = self._l8_barray # pressure(0xF7): ((msb << 16) | (lsb << 8) | xlsb) >> 4 raw_press = ((readout[0] << 16) | (readout[1] << 8) | readout[2]) >> 4 # temperature(0xFA): ((msb << 16) | (lsb << 8) | xlsb) >> 4 raw_temp = ((readout[3] << 16) | (readout[4] << 8) | readout[5]) >> 4 # humidity(0xFD): (msb << 8) | lsb raw_hum = (readout[6] << 8) | readout[7] result[0] = raw_temp result[1] = raw_press result[2] = raw_hum def read_compensated_data(self, result=None): """ Reads the data from the sensor and returns the compensated data. Args: result: array of length 3 or alike where the result will be stored, in temperature, pressure, humidity order. You may use this to read out the sensor without allocating heap memory Returns: array with temperature, pressure, humidity. Will be the one from the result parameter if not None """ self.read_raw_data(self._l3_resultarray) raw_temp, raw_press, raw_hum = self._l3_resultarray # temperature var1 = ((raw_temp >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11) var2 = (((((raw_temp >> 4) - self.dig_T1) * ((raw_temp >> 4) - self.dig_T1)) >> 12) * self.dig_T3) >> 14 self.t_fine = var1 + var2 temp = (self.t_fine * 5 + 128) >> 8 # pressure var1 = self.t_fine - 128000 var2 = var1 * var1 * self.dig_P6 var2 = var2 + ((var1 * self.dig_P5) << 17) var2 = var2 + (self.dig_P4 << 35) var1 = (((var1 * var1 * self.dig_P3) >> 8) + ((var1 * self.dig_P2) << 12)) var1 = (((1 << 47) + var1) * self.dig_P1) >> 33 if var1 == 0: pressure = 0 else: p = 1048576 - raw_press p = (((p << 31) - var2) * 3125) // var1 var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25 var2 = (self.dig_P8 * p) >> 19 pressure = ((p + var1 + var2) >> 8) + (self.dig_P7 << 4) # humidity h = self.t_fine - 76800 h = (((((raw_hum << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) + 16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h * self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) * self.dig_H2 + 8192) >> 14)) h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4) h = 0 if h < 0 else h h = 419430400 if h > 419430400 else h humidity = h >> 12 if result: result[0] = temp result[1] = pressure result[2] = humidity return result return array("i", (temp, pressure, humidity)) @property def values(self): """ human readable values """ t, p, h = self.read_compensated_data() p = p // 256 pi = p // 100 pd = p - pi * 100 hi = h // 1024 hd = h * 100 // 1024 - hi * 100 return ("{}*C".format(t / 100), "{}.{:02d} hPa".format(pi, pd), "{}.{:02d} %".format(hi, hd)) |
main.py
open another tab on Thonny IDE and paste the following code. Remember to save the file as main.py on Raspberry Pi Pico.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
from machine import Pin, I2C #importing relevant modules & classes from time import sleep import utime import socket import network import bme280 #importing BME280 library i2c=I2C(0,sda=Pin(20), scl=Pin(21), freq=400000) #initializing the I2C method wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect("Romeo","hackster") def web_page(): bme = bme280.BME280(i2c=i2c) #BME280 object created html = """<html><head><meta http-equiv="refresh" content="5"><meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="data:,"><style>body { text-align: center; font-family: "Helvetica", Arial;} table { border-collapse: collapse; width:55%; margin-left:auto; margin-right:auto; } th { padding: 12px; background-color: #87034F; color: white; } tr { border: 2px solid #000556; padding: 12px; } tr:hover { background-color: #bcbcbc; } td { border: none; padding: 14px; } .sensor { color:DarkBlue; font-weight: bold; background-color: #ffffff; padding: 1px; </style></head><body><h1>BME280 Pi Pico W Weather Station</h1> <table><tr><th>Parameters</th><th>Value</th></tr> <tr><td>Temperature</td><td><span class="sensor">""" + str(bme.values[0]) + """</span></td></tr> <tr><td>Pressure</td><td><span class="sensor">""" + str(bme.values[1]) + """</span></td></tr> <tr><td>Humidity</td><td><span class="sensor">""" + str(bme.values[2]) + """</span></td></tr> <head><meta http-equiv="refresh" content="5"><meta name="viewport" content="width=device-width, initial-scale=1"><style>img{display: block; margin-left: auto; margin-right: auto;}</style></head><body><img src="data:image/jpeg;base64,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" alt="pico" style="max-width:100%;"> </body></html>""" return html # Wait for connect or fail wait = 10 while wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break wait -= 1 print('waiting for connection...') time.sleep(1) # Handle connection error if wlan.status() != 3: raise RuntimeError('wifi connection failed') else: print('connected') ip=wlan.ifconfig()[0] print('IP: ', ip) # Open socket addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('', 80)) server.listen(5) print('listening on', addr) while True: try: conn, addr = server.accept() conn.settimeout(3.0) print('client connected from', addr) request = conn.recv(1024) conn.settimeout(None) # HTTP-Request receive print('Request:', request) # HTTP-Response send response = web_page() conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') conn.sendall(response) conn.close() except OSError as e: conn.close() print('connection closed') |
Execute the main.py file now. If the hardware connection is correct, the Shell shows the following results.
Copy the IP Address and paste it on any Web browser and hit enter button.
The Webpage will also display the temperature, pressure & humidity readings of the BME280 sensor.
Conclusion
In conclusion, the Raspberry Pi Pico W Web Server With BME280 is a great way to monitor the weather conditions in your area. By connecting the Pico to the internet, you can keep an eye on the current conditions and forecasts for your area.
Raspberry Pi Pico W Weather Station Video
4 Comments
Pingback: BME280 Sensor With Raspberry Pi Pico W Using MicroPython Code
Pingback: BMP180 Pressure Sensor Monitor On Adafruit Io With ESP32
I have two suggested improvements:
In main.py
To stop the EADDRINUSE error on line 54 – server.bind((”, 80))
You can either wait two minutes, reboot the Pico, or use the socket.SO_REUSEADDR option. So the code should look like this:
# Open socket
addr = socket.getaddrinfo(‘0.0.0.0’, 80)[0][-1]
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((”, 80))
—————
In bme280.py
If someone in the US wanted to use imperial units, they could change out the last few likes of bme280.py to look like this:
@property
def values(self):
“”” human readable values “””
t, p, h = self.read_compensated_data()
t = t / 100
t = t * 9 / 5 + 32
p = p // 256
p = p / 3386.39
hi = h // 1024
return (“{:.1f} *F”.format(t), “{:.2f} inHg”.format(p),
“{} %”.format(hi))
—————
In main.py
I never could get line 2
from time import sleep
to work, so I just replaced it with
import time
I need time because I’m going to display the current time on the page.
Thank you for you excellent project
Bruce
waiting for connection…
Traceback (most recent call last):
File “”, line 45, in
RuntimeError: wifi connection failed