ラズパイ4を用いた<ラズパイ 2023年10月更新 bookworm 連載記事>をラズパイ5で再検証した記事です。
前回、I2Cバスに接続した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)
このあと、ラズパイが立ち上がったら、このプログラムが自動で実行できるようにするという設定にチャレンジしましたが、実現できていません。bookwormに代わって、systemdの記述が変わったという解説は見つかっていませんが。