032 – MicroPython TechNotes: BMP280 Sensor

In this article, we will learn to use the BMP280 sensor with ESP32 using MicroPython.
PINOUT:
- GND – for the ground pin.
- VCC – for the supply voltage.
- SDA – for the i2c serial data pin.
- SCL – for the i2c serial clock pin.
BILL OF MATERIALS:
- ESP32 development board.
- ESP32 shield from Gorillacell ESP32 development kit.
- 4-pin female-female dupont wires.
- BMP280 temperature, pressure, and altitude sensor module.
HARDWARE INSTRUCTION:
- First, attach the ESP32 board on top of the ESP32 shield making sure that both USB port are on the same side.
- Next, attach the dupont wires to the BMP280 sensor by following a color coding which is black for the ground, red for the VCC, yellow for the SDA pin, and white for the SCL pin.
- Next, attach the other end of the dupont wires to the ESP32 shield by matching the colors of the wires to the colors of the pin headers which is black to black, red to red, yellow and the following colors to the yellow pin headers. For this, I choose GPIO 21 for the SDA pin and GPIO 22 for the SCL pin.
- Next, power the ESP32 shield with an external power supply with a type-C USB connector and make sure that the power switch is set to ON state.
- Lastly, connect the ESP32 to the computer through the micro USB cable.
SOFTWARE INSTRUCTION:
- Copy and paste the bmp280.py to Thonny IDE and save it to ESP32 MicroPython device root directory by clicking the File menu and select Save As. Click MicroPython Device and save it as bmp280.py.
- Copy and paste the examples to Thonny IDE. You may modify it according to your needs.
- Happy tinkering.
VIDEO DEMONSTRATION:
For any concern, write your message in the comment section.
You might also like to support my journey on Youtube by Subscribing. Click this to Subscribe to TechToTinker.
Thank you and have a good days ahead.
See you,
– George Bantique | tech.to.tinker@gmail.com
SOURCE CODE:
1. Example # 1, exploring the basics of BMP280 sensor:
# More details can be found in TechToTinker.blogspot.com
# George Bantique | tech.to.tinker@gmail.com
from machine import Pin
from machine import I2C
from bmp280 import BMP280
i2c_bus = I2C(0, sda=Pin(21), scl=Pin(22))
bmp = BMP280(i2c_bus)
# The following lines of code should be tested in the REPL:
# 1. To get envirment temperature (^C):
# bmp.getTemp()
#
# 2. To get Pressure (hPa):
# bmp.getPress()
#
# 3. To calculate absolute altitude (m):
# bmp.getAlti()
2. Example # 2, displaying the BMP280 sensor readings in the OLED display:
# More details can be found in TechToTinker.blogspot.com
# George Bantique | tech.to.tinker@gmail.com
from machine import Pin
from machine import I2C
from bmp280 import BMP280
from ssd1306 import SSD1306_I2C
import freesans20
from writer_minimal import Writer
from time import sleep_ms
oled_i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
oled = SSD1306_I2C(128, 64, oled_i2c, addr=0x3C)
font_writer = Writer(oled, freesans20)
bmp_bus = I2C(0, sda=Pin(21), scl=Pin(22))
bmp = BMP280(bmp_bus)
while True:
# Get the current readings
temp = bmp.getTemp()
press = bmp.getPress()
alti = bmp.getAlti()
# Update the OLED with current readings
oled.fill(0)
font_writer.set_textpos(0, 0)
font_writer.printstring('T:{:.2f}^C'.format(temp))
font_writer.set_textpos(20, 0)
font_writer.printstring('P:{:.0f}hPa'.format(press))
font_writer.set_textpos(40, 0)
font_writer.printstring('A:{:.2f}m'.format(alti))
oled.show()
# Also send to the REPL the current readings
print('T:{:.2f}^C'.format(temp),
'P:{:.0f}hPa'.format(press),
'A:{:.2f}m'.format(alti))
# Read and update only every 1000 ms
sleep_ms(1000)
3. bmp280.py driver library for BMP280:
'''
mpy drive for BMP280 Digital Pressure Sensor
Author: shaoziyang
Date: 2018.2
http://www.micropython.org.cn
'''
from micropython import const
from machine import I2C
BMP280_I2C_ADDR = const(0x76)
class BMP280():
def __init__(self, i2c):
self.i2c = i2c
self.tb = bytearray(1)
self.rb = bytearray(1)
self.dig_T1 = self.get2Reg(0x88)
self.dig_T2 = self.short(self.get2Reg(0x8A))
self.dig_T3 = self.short(self.get2Reg(0x8C))
self.dig_P1 = self.get2Reg(0x8E)
self.dig_P2 = self.short(self.get2Reg(0x90))
self.dig_P3 = self.short(self.get2Reg(0x92))
self.dig_P4 = self.short(self.get2Reg(0x94))
self.dig_P5 = self.short(self.get2Reg(0x96))
self.dig_P6 = self.short(self.get2Reg(0x98))
self.dig_P7 = self.short(self.get2Reg(0x9A))
self.dig_P8 = self.short(self.get2Reg(0x9C))
self.dig_P9 = self.short(self.get2Reg(0x9E))
self.mode = 3
self.osrs_p = 3
self.osrs_t = 1
self.setReg(0xF4, 0x2F)
self.setReg(0xF5, 0x0C)
self.filter = 3
self.T = 0
self.P = 0
self.version = '1.0'
def short(self, dat):
if dat > 32767:
return dat - 65536
else:
return dat
# set reg
def setReg(self, reg, dat):
self.tb[0] = dat
self.i2c.writeto_mem(BMP280_I2C_ADDR, reg, self.tb)
# get reg
def getReg(self, reg):
self.i2c.readfrom_mem_into(BMP280_I2C_ADDR, reg, self.rb)
return self.rb[0]
# get two reg
def get2Reg(self, reg):
return self.getReg(reg) + self.getReg(reg+1) * 256
def get(self):
adc_T = (self.getReg(0xFA)<<12) + (self.getReg(0xFB)<<4) + (self.getReg(0xFC)>>4)
var1 = (((adc_T>>3)-(self.dig_T1<<1))*self.dig_T2)>>11
var2 = (((((adc_T>>4)-self.dig_T1)*((adc_T>>4) - self.dig_T1))>>12)*self.dig_T3)>>14
t = var1+var2
self.T = ((t * 5 + 128) >> 8)/100
var1 = (t>>1) - 64000
var2 = (((var1>>2) * (var1>>2)) >> 11 ) * self.dig_P6
var2 = var2 + ((var1*self.dig_P5)<<1)
var2 = (var2>>2)+(self.dig_P4<<16)
var1 = (((self.dig_P3*((var1>>2)*(var1>>2))>>13)>>3) + (((self.dig_P2) * var1)>>1))>>18
var1 = ((32768+var1)*self.dig_P1)>>15
if var1 == 0:
return # avoid exception caused by division by zero
adc_P = (self.getReg(0xF7)<<12) + (self.getReg(0xF8)<<4) + (self.getReg(0xF9)>>4)
p=((1048576-adc_P)-(var2>>12))*3125
if p < 0x80000000:
p = (p << 1) // var1
else:
p = (p // var1) * 2
var1 = (self.dig_P9 * (((p>>3)*(p>>3))>>13))>>12
var2 = (((p>>2)) * self.dig_P8)>>13
self.P = p + ((var1 + var2 + self.dig_P7) >> 4)
return [self.T, self.P]
# get Temperature in Celsius
def getTemp(self):
self.get()
return self.T
# get Pressure in Pa
def getPress(self):
self.get()
return self.P
# Calculating absolute altitude
def getAlti(self):
return 44330*(1-(self.getPress()/101325)**(1/5.255))
# sleep mode
def poweroff(self):
self.setReg(0xF4, 0)
# normal mode
def poweron(self):
self.setReg(0xF4, 0x2F)
4. Copy ssd1306.py from:
5. Copy the custom fonts, writer_minimal.py, and freesans20.py from:
REFERENCES AND CREDITS:
1. Purchase your Gorillacell ESP32 development kit at:
2. Zhaoziyang BMP280 driver library: