「raspberry pi 3でC言語による環境センサー「BME280」の接続」でC言語により温湿度・気圧データを入力しましたが、今回はPython言語により温湿度・気圧データを入力して、raspberry pi 3からjson形式でネット上にアップロードします。json形式でネット上にアップロードするには、「python言語でHTTP Request-jsonによるデータ送信」を使用します。
「raspberry pi 3への環境センサー「BME280」の接続」と「raspberry pi 3でのBME280の接続確認」については、上記のリンクを参照ください。
環境センサー「BME280」プログラムの作成
環境センサー「BME280」のPython言語によるプログラムは、スイッチサイエンスの「SWITCHSCIENCE/BME280」を流用します。
Pythonから操作ために、次のように「python-smbus」パッケージをインストールします。
$ sudo apt-get install python-smbus
I2C 通信には smbus ライブラリを利用します。smbus.SMBus(bus_number) にてコネクションオブジェクトを取得し、write_byte_data で指定したアドレスに一バイトのデータを出力し、read_byte_dataで指定したアドレスから一バイトのデータを入力します。
「jsondump.php」は、サーバから受け取ったhttpメッセージのヘッダとbodyをレスポンスとして返すphpプログラムです。
bme280.py
# coding: utf-8 import smbus import json import requests bus_number = 1 i2c_address = 0x76 bus = smbus.SMBus(bus_number) digT = [] digP = [] digH = [] t_fine = 0.0 def writereg(reg_address, data): bus.write_byte_data(i2c_address, reg_address, data) def get_calib_param(): calib = [] for i in range(0x88, 0x88 + 24): calib.append(bus.read_byte_data(i2c_address, i)) calib.append(bus.read_byte_data(i2c_address, 0xA1)) for i in range(0xE1, 0xE1 + 7): calib.append(bus.read_byte_data(i2c_address, i)) digT.append((calib[1] << 8) | calib[0]) digT.append((calib[3] << 8) | calib[2]) digT.append((calib[5] << 8) | calib[4]) digP.append((calib[7] << 8) | calib[6]) digP.append((calib[9] << 8) | calib[8]) digP.append((calib[11] << 8) | calib[10]) digP.append((calib[13] << 8) | calib[12]) digP.append((calib[15] << 8) | calib[14]) digP.append((calib[17] << 8) | calib[16]) digP.append((calib[19] << 8) | calib[18]) digP.append((calib[21] << 8) | calib[20]) digP.append((calib[23] << 8) | calib[22]) digH.append(calib[24]) digH.append((calib[26] << 8) | calib[25]) digH.append(calib[27]) digH.append((calib[28] << 4) | (0x0F & calib[29])) digH.append((calib[30] << 4) | ((calib[29] >> 4) & 0x0F)) digH.append(calib[31]) for i in range(1, 2): if digT[i] & 0x8000: digT[i] = (-digT[i] ^ 0xFFFF) + 1 for i in range(1, 8): if digP[i] & 0x8000: digP[i] = (-digP[i] ^ 0xFFFF) + 1 for i in range(0, 6): if digH[i] & 0x8000: digH[i] = (-digH[i] ^ 0xFFFF) + 1 def readdata(): data = [] for i in range(0xF7, 0xF7 + 8): data.append(bus.read_byte_data(i2c_address, i)) pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4) temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4) hum_raw = (data[6] << 8) | data[7] return compensate_t(temp_raw), compensate_p(pres_raw), compensate_h(hum_raw) def compensate_p(adc_p): global t_fine pressure = 0.0 v1 = (t_fine / 2.0) - 64000.0 v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5] v2 += ((v1 * digP[4]) * 2.0) v2 = (v2 / 4.0) + (digP[3] * 65536.0) v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8) + ((digP[1] * v1) / 2.0)) / 262144 v1 = ((32768 + v1) * digP[0]) / 32768 if v1 == 0: return 0 pressure = ((1048576 - adc_p) - (v2 / 4096)) * 3125 if pressure < 0x80000000: pressure = (pressure * 2.0) / v1 else: pressure = (pressure / v1) * 2 v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096 v2 = ((pressure / 4.0) * digP[7]) / 8192.0 pressure += ((v1 + v2 + digP[6]) / 16.0) return pressure / 100 def compensate_t(adc_t): global t_fine v1 = (adc_t / 16384.0 - digT[0] / 1024.0) * digT[1] v2 = (adc_t / 131072.0 - digT[0] / 8192.0) * (adc_t / 131072.0 - digT[0] / 8192.0) * digT[2] t_fine = v1 + v2 temperature = t_fine / 5120.0 return temperature def compensate_h(adc_h): global t_fine var_h = t_fine - 76800.0 if var_h != 0: var_h = (adc_h - (digH[3] * 64.0 + digH[4] / 16384.0 * var_h)) * ( digH[1] / 65536.0 * (1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h))) else: return 0 var_h *= (1.0 - digH[0] * var_h / 524288.0) if var_h > 100.0: var_h = 100.0 elif var_h < 0.0: var_h = 0.0 return var_h def setup(): osrs_t = 1 # Temperature oversampling x 1 osrs_p = 1 # Pressure oversampling x 1 osrs_h = 1 # Humidity oversampling x 1 mode = 3 # Normal mode t_sb = 5 # Tstandby 1000ms filter = 0 # Filter off spi3w_en = 0 # 3-wire SPI Disable ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode config_reg = (t_sb << 5) | (filter << 2) | spi3w_en ctrl_hum_reg = osrs_h writereg(0xF2, ctrl_hum_reg) writereg(0xF4, ctrl_meas_reg) writereg(0xF5, config_reg) setup() get_calib_param() if __name__ == '__main__': sensor = {} try: sensor["Temperature"], sensor["Pressure"], sensor["Humidity"] = readdata() response = requests.post( 'http://192.168.0.100/jsondump.php', json.dumps(sensor), headers={'Content-Type': 'application/json'}) print response.text except KeyboardInterrupt: pass
__name__ とは
上記の「bme280.py」の場合、基本的に、「setup()」と「get_calib_param()」は絶対実行されます。「 if __name__ == ‘__main__’:」の判定は、コマンドラインから実行した場合、__name__という変数(属性)の中に自動的に__main__が代入されてTrueとなり、import文でモジュールとしてインポートされた場合、そのモジュール名 が__name__に入り、Falseとなります。
環境センサー「BME280」プログラムの実行
作成したプログラム「bme280.py」を実行すると、次のように端末に表示されます。気圧(Pressure)、温度(Temperature)、湿度(Humidity)の各センサ情報が、json形式になっていることが確認できます。
$ python bme280.py Array ( [Host] => 192.168.0.100 [Content-Length] => 98 [Accept-Encoding] => gzip, deflate [Accept] => */* [User-Agent] => python-requests/2.4.3 CPython/2.7.9 Linux/4.1.19-v7+ [Connection] => keep-alive [Content-Type] => application/json ) body{"Pressure": 1024.0542897935327, "Temperature": 20.222181864851155, "Humidity": 51.97098824435462}