ブログだいちゃん

ブログだいちゃん

趣味のブログ

ブログだいちゃん

Raspberry Pi Pico と MH-Z19Cを使用し CO2濃度測定器を作成してみました

寒い日が続き室内で窓を閉め切りファンヒーターなどを付けていると、CO2濃度もどんどん上昇していると思いますが、実際どの位の濃度になっているのか見当が付きません。

最近またコロナの感染者が増えてきました、室内の空気を入れ換え感染症の予防も必要です、換気の目安を知るためCO2センサーを使って二酸化炭素濃度測定器を作成してみようと思います。
 

 

参考サイト

 

CO2測定について書かれている記事です

plaza.rakuten.co.jp
 

SH1106 DriverのGithub です、Thonnyのパッケージ管理からではインストール出来ないので。

github.com
 

Micropython 用 日本語フォント、OLEDに日本語で表示させるため。

github.com
 

回路図

 

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)

 #==================================

 

ブレッドボードに配線して動かしてみました

 

ブレッドボードに配線しました

タイトルは16×16ドット、CO2測定値は24×24ドットで表示しています。
CO2センサーのキャリブレーションはマニュアルの通り屋外で設定しました。


CO2とLEDの表示について

CO2の表示は約3秒ごとに更新されます。
LEDの表示は前述の基準に達しているLEDが点滅し、それ以下のLEDは点灯します。


www.youtube.com
 
画像と動画ではディスプレイが180度回転していますが、プログラムでは修正してあります。

なんとか表示出来たのでケースを作成し組み込んでみようと思います。
 

2月5日追記

 

ケースに組み込み完成させました