ラズパイ5 2023年10月更新 bookworm ④ 気圧センサBME280をデバイス・ドライバで利用

　[第2回目](https://qiita.com/jamjam/items/c34dcfd59d1ac624d925)は、気圧センサLPS22HBを利用し、I2Cバスのアクセスは、smbus2ライブラリを利用してpythonで記述しました。

　ここでは、気圧センサBME280を利用します。温度、気圧、湿度が読み出せます。LPS22HBのつながっているI2CバスにStemma QT/Qwiicコネクタで増設します。LPS22HBをつなげたままにしているのは、外すのが面倒だっただけで他意はありません。両端がStemma QT/Qwiicコネクタのケーブルは市販されています。ラズパイのI2Cピン付近にStemma QT/Qwiicコネクタのメスが付いた製品もどこかで見かけました。

 ![bme260-b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/05e229f6-5b00-66eb-d118-d777defeb284.png)

　BME280は、ラズパイにはデバイス・ドライバが用意されているので、組み込んで、温度、気圧、湿度が読み出します。/boot/overlaysのREADMEによると、I2Cバス用のセンサは、各種利用できるようです。


:::note info

Name:   i2c-sensor
Info:   Adds support for a number of I2C barometric pressure, temperature,
        light level and chemical sensors on i2c_arm
Load:   dtoverlay=i2c-sensor,<param>=<val>
Params: addr                    Set the address for the BH1750, BME280, BME680,
                                BMP280, CCS811, DS1621, HDC100X, JC42, LM75,
                                MCP980x, MPU6050, MPU9250, MS5637, MS5803,
                                MS5805, MS5837, MS8607, SHT3x or TMP102

        aht10                   Select the Aosong AHT10 temperature and humidity
                                sensor

        bh1750                  Select the Rohm BH1750 ambient light sensor
                                Valid addresses 0x23 or 0x5c, default 0x23

        bme280                  Select the Bosch Sensortronic BME280
                                Valid addresses 0x76-0x77, default 0x76

        bme680                  Select the Bosch Sensortronic BME680
                                Valid addresses 0x76-0x77, default 0x76

        bmp085                  Select the Bosch Sensortronic BMP085

        bmp180                  Select the Bosch Sensortronic BMP180

        bmp280                  Select the Bosch Sensortronic BMP280
                                Valid addresses 0x76-0x77, default 0x76

        bno055                  Select the Bosch Sensortronic BNO055 IMU
                                Valid address 0x28-0x29, default 0x29

        ccs811                  Select the AMS CCS811 digital gas sensor
                                Valid addresses 0x5a-0x5b, default 0x5b

        ds1621                  Select the Dallas Semiconductors DS1621 temp
                                sensor. Valid addresses 0x48-0x4f, default 0x48

        hdc100x                 Select the Texas Instruments HDC100x temp sensor
                                Valid addresses 0x40-0x43, default 0x40

        htu21                   Select the HTU21 temperature and humidity sensor

        int_pin                 Set the GPIO to use for interrupts (max30102,
                                mpu6050 and mpu9250 only)

        jc42                    Select any of the many JEDEC JC42.4-compliant
                                temperature sensors, including:
                                  ADT7408, AT30TS00, CAT34TS02, CAT6095,
                                  MAX6604, MCP9804, MCP9805, MCP9808,
                                  MCP98242, MCP98243, MCP98244, MCP9843,
                                  SE97, SE98, STTS424(E), STTS2002, STTS3000,
                                  TSE2002, TSE2004, TS3000, and TS3001.
                                The default address is 0x18.

        lm75                    Select the Maxim LM75 temperature sensor
                                Valid addresses 0x48-0x4f, default 0x4f

        lm75addr                Deprecated - use addr parameter instead

        max17040                Select the Maxim Integrated MAX17040 battery
                                monitor

        max30102                Select the Maxim Integrated MAX30102 heart-rate
                                and blood-oxygen sensor

        mcp980x                 Select the Maxim MCP980x range of temperature
                                sensors (i.e. MCP9800, MCP9801, MCP9802 and
                                MCP9803). N.B. For MCP9804, MCP9805 and MCP9808,
                                use the "jc42" option.
                                Valid addresses are 0x18-0x1f (default 0x18)

        mpu6050                 Select the InvenSense MPU6050 IMU. Valid
                                valid addresses are 0x68 and 0x69 (default 0x68)

        mpu9250                 Select the InvenSense MPU9250 IMU. Valid
                                valid addresses are 0x68 and 0x69 (default 0x68)

        ms5637                  Select the Measurement Specialities MS5637
                                pressure and temperature sensor.

        ms5803                  Select the Measurement Specialities MS5803
                                pressure and temperature sensor.

        ms5805                  Select the Measurement Specialities MS5805
                                pressure and temperature sensor.

        ms5837                  Select the Measurement Specialities MS5837
                                pressure and temperature sensor.

        ms8607                  Select the Measurement Specialities MS8607
                                pressure and temperature sensor.

        no_timeout              Disable the SMBUS timeout. N.B. Only supported
                                by some jc42 devices - using with an
                                incompatible device can stop it from being
                                activated.

        reset_pin               GPIO to be used to reset the device (bno055
                                only, disabled by default)

        sht3x                   Select the Sensirion SHT3x temperature and
                                humidity sensors. Valid addresses 0x44-0x45,
                                default 0x44

        sht4x                   Select the Sensirion SHT4x temperature and
                                humidity sensors. Valid addresses 0x44-0x45,
                                default 0x44

        si7020                  Select the Silicon Labs Si7013/20/21 humidity/
                                temperature sensor

        sps30                   Select the Sensirion SPS30 particulate matter
                                sensor. Fixed address 0x69.

        sgp30                   Select the Sensirion SGP30 VOC sensor.
                                Fixed address 0x58.

        tmp102                  Select the Texas Instruments TMP102 temp sensor
                                Valid addresses 0x48-0x4b, default 0x48

        tsl4531                 Select the AMS TSL4531 digital ambient light
                                sensor

        veml6070                Select the Vishay VEML6070 ultraviolet light
                                sensor

        i2c0                    Choose the I2C0 bus on GPIOs 0&1

        i2c_csi_dsi             Choose the I2C0 bus on GPIOs 44&45

        i2c3                    Choose the I2C3 bus (configure with the i2c3
                                overlay - BCM2711 only)

        i2c4                    Choose the I2C3 bus (configure with the i2c3
                                overlay - BCM2711 only)

        i2c5                    Choose the I2C5 bus (configure with the i2c4
                                overlay - BCM2711 only)

        i2c6                    Choose the I2C6 bus (configure with the i2c6
                                overlay - BCM2711 only)
:::


### 接続

![lps22-bme280-TFT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/24c29cf6-d5fa-e926-21a4-9ed40f240779.png)


### BME280のデバイス・ドライバを組み込む

　~~`$ sudo nano /boot/config.txt`~~ <-2かしょにおなじもの？がある。
 `sudo nano /boot/firmware/config.txt`を立ち上げ、最後の行に、次の1行を追加します。

~~dtoverlay = i2c-sensor,bme280,addr=0x77~~
dtoverlay=i2c-sensor,bme280,addr=0x77

　イコールの前後のスペースは不要のようです。

　スレーブ・アドレスはデフォルトが0x76なので、その場合は、addr=の記述は不要です。利用しているAdafruitのStemma QT/Qwiicボードはデフォルトが0x77なので、上記の記述になります。

　デバイス・ドライバの組み込みのログをとるためには、そのあとに、つまり、最後の行にdtdebug=1を追加します。READMEの最後に書かれています。

CTRL-Oで上書き保存をし、CTRL-Xでnanoを抜けます。rebootします。

　デバイス・ドライバの組み込み時のメッセージは、 sudo vcdbg log msgで読み出せます。 vcdbg はapt-getでinstallします。

　リブート後システムが立ち上がったら、I2Cバスにつながっているセンサを表示します。

　0x5dはLPS22HBです。0x77のところはUUと表示され、BME280のデバイス・ドライバが組み込まれたことを示しています。

![ras501.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/aa5f1315-c3b7-a60c-4da9-65a5443f722b.png)


　デバイス・ドライバが組み込まれると次のディレクトリができているので、テキスト・ファイルを表示します。1-0077は、1-0076かもしれません。

$ ls /sys/bus/i2c/devices/1-0077/iio:device0/

in_humidityrelative_input               in_pressure_oversampling_ratio  name     subsystem
in_humidityrelative_oversampling_ratio  in_temp_input                   of_node  uevent
in_pressure_input                       in_temp_oversampling_ratio      power    waiting_for_supplier

　温度、気圧、湿度を読み出します。

$ cat /sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_temp_input
20750
$ cat /sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_pressure_input
101.522187500
$ cat /sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_humidityrelative_input
36620


　温度は千倍になっているので、20.75℃、気圧はPaなので、1015.22187500hPa、湿度は千倍になっているので、36.62%です。

　読み出しのプログラムです。

```python
import time
while 1:
    f = open('/sys/bus/i2c/devices/1-0077/iio:device0/in_temp_input')
    Temp = round(int(f.read()) / 1000.0, 1)
    f.close
    f = open('/sys/bus/i2c/devices/1-0077/iio:device0/in_humidityrelative_input')
    Humi = round(int(f.read()) / 1000.0, 0)
    f.close
    f = open('/sys/bus/i2c/devices/1-0077/iio:device0/in_pressure_input')
    Press = round(float(f.read()) * 10.0, 1)
    f.close
    message = "Temp : %sC, Humi : %sRH, Press : %shPa"
    print(message % (Temp, Humi, Press))
    time.sleep(2)
```

### 測定値をグラフィック・ディスプレイに表示

　[第3回目](https://qiita.com/jamjam/items/f96c041d9c10d229af9f)のコントローラST7789を使用したAdafruit 2.0" 320x240 Color IPS TFT Displayに、測定結果を表示します。

　st7789のライブラリは入ったままです。

```
$ pip list | grep ST7*
ST7789                             0.0.4
```

　プログラムです。

 ```python
 import time
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

import ST7789

disp = ST7789.ST7789(height=240,width=320,rotation=0,
    port=0,cs=0,dc=22,rst=25,backlight=None,
    spi_speed_hz=80 * 1000 * 1000
)

disp.begin()
img = Image.new('RGB', (disp.width, disp.height), color=(32, 32, 32))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf", 30)
draw.text((10,0),'Temp, press, Humi', font=font, fill=(255,0,0))
disp.display(img)
time.sleep(1)

while 1:
    f = open('/sys/bus/i2c/devices/1-0077/iio:device0/in_temp_input')
    Temp = round(int(f.read()) / 1000.0, 1)
    f.close
    f = open('/sys/bus/i2c/devices/1-0077/iio:device0/in_humidityrelative_input')
    Humi = round(int(f.read()) / 1000.0, 0)
    f.close
    f = open('/sys/bus/i2c/devices/1-0077/iio:device0/in_pressure_input')
    Press = round(float(f.read()) * 10.0, 1)
    f.close
    message = "Temp : %sC, Humi : %sRH, Press : %shPa"
    print(message % (Temp, Humi, Press))

    draw.rectangle((20, 50, 200,210), (32,32,32))
    draw.text((20,50),str(Temp)+'`C', font=font, fill=(25,255,25))
    draw.text((20,100),str(Humi) +'%', font=font, fill=(25,255,25))
    draw.text((20,150),str(Press)+'hPa', font=font, fill=(25,255,25))
    disp.display(img)
    time.sleep(2)
```

実行結果です。

![IMGP2092.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/6d825b49-1731-4c81-a4fe-41919d235356.png)


:::note alert
　ラズパイ5で、頻繁にリード・エラーが出るようになった。リトライを組み込むのがよさそう
 ```shell
Traceback (most recent call last):
  File "/home/yoshi/bme280_LCD.py", line 23, in <module>
    Temp = round(int(f.read()) / 1000.0, 1)
                     ^^^^^^^^
OSError: [Errno 5] Input/output error
```
:::