気の向くままに辿るIT/ICT/IoT
IoT・電子工作

Orange Pi Zero 3でJulius/Open JTalkスマートスピーカーを作る

ホーム前へ次へ
Orange Piって?

Orange Pi Zero 3でJulius/Open JTalkスマートスピーカーを作る

Orange Pi Zero 3でJulius/Open JTalkスマートスピーカーを作る

2023/10/08

 Orange Pi Zero 3で音声認識エンジンJulius音声合成Open JTalkによるスマートスピーカーを自作してみるページ。

 というか、実は、購入から5年、監視カメラとして仕込み中だったラズパイ3B+をショートさせて壊してしまい、Raspberry Pi/Julius/Open JTalkスマートスピーカーでも使っていた同じく5年ほど経過の3B+を使うべく、これをOrange Pi Zero 3に交代させた話。

 サーバ用に購入から7年半ほどの2Bを3B+を入れ替えたりしていて2Bが余っているときに監視カメラに音声を加えた時点で厳しさを感じ、ラズパイはここ数年入手困難、価格高騰が続いてる中、更に急激な円安の煽りはある...。

 が、正常に流通時のラズパイ3B+と同程度でRAM4GBが手に入るのならOrange Pi Zero 3を使うのもありかと血迷って買ってしまったものの、監視カメラにハードもソフトもがっつり大陸製っていうのもという点もありつつ、サーバで使っていた3B+を2Bに代え、結果、試すと上々だった3B+でいくことにして、あとは検証かなというところで壊した...。

 ほぼできていたこと、ラズパイ用IRスポットライト付きナイトビジョンカメラも買っていたこと、監視カメラは外用なので配線を考えた際、LANケーブル1本で電源供給もできるようにと他用途は思いつかないながら新たにPoE+ハブとPoE+スプリッタの導入を決め、後者はmicroUSBタイプを買ったのでmicroUSB-Type Cアダプタの存在はともかく、防犯カメラには、ラズパイ3B+を使いたかった次第。

Orange Pi Zero 3/Debian bookwormサーバベースOrange Pi OS

 今回ベースとするOrange Pi Zero 3のOSは、動作確認に利用した公式の1つDebian bookwormサーバベースのOrange Pi OS、これを元にスマートスピーカーに仕立てていきます。

 orangepi-configでtimezone、localization、hostnameなど設定済み。

 また、orangepi-configでAVAHIインストール済み(も後にlibnss-mdnsなど追加インストールを要しました)。

 技適を通っていない内蔵Wi-Fiは使わず、LANケーブルを接続、有線LANでネットワークを確保、念の為、IPを固定。

 Orange Pi Zero 3には、Zero系用拡張ボードも搭載、Zero 3では同ボード上のマイクは使えないものの、ラズパイスピーカーで使っていたマイク内蔵USBカメラを使用するので問題なし。

 スピーカーも別電源をとった冷却ファンもラズパイの時と同じものを流用。

 動作確認で使用した起動・システム用デバイスは、32GBのUSBメモリ、ラズパイ時のSSD 120GBに差し替えても良かったものの、十分いけてるのでUSBメモリをそのまま採用。

 今までスマートスピーカーとして使っていたRaspberry Piからリポジトリも大陸上のクラウドなOrange Pi Zero 3への変更なので途中インストールするであろうパッケージのことを考えると単にUUIDを書き換えて運用中だったSSDを持ってきて差し替えれば良いという話ではないのでスマートスピーカー機能を一から導入。

JuliusとOpen JTalkの準備

 Open JTalkは、Open JTalkの通りでリポジトリからのインストールで簡単に最新版(と言っても2018年12月25日付ver1.11)が入ります。

 一方、バージョン4.4、4.5、4.6、OSS、ALSA、PulseAudioと変遷し、だいぶ慣れたはずのJuliusの./configureで少し苦戦。

 path/to/に移動、4.6をgit clone、julius/にcd、./support/config.guessの出力から--buildオプション値を求め、PulseAudioを使いたいので、./configure --build=aarch64 --with-mictype=pulseaudioとして実行してみると...。

 pulseaudioのヘッダファイルがないとか、libsentがないとか...。

 4.5も4.6も--with-mictype=alsaなら./configureは通るもmakeでつまづき...

 ならばと、まず、pulseaudioから対処してみるか、うまくいけば、よくわからないlibsentの件も解決してくれるでしょ。

 ありゃ、そもそもPulseAudio入れてないじゃん...と入れてみるも変わらず...。

 ヘッダファイルならlibなんちゃらpulseにdevとかつくやつでしょということでapt-search .*pulse*してみると、まさに[libpulse-dev - PulseAudio client development headers and libraries]とか[libpulse0 - PulseAudio client libraries]があり、dpkg -lしてみると後者はあるも前者がないのでインストール。

 すると見事、./configureもmakeも通り、sudo make install。

 つまり、apt install libpulse-devしてから、JuliusをインストールすることでJuliusバージョン4.6のインストールが無事完了。

 続いて以下を取得、展開(今回使用しない2つめはとあるファイルだけあればよいのですが)。

 Grammar Toolkitは、今尚、gitからでよいのですが、Dictaition Kitは現在は未確認も当時、gitだとエラーになった為、別途v4.4を取りに行ってますが、試したところ、既に4.4はなく、4.5のダウンロードページに遷移しつつ、その4.5はどうにもダウンロードできず...。

 ということで自身は、ラズパイスマートスピーカー専用機の他にもdynabook/Debian bookworm、Raspberry Pi 400/Raspberry Pi OS bullseyeパソコンにも同スマートスピーカー機能を入れており、ここからコピーすることに。

 が、ラズパイスマートスピーカーで使っていたSSDにはv4.5が入っていたのに間違えて結果、ラズパイ400パソコンに入っていたv4.4をscpしてしまいました。

 実用上問題ないですけどね。

各種設定ファイルをコピー

 JuliusとOpen JTalkをインストールができたので続いてラズパイスマートスピーカーで使っていたSSDをマウントし、前述のDictation Kit類以外に次のようなファイル群をコピー。

 もちろん、自作スクリプト含め、コピー元とコピー先で各種パスを一致させておかないと後で修正が必要になるので注意のこと。

orange_pi_os~$ sudo mkdir /mnt/nas
orange_pi_os~$ cat /etc/fstab
...
//server.local/nas /mnt/nas cifs credentials=/home/xyz/.smb_credentials,user,noauto 0 0
...
orange_pi_os~$

 /mnt以下にSamba用マウントポイントを作成、これを踏まえ、sudoなしでマウントできるよう/etc/fstabにSambaサーバマウント設定行を追記。

 リッピング音源再生などにおいてサーバをマウントできるかという判定もしている為。

apt installしたパッケージ

orange_pi_os~$ sudo apt update && sudo apt upgrade -y
orange_pi_os~$ sudo apt install -y \
tightvncserver \
pulseaudio libpulse-dev \
open-jtalk \
open-jtalk-mecab-naist-jdic \
hts-voice-nitech-jp-atr503-m001 \
python3-pip ffmpeg mpv \
smbclient cifs-utils \
libwww-perl \
python3-avahi \
libavahi-compat-libdnssd1 \
libavahi-glib1 \
libasound2-dev
orange_pi_os~$

 apt installしたパッケージ。

 tightvncserverはVNCサーバとする為ですが、ディスプレイ関係のエラーが出る場合はtigervncの方が吉かも。

 pulseaudioはオーディオサーバとして使うので、libpulse-devはヘッダファイルがないとエラーが出たので。

 open-jtalk系は音声合成の主役、hts-voice-*は何も考えなくともmeiさんを入れるディレクトリを作ってくれるので。

 python3-pipはpipパッケージを使う為。

 smbclientとcifs-utilsは、Sambaサーバ上にリッピング・保存した音源アクセス用。

 ffmpegはffplay目的、そして(当初使用のmplayerから移行した)mpvともに音源再生用。

 libwww-perlは、pythonに移行しつつ、数少なくなったperlスクリプト用。

 avahi関連とlibasound2-devは、果たして必要だったか謎。

pip installしたパッケージ

orange_pi_os~$ python -m pip install --upgrade pip setuptools
orange_pi_os~$ pip install \
virtualenv\
yt-dlp youtube-dl \
beautifulsoup4 \
requests scapy \
feedparser lxml
orange_pi_os~$

 pip installしたパッケージ。

 virtualenv(aptにpython3-venvもある)は、externally-managed-environmentエラーの解決策として。

 yt-dlpはYouTubeのプレイリストダウンロードの為、yt-dlpに代替されたyoutube-dlは名残でなんとなく。

 beautifulsoup4、requests、scapy、feedparser、lxmlはオリジナルスクリプトで必要なライブラリだったので。

mDNSアドレス解決できない問題をlibnss-mdnsで解決

orange_pi_os~$ sudo apt update && sudo apt upgrade -y
orange_pi_os~$ sudo apt install -y libnss-mdns
orange_pi_os~$

 追加でapt installしたパッケージ。

 冒頭、orangepi-configでAvahiは入れてあり、systemdユニットファイルとしてavahi-daemonもあり、restartしても名前解決に失敗することがあったため、解決策として。

pipでexternally-managed-environmentエラー

 pipコマンド使用中にお初にお目にかかるexternally-managed-environmentエラーに遭遇。

 Troubleshooting 'Externally Managed Environment' Error in Debian 12 Pip3 Installationにいくつかの選択肢がある模様。

 aptで代替できるパッケージを探す、aptでpython3-venv(pipならvirtualenv)を使用、aptでpipxをインストールして利用、EXTERNALLY-MANAGEDファイルの削除といった対策があるとのこと。

 他の情報として4つめと似た[break-system-packages = true]を設定するという5つめとなる策もありました。

virtualenvを追加インストールし解決

orange_pi_os~$ pip install virtualenv
orange_pi_os~$ python -m venv ~/.path/to
orange_pi_os~$ source ~/.path/to/bin/activate
orange_pi_os~$

 複数あるpipでexternally-managed-environmentエラー対策の内、1つめは限界がありそう、3つめは興味はある、4つめや5つめは乱暴に見える...。

 結果、リンク先も推奨していた2つめの方法が妥当に思えたのでvirtualenvを追加インストール。

2023/11/11

 最近、Pythonプロジェクトの方針としてpipを遣う場合は、venv環境を強く推奨するらしいことをRaspberry Pi OS Bookwormへのアップグレード時に知りました。

 この状況もそれによるものだったのかもしれません。

 その結果、pip関連でエラーとなり、続けてvenvを対策として勧められた場合、ここでやったようにvirtualenvをpip installすることはできず(同じエラーが出る為)、sudo apt install python3.11-venvする必要があるでしょう。

 また、pipコマンドを使う際、python -m venv ANY_PATHとした場合、ANY_PATH/binにあるpipを使わないとエラーになるかと思います。

 その際は、export PATH=ANY_PATH/bin:$PATHしておく必要があるでしょう(PATH先頭に追加することで他のpipパスがあってもより優先されるので)。

 筆者は、まさに今日遭遇したばかり、以前、サブマシンでは使わないからとArduino環境を一掃後、確認のために必要となり、後にArduino IDEだけを入れていたところ、今日になってesp32 coreが必要となり、Linux環境でこれをインストールする際にpip...という状況に直面、python3.11-venvのインストールからPATHへの追加、後述のPYTHONUSERBASEの設定まで行う必要がありました。

orange_pi_os~$ less ~/.profile
...
python -m venv ~/.path/to
source ~/.path/to/bin/activate
...
orange_pi_os~$

 コマンドラインからの指定は一時的なようだったので恒久策として~/.profileに追記することにしました。

 結果、externally-managed-environmentエラーが出ることはなくなり、解決しました。

virtualenvゆえモジュールが認識されない問題を解決

 virtualenvを追加インストールによって解決したpipでexternally-managed-environmentエラー問題ですが、これに起因してpipでインストールしたはずのモジュールが見つからない状況に遭遇(自身のケースでは、requires)。

 名前の通り、仮想環境ですし、pip installしたパッケージやライブラリは、先ほど~/.profileにも追記した通り、~/.path/to以下にあるはず。

 探してみると実行可能なパッケージは、~/.path/to/bin/以下に、ライブラリは、~/.path/to/lib/python3.11/site-packages/以下にありました。

orange_pi_os~$ less ~/.profile
...
python -m venv ~/.path/to
source ~/.path/to/bin/activate
export PYTHONUSERBASE=~/.path/to
...
orange_pi_os~$

 このパスを探索してもらうためには...と検索するとPYTHONUSERBASEが使えそうということで~/.profileに追記。

 その後、sourceではなく、ログインし直してみたところ、ライブラリが見つからない問題が解決しました。

orange_pi_os~$ python -m site --user-base
/home/xyz/.path/to
orange_pi_os~$ python -m site --user-site
/home/xyz/.path/to/lib/python3.11/site-packages
orange_pi_os~$

 site — Site-specific configuration hookを見るとvirtualenv環境もsite-packagesの場所もコマンド一発でわかるんですね。

 ただ、自身の環境においてスマート家電である空気清浄機の操作を自前で行った際、arpコマンドに管理者権限が必要で同機操作の際、sudoを要することに。

 sudoを使う=管理者権限=rootには、現時点で先のパスが見えないので対処する必要が。

 前掲2件の公式ドキュメントをたどると.pthファイルを配置する方法があり、他の手がないか探してみようか、しばし悩んだものの、スマートスピーカー専用機だし、いっかということでrootのsys.pathの1つに/home/xyz/.path/to/lib/python3.11/site-packagesとだけ書いたxyz.pthファイルを配置することに。

orange_pi_os:~$ su -
Password:
 
Wi-Fi is currently blocked by rfkill.
Use raspi-config to set the country before use.
 
root@orange_pi:~# python
Python 3.11 (default, *** ** ****, **:**:**)
[GCC **.*.* ********] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.path)
['', '/usr/lib/python39.zip', '/usr/lib/python3.11', '/usr/lib/python3.11/lib-dynload', '/usr/local/lib/python3.11/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.11/dist-packages']
>>> import pprint
>>> pprint.pprint(sys.path)
['',
'/usr/lib/python311.zip',
'/usr/lib/python3.11',
'/usr/lib/python3.11/lib-dynload',
'/usr/local/lib/python3.11/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3.11/dist-packages']
>>>
 
([Ctrl]+d)
root@orange_pi_os:~# echo /home/xyz/.path/to/lib/python3.11/site-packages \
        > /usr/local/lib/python3.11/dist-packages/USER_xyz.pth
root@orange_pi_os:~#

 デフォルトのrootのsys.path。

 localな感じから/usr/local/lib/python3.11/dist-packages以下に探索して欲しいパスを書いた任意の名前の.pthファイルを置くことに。

root@orange_pi_os:~# python
Python 3.11 (default, *** ** ****, **:**:**)
[GCC **.*.* ********] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)
['',
'/usr/lib/python311.zip',
'/usr/lib/python3.11',
'/usr/lib/python3.11/lib-dynload',
'/usr/local/lib/python3.11/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3.11/dist-packages',
'/home/xyz/.path/to/lib/python3.11/site-packages']
>>>
 
([Ctrl]+d)
root@orange_pi_os:~#

 rootのsys.pathの1つに.pthファイルを配置後。

 期待通り、.pthファイルに記載したパスがrootのsys.pathに追加されました。

 結果、sudoを使った空気清浄機操作スクリプトの実行もできるようになり解決しました。

visudoでNOPASSWD設定

orange_pi_os:~$ sudo visudo
...
#%sudo ALL=(ALL:ALL) ALL:ALL
%sudo ALL=(ALL:ALL) NOPASSWD:ALL
...
([Ctrl]+x)([Ctrl]+y)([Enter])
root@orange_pi_os:~#

 visudoでNOPASSWD設定。

 本来はタブー、やるにしても特定コマンドに絞ってやるべきところですが...。

プッシュスイッチによるreboot/poweroff回路

 物理ボタン回路によるreboot/poweroffのGPIOをラズパイ用から適宜書き換えていきます...

 が、ざっと検索して唯一無二と思っていたwiringPiっぽいwiringOPもwiringOP-Pythonも、その他大勢もLinuxにおいて、そのベースとなる技術sysfsが非推奨となり、置き換えられている真っ最中のようで利用できたとしても、かなり面倒なことになりそうです。

 Orange PiシリーズでのGPIO操作はメーカーが提供しているwiringOPを使う模様。

 ただ、Orage Pi Zero 3 User ManualOrange Pi Zero 3 Wikiによればデフォルトで入っているので、普通はあえてgit cloneする必要はないとのこと。

Orange Pi Zero 3/Debian bookworm based Orange Pi OSでwiringOPのgpio readallコマンド出力結果

 よってroot権限も必要なく、gpio readallしてみると一覧が表示されました。

 SoCがH618のOrange Pi Zero 3ボードにも関わらず、変更がないのかZero 2と思しきH616となっているのは少し気になりますが。

 操作に際しては、次のようになるとのこと。

 操作するピン番号は、gpio readall結果中央の[Physical]番号に合致する[wPi]の値。

 [Physical]番号1〜26までは26ピン側、27、29、31、33は13ピン(拡張ボードでも使うピン)側。

orange_pi_os:~$ gpio mode [wPi]値 out
orange_pi_os:~$ gpio read [wPi]値
0
orange_pi_os:~$ gpio write [wPi]値 1
orange_pi_os:~$ gpio read [wPi]値
1
orange_pi_os:~$ gpio write [wPi]値 0
orange_pi_os:~$ gpio read [wPi]値
0
orange_pi_os:~$

 出力設定としてgpio mode [wPi]値 outとした後、gpio write [wPi]値 0/gpio write [wPi]値 1とするとそれぞれLOW/HIGH設定、設定値は、gpio read [wPi]値で確認。

orange_pi_os:~$ gpio mode [wPi]値 in
orange_pi_os:~$ gpio read [wPi]値
0
orange_pi_os:~$ gpio mode [wPi]値 up
orange_pi_os:~$ gpio read [wPi]値
1
orange_pi_os:~$ gpio mode [wPi]値 down
orange_pi_os:~$ gpio read [wPi]値
0
orange_pi_os:~$

 入力設定としてgpio mode [wPi]値 inとした後、gpio mode [wPi]値 up/gpio mode [wPi]値 downとするとそれぞれプルアップ/プルダウン設定、設定値確認は、やはり、gpio read [wPi]値。

 入力設定変更については、出力のwriteとは異なり、modeである点に注意。

orange_pi_os:~$ sudo apt install -y swig python3-dev
orange_pi_os:~$ git clone --recursive https://github.com/orangepi-xunlong/wiringOP-Python -b next
orange_pi_os:~$ cd wiringOP-Python
orange_pi_os:~$ git submodule update --init --remote
orange_pi_os:~$ python3 generate-bindings.py > bindings.i
orange_pi_os:~$ python3 setup.py install
orange_pi_os:~$

 続いてスクリプトから、Pythonから操作する方法を検索してみると、やはり、メーカーが用意したorangepi-xunlong/wiringOP-Pythonがあったのでインストール。

 ただ、githubだけではなく、git clone時、-b nextオプションや、その後のgit submodule update --init --remoteの実行が紹介されている前掲のWikiも参照しながら、インストールしてみました。

 githubにあった事前インストールが必要なパッケージの内、python3-setuptoolsは既にあったのでaptでswigとpython3-devをインストール。

 githubでもWikiでもpython3 setup.py installには、sudoを付けていましたが(っていうかWikiではプロンプトが常にbashではrootを表す#なのはさておきますが)、試しにsudoなしでやってみたら、今回利用していたvirturalenv環境にインストールされたことで正常に完了しました。

 ちなみにOrange Pi OSにも、もはや2系は入っていないようですし、3系で統一しているならpythonコマンドは、python3でなくともpythonでも良いかと。

import wiringpi
...
wiringpi.wiringPiSetup()
...
wiringpi.pinMode(2, 0) # INPUT
wiringpi.pinMode(3, 1) # OUTPUT
...
wiringpi.digitalRead(2)
...
wiringpi.digitalWrite(3, 0) # LOW
wiringpi.digitalWrite(3, 1) # HIGH
...
orange_pi_os:~$

 pythonスクリプトから操作する場合、import wiringpiし、wiringpi.wiringPiSetup()行の記述は必須。

 pythonから操作するピン番号もgpio readall結果中央の[Physical]番号に合致する[wPi]の値。

 入出力設定は、Arduino IDE同様の方法とのことで下記の通り。

 入出力設定する際は、まず、wiringpi.pinMode([wPi]値, 0)もしくは、wiringpi.pinMode([wPi]値, 1)としておく(この0/1はINPUT/OUTPUTとしても可)。

 入力なら、wiringpi.digitalRead([wPi]値)とすることで値を読むことができる。

 出力なら、digitalWrite([wPi]値, 1)/digitalWrite([wPi]値, 0)とし、この1/0はHIGH/LOWとしても可。

import wiringpi
from wiringpi import GPIO
...
wiringpi.wiringPiSetup()
...
wiringpi.pinMode(2, GPIO.INPUT)
wiringpi.pinMode(3, GPIO.OUTPUT)
...
wiringpi.digitalRead(2)
...
wiringpi.digitalWrite(3, GPIO.LOW)
wiringpi.digitalWrite(3, GPIO.HIGH)
...
orange_pi_os:~$

 (にわかにはメリットがあるようには思えませんが、)この時、import wiringpiに加え、from wiringpi import GPIOとすれば、GPIO.INPUT|wiringpi.GPIO.INPUT/OUTPUTとか、GPIO.OUTPUT|wiringpi.GPIO.OUTPUTなどとすることも可。

import wiringpi
from wiringpi import GPIO
...
wiringpi.wiringPiSetup()
...
wiringpi.pinMode(2, GPIO.INPUT)
wiringpi.pinMode(3, GPIO.INPUT)
...
wiringpi.pullUpDnControl(2, PUD_UP)
...
wiringpi.pullUpDnControl(3, PUD_DOWN)
...
orange_pi_os:~$

 プルアップ・プルダウンは共にwiringpi.pullUpDnControl()関数を使って次のような感じ。

 プルアップ設定は、wiringpi.pullUpDnControl([wPi]値, PUD_UP)、PUD_UPについては、GPIO.PUD_UP、wiringpi.GPIO.PUD_UPも可。

 プルダウン設定は、サンプルにないようですが、PUD_DOWNでよさ気?

 PWMは、現状ソフトウェアPWMのみでハードウェアプルダウン設定は、ないとのこと。

 そのソフトウェアPWM設定は、wiringpi.pinMode([wPi]値, OUTPUT)で出力設定後、wiringpi.softPwmCreate([wPi]値, MIN, MAX)、MIN/MAXは範囲の最小/最大値、ループで回してwiringpi.softPwmWrite([wPi]値, 値)、値を入れていく要領。

 他にもTone設定などいろいろできるようです。

 というわけでスマートスピーカーとしたOrange Pi Zero 3を物理ボタンでreboot、poweroff(shutdown -r、shutdown -h|halt)するスクリプト。

 視覚的な情報としてのLED1つ、GNDを含め、4ピン使うので、なんとなく、GNDの隣に3ピン平凡なピンの並びのある[Physical]番号9/11/13/15、[wPi]の値-/5/7/8を使うことにします。

 筆者メモ:黄3青4橙6灰G。

 とりあえず、テストスクリプトを書いて実行してみると...

[wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: No such file or directory.]

のようなエラーが表示され、結果、解決するには強引な方法が必要な模様。

 それもそのはず、Linux界隈では、そのベースとなる技術sysfsが非推奨となり、刷新されている真っ最中なのだとか。

 /dev/memoや/dev/gpiomemを開くことができない、そんなファイルもディレクトリもないしと冷たい対応を受けてしまったWiringOP-Python...。

 そもそも/dev/gpiomemはなく、/dev/memはありましたが...。

 となると、もしかすると他にgpio系のデバイスがあるんじゃ?と思うに至り、ls /dev/*gpio*してみると/dev/gpiochip0と/dev/gpiochip1というものを発見。

 これは、それっぽ過ぎるでしょと検索してみるとLinux GPIO: Evolution and Current State of the User APIなるものがヒット。

 読んでみるとLinuxにおける従前のGPIOへのソフトウェア的なアクセス方式のベースはsysfsだったようで恩恵もあった一方で改善の余地も多々あって今となっては非推奨、cdev、結果、GPIO chardev v2に置き換わることになったっぽいです。

 GPIO chardev v2のCライブラリが(libgpiodの後継っぽい)libgpiod2、コマンドラインインタフェースを提供するデーモンとしてgpiodがあるらしく、apt-cache searchしてみると確かにこれらがあります。

 この言語バインディングとしてC++とPythonも登場、リポジトリには、python3-libgpiodがありました。

 また、pipには、gpiodev 0.0.1(アルファ版)python-peripheryはありますが、python3-libgpiod含め、道半ばな模様で、まだまだ誰もが気軽に使える状態にはなさ気...。

 よって現時点では、gpiodでshellスクリプト...と思ったら、この辺も併せて読んでも今のところ実装されているコマンドはgpiodetect、gpioinfo、gpioset、gpioget、gpiofind、gpiomon程度な模様。

orange_pi_os~$ sudo install gpiod
...
orange_pi_os~$ sudo gpiodetect
gpiochip0 [*******.pinctrl] (288 lines)
gpiochip1 [*******.pinctrl] (32 lines)
orange_pi_os~$

 何れにせよ前進とばかりに、とりあえず、gpiodをインストールしてみた結果、libgpiod2も併せてインストールされました。

 これで先のコマンドも使えるようになりますし、使い方をmanで調べることもできます。

orange_pi_os~$ sudo group add gpio
orange_pi_os~$ sudo usermod -aG gpio USER_xyz
orange_pi_os~$ sudo vi /etc/udev/rules.d/99-gpio.rules
SUBSYSTEM=="gpio", KERNEL=="gpiochip[0-1]", GROUP="gpio", MODE="0660"
orange_pi_os~$

 ただ、このままだとgpiod系のコマンドは、rootでしか実行できないのでユーザーでも実行できるようにとあるgit issuesへのmakermelissa氏のリプライなどを参考にセットアップしてみました。

 まず、gpioグループを作成、gpiodを実行したいユーザーを同グループに追加。

 続いてudevが動いているシステムでは、例えば、このように設定。

 そしてOrange Pi Zero 3の再起動。

orange_pi_os~$ gpiodetect
gpiochip0 [*******.pinctrl] (288 lines)
gpiochip1 [*******.pinctrl] (32 lines)
orange_pi_os~$

 再起動後は、sudoがなくともgpioグループ権限で、これに属する一般ユーザーでも実行が可能になりました。

orange_pi_os~$ vi gpiodtest.py
import gpiod
...

 さて、pythonスクリプトは、どう書いたものか...。

orange_pi_os~$ vi gpiodtest.sh
#/bin/bash
...

 それともshellスクリプトの方が良いのか...。

gpiod/gpioinfo出力結果 Orange Pi Zero 3(写真左)/Raspberry Pi 3B+(写真右)

 gpioget、gpiosetでGPIOアクセスし、ステータスの取得・変更はできそうですが、ピン番号には何を使えば...。

 と思ったら、Orange Pi Zero 3(写真左)ではunamedな部分が、ラズパイ3B+(写真右)では、ことごとく名称が入っており、GPIO番号が振られているものもありました...。

 きっとOrange Pi Zero 3でも、これが表示されないと先に進めないでしょ...。

2023/12/09

 Orange Pi Zero 3でGPIO操作する方法を模索、WireingPiもwiringOP-Pythonもsysfs問題でlibgpiod/libgpiod2への移行過渡期な模様で、さてどうしたものかと思っていましたが...。

 Raspberry Pi zero/Raspbian Busterでの話ながら、ShellスクリプトでWiringPiコマンドを使う再起動とシャットダウンをプッシュスイッチで行えるようにするなら、今時点でもいけることが判明。

orange_pi_zero_3:~$ cat .opi_reboot_poweroff.sh
#!/bin/bash
 
/usr/bin/gpio mode 6 out
/usr/bin/gpio mode 9 in
/usr/bin/gpio mode 9 up
/usr/bin/gpio mode 10 in
/usr/bin/gpio mode 10 up
 
while :
do
  btn_reboot=`/usr/bin/gpio read 9`
  btn_poweroff=`/usr/bin/gpio read 10`
  if [ $btn_reboot -eq 0 ]
  then
    #echo "push btn_reboot"
    for i in `seq 3`;do
      /usr/bin/gpio write 6 1
      sleep 1
      /usr/bin/gpio write 6 0
      sleep 1
    done
    /sbin/reboot
  elif [ $btn_poweroff -eq 0 ]
  then
    #echo "push btn_poweroff"
    /usr/bin/gpio write 6 1
    sleep 3
    /usr/bin/gpio write 6 0
    /sbin/shutdown -h now
  fi
  sleep 1
done
orange_pi_zero_3:~$

 それをこんな風にアレンジ。

 ラズパイと違ってオレンジパイでは、プルアップ|プルダウン時、内部ではなく外部にプルアップ|プルダウン抵抗が必要とのこと。

 今回は、ボタンOFFでHIGHに固定、ONでLOWとすべく、3.3Vと当該GPIOピン9及び10(共にgpio readallのwPi値)間にプルアップ抵抗(今回は10k)を入れることにしました。

 また、再起動の際は、LEDを点滅(1秒毎のON/OFFを3回)、電源断では3秒点灯としました。

orange_pi_zero_3:~$ cat /etc/systemd/system/opi_reboot_poweroff.service
[Unit]
Description=Shutdown Service
After=multi-user.target
 
[Service]
Type=idle
ExecStart=/home/USER/.opi_reboot_poweroff.sh
 
[Install]
WantedBy=multi-user.target
orange_pi_zero_3:~$

 リンク先では実行権限を付与した上、/usr/local/binにおいてバックグラウンド起動させていましたが、ここは従前ラズパイでやっていた時と同様にsystemdユニットファイルで永続的に自動起動させることに。

Orange Pi Zero 3自作スマートスピーカー用リブート/シャットダウン物理ボタン回路

(筆者メモ ヘッダ:橙/灰/青/黄/赤 GPIO:橙/紫/黄/青)

 物理スイッチは、ちょっと大きめですが、100均の名刺入れに初めて使った大きめのタクトスイッチと差し込みのコネクタヘッダ用の穴をあけ、再起動・パワーオフでそれぞれ点滅・点灯する共用のLEDはグリーンとし、こんな感じになりました。

 スマートスピーカーを載せてある食器棚の横板に先代ラズパイの同回路を引っ剥がし、粘着力十二分なナノテープはそのままに差し替えて貼り付けました。

 尚、poweroffコマンドを使ったシャットダウンですが、(ラズパイではUSB給電も一瞬、断されつつ、即通電という感じでしたが、Orange Pi Zero 3では、)緑のLED点滅が終わり、赤LEDが消えてもUSBへの給電は継続されるようでスピーカーの電源LEDも点灯したまま、ACアダプタに付属するスイッチは筐体内にあり、ON/OFFは、ラズパイの頃からACアダプタを挿しているスイッチ付き電源タップで行っています。

 後述のようにGPIOライブラリを使ったPythonスクリプトでもいけそうながら完成に至らず、当面、このShellスクリプト版で凌ぐことにします。

 というか、ラズパイの時と同様に再起動ボタン機能もつけているものの、Orange Piシリーズ、どうやら以前からEthernetのチップに起因するバグがある模様ながらカーネルによっては動くという話もあるようなので事実なら原因はカーネルということになりますが、ソフトウェア的なreboot(rebootやshutdonw -r now)コマンドだと再起動自体はするものの、IPアドレスが割り当てられないという事象に遭遇しており、未解決、結果、後述の通り、あえて使っていたイーサネットのみ見舞われる症状なのでUSB Wi-Fiアダプタへの変更を要しました...。

 尚、shutdown -h nowの時は、Orange Pi Zero 3の緑のアクセスランプは最終的に消灯、赤LEDも点灯しない、一方、reboot/shutdown -r nowの時は、アクセスランプ消灯後に赤LEDが点灯、アクセスランプが再び点滅しているので、再起動はしているはず。

 これを確認していたので最初からネットワークの問題だろうとあたりを付けて検索してみると、その情報は限られ、というか先のリンクを見つけた時点で探すのをやめたからかもしれませんが、たいていは、カーネルやmicroSDカードの品質への言及止まりのようでした。

 ただ、イーサネットチップに起因するとまでは思っておらず、Orange Pi Zero 3で無線LANドングルを使えることは確認済みなので試してみたところ、端末からのsudo rebootでも普通に再起動することを確認しました。

 今日まで再起動させたことがなかったのでOrange Pi Zero 3の再起動にこんな罠があること自体気づきませんでした。

 自身の場合、自作スマートスピーカーとして、あえて有線LANで使っていたのですが、これを機に少なくとも本件が解決するまでの間、固定IP用のネットワークインタフェースもend0からwlan0にし、無線LANに切り替えることにします。

 そこで、また、ちょっとハマったのが、Orange Pi系においては、/etc/dhcpcd.confでも/etc/network/interfaces(.d)でもなく、nmtuiかnmcliで設定する必要がありました(そうしないと無線LAN用に固定IPを割り当てられませんでした)。

【番外編】

 ちなみにOrange Pi Zero 3 GPIO Python LibraryにOrange Pi Zero 3でも同様のピン配列なZero 2用のGPIO.setboard(GPIO.H616)を使えば、GPIOライブラリhttps://github.com/eutim/OPI.GPIO(pipでいけるOPi.GPIOではない)を使えるという情報が。

 その後、ふとOrangePi Zero2でPythonからGPIOを利用しようとしたら苦労した話に遭遇、パッチが必要だったかということでリンク先の手順通り、手作業で修正・追記したところ、GPIO操作に管理者権限がいるため、sudoでスクリプトを実行できることを確認。

 続いてShut down OPi Zero using a push button on GPIOでシャットダウン方法のついでに再起動方法の話になり、ライブラリが異なる模様もGPIOライブラリならいけるよという情報が。

 更にOPI.GPIOでそのままいけるshutdown版power-switch-Ozero / power-switch-Ozero.pyを発見。

 ということでOPI.GPIOでがっちゃんこ、と思ったら、wait_for_edge()の使い方か何か間違えているのか、rebootかshutdown何れかしかできない状況に...。

2023/12/19

 デスクで一通り動作確認した後、他の用途で使ったりして、今日、久々に自作スマートスピーカー設置場所に配置、nmapに固定IPに表示されるこもあるも、それでさえ、ssh接続できない事態に。

 原因は、デスク付近にあるAPに接続したことで、そう離れているわけでもないものの、環境がよろしくないようで自作スマートスピーカー設置場所では、無線接続できない、できても際どい状況による模様で結果、より近いAPに接続することで安定稼働するようになりました。

 設置場所付近では、デスク側APに接続して安定稼働しているESP32ボードなどもいくつかあるのですが、このWi-Fiアダプタは、数年前の購入当初から場所を選ぶ繊細さがあったので。

 さておき、それよりも、nmtuiを使った場合、設定した有線なり、Wi-Fiの設定後は、画面を1つ戻ってアクティベートする必要があるので要注意。

 この際、Orange Pi Zero 3なのか、他のシリーズもなのか、ユーザーマニュアルにあるように必要ないはずという理由で有線と無線両方使うことができないという仕様であるからか、何れかをアクティベートすると他方は(少なくとも再アクセス時には[*]が外れ、)自動でアクティベート解除されるようです。

ホーム前へ次へ