梅雨が明けてかなり暑くなってきました。我が家は2Fにリビングと寝室があるので夏場は熱気が溜まってかなりの暑さになります。
先日、就寝中の動画を取得するツールを作成しましたが、
RaspberryPi3とPythonで就寝中の自分の音声付き動画を取得する
部屋の温湿度が自分の就寝具合(夜中に目が覚めたり、イビキが増減)にどういった影響を与えるかを確かめるために、温湿度の監視も追加することにしました。
環境
ハードウェア
・RaspberryPi3
・BME280
ソフトウェア
・Python3.5.3
・jupyter Notebook
やり方
(1) 既に動画撮影用に部屋にRaspberryPi3が設置してあるのでここにセンサを追加します。Pi3ならWifi経由のデータも容易です。
(2) 使用するセンサはBME280としました。
よく使われているらしくweb上でも情報が豊富です。
(3) RaspberryPi3に配線
RaspberryPiのI2C用のピンにはプルアップ抵抗が内蔵されているため接続するだけでOKです。
(4)BME280のデータ取得とcsvファイル保存
I2Cでセンサーのデータを取得してcsvファイルに保存するPythonスクリプトを作成します。こちらの記事を参考にPython3用にわずかに変更しました。1分毎に「bme280.csv」という名前のファイルに追記しています。
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 |
#coding: utf-8 import smbus import datetime import csv from time import sleep bus_number = 1 i2c_address = 0x76 DATA_DIR = '/home/pi/data/' 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(): #get record_time and date record_datetime = datetime.datetime.now() record_file_name = 'bme280.csv' #record_file_name = record_datetime.strftime('%Y%m%d') + '_bme280.csv' record_time = record_datetime.strftime('%X') #get data 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] T=compensate_T(temp_raw) P=compensate_P(pres_raw) H=compensate_H(hum_raw) #record_date writer = csv.writer(open(record_file_name,'a')) writer.writerow([record_time,T,P,H]) 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 = 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 = pressure + ((v1 + v2 + digP[6]) / 16.0) print ("pressure : %7.2f hPa" % (pressure/100)) 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 print ("temp : %-6.2f ℃" % (temperature)) 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 = 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 print ("hum : %6.2f %" % (var_h)) 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__': try: while True: readData() sleep(60) except KeyboardInterrupt: pass |
(5) BME280データの可視化
jupyterでPandas,matplotlibを使って可視化するコードを描いてみました。
(4)で作成したcsvファイルを読み込んで、pandasのplotでグラフ化しています。
plot内の引数は理解が浅いこともありゴチャゴチャしています。
日本語から変換した℃だとグラフ上の表記が□になってしまったので
どうしたものかと思っていたところ'Temperature($^\circ$C)'と記載すると
Temperature(℃)と表示できました。
結果
試しに16:30〜18:30頃のエアコン無しの寝室の温度、湿度、気圧をプロットしてみた時の結果です
夕方4時過ぎで37℃を超えていました。
手持ちの温度計で測った際にも37℃くらいだったので値は概ね正しそうです。
これから本格的な夏を迎えた時にはどうなってしまうのでしょうか。。
以上。
参照
Raspberry Pi 3 でK09421(BME280)のセンサ出力を定期的にcsvへ出力する
http://kagemomiji.hateblo.jp/entry/2016/08/16/003224
python – matplotlibで摂氏記号を印刷する方法
https://codeday.me/jp/qa/20190311/411129.html