Raspberry PiとUbuntuでGPIO制御
以前PicoとPi Zero2をUARTで繋いでROS2連携しました。
このとき、母艦となるPi Zero2が起動してWifi接続やAgent起動してから
Picoを通電させたほうが良いというコメントしました。
そういえば、UbuntuインストールしたラズパイでGPIO制御やったことなかったので、
そのあたり含めて確認しときます。
- Ubuntu22.04でGPIO制御でLチカなどやってみる
- Wifi疎通チェック(ネットワーク設定は事前に設定済み)
- 上記をPythonで実行できるようにする
- 上記をサービス起動できるようにする
これができると、PiZero2を起動してスタンバイになったか視覚的にもわかるし、
Pico側に「準備できたよ」と知らせることができる。
Ubuntu22.04でのGPIO制御でLチカ
Raspberry Pi OSであればPi.GPIOとかありましたが、Ubuntu22.04の場合はlgpioなるものを使う。
> sudo apt install python3-lgpio -y
Lチカプログラム。GPIO18番でON/OFFします。
# test_led.py
import lgpio
import time
# GPIO18 (物理ピン10)
LED_PIN = 18
# GPIOチップを開く
chip = lgpio.gpiochip_open(0)
# ピンをOUTPUTモードに設定
lgpio.gpio_claim_output(chip, LED_PIN)
try:
pin_flg = 0
while True:
# LED ON/OFF
pin_flg ^= 1
lgpio.gpio_write(chip, LED_PIN, pin_flg)
print("LED flg = %s"%(pin_flg))
# 0.1sec
time.sleep(0.1)
except KeyboardInterrupt:
pass
finally:
# GPIOチップを閉じる
lgpio.gpiochip_close(chip)
Raspberry Pi Zero 2のピンレイアウトのおさらい。
SPIがもう1個ありそうでしたが省略してます。
GPIO18とGNDを接続してプログラムを実行します。ついでに標準出力をシリアルコンソールに表示するため、UART接続(GPIO14、15)もしてみます。
プログラム停止はCtrl+Cで強制終了する。
> python3 test_led.py
LED flg = 1
LED flg = 0
LED flg = 1
:
0.1sec間隔でLチカできました。
Wifi接続確認およびIPアドレス取得
いろいろあるけど、psutilが良いと思います。
> sudo apt install python3-psutil -y
wlan0のIPアドレスを取得して取れたらOKとします。
# test_wifi.py
import psutil
def get_wifi_address(wlan="wlan0"):
try:
net_if_addrs = psutil.net_if_addrs()
for addr in net_if_addrs[wlan]:
# check IPv4
if addr.family == 2:
return str(addr.address)
except Exception as ex:
print("get_wifi_address error : %s"%(str(ex)))
return None
ip_addr = get_wifi_address()
print("wlan ip address : %s"%(ip_addr))
実行すると、IPv4のアドレスがとれます。
> python3 test_wifi.py
wlan ip address : 192.168.0.226
インターネットに接続確認が必要なケースもありますが、そこはラズパイ云々じゃないので、別プログラムでチェックします。
電源ONしたら自動的にプログラムをバックグラウンド起動させたい
- ユーザはrootではなく、普段使うユーザで(ubuntu)
- ネットワークデバイス関連が準備できた後で
- 実行はPythonプログラム
systemdにサービスを登録するのがベストだと思います。
プログラムは先ほどのLチカプログラムで、起動したら自動的に点滅させてみます。
ポイントはnetwork-online.targetが稼働したあとで開始します。また、ユーザサービスとして登録しているので、rootではなくubuntuユーザでプログラムが実行されるところです。
[Unit]
Description=My Launch Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/ubuntu/work/test_led.py
Restart=always
WorkingDirectory=/home/ubuntu
[Install]
WantedBy=multi-user.target
上記のファイルをlaunch_my_service.serviceという名前で、ubuntuホーム以下(今回はworkサブフォルダ)に保存して、シンボリックリンクをsystemdのサービスフォルダに作成する。
> sudo ln -s /home/ubuntu/work/launch_my_service.service /etc/systemd/system/launch_my_service.service
> ls -l /etc/systemd/system/launch_my_service.service
lrwxrwxrwx 1 root root 43 Feb 15 14:35 /etc/systemd/system/launch_my_service.service -> /home/ubuntu/work/launch_my_service.service
サービスを登録する
> sudo systemctl daemon-reload
> sudo systemctl enable launch_my_service.service
Created symlink /etc/systemd/system/multi-user.target.wants/launch_my_service.service → /home/ubuntu/work/launch_my_service.service.
> sudo systemctl start launch_my_service.service
これにより、ユーザーubuntuがログインしていなくても、systemdのユーザーサービスが実行されるようになる。
> sudo systemctl status launch_my_service.service
● launch_my_service.service - My Launch Service
Loaded: loaded (/etc/systemd/system/launch_my_service.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2025-02-15 14:37:44 JST; 19s ago
Main PID: 3476 (python3)
Tasks: 4 (limit: 372)
Memory: 9.6M
CPU: 448ms
CGroup: /system.slice/launch_my_service.service
└─3476 /usr/bin/python3 /home/ubuntu/work/test_led.py
Feb 15 14:37:44 pizero2 systemd[1]: Started My Launch Service.
停止させたい場合は
> sudo systemctl stop launch_my_service.service
ほかのサービスと同じです。サービスが開始してLEDが点滅することが分かったら、再起動して、自動的にLED点滅できたら一連のサービス化は成功です。
余談) Pi Zero 2のWifi接続でハマる
なぜか最近Wifi接続できない現象が続いてました。(もちろん設定済み)
以下を参考に対応して様子見してます。
hidden: trueを追加しました。ステルスモード対応ですが、そうじゃなくても入れといたほうが良いかもしれない。
network:
version: 2
wifis:
renderer: networkd
wlan0:
access-points:
{SSID}:
hidden: true
password: {パスワード}
dhcp4: true
optional: true
以下で反映する
sudo netplan --debug try
sudo netplan --debug generate
sudo netplan apply
再起動や電源ONしたときにちゃんとつながるか確認
Discussion