ラズパイPicoを温湿度計として使う

QOL -生活-

温湿度機能の実装          

必要なモジュール

今回は、DHT22という温湿度センサのモジュールを使用する。

サンプル配線

今回の温湿度計モジュールは3V電源、GND、信号ラインの3本を接続する必要がある。

今回は信号線を4pin(GP2)に接続して使用する。

サンプルコード

まずは、Thonny上で温湿度を出力するサンプルコードで動作を確認する。

import machine
import dht
import time

# DHT22を接続するピンを指定(例: GP2)
dht_pin = machine.Pin(5)
sensor = dht.DHT22(dht_pin)

while True:
    try:
        sensor.measure()  # 測定を実行
        temperature = sensor.temperature()  # 温度を取得(摂氏)
        humidity = sensor.humidity()  # 湿度を取得
        
        print(f"Temperature: {temperature:.1f}°C, Humidity: {humidity:.1f}%")
    except OSError as e:
        print("Failed to read sensor.", e)
    
    time.sleep(2)  # 2秒ごとに測定

上記のサンプルコードで実行すると、温湿度が2秒おきに出力される。

LCDと温湿度計の併用

このままでは、温湿度の確認に必ずPCが必要となる。今回は、PCなしで表示までできるようにしていく。

そのためにラズパイPicoにLCDモジュールを接続する。

使用するLCD

今回使用するのは、以下のLCD。セットアップの詳細は以前の記事を参照。

LCDモジュールで使用しているヘッダーピン

LCDモジュールと温湿度モジュールを併用する上で、まず考えないといけないのが、LCDモジュールがラズパイPicoのヘッダーピンのどのピンを実際に使用しているのかの確認である。

LCDモジュールは40pinヘッダーソケットを介して、ラズパイPicoと接続される。

しかしながら、実際のところ40pinすべてを使用しているわけではない。

下記の製品ページを見ると、4,5,11,12,14,15,16,17,20,21,22,24,26,39のピンと、どこか一か所のGNDが接続されていれば良い模様。

Pico LCD 1.14 - Waveshare Wiki

ヘッダーピンの改造

LCDモジュールで使用しない部分のピンをL字に曲げる。

今回は、pin7(GP5)と、pin8(GND)と、pin36(3V電源ライン)を温湿度計用に使用する。

その後、折り曲げたヘッダーピン以外の部分に、ヘッダーソケットを一段追加。

LCDモジュール+温湿度計モジュールとの接続

温湿度計モジュールとの接続としては以下のイメージ。

その他のピンはLCDモジュールと接続されている。

サンプルコード

from machine import Pin, SPI, PWM
import framebuf
import dht
import time

# 定数の設定(LCDのピン番号)
BL = 13
DC = 8
RST = 12
MOSI = 11
SCK = 10
CS = 9
DHT_PIN = 5 #DHT22のデータピン

class LCD_1inch14(framebuf.FrameBuffer):
    def __init__(self):
        # LCDの解像度
        self.width = 240
        self.height = 135
        
        # ピンの初期化
        self.cs = Pin(CS, Pin.OUT)
        self.rst = Pin(RST, Pin.OUT)
        
        # SPI通信の初期化
        self.cs(1)
        self.spi = SPI(1)
        self.spi = SPI(1,1000_000)
        self.spi = SPI(1,10000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None)
        self.dc = Pin(DC,Pin.OUT)
        self.dc(1)
        
        # フレームバッファの作成
        self.buffer = bytearray(self.height * self.width * 2)
        super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
        
        # LCDの初期化
        self.init_display()
        
        # カラー定義
        self.red = 0x07E0
        self.green = 0x001f
        self.blue = 0xf800
        self.white = 0xffff

    def write_cmd(self, cmd):
        """LCDにコマンドを送信"""
        self.cs(1)
        self.dc(0)
        self.cs(0)
        self.spi.write(bytearray([cmd]))
        self.cs(1)

    def write_data(self, buf):
        """LCDにデータを送信"""
        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(bytearray([buf]))
        self.cs(1)

    def init_display(self):
        """LCDの初期設定"""
        self.rst(1)
        self.rst(0)
        self.rst(1)
        
        self.write_cmd(0x36)
        self.write_data(0x70)

        self.write_cmd(0x3A) 
        self.write_data(0x05)

        self.write_cmd(0xB2)
        self.write_data(0x0C)
        self.write_data(0x0C)
        self.write_data(0x00)
        self.write_data(0x33)
        self.write_data(0x33)

        self.write_cmd(0xB7)
        self.write_data(0x35) 

        self.write_cmd(0xBB)
        self.write_data(0x19)

        self.write_cmd(0xC0)
        self.write_data(0x2C)

        self.write_cmd(0xC2)
        self.write_data(0x01)

        self.write_cmd(0xC3)
        self.write_data(0x12)   

        self.write_cmd(0xC4)
        self.write_data(0x20)

        self.write_cmd(0xC6)
        self.write_data(0x0F) 

        self.write_cmd(0xD0)
        self.write_data(0xA4)
        self.write_data(0xA1)

        self.write_cmd(0xE0)
        self.write_data(0xD0)
        self.write_data(0x04)
        self.write_data(0x0D)
        self.write_data(0x11)
        self.write_data(0x13)
        self.write_data(0x2B)
        self.write_data(0x3F)
        self.write_data(0x54)
        self.write_data(0x4C)
        self.write_data(0x18)
        self.write_data(0x0D)
        self.write_data(0x0B)
        self.write_data(0x1F)
        self.write_data(0x23)

        self.write_cmd(0xE1)
        self.write_data(0xD0)
        self.write_data(0x04)
        self.write_data(0x0C)
        self.write_data(0x11)
        self.write_data(0x13)
        self.write_data(0x2C)
        self.write_data(0x3F)
        self.write_data(0x44)
        self.write_data(0x51)
        self.write_data(0x2F)
        self.write_data(0x1F)
        self.write_data(0x1F)
        self.write_data(0x20)
        self.write_data(0x23)
        
        self.write_cmd(0x21)

        self.write_cmd(0x11)

        self.write_cmd(0x29)
    
    def show(self):
        """LCDにバッファの内容を描画"""
        self.write_cmd(0x2A)
        self.write_data(0x00)
        self.write_data(0x28)
        self.write_data(0x01)
        self.write_data(0x17)
        
        self.write_cmd(0x2B)
        self.write_data(0x00)
        self.write_data(0x35)
        self.write_data(0x00)
        self.write_data(0xBB)
        
        self.write_cmd(0x2C)
        
        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(self.buffer)
        self.cs(1)
    
    def text_scaled(self, text, x, y, color, scale=1):
        """拡大表示するテキスト描画関数"""
        # 一時的なフレームバッファを作成(文字描画用)
        temp_fb = framebuf.FrameBuffer(bytearray(8 * len(text) * 8), 8 * len(text), 8, framebuf.MONO_HLSB)
        temp_fb.fill(0)  # 背景をクリア
        temp_fb.text(text, 0, 0, 1)  # 文字を描画
        
        # 各ピクセルを拡大して描画
        for yy in range(8):
            for xx in range(8 * len(text)):
                if temp_fb.pixel(xx, yy):  # 文字のピクセルがある場合
                    self.fill_rect(x + xx * scale, y + yy * scale, scale, scale, color)
    
if __name__ == '__main__':
    # LCDのバックライト設定
    pwm = PWM(Pin(BL))
    pwm.freq(1000)
    pwm.duty_u16(32768)  # 最大値65535の半分

    # LCDの初期化
    LCD = LCD_1inch14()
    
    # DHT22の初期化
    sensor = dht.DHT22(Pin(DHT_PIN))
    
    while True:
        try:
            sensor.measure()
            temp = sensor.temperature()
            hum = sensor.humidity()
            
            # 画面クリア
            LCD.fill(LCD.white)
            
            # 温度・湿度を表示
            LCD.text_scaled("Temp", 10, 10, LCD.blue, scale=2)
            LCD.text_scaled(f"{temp:.1f}C", 30, 30, LCD.blue, scale=4)
            LCD.text_scaled("Hum", 10, 70, LCD.green, scale=2)
            LCD.text_scaled(f"{hum:.1f}%", 30, 90, LCD.green, scale=4)
            
            # 画面更新
            LCD.show()
            
            time.sleep(2)
        except Exception as e:
            print("DHT22 Error:", e)

以上のコードを実行すると、下図のように温湿度がLCD画面に表示され、2秒ごとに更新される。

これで、PCなしでも温湿度を確認することが可能となった。

タイトルとURLをコピーしました