
#!/usr/bin/python3
from fcntl import ioctl
import os
import time
# return two bytes from data as an unsigned 16-bit value
def get_uint16(dat, index):
return (dat[index] << 8) + dat[index + 1]
# return two bytes from data as a signed 16-bit value
def get_int16(dat, index):
val = (dat[index] << 8) + dat[index + 1]
if val > 32767:
val = val - 65536
return val
# refine bmp180 raw sample, ref. bmp180 datasheet
def refine_UT_UP(UT, UP, OVERSAMPLE = 3):
# Refine temperature
X1 = ((UT - AC6) * AC5) >> 15
X2 = (MC << 11) / (X1 + MD)
B5 = X1 + X2
temperature = int(B5 + 8) >> 4
# Refine pressure
UP = UP >> (8 - OVERSAMPLE)
B6 = B5 - 4000
B62 = int(B6 * B6) >> 12
X1 = (B2 * B62) >> 11
X2 = int(AC2 * B6) >> 11
X3 = X1 + X2
B3 = (((AC1 * 4 + X3) << OVERSAMPLE) + 2) >> 2
X1 = int(AC3 * B6) >> 13
X2 = (B1 * B62) >> 16
X3 = ((X1 + X2) + 2) >> 2
B4 = (AC4 * (X3 + 32768)) >> 15
B7 = (UP - B3) * (50000 >> OVERSAMPLE)
P = (B7 * 2) / B4
X1 = (int(P) >> 8) * (int(P) >> 8)
X1 = (X1 * 3038) >> 16
X2 = int(-7357 * P) >> 16
pressure = int(P + ((X1 + X2 + 3791) >> 4))
# Return temperature in degree C; pressure in mbar
return(temperature/10.0, pressure/100.0)
# ======== gpio ===========
# gpio0 --> touch sensor power
# gpio1 <-- touch sensor output
os.system('echo in > /sys/class/gpio/gpio1/direction')
os.system('echo out > /sys/class/gpio/gpio0/direction')
# Set gpio0 high, touch sensor power on, LED on
os.system('echo 1 > /sys/class/gpio/gpio0/value')
gpio1 = open("/sys/class/gpio/gpio1/value", "r")
#===== bmp180 i2c open and read calibration data ====
bmp180_i2c = open("/dev/i2c-1", "r+b", buffering=0)
# bmp180 i2c slave address 0x77
I2C_SLAVE_ADDR = 0x77
# ioctl function number: force set i2c slave address
I2C_SLAVE_FORCE = 0x0706
rt = ioctl(bmp180_i2c, I2C_SLAVE_FORCE, I2C_SLAVE_ADDR)
#read 22 bytes starting from register 0xAA
rt = bmp180_i2c.write(bytes([0xaa]))
dat = bmp180_i2c.read(22)
# Convert calibration byte data to word values
AC1 = get_int16(dat, 0)
AC2 = get_int16(dat, 2)
AC3 = get_int16(dat, 4)
AC4 = get_uint16(dat, 6)
AC5 = get_uint16(dat, 8)
AC6 = get_uint16(dat, 10)
B1 = get_int16(dat, 12)
B2 = get_int16(dat, 14)
MB = get_int16(dat, 16)
MC = get_int16(dat, 18)
MD = get_int16(dat, 20)
touch_state = 0
#===== Main Loop ======
while True:
#====== touch sensor action
gpio1.seek(0) # rewind for read
if gpio1.read() == '1\n':
touch = 1
else:
touch = 0
if touch == 1 and touch_state == 0:
# say Good on LED display
os.system('echo \"Good\" > /tmp/led')
elif touch == 0 and touch_state == 1:
# default LED display
os.system('echo \"&&\" > /tmp/led')
touch_state = touch
#====== BMP180 i2c
# write 0x2E to reg. 0xF4, start sampling UT
rt = bmp180_i2c.write(bytes([0xf4, 0x2e]))
time.sleep(.0045)
# read 2 bytes starting from reg. 0xF6
rt = bmp180_i2c.write(bytes([0xf6]))
dat = bmp180_i2c.read(2)
UT = get_uint16(dat, 0)
# write 0x34+(OVERSAMPLE<<6) to reg. 0xF4, start sampling UP
rt = bmp180_i2c.write(bytes([0xf4, 0x34 + (3<<6)]))
time.sleep(.0225)
# read 3 bytes starting from reg. 0xF6
rt = bmp180_i2c.write(bytes([0xf6]))
dat = bmp180_i2c.read(3)
UP = (dat[0]<<16) + get_uint16(dat, 1)
temperature, pressure = refine_UT_UP(UT, UP)
# The pressure change per meter of sensor altitude should be approximately 0.12 mbar
print("touch =", touch_state, " Temp =", temperature, "C Pressure =", pressure, "mbar")
time.sleep(0.2)
這是一個 Python3 程式,用於讀取和處理 BMP180 溫度和氣壓感測器的數據,以及監控觸摸感測器的狀態。以下是該程式碼的解釋:
導入所需的庫:
fcntl
,os
, 和time
。定義兩個函數
get_uint16()
和get_int16()
,它們將從二進制數據中提取無符號和有符號 16 位值。定義函數
refine_UT_UP()
,該函數根據 BMP180 數據表對原始樣本進行修正,並返回溫度(攝氏度)和壓力(mbar)值。初始化 GPIO 並設置觸摸感測器的電源和輸出。
開啟 BMP180 I2C 連接,並讀取校準數據。
初始化觸摸感測器狀態。
進入主循環,進行以下操作: a. 讀取觸摸感測器的狀態,並根據狀態改變 LED 顯示。 b. 讀取 BMP180 的溫度(UT)和壓力(UP)數據。 c. 使用
refine_UT_UP()
函數獲得精確的溫度和壓力值。 d. 打印觸摸感測器狀態、溫度和壓力值。 e. 暫停 0.2 秒後繼續循環。
該程式運行時將不斷監控觸摸感測器的狀態,並顯示 BMP180 溫度和氣壓感測器的數據。
執行程式:
$ sudo testMPIO10.py
用手指按觸 “Touch here” 區域,螢幕顯示會由 touch = 0 變成 touch =1 。
請注意,示範程式顯示的溫度和氣壓值未經校正。如何校正請參考:
BMP180 Digital Pressure Sensor Data Sheet
停止程式執行按 Ctrl+c。