TOPに戻る

ラズパイ2023年10月更新 bookworm ⑥ CPUの温度を4桁7セグメントLED表示器に

 前回4桁7セグメントLED表示器に室温を表示しました。ここでは、ラズパイ本体のCPUの温度を表示します。

CPU温度の取得

$ vcgencmd measure_temp

temp=37.4'C

 pythonで実行して、温度を取得します。subprocessライブラリを利用します。

 最初に、subprocess.check_output()関数を使います。結果はbyte列で受け取るので、デコードします。

proc = subprocess.check_output('vcgencmd measure_temp',shell=True )

print(proc.decode())

temp=37.0'C

が得られます。

 調べると、subprocess.run()関数を利用するほうが良いような記述が出てきたので実行します。

proc = subprocess.run('vcgencmd measure_temp',shell=True, capture_output=True, text=True)

 実行結果はデコードされて.stoutで得られます。

print(proc.stdout)

temp=37.0'C

 温度の数値が欲しいので、'='で分離します。


print(proc.stdout.split('='))

['temp', "37.0'C\n"]

 後ろ側を取り出します。


print((proc.stdout.split('='))[1])

37.0'C

 ’’’でで分離します。


print(((proc.stdout.split('='))[1]).split('\''))

['37.0', 'C\n']

 前側を取り出します。

print((((proc.stdout.split('='))[1]).split('\''))[0])

37.0

 文字列を実数に変換します。

print(float((((proc.stdout.split('='))[1]).split('\''))[0]))

37.0

 プログラムです。

import subprocess

proc = subprocess.check_output('vcgencmd measure_temp',shell=True )
print(proc.decode())

proc = subprocess.run('vcgencmd measure_temp',shell=True, capture_output=True, text=True)
print(proc.stdout)
print(proc.stdout.split('='))
print((proc.stdout.split('='))[1])
print(((proc.stdout.split('='))[1]).split('\''))
print((((proc.stdout.split('='))[1]).split('\''))[0])
print(float((((proc.stdout.split('='))[1]).split('\''))[0]))

 別の方法、正規化reライブラリのsub()を併用します。

 '\D'は元の文字列から数字以外を削除(数字を抽出)を使って数字を抽出すると、小数点が文字として捨てられます。

num = re.sub( r'\D', '', proc.stdout)

 xx.yという温度が得られるのがわかっていて、xxyという数字が得られるので、実数に変換して10で割ります。

print(float(num)/10.0)

 検索して、小数点を含む数字を得られる記述がありました。

[^\d.]

 勉強不足でこの正規表現を理解できませんが、使ってみます。

num = re.sub( r'[^\d.]', '', proc.stdout)
print(float(num))

 どちらの方法も、CPUの温度を得られました。文字列中に数字が1か所しか出てこないという事例です。

 プログラムです。短くなりました。

import subprocess
import re

proc = subprocess.run('vcgencmd measure_temp',shell=True, capture_output=True, text=True)

num = re.sub( r'\D', '', proc.stdout)
print(float(num)/10.0)

num = re.sub( r'[^\d.]', '', proc.stdout)
print(float(num))

CPUの温度を4桁7セグメントLED表示器に表示

 上記で得られたCPUの温度を4桁7セグメントLED表示器に表示するプログラムです。

import time
import smbus2
import subprocess
import re

i2c_address=0x71
i2c=smbus2.SMBus(1)

HT16K33_GENERIC_SYSTEM_ON=0x21
HT16K33_GENERIC_DISPLAY_ON=0x81
i2c.write_byte_data(i2c_address,HT16K33_GENERIC_SYSTEM_ON,0)
i2c.write_byte_data(i2c_address,HT16K33_GENERIC_DISPLAY_ON,0)

HT16K33_GENERIC_CMD_BRIGHTNESS=0xe0
i2c.write_byte_data(i2c_address,HT16K33_GENERIC_CMD_BRIGHTNESS,8)

def clearLED():
    i2c.write_i2c_block_data(i2c_address,0,[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])

num={0:0x3f,1:0x06,2:0x5b,3:0x4f,4:0x66,5:0x6d,6:0x7d,7:0x07,8:0x7f,9:0x67} # -;0x40,dot;0x80
seg={1:0,2:2,3:6,4:8}

def dispLED(segment,number,dot):
    if dot:
        i2c.write_byte_data(i2c_address, seg[segment], num[number] +128)  #  |= 0x80
    else:
        i2c.write_byte_data(i2c_address, seg[segment], num[number])

def disp7seg(data):
    if data<0 :
        neg=True
    else:
        neg=False
    dataString=str(data)
    dotNumPlace=dataString.find('.')+1

    dataString=str(abs(data))
    dotNumPlace=dataString.find('.')+1

    segmentPlace=1
    if neg==True:
        i2c.write_byte_data(i2c_address, seg[1], 0x40)
        segmentPlace=2
    lenString= len(dataString)
    mojiichi=1

    while lenString>0:
        dispNum=dataString[mojiichi-1:mojiichi]
        if  dispNum==".":
            mojiichi=mojiichi-1
            segmentPlace=segmentPlace-1
            dispNum=dataString[mojiichi-1:mojiichi]
            dispLED(segmentPlace,int(dispNum),True)
            mojiichi=mojiichi+1
        else:
            dispLED(segmentPlace,int(dispNum),False)
        segmentPlace=segmentPlace+1
        lenString=lenString-1
        mojiichi=mojiichi+1

# main
print("test start")
while 1:
    clearLED()
    proc = subprocess.run('vcgencmd measure_temp',shell=True, capture_output=True, text=True)
    data=float(re.sub( r'[^\d.]', '', proc.stdout))
    print(data)
    disp7seg(data)
    time.sleep(3)

-