Raspberry Pi 電子工作 08:温度・湿度センサーとLCDディスプレイ(I2C接続)にCPU、メモリ状態を表示

16文字2行のLCDディスプレイ。

これに、以下の情報を1秒ごとに表示します。

・現在の日付、時刻

・温度、湿度

・CPU温度と使用率、メモリの使用量と総量

 

温度・湿度計とディスプレイのGPIOへの接続は以前の記事を参考にしてください。

今回はPythonでのスクリプトを変更します。

 

 

1. Pythonプログラミング

  以下のコードで実現できます。

  CPU温度の取得方法は2種類用意しています使用するのは1種類)
  メモリの情報は、「psutil」を使用しています。標準ライブラリです。

  「psutil」はいろいろなハードウェア情報を取得できるようですので、掘っていくと面白いかもしれません。

  なお、今回は別ファイルに保存していたスクリプトもこちらへ移動しています。

 

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
from time import sleep
import smbus
import datetime
import subprocess
import re
import psutil

# 定数の定義
# LCDディスプレイのI2Cのアドレス
LCD_I2C_ADDR = 0x27
# LCDの1行目のアドレス
LCD_LINE_1 = 0x80
# LCDの2行目のアドレス
LCD_LINE_2 = 0xC0
# 1行あたりの文字数
LCD_WIDTH = 16
# バックライトのON/OFF(ON:0X08, OFF:0X00を指定)
LCD_BACKLIGHT = 0X08
LCD_CHR = 1
LCD_CMD = 0
ENABLE = 0b00000100
E_PULSE = 0.0005
E_DELAY = 0.0005

def init_lcd():
    """
    LCDの初期化処理
    """
    lcd_byte(0x33, LCD_CMD)
    lcd_byte(0x32, LCD_CMD)
    lcd_byte(0x06, LCD_CMD)
    lcd_byte(0x0C, LCD_CMD)
    lcd_byte(0x28, LCD_CMD)
    lcd_byte(0x01, LCD_CMD)
    sleep(E_DELAY)

def lcd_byte(bits, mode):
    """
    LCDへの書き込み2
    """
    bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
    bits_low =  mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT
    bus.write_byte(LCD_I2C_ADDR, bits_high)
    lcd_toggle_enable(bits_high)
    bus.write_byte(LCD_I2C_ADDR, bits_low)
    lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
    """
    LCDへの書き込みサブ
    """
    sleep(E_DELAY)
    bus.write_byte(LCD_I2C_ADDR, (bits | ENABLE))
    sleep(E_PULSE)
    bus.write_byte(LCD_I2C_ADDR, (bits & ~ENABLE))
    sleep(E_DELAY)

def lcd_string(message: str, dispLine):
    """
    LCDへの文字の表示(半角文字列のみ)
    """
    # 表示対象行の初期化
    lcd_byte(dispLine, LCD_CMD)
    # 文字列を1行あたりの文字数に調整
    message = message.ljust(LCD_WIDTH)
    # 表示処理
    for dispIndex in range(LCD_WIDTH):
        lcd_byte(ord(message[dispIndex]), LCD_CHR)

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import smbus
from time import sleep

def tempelature_humidity():
    """
    温度と湿度を取得する
    """

    ADR = 0x44
    # I2Cの取得
    ic2 = smbus.SMBus(1)

    # 測定頻度の設定
    ic2.write_byte_data(ADR, 0x23, 0x34)
    sleep(0.5)
    # 測定値の読出し
    ic2.write_byte_data(ADR, 0xe0, 0x0)
    sleep(0.5)

    # 6バイト取得
    d = ic2.read_i2c_block_data(ADR, 0x0, 6)

    # 0~1バイトが温度
    # 測定データ(生データ)を取得
    t = ((d[0]) << 8) | (d[1])
    # 換算する
    t = -45 + (175 * t / 65535)

    # 3~4バイトが湿度
    # 測定データ(生データ)を取得
    h = ((d[3]) << 8) | (d[4])
    # 換算する
    h = 100 * h / 65535

    # 結果を返却
    return t, h

def cpu_temp():
    """
    CPU温度の取得
    """
    f = open("/sys/class/thermal/thermal_zone0/temp","r")
    cpu_temp = 0
    for t in f:
        cpu_temp = t[:2]
        # 小数点以下2桁まで表示する場合
        # cpu_temp = t[:2]+"."+t[2:3]
    f.close()
    return cpu_temp

def cpu_temp_command():
    """
    CPU温度の取得(コマンドで取得)
    """
    proc = subprocess.run(["vcgencmd", "measure_temp"], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    cpu_temp = re.split("[=\']", proc.stdout.decode("utf8"))[1]
    return float(cpu_temp)

def cpu_percent():
    """
    CPU使用率の取得
    """
    cpu_percent = psutil.cpu_percent(interval=1)
    return round(cpu_percent)

def memory_info():
    """
    メモリ情報(使用量[MB]、総量[MB])の取得
    """
    mem = psutil.virtual_memory()
    mem_used = round(mem.used / 1024 / 1024)
    mem_total = round(mem.total / 1024 / 1024)
    return (mem_used, mem_total)

# I2Cの取得
bus = smbus.SMBus(1)

try:
    # LCD初期化
    init_lcd()
    # 無限ループ、各情報を1秒間隔で表示
    dispMode = 0
    while True:
        if (dispMode == 0):
            sleep(1)
            # 「年月日と時分秒」を表示
            now = datetime.datetime.now()
            lcd_string(f'date: {now.strftime("%Y/%m/%d")}' , LCD_LINE_1)
            lcd_string(f'time: {now.strftime("%H:%M:%S")}', LCD_LINE_2)
            dispMode = 1
        elif (dispMode == 1):
            # 「温度と湿度」を表示
            templature , humidity = tempelature_humidity()
            lcd_string(f'temp: {str(templature)[:4]}\337C', LCD_LINE_1)
            lcd_string(f'hum : {str(humidity)[:4]}%', LCD_LINE_2)
            dispMode = 2
        elif (dispMode == 2):
            # 「CPU温度」「CPU使用率」と「メモリ情報」を表示
            mem_info = memory_info()
            lcd_string(f'cpu : {cpu_temp()}\337C {cpu_percent()}%', LCD_LINE_1)
            lcd_string(f'mem : {mem_info[0]}/{mem_info[1]}MB', LCD_LINE_2)
            dispMode = 0
finally:
    lcd_byte(0x01, LCD_CMD)