しろふくろうず (しろふくろーず)

修繕に関するDIYをメインに趣味や時事ネタなども

ラズベリーパイ pythonプログラム(OpenCVで表示しつつ)の自動起動方法の見直し autostart.desktopからsystemdへ

こんにちは。DIYフクロウの備忘録です(・ω・)ノ

生成AI(今回はGemini)のメモがたっぷり混じっています(・ω・)

raspberry pi で/etc/systemd/system.confを編集してウォッチドッグを有効化するために

#RuntimeWatchdogSec=off を RuntimeWatchdogSec=15 に変更した。まだ、再起動していないので有効にはなっていないが、dmesgでウォッチドッグが有効になっていることを確認するために、dmesg | grep watchdogのコマンドで確認した後、有効になっていれば、

 

pi@raspberrypi:~/.config/autostart $ cat windowpi.desktop 

[Desktop Entry]

Type=Application

Name=windowpy

 

Exec=lxterminal -e python3 /home/pi/TensorflowLite-bin/mobilenetv2ssd-sync-usbcam_rev16.py --model="/home/pi/TensorflowLite-bin/models/mobilenet_ssd_v2_coco_quant_postprocess.tflite"  --num_threads="1" --usbcamno="0"

 

に記載しているmobilenetv2ssd-sync-usbcam_rev16.pyがアプリケーションが例外などで終了したときに自動で再起動する設定(TFlite.service)に変更することを本ページの狙いとします(`・ω・´)v

 

本記事では User=pi としていますが、皆様の環境によって変えていただければ幸いです。

----------------------------------------------------------------------------------------------


1. ウォッチドッグの確認方法(再起動後)

dmesg | grep -i watchdog


2. TFlite.service の作成

 

sudo nano /etc/systemd/system/TFlite.service

 

[Unit]
Description=MobileNetV2 SSD TFlite with Terminal Display
# デスクトップ環境(GUI)が完全に準備できてから起動させる
After=graphical.target

[Service]
User=pi
Group=pi
WorkingDirectory=/home/pi/TensorflowLite-bin/

# GUIを表示するための「おまじない」
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/pi/.Xauthority
Environment=PYTHONUNBUFFERED=1

# lxterminal を開き、その中で Python を実行
# --geometry=80x24 などでサイズ指定も可能(任意)
ExecStart=/usr/bin/lxterminal --geometry=100x30 -e "/usr/bin/python3 /home/pi/TensorflowLite-bin/mobilenetv2ssd-sync-usbcam_rev16.py --model='/home/pi/TensorflowLite-bin/models/mobilenet_ssd_v2_coco_quant_postprocess.tflite' --num_threads='1' --usbcamno='0'"

# アプリが落ちたら5秒後に再起動
Restart=always
RestartSec=5s

[Install]
# マルチユーザーモードではなく、グラフィカルモード(GUI)をトリガーにする
WantedBy=graphical.target

 

3. サービスの有効化と起動

ファイルを作成したら、以下の手順でシステムに認識させ、起動します。

1.設定の反映

sudo systemctl daemon-reload

2.サービスの有効化(次回起動時から自動実行)

sudo systemctl enable TFlite.service
    ```
3.  **今すぐ起動**
    ```bash
    sudo systemctl start TFlite.service
    ```
4.  **ステータス確認**
    ```bash
    sudo systemctl status TFlite.service
    ```
    ここで `Active: active (running)` となっていれば成功です。

---

## 重要な注意点

### 1. GUI(ウィンドウ)の表示について
もしこのPythonスクリプトが OpenCV の `cv2.imshow()` などで**画面に映像を表示する**タイプの場合、systemd(バックグラウンド)から実行すると「画面が見つからない」というエラーで落ちることがあります。
その場合は、上記のサービスファイル内の `Environment=DISPLAY=:0` のコメントアウトを外すか、GUI環境が必要ない(Headless)ようにコードを修正してください。

### 2. ログの確認方法
`.desktop` 起動の時はターミナル(lxterminal)で見えていた出力は、今後は以下のコマンドで確認できます。
```bash
journalctl -u TFlite.service -f

 

現在の .desktop ファイルでの自動起動(/home/pi/.config/autostart/windowpi.desktop)は、不要になったので削除しても大丈夫ですか?

はい、削除(または無効化)することを強くおすすめします。

理由はシンプルで、現在の設定のままだと「1つのアプリを2重に起動しようとしてしまう」からです。

 

 

なぜ lxterminal を使いたいのですか?

もし目的が「プログラムが動いている様子(print文など)をリアルタイムで見たい」ということであれば、前回の回答で紹介した journalctl -u TFlite.service -f コマンドが標準的なプロの方法です。

しかし、「現場でディスプレイだけ繋いで、マウスもキーボードもない状態でパッと画面が出てほしい」という用途であれば、今回の lxterminal を通す方法は非常に視認性が良くて便利だと思います。

 

 

「パッと画面を出す」ための必須条件

① 自動ログインの設定

② スリープ(スクリーンセーバー)の無効化

 

最後に

なぜ .desktop より systemd がいいのか

今回の「現場運用」において、systemd に切り替えるメリットは以下の通りです。

  • ゾンビ化防止: .desktop は一度落ちたらそれっきりですが、systemdRestart=always のおかげで、Pythonがセグメンテーションフォルトなどで異常終了しても、勝手にターミナルを立ち上げ直してくれます。

  • 起動順序の制御: After=graphical.target と書くことで、「まだデスクトップの準備ができていないのにアプリを起動しようとしてエラーになる」という事故を防げます。

 

本記事をお読みいただき、ありがとうございます。

以上となります(`・ω・´)v

ラズベリーパイ 5 スワップサイズの変更(拡張) Bookworm 64bitにて

こんにちは。DIYフクロウです(・ω・)ノ

 


ラズベリーパイ 5 スワップサイズの変更(拡張) 備忘録です
(Bookwrom 64bitにて確認)


0. LXTerminalを起動

 

1. スワップの状況を確認

free -h

→Swapのtotalが99Mi (最近は511Mi)

 

2. スワップの設定を編集する

sudo nano /etc/dphys-swapfile

 

CONF_SWAPSIZE=100 を 1024とか2048とか4096に変える

Ctrl + o (上書き保存) そしてEnter。

Ctrl + x (nanoエディタ終了)

 

3. スワップのサービスを再起動(停止、スタート)する

sudo dphys-swapfile setup

sudo dphys-swapfile swapon

 

4. スワップの状況を再確認

free -h

 

→Swapのtotalが1.0Gi/2.0Gi/4.0Giに変わっていると思います。

 

ここで、4096以上にしたい場合(例:8.0Giの場合)上記の手順のままですと

次のエラーがでてしまうかと思います。

want /var/swap=8192MByte, restricting to config limit: 4096MBytes, checking existing: keeping it
その場合はCONF_MAXSWAPを有効にします。

sudo nano /etc/dphys-swapfile で

CONF_SWAPSIZE=8192 だけではなく、最下部にあるCONF_MAXSWAPの#を外して数値を入れます。

CONF_MAXSWAP=8192 

Ctrl + o (上書き保存) そしてEnter。

Ctrl + x (nanoエディタ終了)

sudo dphys-swapfile setup

sudo dphys-swapfile swapon

free -h  もしくは sudo swapon --show


すでに反映されていると思いますが
再起動(sudo reboot)したら完了です。

以上となります(`・ω・´)v

ラズベリーパイ OS Bookworm Trixie WayVNC ポート番号変更方法

こんにちは。DIYフクロウです(・ω・)ノ

 

ラズベリーパイ OS

Bookworm trixieVNC(WayVNC)でポート番号を5900からXXXXXへ変更する方法の備忘録です。

 

VNCを有効にしてから、ターミナルから該当ファイルをエディタで変更しちゃいましょう。

sudo mousepad /etc/wayvnc/config

 

-----変更前----

use_relative_paths=true
address=::
enable_auth=true
enable_pam=true
private_key_file=tls_key.pem
certificate_file=tls_cert.pem
rsa_private_key_file=rsa_key.pem

------------------

の末尾にport=xxxxx(xは数値65535迄)を入れて保存後、再起動すれば反映。(`・ω・´)v

-----変更後-----

use_relative_paths=true
address=::
enable_auth=true
enable_pam=true
private_key_file=tls_key.pem
certificate_file=tls_cert.pem
rsa_private_key_file=rsa_key.pem

port=xxxxx

------------------

 

ちなみに、SSHのポート番号を変更するときは

sudo nano /etc/ssh/sshd_config

からエディタを開いて

#Port 22 の#を消して、22を変更先の数値に変えて再起動すればOKです。

 

Pi Zero 2W など512MBメモリしかないラズパイで
GPUメモリがデフォルトで64Mなので32MBに減らして
メインメモリを追加確保したい場合は、Bookwormの場合

sudo nano /boot/firmware/config.txt で末尾に
gpu_mem=32 を記載して保存+再起動です。(PiCamera使用時は変更しないほうが良いです)

 

本記事をお読みいただき、ありがとうございます。

以上となります(`・ω・´)v

 

【ラズパイ】Pi3B+のBullseyeで、Piカメラ2を認識させて動作確認に苦労

こんにちは。DIYフクロウです(・ω・)ノ

 

Pi3B+で、Piカメラ2を認識させて動作確認するのに苦労したので、その備忘録です。


【ラズパイ本体】Raspberry Pi 3B+
【OS】Bullseye (=Bookwormの1世代前)
【カメラ】Picamera2 (IMX219) 

sudo apt install -y python3-picamera2

 

■その1

sudo mousepad /boot/config.txt

(1)
dtoverlay=vc4-kms-v3d の頭に#をつけて
#dtoverlay=vc4-kms-v3d にする。

(2)
dtoverlay=imx219 を末尾などに追記して保存し再起動する。

 

これで

vcgencmd get_camera コマンドで
supported=1 detected=0, libcamera interfaces=1
になっているはずです。

 

■その2

sudo mousepad /boot/cmdline.txt

を開くと

長い1行があると思います。その末尾に

 cma=400M

を追加して保存します。

追記しないと、Cannot allocate memory のエラーが出て動作しないと思います。

 

OpenCV 、関連ライブラリのインストール(していない場合)

sudo apt install libopencv-dev python3-opencv

sudo apt install libatlas3-base

■Numpi インストール(していない場合)

sudo pip3 install numpy

 

pythonコードサンプル(動画表示)

 

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import cv2

from picamera2 import Picamera2
from libcamera import controls

camera = Picamera2()
camera.configure(camera.create_preview_configuration(main={"format": 'XRGB8888', "size": (640, 480)}))
camera.start()

count_max = 0

if __name__ == '__main__':
    count = 0

    while True:
        img = camera.capture_array()

        key = cv2.waitKey(1)
        if key == 27: # when ESC key is pressed break
            break

        count += 1
        if count > count_max:
            cv2.imshow('View', img)
            count = 0

    camera.close()
    cv2.destroyAllWindows()

 

これで動作しなかったら、フィルムケーブルの接続具合なども含めて確認しつつ
インターネット上にある他の記事もして下さい。(;ω;)
 
ちなみに、上記の状態で
libcamera-still -o test.jpg コマンドでは撮影が成功しないのでさらなる調査が必要です・・・
 

本記事をお読みいただき、ありがとうございます。

以上となります(`・ω・´)v

 

rpi connect - the raspberrypi connect api returned an error 発生で困ったの巻き

こんにちは。新年あけましておめでとうございます。DIYフクロウです(・ω・)ノ

 

raspberrypi connect (BETA版)が便利で

P社のcloudpi2が不要になっても大丈夫そうな今日この頃です。

 

そんな中で

Raspberry Pi5 Bookworm 64bitで発生したトラブルを備忘録として残しておきます。

 

the raspberrypi connect api returned an error

が発生して繋がらなくなった!(T_T)

 

いろいろ調査していると、確定ではないですが

どうやら、eth0経由のインターネット接続でrpi connectを使用していた状態を

すっかり失念したままrpi-connect signoutコマンドを実施せずにLANケーブルを抜いて

wlan0経由のインターネット接続でrpi-connect signinを試みようとしたから

だったのかもしれない模様でした。

 

本当にダメだったらmicroSDカードのOS Image作り直しで復旧するとは思いますが

かなり戻ってしまうので参考になれば幸いです。

 

写真とるの忘れました(;ω;)以上になります。

 

PythonでSlackへ画像をUploadする方法サンプル(新API仕様)

こんにちは。DIYフクロウです(・ω・)ノ

 

またいきなりですが

Raspberry pi などのクライアント側から

slackへ画像ファイルをUploadするAPI仕様が変わっていたので

python用のコードを準備してみました。

 

slack側の設定は従来通りです。

 

参考にさせていただきました情報は次の2つです。

1.

zenn.dev

2.

qiita.com

 

 

# coding: utf-8

import requests
import json
import os
import datetime

 

# 変数など

token = 'xoxb-で始まる値'
name = datetime.datetime.now().strftime("%Y%m%d %H:%M:%S")  #任意の文字列

channel = 'チャンネルID'

 

# 1. 画像ファイルのサイズを取得
file_blob = "/home/pi/gazou.jpg" ←画像アドレスは必要に応じて書き換えて下さい
file_size = os.path.getsize(file_blob)
print("file_size:",file_size)

 

upload_url_response = requests.get(f"https://slack.com/api/files.getUploadURLExternal?filename={name}&length={file_size}",headers={"Authorization": f"Bearer {token}",})
 
# 2. files.getUploadURLExternal APIを呼び出してURLとファイルIDを取得
upload_url_json = upload_url_response.json()
if not upload_url_json.get("ok"):
raise Exception("Failed to get upload URL: " + upload_url_json.get("error", "Unknown error"))
 
upload_url = upload_url_json["upload_url"]
print("upload_url:",upload_url)
 
file_id = upload_url_json["file_id"]
print("file_id:",file_id)
 
# 3. 取得したURLにファイルをアップロード
upload_response = requests.post(upload_url,files={"file":(name, open(file_blob,'rb'))},data={"token": token,"filename": name})
 
if upload_response.status_code != 200:
raise Exception("Failed to upload file: " + upload_response.text)
 
# 4. files.completeUploadExternal APIにファイルIDとオプション引数を送信してアップロードを完了
complete_upload_payload = {"files": [{"id": file_id, "title": name}]}
 
complete_upload_payload["channel_id"] = channel
 
complete_upload_response = requests.post("https://slack.com/api/files.completeUploadExternal",headers={"Authorization": f"Bearer {token}","Content-Type": "application/json"}, data=json.dumps(complete_upload_payload))
print("complete_upload_response:",complete_upload_response)
 
complete_upload_json = complete_upload_response.json()
print("complete_upload_json:",complete_upload_json)
 
不要な行もあるかと思いますのでカスタマイズして下さい。
 

本記事をお読みいただき、ありがとうございます。

以上となります(`・ω・´)v

Raspberry Pi OS Bookworm Python3.11.2 TF2 メモリリーク強制終了 → 学習済モデル変更して解決

こんにちは。DIYフクロウです(・ω・)ノ

 

Bookworm で困っていること。

 

Raspberry Pi OS が一つ前世代の Bullseye 64bit 環境下では

Tensorflow2を用いたPythonプログラムを動かしても、

ループで動かしたPythonが止まることはなかったのです。

 

さらに、

Raspberry Pi Zero 2 W や Raspberry Pi 3A+ といった、RAM=512MBのPiでもTensorflow2(TF2)の物体検出処理が重かろうが動いていました。

 

しかし、現行OSのBookworm環境下でTensorflow2を動かすと、

メモリリークが発生しているのか

どんなハードのPiでも(最新のRaspberry Pi 5でも)Bookwormだと・・・

仮想メモリ使用率が徐々に増えていき99%(※)近くになると

強制終了 してしまうのです。

 

現状お手上げ!(・ω・)ノ

import psutil

psutil.virtual_memory() 

print(mem.percent)

 

逃げ道、回避策、ワークアラウンドとしては、使用した変数を頻繁にdelして使用率の上昇を抑えつつ、数時間に1回、もしくは98%くらいになったら再起動コマンドを実行するしかない状況です。

 

1世代前のBullseyeですと使用率が99%になることはまずなく、80%くらいまで上昇しても、それ以上は上がっていかず、ずっと安定して動いています。

 

現行のBookworm は、Hailo AIやNVMe SSDといったデバイスや、遠隔接続の

Raspberry Pi Connectが使えるのですが、肝心なPython上のTF2プログラムが連続動作してくれなくて

環境をなかなか移行できない状況です(Tω

 

2025/5/10追記:
学習済みモデルを、気に入ってたssd_mobilenet_v2_cocoから

 SSD MobileNet V2 FPNLite 640x640 に変更するとmemory leakがFixされました
(;ω;)ノ

python - Fixing memory leak in tensorflow2 during loading the model - Stack Overflow

 

赤マーカーが従来のssd_mobilenet_v2_cocoで動作させてしばらくしてメモリリークによりRAMとSWAPがパンクしラズパイがフリーズ。
緑マーカーが SSD MobileNet V2 FPNLite 640x640です。

Raspi5(4GB)のRAM使用率が50%で安定しています(;ω;)v

モデル変更前後

追記。4.5日で約10%ほどRAM使用率が増加するようです。
(Pi5 4GBなので10%は約400MB)

モデル変更前後(緑は2.5日と4.5日)






本記事をお読みいただき、ありがとうございます。

以上となります(`・ω・´)v