前回、とても苦労したがRaspberry Pi Zero 2 Wで、Windows PCからリモートで接続して動かすことが出来るようになった。
これで、ようやくプログラムを作って試すことが出来る。
まずは、なんと言っても基本はLチカ。
とりあえず、GPIO4にLEDを繋いでおいた。
おじさんはRaspberry PiもPythonもズブの素人なので、ChatGPTにLチカのコードをお願いしてみる。
Raspberry Pi Zeroのスタートメニュー?からThonnyを立ち上げて、コピペして動かす。
Runボタンを押して動かすと、おお、ちゃんと動く。
次に、240×320dot カラーLCDを繋いでいく。
これはおじさんの以前の記事↓で試したもので、手元に残っていた。
ST7789というICで駆動するSPI接続のカラー液晶。
明るくて発色が良く、とてもきれいに表示してくれる。
ただ、バックライト制御端子が出ていないのでPWMによる輝度調整は出来ない。
あと、2インチなので、やや画面が小さい。
例によって、どのように動かすのか分からないので、ChatGPTに訊いてみる。
まずは、結線についての指示があったので、このように接続。
DCとRSTは任意のGPIOでOKらしい。
サンプルプログラムを書いてもらったが、また動かない。
しょうがないので、いろいろやり取りする。
ChatGPTの指示に従って、最初Pimoroni の st7789 ライブラリを使って動かそうとしたのだが、何故か動かない。次に adafruit-circuitpython-st7789を使って動かそうとするも、何故か上手くいかない。
最後に Luma.lcd を使って動かしてみると、液晶に表示できるようになった。
まとめると
●Luma.lcdのインストール
sudo apt update
sudo apt install python3-luma.lcd python3-pil
sudo apt install python3-luma.lcd python3-pil
●日本語対応フォントがインストールされていないので、noto-cjkをインストール。
sudo apt install fonts-noto-cjk
ChatGPTが書いた以下のコードを、Thonnyにコピペして実行
from luma.core.interface.serial import spi
from luma.lcd.device import st7789
from PIL import Image, ImageDraw, ImageFont
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
# SPI接続
serial = spi(port=0, device=0, gpio_DC=24, gpio_RST=25)
# ディスプレイ (320x240 横長)
device = st7789(serial, width=320, height=240, rotate=0)
# 画像生成
image = Image.new("RGB", (320, 240), "black")
draw = ImageDraw.Draw(image)
# フォントの読み込み(サイズは適宜調整)
font_path = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
font = ImageFont.truetype(font_path, 32)
# 英数字描画
draw.text((20, 40), "Hello, World!", font=font, fill="white")
# 区切り線(横線)
draw.line((20, 90, 300, 90), fill="yellow", width=2)
# 日本語描画
draw.text((20, 120), "こんにちは世界", font=font, fill="cyan")
# 画面に表示
device.display(image)
ここまで、ずいぶんと苦労したが、ようやく動くように。
TrueTypeフォントなので文字がギザギザしてなくてきれい
次に、文字列が長い場合、普通にdraw.textで表示させると、画面にはみ出した文字は折り返して表示できない。
これも、ChatGPTにお願いして解決してもらう。
指定幅を超えると、折り返したtextを返すようにコードを書いてくれた。
で、それをベースにWebラジオをイメージして表示プログラムにしてみた
from luma.core.interface.serial import spi
from luma.lcd.device import st7789
from PIL import Image, ImageDraw, ImageFont
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
# SPI設定
serial = spi(port=0, device=0, gpio_DC=24, gpio_RST=25)
device = st7789(serial, width=320, height=240, rotate=0)
# 描画用キャンバス
image = Image.new("RGB", (320, 240), "black")
draw = ImageDraw.Draw(image)
# フォント設定
font_path = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
font_bold = "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc"
font40 = ImageFont.truetype(font_bold, 40)
font32 = ImageFont.truetype(font_bold, 32)
font28 = ImageFont.truetype(font_path, 28)
font28_bold = ImageFont.truetype(font_bold, 28)
font20 = ImageFont.truetype(font_bold, 20)
#global
ch_no = 0
volume_level = 10
bit_rate = 128
station_name = "181.FM - Power 181 (Top 40) US"
streamtitle = "Poppin'party(戸山香澄(愛美)、花園たえ(大塚紗英)、牛込りみ(西本りみ)、山吹沙綾(大橋彩香)、市ヶ谷有咲(伊藤彩沙)) - 開けたらDream!"
# 折り返し関数
def wrap_text(text, font, draw, max_width):
lines = []
line = ""
for char in text:
test_line = line + char
w = draw.textbbox((0, 0), test_line, font=font)[2]
if w <= max_width:
line = test_line
else:
lines.append(line)
line = char
if line:
lines.append(line)
return lines
def show_ch():
global ch_no , font40
ch = "Ch:"+str(ch_no)
draw.rectangle((0, 0, 160, 48), fill="black")
draw.text((0, 0), ch, font=font40, fill="yellow")
def show_vol():
global volume_level ,font32
vol = "Vol:"+str(volume_level)
draw.rectangle((140, 0, 259, 48), fill="black")
draw.text((140, 10), vol, font=font32, fill="cyan")
def show_bitrate():
global bit_rate ,font20
bitr = str(bit_rate) + "K"
draw.rectangle((240, 0, 320, 52), fill="black")
draw.text((260, 0), bitr, font=font20, fill="magenta")
draw.text((260, 20), "bps", font=font20, fill="magenta")
def show_station():
global station_name,font28_bold
draw.rectangle((0, 58, 320, 127), fill="black")
station = station_name
lines = wrap_text(station, font28_bold, draw, max_width=315)
y = 54
for line in lines:
draw.text((0, y), line, font=font28_bold, fill="lime")
bbox = font28.getbbox(line)
line_height = bbox[3] - bbox[1]
y += line_height # 行間0
def show_streamtitle():
global station_name,font28
draw.rectangle((0, 129, 320, 240), fill="black")
stream = streamtitle
lines = wrap_text(stream, font28, draw, max_width=315)
y = 129
for line in lines:
draw.text((0, y), line, font=font28, fill="white")
bbox = font28.getbbox(line)
line_height = bbox[3] - bbox[1]
y += line_height # 行間0
#イメージの作成
show_ch()
show_vol()
show_bitrate()
draw.line((0, 56, 320, 56), fill="orange", width=2)
show_station()
draw.line((0, 128, 320, 128), fill="orange", width=2)
show_streamtitle()
# 表示
device.display(image)
こんな感じ
拡大すると、こんな感じ。TrueType文字がきれい。
ああ、今回も最初はうまく動かなくて苦労した。
Arduino IDE環境なら簡単に動き出すのに、Raspberry Pi Zeroだと動き出すまでに、やたらと苦労するのである。
素人のおじさんにとって、つまずいたら二度と起き上がれなくなるのではないか?と思うくらいなのである。
まぁ、しょうがないから気長にぼちぼちやっていく。
「おいらも、起き上がるのに苦労するニャ」
いや、それはやばいって








