寒い日が続き室内で窓を閉め切りファンヒーターなどを付けていると、CO2濃度もどんどん上昇していると思いますが、実際どの位の濃度になっているのか見当が付きません。
最近またコロナの感染者が増えてきました、室内の空気を入れ換え感染症の予防も必要です、換気の目安を知るためCO2センサーを使って二酸化炭素濃度測定器を作成してみようと思います。
使用パーツ
CO2センサー MH-Z19C
1.3インチOLED 白色表示 SH1106 Driver
その他
3mmLED4色 2.2kΩ抵抗 ピンヘッダー ユニバーサル基板など
参考サイト
CO2測定について書かれている記事です
SH1106 DriverのGithub です、Thonnyのパッケージ管理からではインストール出来ないので。
Micropython 用 日本語フォント、OLEDに日本語で表示させるため。
回路図
OLEDにCO2濃度を表示し濃度を4段階に分けLEDで表示します。
OLED端子のGNDとVCCが入れ替わっているモジュールがあります注意が必要です。
回路図のCO2センサーはMH-Z19Bですが使用したのはMH-Z19Cです。
ソフトウエアのインストール
Picoへのインストールには Thonny を使用しました
Rspberry Pi Pico へのMicropython farmwareのインストール、Thonny の使用方法については省きます。
1. OLEDのドライバーをGithubからダウンロードしてインストールします。
2. 日本語フォントをGithubからダウンロードして解凍したファイルの中のmfontフォルダーをPicoにアップロードします。
※ 日本語フォントは u_16x16.fnt と u_24x24.fnt だけを使用しますのでそれ以外のフォントは削除してからアップロードしないとメモリーオーバーになります。
3. LEDが点滅するCO2濃度の基準値は次のようにしました。
青色LED:~1000PPM
緑色LED:1001~2000PPM
黄色LED:2001~3000PPM
赤色LED:3001~
4. プログラムについてはド素人ですので間違いがあるとは思いますが、一応動いたので載せておきますご指摘がありましたらコメント下さい。
※ 2024/03/09 OLED表示部分のプログラムを一部修正しました。
########################################################## # SH1106 OLED Display I2C Driver for Raspberry Pi Pico # https://github.com/robert-hh/SH1106 # 日本語フォントを使用する # https://github.com/Tamakichi/pico_MicroPython_Multifont ########################################################## from machine import Pin, I2C from sh1106 import SH1106_I2C import utime from micropython import const from mfont import mfont #----LED設定----- led_red = Pin(16,Pin.OUT) led_orange = Pin(17,Pin.OUT) led_green = Pin(18,Pin.OUT) led_blue = Pin(19,Pin.OUT) # 定数(デフォルトは、Seeed XIAO RP2040用) I2C_ID = const(1) # I2C ID I2C_FREQ = const(400_000) # I2C バス速度 OLED_WIDTH = const(128) # OLEDの横ドット数 OLED_HEIGHT = const(64) # OLEDの縦ドット数 OLED_ADDR = const(0x3c) # OLEDのI2Cアドレス OLED_SCL = const(15) # OLEDのSCLピン OLED_SDA = const(14) # OLEDのSDAピン # OLEDディスプレイのインスタンスの生成 i2c = I2C(I2C_ID, scl=Pin(OLED_SCL), sda=Pin(OLED_SDA), freq=I2C_FREQ) oled = SH1106_I2C(OLED_WIDTH, OLED_HEIGHT, i2c, addr=OLED_ADDR, rotate=180) oled.contrast(255) oled.invert(False) # フォントの表示 def drawFont(self, font, x, y, w, h, flg=False): bn = (w+7)>>3 py = y for i in range(0, len(font), bn): px = x for j in range(bn): for k in range(8 if (j+1)*8 <=w else w % 8): self.pixel(px+k,py, 1 if font[i+j] & 0x80>>k else 0) px+=8 py+=1 if flg: self.show() # テキストの表示 def drawText(self, text, x, y, fs, wt=0): self.x = x self.y = y # フォントの設定 self.mf = mfont(fs) self.mf.begin() # テキスト表示 for c in text: code = ord(c) font = self.mf.getFont(code) self.drawFont(font, self.x, self.y, self.mf.getWidth(), self.mf.getHeight(), True) if wt: utime.sleep_ms(wt) self.x+=self.mf.getWidth() self.mf.end() # SH1106_I2Cに漢字表示インスタンス・メソッドの追加 SH1106_I2C.drawText = drawText SH1106_I2C.drawFont = drawFont #----タイトル表示---- txt = "CO2 濃度測定" fsize = 16 oled.fill(0) oled.drawText(txt,15,0,fsize,50) oled.show() #----CO2数値の表示--- mhz19c=machine.UART(1,baudrate=9600) # UART while True: for gx in range(98): data=bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]) mhz19c.write(data) mhz19c.readinto(data,len(data)) co2=data[2]*256+data[3] print(str(co2)+'ppm') fsize = 24 txt = str(co2) oled.drawText(txt+" ",15,35,fsize,50) oled.drawText("PPM",87,35,fsize,50) oled.show() #----LED表示---- if (co2 > 3000): led_red.value(1) led_orange.value(1) led_green.value(1) led_blue.value(1) utime.sleep(3) led_red.value(0) elif (co2 > 2000): led_red.value(0) led_orange.value(1) led_green.value(1) led_blue.value(1) utime.sleep(3) led_orange.value(0) elif (co2 > 1000): led_red.value(0) led_orange.value(0) led_green.value(1) led_blue.value(1) utime.sleep(3) led_green.value(0) elif (co2 <= 1000): led_red.value(0) led_orange.value(0) led_green.value(0) led_blue.value(1) utime.sleep(3) led_blue.value(0) #==================================
ブレッドボードに配線して動かしてみました
CO2とLEDの表示について
CO2の表示は約3秒ごとに更新されます。
LEDの表示は前述の基準に達しているLEDが点滅し、それ以下のLEDは点灯します。
www.youtube.com
画像と動画ではディスプレイが180度回転していますが、プログラムでは修正してあります。
なんとか表示出来たのでケースを作成し組み込んでみようと思います。
2月5日追記