라즈베리 파이 BMP085: I2C로 정확한 온도 및 기압 측정하기
보쉬 BMP085는 정밀한 기압과 온도 측정을 제공하는 소형 저가 I2C 센서입니다. 이베이에서 몇 달러에 구입할 수 있으며 기상 관측소, 고도 로거, 신뢰할 수 있는 환경 데이터가 필요한 모든 프로젝트에 이상적인 구성품입니다.
Adafruit의 BMP085 가이드와 라이브러리가 턴키 솔루션을 제공하지만, 코드를 깊이 들여다보면 원시 센서 데이터를 사람이 읽을 수 있는 값으로 변환하는 보상 공식을 이해할 수 있습니다. 아래에서 Adafruit 레퍼런스와 나만의 파이썬 구현을 결합해 센서가 정확히 어떻게 작동하는지 보여줍니다.
BMP085를 라즈베리 파이에 배선하는 것은 간단합니다: VCC를 3.3V, GND를 그라운드, SDA를 GPIO2, SCL을 GPIO3에 연결하세요. 기본 I2C 주소는 0x77입니다.
# BMP085 I2C 주소
BMP085_ADDR = 0x77
파이썬 구현
import smbus
import time
class BMP085:
# 오버샘플링 설정 (0~3). 3이 가장 높은 정확도.
OSS = 3
def __init__(self, i2c, address=BMP085_ADDR):
self.i2c = i2c
self.address = address
# 보정 계수 – EEPROM에서 한 번 읽음
self.ac1 = self._read_signed(0xAA)
self.ac2 = self._read_signed(0xAC)
self.ac3 = self._read_signed(0xAE)
self.ac4 = self._read_unsigned(0xB0)
self.ac5 = self._read_unsigned(0xB2)
self.ac6 = self._read_unsigned(0xB4)
self.b1 = self._read_signed(0xB6)
self.b2 = self._read_signed(0xB8)
self.mb = self._read_signed(0xBA)
self.mc = self._read_signed(0xBC)
self.md = self._read_signed(0xBE)
def _read_unsigned(self, reg):
msb = self.i2c.read_byte_data(self.address, reg)
lsb = self.i2c.read_byte_data(self.address, reg + 1)
return (msb << 8) + lsb
def _read_signed(self, reg):
val = self._read_unsigned(reg)
return val - 65536 if val > 32767 else val
def _read_ut(self):
# 온도 측정 트리거
self.i2c.write_byte_data(self.address, 0xF4, 0x2E)
time.sleep(0.0045)
return self._read_unsigned(0xF6)
def read_temperature(self):
ut = self._read_ut()
x1 = ((ut - self.ac6) * self.ac5) >> 15
x2 = (self.mc << 11) // (x1 + self.md)
self.b5 = x1 + x2
temp = (self.b5 + 8) >> 4 # 0.1°C 단위
return temp / 10.0
def _read_up(self):
# 선택한 OSS로 기압 측정 트리거
cmd = 0x34 + (self.OSS << 6)
self.i2c.write_byte_data(self.address, 0xF4, cmd)
delay = (2 + (3 << self.OSS)) / 1000.0
time.sleep(delay)
msb = self.i2c.read_byte_data(self.address, 0xF6)
lsb = self.i2c.read_byte_data(self.address, 0xF7)
xlsb = self.i2c.read_byte_data(self.address, 0xF8)
up = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.OSS)
return up
def read_pressure(self):
up = self._read_up()
b6 = self.b5 - 4000
x1 = (self.b2 * (b6 * b6) >> 12) >> 11
x2 = (self.ac2 * b6) >> 11
x3 = x1 + x2
b3 = (((self.ac1 * 4 + x3) << self.OSS) + 2) >> 2
x1 = (self.ac3 * b6) >> 13
x2 = (self.b1 * (b6 * b6) >> 12) >> 16
x3 = ((x1 + x2) + 2) >> 2
b4 = (self.ac4 * (x3 + 32768)) >> 15
b7 = (up - b3) * (50000 >> self.OSS)
if b7 < 0x80000000:
p = (b7 * 2) // b4
else:
p = (b7 // b4) << 1
p = ((p + 1) * 1) >> 1
x1 = (p >> 8) * (p >> 8)
x1 = (x1 * 3038) >> 16
x2 = (-7357 * p) >> 16
p = p + ((x1 + x2 + 3791) >> 4)
return p # Pa 단위
# 사용 예시
bus = smbus.SMBus(1) # 라즈베리 파이 I2C 버스
bmp = BMP085(bus)
print(f"Temperature: {bmp.read_temperature():.2f} °C")
print(f"Pressure: {bmp.read_pressure() / 100:.2f} hPa")
이 스크립트는 보쉬의 BMP085 데이터시트에 설명된 전체 보정 루틴을 수행합니다. 프로그램을 실행하면 섭씨 온도와 헥토파스칼 단위 기압이 출력되어 파이썬 애플리케이션에서 바로 사용할 수 있습니다.
직접 구현하는 이유?
Adafruit 라이브러리를 사용하면 시간을 아낄 수 있지만, 센서 뒤의 수학을 이해하면 샘플링 속도 조정, 원시 데이터 스트림 처리, 다른 마이크로컨트롤러로 코드 이식 등이 가능해집니다. 취미가든 숙련된 엔지니어든 BMP085의 내부를 마스터하면 툴킷에 귀중한 기술이 추가됩니다.