RaspberryPiでBME280を使って20x4 LCDに表示する

準備

LCDの接続(LCDは3.3V用を使う)

lcd_d0= n.c
lcd_d1= n.c
lcd_d2= n.c
lcd_d3= n.c
lcd_d4= GP-5(29ピン)
lcd_d5= GP-6(31ピン)
lcd_d6= GP-13(33ピン)
lcd_d7= GP-19(35ピン)
lcd_rs= GP-20(38ピン)
lcd_en= GP-21(40ピン)
lcd_rw= GND

LCDのR/WピンをLow固定にして書き込み固定モードであれば、5V電源LCDを3.3V信号で駆動することも可能。
パラレルではなくI2Cの場合は双方向になるので無理。

MBE280の接続~

BME_SDA= 3ピン
BME_SCL= 5ピン

VCC/GNDの接続

VCC= 1ピン(3.3V)
GND= 6ピン

ソースコード

pi@pi3b2:~/bme280$ cat bme280_lcd.py
#coding: utf-8

from smbus2 import SMBus
import time

import Adafruit_CharLCD as LCD
from datetime import datetime

import os
import commands

bus_number  = 1
i2c_address = 0x77

bus = SMBus(bus_number)

digT = []
digP = []
digH = []

t_fine = 0.0

# GND Pin: 6 9 14 30 25 30 34 39
# LCD pin assign(GPIO Num)
lcd_rs= 20      # 38pin
lcd_en= 21      # 40pin
lcd_d4= 5       # 29pin
lcd_d5= 6       # 31pin
lcd_d6= 13      # 33pin
lcd_d7= 19      # 35pin
lcd_backlight = 4

# Define LCD column and row size.
lcd_columns= 20
lcd_rows= 4

# Initialize the LCD using the pins above.
lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7,lcd_columns, lcd_rows, lcd_backlight)

lcd.clear()




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]

        compensate_T(temp_raw)
        compensate_P(pres_raw)
        compensate_H(hum_raw)

def compensate_P(adc_P):
        global  t_fine,p
        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 "%7.2f hPa" % (pressure/100)
        p = "%4.0f" % (pressure/100)

def compensate_T(adc_T):
        global t_fine,t
        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 "  %-6.2f℃" % (temperature)
        t = "%-4.1f" % (temperature)

def compensate_H(adc_H):
        global t_fine,h
        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 " %6.2f %" % (var_h)
        h = "%2.0f" % (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:
                time.sleep(1)
                lcd.clear()
                while True:
                        readData()

                        cpu_temp = commands.getoutput("vcgencmd measure_temp").split('=')
                        #cpu_volt=commands.getoutput("vcgencmd measure_volts").split('=')
                        cpu_mem=commands.getoutput("vcgencmd get_mem arm").split('=')
                        cpu_gpu=commands.getoutput("vcgencmd get_mem gpu").split('=')

                        dt_now = datetime.now()
                        week_num = dt_now.strftime("%w")
                        if week_num == "0":
                                week_text = 'Sun'
                        if week_num == "1":
                                week_text = 'Mon'
                        if week_num == "2":
                                week_text = 'Tue'
                        if week_num == "3":
                                week_text = 'Wed'
                        if week_num == "4":
                                week_text = 'Thu'
                        if week_num == "5":
                                week_text = 'Fri'
                        if week_num == "6":
                                week_text = 'Sat'

                        lcd.blink(False)
                        #message_text = dt_now.strftime("%Y/%m/%d ")
                        message_text = dt_now.strftime("%m/%d") + "(" + week_text + ")  " + dt_now.strftime("%H:%M:%S")
                        lcd.message(message_text)
                        lcd.set_cursor(0,2)
                        message_text = "CPU:" + cpu_temp[1] + " " + cpu_mem[1] + " " + cpu_gpu[1]
                        lcd.message(message_text)
                        lcd.set_cursor(0,3)
                        message_text = "Ext:" + p + "hP " + t + "C " + h + "%" + ""
                        lcd.message(message_text)

                        time.sleep(0.2)
                        lcd.home()

        except KeyboardInterrupt:
                lcd.clear()
                time.sleep(1.0)

付録(10分おきにファイルに記録)

準備

ソースコードは全て/home/pi/bme280に置いておく
データの保存先は/home/pi/bme280/dataにする
その他必要なファイルも置いておく

ソースコード

pi@pi3b2:~/bme280$ cat bme280_csv.py
#coding: utf-8

import bme280_custom
import bme280_temp
import bme280_pres
import bme280_humid
import datetime
import os

dir_path = '/home/pi/bme280/data'

now = datetime.datetime.now()
filename = now.strftime('%Y%m%d')
label = now.strftime('%H:%M')
date = now.strftime('%Y/%m/%d %H:%M')
csv = bme280_custom.readData()
csv_t = bme280_temp.readData()
csv_p = bme280_pres.readData()
csv_h = bme280_humid.readData()

if not os.path.exists('/home/pi/bme280/data'):
    os.makedirs('/home/pi/bme280/data')

f = open('/home/pi/bme280/data/'+filename+'.csv','a')
f.write("'"+date+"',"+csv+"\n")
f.close()

f = open('/home/pi/bme280/data/'+filename+'_t.csv','a')
f.write("'"+date+"',"+csv_t+"\n")
f.close()
f = open('/home/pi/bme280/data/'+filename+'_p.csv','a')
f.write("'"+date+"',"+csv_p+"\n")
f.close()

f = open('/home/pi/bme280/data/'+filename+'_h.csv','a')
f.write("'"+date+"',"+csv_h+"\n")
f.close()

crontabで10分おきに実行する

@reboot python ~/bme280/bme280_lcd.py
0,10,20,30,40,50 * * * * python ~/bme280/bme280_csv.py

モジュールの種類

3.3V専用(秋月でも売ってるタイプ)

アドレス:0x77 BME-Blue.jpg

3.3V/5V兼用

アドレス:0x76 BME-Purple.jpg

BMEとBMPの見分け方

BMPは湿度が測れない(そのかわり安い) BME280_U.jpg

BME280 Rasbee製(3.3V専用)

SDOCSBSDASCLGNDVCC
PDPUPUPU

CSBがPUされているのでI2Cモード
SDOがPDされているので、I2C Addressは0x76
→SDOをVDDに繋ぐと0x77

BME280_Rasbee.jpg


添付ファイル: filebme280_lcd.py 145件 [詳細] filebme280_custom.py 149件 [詳細] fileBME-Purple.jpg 374件 [詳細] filebme280_humid.py 167件 [詳細] fileBME280.pdf 130件 [詳細] filebme280_pres.py 150件 [詳細] fileBME-Blue.jpg 383件 [詳細] filebme280_temp.py 149件 [詳細] fileBME280_U.jpg 374件 [詳細] fileBME280_Rasbee.jpg 320件 [詳細] fileBMP280.jpg 281件 [詳細] filebme280_csv.py 176件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-11-27 (月) 23:39:34