Adafruit-Blinkaを使ってみる

PlatformDetectへのボード追加


Adafruit-Blinkaはチップとボードの検出にAdafruit_Python_PlatformDetectライブラリを使っていま す。
このライブラリがチップとボードの検出に失敗すると、Adafruit-Blinkaは初期化に失敗します。
Adafruit-Blinkaに新しいボードのサポートを追加するためには、まずは Adafruit_Python_PlatformDetectに
新しいボードを追加する必要が有ります。
そこで、Adafruit_Python_PlatformDetectに新しいチップとボードを追加する手順を紹介します。

チップとはSoCのことで例えばAllwinner H3やAllwinner A64などです。
同じSoCを使っているボードは多数あります。
例えばOrangePi PC、OrangePi ZERO、NanoPi NEOなどはAllwinner H3を採用しています。
ボードとはOrangePi PC、OrangePi ZERO、NanoPi NEOのことです。
Adafruit_Python_PlatformDetectは最初にチップの自動検出を行います。
チップの自動検出ができないときは、その時点で処理を終わります。
チップの自動検出に成功したら、チップ情報を元にボードの自動検出を行います。

PlatformDetectライブラリへのチップとボードの追加は以下の手順で行います。
・対応状況の確認
・チップ定義の追加
・チップ検出処理の追加
・ボード定義の追加
・ボード検出処理の追加



◇対応状況の確認
以下のスクリプトを実行することで対応状況を確認することができます。
$ cat detect.py
from adafruit_platformdetect import Detector
detector = Detector()
print("Chip id: ", detector.chip.id)
print("Board id: ", detector.board.id)

このスクリプトを実行してChip idとBoard idが表示されれば、自動検出は成功です。
自動検出できない場合、以下の様にNoneが表示されます。


pipを使ってAdafruit_Python_PlatformDetectをインストールした場合、ライブラリは以下のディレクトリにインス トールされます。
$HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect
python3.10の部分は、インストールされているpythonのバージョンに置き換わります。
pipを使ってインストールしたファイルと、githubのmasterブランチのファイルは一部差分が有ります。
$ python3 -m pip install install Adafruit-PlatformDetect

$ git clone https://github.com/adafruit/Adafruit_Python_PlatformDetect

$ diff $HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect/chip.py$HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect/
34c34
< __version__ = "3.66.0"
---
> __version__ = "0.0.0+auto.0"

$ diff $HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect/board.py$HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect/
34c34
< __version__ = "3.66.0"
---
> __version__ = "0.0.0+auto.0"

そこで、githubのmasterブランチを正として、あらかじめこの差分を無くしておきます。
これをこの時点でやっておかないと、テスト後の処理が面倒になります。
$ cd $HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect
$ cp *.py /home/orangepi/.local/lib/python3.11/site-packages/adafruit_platformdetect/

$ cd constants/
$ cp *.py /home/orangepi/.local/lib/python3.11/site-packages/adafruit_platformdetect/constants/

これ以降、以下のディレクトリを基準のディレクトリとします。
$ cd $HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect



◇チップ定義の追加
「constants/chips.py」にチップ定義を追加します。
今回はRV1103を追加しました。
RV1103 = "RV1103"



◇チップ検出処理の追加
「chip.py」にチップ検出処理を追加します。
チップの検出は「/proc/device-tree/compatible」や「/proc/device-tree/model」などの内容 を判 定して行います。
この部分は既存ソースと、インストールされているシステムファイルの内容を判断して、新しいコードを追加することになります。
今回は以下のコードを追加しました。
        if self.detector.check_dt_compatible_value("rockchip,rv1103"):
            return chips.RV1103"

この時点で、検出スクリプトを実行すると、Chip idが表示されるようになります。




◇ボード定義の追加
「constants/boards.py」にボード定義を追加します。
今回はLUCKFOX_PICO_MINIを追加しました。
LUCKFOX_PICO_MINI = "LUCKFOX_PICO_MINI"

このファイルには以下の様なボードグループが定義されている場合が有ります。
これを見ても分かる様に、ボードグループ内のボードは同じチップを使っているわけではありません。
# OrangePI
_ORANGE_PI_IDS = (
    ORANGE_PI_PC,
    ORANGE_PI_R1,
    ORANGE_PI_ZERO,
    ORANGE_PI_ONE,
    ORANGE_PI_LITE,
    ORANGE_PI_PC_PLUS,
    ORANGE_PI_PLUS_2E,
    ORANGE_PI_2,
    ORANGE_PI_ZERO_PLUS_2H5,
    ORANGE_PI_ZERO_PLUS,
    ORANGE_PI_ZERO_2,
    ORANGE_PI_3,
    ORANGE_PI_3B,
    ORANGE_PI_3_LTS,
    ORANGE_PI_4,
    ORANGE_PI_4_LTS,
    ORANGE_PI_5,
    ORANGE_PI_5_PLUS,
)

この定義は以下の関数で使われていて、ボードグループ内の何れかのボードであればTrueを戻します。
    def any_orange_pi(self) -> bool:
        """Check whether the current board is any defined Orange Pi."""
        return self.id in boards._ORANGE_PI_IDS

そこで、今回以下のボードグループを追加しました。
# Luckfox
_LUCKFOX_IDS = (
    LUCKFOX_PICO_MAX,
    LUCKFOX_PICO_MINI,
)



◇ボード検出処理の追加
「board.py」にボード検出処理を追加します。
検出したチップIDを元にボードIDの検出を行います。
ボードの検出は「/proc/device-tree/compatible」や「/proc/device-tree/model」などの内容 を判 定して行います。
この部分も既存ソースと、インストールされているシステムファイルの内容を判断して、新しいコードを追加することになります。
今回は以下のコードを追加しました。
        elif chip_id == chips.RV1103:
            board_id = self._rv1103_id()

(中略)

    def _rv1103_id(self) -> Optional[str]:
        """Check what type of rv1103 board."""
        board_value = self.detector.get_device_model()
        board = None
        if board_value and "Luckfox Pico Mini" in board_value:
            board = boards.LUCKFOX_PICO_MINI
        return board

ここまで変更して、検出スクリプトを実行すると、Chip idとBoard idが表示されるようになります。
これで新しいチップとボードの追加は完了です。


ボード検出のスクリプトはPlatformDetect本体にも付属しています。
以下の手順で本体に付属しているボード検出のスクリプトを実行することができます。
自分のボードを正しく検出できるかだけでなく、他のボードとして誤検出しないことを確認することができます。
$ cd $HOME/Adafruit_Python_PlatformDetect/bin

$ python3 ./detect.py
Board Detection Test

Check that the Chip and Board IDs match your board and that this it is
correctly detecting whether or not it is a Linux board.

Chip id:  RV1106
Board id:  LUCKFOX_PICO_MAX

Linux Detection
---------------
Is this an embedded Linux system? True

Raspberry Pi Boards
-------------------
Is this a Pi 3B+? False
Is this a Pi 4B? False
Is this a 40-pin Raspberry Pi? False
Is this a Raspberry Pi Compute Module? False

Other Boards
-------------------
Is this a Siemens Simatic IOT2000 Gateway? False
Is this a 96boards board? False
Is this a BeagleBone board? False
Is this a Giant board? False
Is this a Coral Dev board? False
Is this a MaaXBoard? False
Is this a SiFive board?  False
Is this a PYNQ board? False
Is this a Rock Pi board? False
Is this a NanoPi board? False
Is this a Khadas VIM3 board? False
Is this a Clockwork Pi board? False
Is this a Seeed Board? False
Is this a UDOO board? False
Is this an ASUS Tinker board? False
Is this an STM32MP1 board? False
Is this a MilkV board? False
Is this a Luckfox Pico board? True
Is this a generic Linux PC? False
Is this an OS environment variable special case? False



動作確認が終わったら、変更したファイルをgithubのマスターリポジトリに反映する手続きを行います。
githubのリポジトリは以下の4種類に分類されます。
・master-remoteリポジトリ 所有者は作者様(今回はAdafruit)です。
・master-localリポジトリ master-remoteリポジトリをローカル環境にcloneしたリポジトリで、変更しても master-remoteリポジトリに反映できません。
・fork-remoteリポジトリ master-remoteリポジトリをforkしたリポジトリで、所有者は貴方になります。
・fork-localリポジトリ fork-remoteリポジトリをローカル環境にcloneしたリポジトリで、変更した内容をfork- remoteリポジトリに反映することができます。

githubのmasterリポジトリの変更は以下の手順で行います。
・master-remoteリポジトリ(こ こ)をforkして、貴方のアカウントにfork-remoteリポジトリを作る。
・fork-remoteリポジトリをローカルにcloneしてfork-localリポジトリを作る。
・fork-localリポジトリで修正、テストを行う。
・fork-localリポジトリの修正結果をfork-remoteリポジトリに反映する。
・fork-remoteリポジトリの変更をmaster-remoteリポジトリに反映する。(PullRequestを発行して作者に承認、 反映してもらう)

Adafruitのこ のレポジトリを開いてリポジトリをforkします。
これで自分のアカウントにfork-remoteリポジトリが追加されます。
fork-remoteリポジトリの所有者は貴方なので、新しいBranchを作ることもできます。
fork-remoteリポジトリをローカル環境(自分のPC)にcloneします。
master-remoteリポジトリをcloneする場合も、fork-remoteリポジトリをcloneする場合も、clone先のディレ クトリは同じになるので
事前にmaster-localリポジトリは削除しておきます。
fork-localリポジトリとpipでインストールしたパッケージとの関係は以下の様になります。
これが、pipでインストールしたパッケージの内容です。
$ ls -l $HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect
合計 84

-rw-rw-r-- 1 nop nop  4273  5月 30 22:56 __init__.py
-rw-rw-r-- 1 nop nop 44046  5月 30 23:01 board.py
-rw-rw-r-- 1 nop nop 16218  5月 30 23:02 chip.py
drwxrwxr-x 2 nop nop  4096  5月 31 19:47 constants
-rw-rw-r-- 1 nop nop  8257  5月 30 22:56 revcodes.py

これが、fork-localリポジトリの内容です。
$ ls -l $HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect
合計 84

-rw-rw-r-- 1 nop nop  4273  5月 30 22:56 __init__.py
-rw-rw-r-- 1 nop nop 44046  5月 30 23:01 board.py
-rw-rw-r-- 1 nop nop 16218  5月 30 23:02 chip.py
drwxrwxr-x 2 nop nop  4096  5月 31 19:47 constants
-rw-rw-r-- 1 nop nop  8257  5月 30 22:56 revcodes.py

修正したファイルをpipのパッケージディレクトリからlocalリポジトリにコピーします。
ここが一番面倒な部分です。
$ cd $HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect

$ cp board.py $HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect/

$ cp chip.py $HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect/

$ cp constants/chips.py $HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect/constants/

$ cp constants/boards.py $HOME/Adafruit_Python_PlatformDetect/adafruit_platformdetect/constants/

これで、localリポジトリのファイルと、pipでインストールしたパッケージのファイルが一致します。
Adafruitのリポジトリ(master-remoteリポジトリ)はpre-commitというツールで、コーディング規則が決められてい ます。
そこで、localリポジトリのファイルに対して、pre-commitを実行します。
初めてpre-commitを実行するときは、各種ツールをダウンロード、インストールするので結構時間が掛かります。
$ python3 -m pip install pre-commit

$ cd $HOME/Adafruit_Python_PlatformDetect

$ pre-commit run --all-files
[INFO] Initializing environment for https://github.com/python/black.
[INFO] Initializing environment for https://github.com/fsfe/reuse-tool.
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Initializing environment for https://github.com/pycqa/pylint.
[INFO] Installing environment for https://github.com/python/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/fsfe/reuse-tool.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/pycqa/pylint.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
black....................................................................Passed
reuse....................................................................Passed
check yaml...............................................................Passed
fix end of files.........................................................Passed
trim trailing whitespace.................................................Passed
pylint (library code)....................................................Passed
pylint (example code)................................(no files to check)Skipped
pylint (test code)...................................(no files to check)Skipped

エラーが有るときは、エラーの内容に応じてファイルを修正します。
この様にファイルのインデントや空白の数など、書式に問題があるときは、blackでエラーになります。
# OrangePI
_ORANGE_PI_IDS = (
    ORANGE_PI_PC,
    ORANGE_PI_R1,
    ORANGE_PI_ZERO,
    ORANGE_PI_ONE,
    ORANGE_PI_LITE,
    ORANGE_PI_PC_PLUS,
    ORANGE_PI_PLUS_2E,
    ORANGE_PI_2,
ORANGE_PI_PC2,
    ORANGE_PI_ZERO_PLUS_2H5,
    ORANGE_PI_ZERO_PLUS,
    ORANGE_PI_ZERO_2,
    ORANGE_PI_3,
    ORANGE_PI_3B,
    ORANGE_PI_3_LTS,
    ORANGE_PI_4,
    ORANGE_PI_4_LTS,
    ORANGE_PI_5,
    ORANGE_PI_5_PLUS,
)

これがblackで書式エラーとなった時のログです。
1つのファイルがreformattedされたことが分かります。
$ pre-commit run --all-files
black....................................................................Failed
- hook id: black
- files were modified by this hook

reformatted adafruit_platformdetect/constants/boards.py

All done! ? ? ?
1 file reformatted, 9 files left unchanged.

blackは自動的に正しい書式にフォーマットしてくれます。
# OrangePI
_ORANGE_PI_IDS = (
    ORANGE_PI_PC,
    ORANGE_PI_R1,
    ORANGE_PI_ZERO,
    ORANGE_PI_ONE,
    ORANGE_PI_LITE,
    ORANGE_PI_PC_PLUS,
    ORANGE_PI_PLUS_2E,
    ORANGE_PI_2,
    ORANGE_PI_PC2,
    ORANGE_PI_ZERO_PLUS_2H5,
    ORANGE_PI_ZERO_PLUS,
    ORANGE_PI_ZERO_2,
    ORANGE_PI_3,
    ORANGE_PI_3B,
    ORANGE_PI_3_LTS,
    ORANGE_PI_4,
    ORANGE_PI_4_LTS,
    ORANGE_PI_5,
    ORANGE_PI_5_PLUS,
)

pre-commitはけっこう重いので、環境によっては、修正、テストを実施したSBC上でpre-commitが動かない場合が有ります。
その様なときは、IA64のUbuntuマシンやDebianマシンに、一旦修正ファイルを転送してからpre-commitを実行する必要 が有ります。
$ USER="転送先ホストのユーザ名"

$ HOST="192.168.10.20"

$ HOMEX="転送先ホストの$HOME"

$ cd $HOME/.local/lib/python3.10/site-packages/adafruit_platformdetect

$ scp board.py ${USER}@${HOST}:${HOMEX}/Adafruit_Python_PlatformDetect/adafruit_platformdetect/

$ scp chip.py ${USER}@${HOST}:${HOMEX}/Adafruit_Python_PlatformDetect/adafruit_platformdetect/

$ scp constants/chips.py ${USER}@${HOST}:${HOMEX}/Adafruit_Python_PlatformDetect/adafruit_platformdetect/constants/

$ scp constants/boards.py ${USER}@${HOST}:${HOMEX}/Adafruit_Python_PlatformDetect/adafruit_platformdetect/constants/

自動成形されたときは、もう1度pre-commitを実行してエラーが無いことを確認します。
pre-commitが終了したらlocalリポジトリ→fork-remoteリポジトリにファイルを反映しますが、
修正作業中にmaster-remoteリポジトリに新しい変更が加わっている可能性が有ります。
そこで、master-remoteリポジトリの変更を、fork-remoteリポジトリに取り込みます。
これはgithubのwebページで「Sync Fork」のボタン一発で取り込むことができます。

git diff でlocalリポジトリとremoteリポジトリの差分を確認することができます。
git configは最初の1度だけ必要です。
$ git status
$ git diff

$ git config --global user.email "あなたのメールアドレス"
$ git config --global user.name "あなたのgithubアカウント"

$ git add .
$ git commit -m "適当なコメント"
$ git push
Username for 'https://github.com': xxxxxxxxxx   -> githubアカウント
Password for 'https://xxxxxxxxxx@github.com':   -> github Personal Access Token

Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 4 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 681 bytes | 136.00 KiB/s, done.
Total 6 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To https://github.com/xxxxxxxxxxAdafruit_Python_PlatformDetect
   a0261fb..e1bc181  main -> main

githubのforkリポジトリを開いて変更が反映されていることを確認します。
githubのforkリポジトリから「Contibute」のボタンを押すと、masterリポジトリにPull Requestを発行することができます。
あとはmasterリポジトリにPRがマージされるのを待ちましょう。

同じ内容がこ ちらに公開されています。

続く...