🌦️

xiao RP2040とセンサーで室内環境を測定してzabbixに送ってみる

2022/02/09に公開

はじめに

キーボードのためにXIAO RP2040を使い始めたのですが、
せっかくなので別のことにも使ってみようかと思いCO2などの測定をしてみようとした記録です。

目的

デスク周りや各部屋の以下の環境データを測定し、換気などの目安を探ってみる。

  • 温度
  • 湿度
  • CO2濃度

測定データはOLEDへ表示し、値の蓄積は既設のZabbix(v5.0系)で行うこととします。

利用するハードとソフト

ハードウェア

  • Seeed XIAO RP2040
  • CCS811(CO2センサー) DF Robot SEN0339
  • BME280(温湿度センサー) SSCI-022361
  • Wiznet W5500(通信モジュール) WIZ850io
  • SSD1306(手元にあった128*32のもの)

ソフトウェア

  • CircuitPython
    XIAOのWIKIにXIAORP2040用のUF2があるのでそれを利用します。

回路について

  • センサー・OLEDは、I2Cで接続する。
    ※XIAO RP2040はI2C1組しかPINがないため、回路上は全て同じSDA/SCLのPINから並列で繋ぎます。

  • WizNet W5500はSPIで接続し、任意のGPIO PINでRSTを繋ぎます。

  • 電源は全て3.3vで接続。

  • 今回利用しているBME280センサーはSDO PINの接続でI2Cアドレスが決まるため、VCCかGNDに繋ぐようにマニュアル記載があります。今回はGNDに繋ぐことにします。(アドレスは0x76になる)

プログラム

前述の通りCircuitPythonを利用します。
XIAO RP2040に今回必要となる以下のモジュール・ファイルを入れます。
(CircuitPythonを入れた状態でPCに接続するとマスストレージを認識するのでそこに入れます)

  • font5x8.bin(モジュールではないが、OLEDの表示で利用)
  • adfruit_bme280
  • adfruit_bus_device
  • adfruit_ccs811
  • adfruit_ssd1306
  • adfruit_wiznet5k
  • adfruit_framebuf
  • adfruit_register
  • adfruit_requests

W5500の通信周りとZabbixへの送信周りは以下のサイトを参考にさせていただきました。
Raspberry Pi Picoに有線LANポートを生やしてみる - あっきぃ日誌
Raspberry Pi Picoで1-Wireの温度センサーを使いつつZabbixに送りつける - あっきぃ日誌

コード

各種モジュールとTimeやJsonのモジュールをインポートする。

import board
import busio
import digitalio
import time
import json
import struct
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
import adafruit_ssd1306
import adafruit_ccs811
from adafruit_bme280 import basic as adafruit_bme280

XIAOの公式イメージはXIAOのI2C、SPIのPINには固定の名称が割り当てられているようで、I2C、SPIの設定は決まった名称を指定すれば良いようです。
※CSnだけ名称指定ができなかったのでGPIOで指定しました。
あわせてW5500のRSTもGPIOのPinを指定しておきます。

#i2c Config
i2c = busio.I2C(board.SCL, board.SDA)

# SPI Config
SPI1_SCK = board.SCK
SPI1_TX = board.MOSI
SPI1_RX = board.MISO
SPI1_CSn = board.D7
W5500_RSTn = board.D0

I2Cデバイスの設定

# ccs811 CO2 sensor
ccs811 = adafruit_ccs811.CCS811(i2c)

# bme280 temp/hum sensor
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c,0x76)

# ssd1306 oled
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, addr=0x3c)

W5500のMACアドレスやIP関連の設定は参考にしたサイトのコードをそのまま利用させていただいているのでここには記載しません。
Zabbixに送信する関数部分についても参考にしたサイトのコードをそのまま利用させていただきました。
メインロジック部は、安価なセンサーでそこかしこにコードが載っていますが、以下のような感じで動かしています。

while not ccs811.data_ready:
    pass
counter = 0
while True:
    co2 = ccs811.eco2
    voc = ccs811.tvoc
    temp = bme280.temperature
    hum = bme280.relative_humidity
    print("co2:",co2)
    print("tvoc:",voc)
    print("temp:",temp)
    print("hum:",hum)

    display.fill(0)
    display.text(' CO2:', 0,0,1)
    display.text(str(co2), 60,0,1)
    display.text('tVOC:', 0,10,1)
    display.text(str(voc), 60,10,1)
    display.text('temp:', 0,20,1)
    display.text(str(round(temp,1)),30,20,1)
    display.text('hum:', 60,20,1)
    display.text(str(round(hum,1)),86,20,1)
    display.show()
    if counter == 60 and zabbix_server:
        data = json.dumps({
            "request":"sender data",
            "data":[
                {"host":"xiao-test","key":"ccs811.co2","value":co2},
                {"host":"xiao-test","key":"ccs811.tvoc","value":voc},
                {"host":"xiao-test","key":"bme280.temperature","value":temp},
                {"host":"xiao-test","key":"bme280.humidity","value":hum}
            ]
        })
        zabbix_send(zabbix_server, data)
        counter = 0
    counter += 10 
    time.sleep(10)

OLEDは10秒に1回更新、Zabbixへの送信は60秒に一度にしています。
OLEDが128*32と小さいので座標を指定して結構詰めて表示しています。
zabbix側の設定は参考にさせていただいた記事同様にzabbixトラッパーで設定しています。

zabbixに送信されたデータ

終わりに

ブレッドボードでざっくり作りましたが、このままでは他の検証に使えなくなってしまうので、基板起こすかユニバーサル基板で対処しようかと思います。
プログラム的にはIP・zabbixサーバアドレス・ホスト名を別ファイルに切り出して、コードファイルに手を入れずに、定義のみ変更できるようにしておきたい所でしょうか。

Discussion