2021年1月30日土曜日

NanoPi NEOにSPI LCD - OpenCVにpythonのthread

 あるカメラ(モジュール)の動作確認・設定を行うための専用の端末が必要になりました。もちろん、そんなものはWindowsなりLinuxなりのPCでやるよう構築できるものと思いますが、現場作業ものだし、『専用』なので、それだけの投資(あるいは維持)をしないとならなくなってしまいます。
そういうこと?で、なるべくお手軽にしておきたいわけで、先日せっかくTinyDRM使って『小型端末化』できるようになったNanoPi NEOにご登場いただこうか、というところです。

OS

いつものごとくarmbian使うんですが、armbianサイトに置かれているbusterイメージ、ぶっ壊れているみたいで、torrentしても、その時はunxzすることできず。手っ取り早くbionicで進めることにしました。
一時は本家Debianばっかり使ってたんですが、rock64でayufanを使う必要があったところから、だんだんubuntuが増えてきてます。(ちなみに、インストール後数日経過してるところで書いてるんですが、今現在focalにupgrade中です…)

まずはシリアルコンソールで立ち上げ、先日のdtsを持ってきてoverlayを追加し、キーボードとマウス、それにUSBドングルタイプのWiFiを用意してセットアップ開始。何分、NEO2ではなくNEOなので、軽くしておきたくGUIとしてxubuntuを選択。

OpenCV

C++から使う能力は私にはないので、python3で使うべくopencv-pythonをpipでインストール。想定どおり、build過程でout of memoryしてこけるので、1Gのfilesystem swapを追加してしまいます。これ、安定して稼働してくれれば無くしても大丈夫なはず。
しかしout of spaceで再度build中断。おや?filesystem full?そんなはずは…と思ったら、どうも、opencv-pythonをソースからbuildさせるとダウンロードしてくるため、/tmpを食いつぶしてしまいそれで起こっているようです。
このため、TMPDIRを設定してやって仕切り直し。
これで問題ないかなーと言うとさにあらず。 No module named 'skbuild' ?なんじゃこりゃ、と、お助けを乞うたところ、pipが古いのだそうな。セットアップしたばっかりなのに…(ったって、そのインストールイメージ作られたのがいつなのか、と言う問題なんだから…)。その他に、setuptoolsもupgradeしておく必要があるようです。

さすがにopencv-pythonのbuildには数時間必要。計ってはないんですが、12時間くらいかかってますかね…。

動作確認。pythonでopencv使ってjpeg読んで、LCDサイズに合わせて表示させました。


 

『箱』

NanoPi NEOには、上の写真に見て取れる、アクリル板を使ったケースというかガードというかなんというかがオプション品にあるんですが、さすがに、用途的に、LCDと、それをつなぐケーブルをぷらぷらさせておくわけにはいきません。そのため、何らか箱に収めたいんですが、NanoPi NEOは高さが結構ある関係で、LCDの配置次第で、大体40mm以上高さがあるケースが必要になります。これって結構な制約条件で、高さ方向として約40mmとろうとすると、結構大きなケースになってしまいます。NanoPiとLCDを横に並べた場合でも、高さは概ね25mm必要です。

その昔、円筒形のガムの空きボトルを使ったことがあります。あれ、ポリエチレンで、カッターで切れるし、直径が70mm近くあるんですが、コネクタ類(USB、Ether)をちゃんと出したいしLCDが2.8"だと2:1くらいに縦割りし、横倒しして使うイメージになるため、転がらないような対策も必要だし、あまりよろしい結果になりそうにありません。アクリルケースは意外と希望サイズに近いものがなく、かつ加工の際に割れるとな〜、放熱もちょっとな〜と思うと、選定しづらい感じ。アクリルのパネルから6枚切り出して…と言うのも考えましたが、コーナーに角材を入れないと接着強度が気になる。

結局アルミケースか、と探してみると、やはり高さネックでなかなかちょうど良いのがなく…と、これだけで結構な時間悩んで、最終的にたどり着いたのがタカチのTS-1S。傾斜ケースで、上面にLCD用の開口とLCD取り付け用の穴を開けないとならないので、結構な作業です。で、側面にUSBとEthernet、USBは拡張コネクタからも引っ張り出しておくので、上面に5つ、側面に3つの都合8個穴を開けることになります。上面はLCDパネルとキャリアボードのサイズの関係で左右が均等にならないし、NEOのRJ-45とUSBはあんまり間隔が開いてないので、そもそもそんな穴あけあんまり精度良くやる自信ないわぁ、と思いつつ、電ドリとハンドニブラー、ヤスリで何とか開けました。案の定若干ずれてますが…。ケースの保護フィルムは張ったままです、多分永遠に(笑)。


これはほぼ最終状態のスナップショットなので、アプリショートカットやら何やら設定した後になります。

 

おまけ -- focalへのupgrade

 これを書いている間に、focalがリリースされたけどインストールする?と、ダイアログがでました。もちろん進めるんですが、do-release-upgradeで何かエラーが起こってる。なになに?KeyError: 'suite'?
これは(も?)初体験に付き調べ回っていると、事象はこちらのサイトで話されていることと同じようです。GzipIndexが使われているのは02-armbian-compress-indexesだけなので、こいつを変更してやると、あとはupgradeが進みました。


2021年1月8日金曜日

NanoPi NEOにSPI LCD - TinyDRM

  ここのところ、GPSや多軸加速度センサを使った工作をarduinoでやったりしていたのですが、あるデバイスをコントロールするための、CUIあるいはGUI付きの箱を一つ作る必要がありそうで、以前このblogにも書いた、NanoPi NEO + LCDで構成することを考えました。

以前の記事、もう2年以上前になっているわけですが、当時はLinux4系列で、fbtftを使っていました。その時でもfbtftはstagingで、すでにtinydrmの紹介はされていましたが、多くの情報があるfbtftをそのまま使い、そのメモ書きを残していたわけです。

いま、armbianはLinux5.9、TinyDRMを使わなければなりません。

fbtftでは、fbtft_deviceを呼ぶ際に、使用するgpio端子を記述でき、initコードもquick hack的に試すことができました。TinyDRMではdevice treeを作成する必要がありますし、使用できるコントローラも限られそうです。initコードを変更する必要があった場合には、ドライバを変更しないとならないようです。手元には、いずれもaitendoで入手したものですが、SPIを使用するQVGA LCD、コントローラがili9328のもの、ili9341のものがあり、ドライバの観点では、ili9341なら容易に動かせるかもしれません。(スタンドアロンでili9328を動かすコードを公開されているかたが居られるので、それを参考に、notroさんが公開しているili9325用のドライバを修正できるかもしれませんが、将来…。)

 ということで始めてはみたものの。

Device treeのドキュメントは存在してはいるようですが、汎用的なため、体系的理解が進めば良いのかもしれませんが、LCDを動かすためにはちょっとだいぶ重荷だったので、世間の皆様に頼ることにしました。

試行錯誤の結果、次のようなdevice treeを作成: 

/dts-v1/;
/plugin/;

/ {
        compatible = "allwinner,sun8i-h3";

        fragment@0 {
                target = <&spi0>;
                __overlay__ {
                        status = "okay";
                        spidev@0{
                                status = "disabled";
                        };
                };
        };

        fragment@1 {
                target = <&pio>;
                __overlay__ {
                        M028C9341SD_pins: M028C9341SD_pins {
                                pins = "PG9", "PA1";
                                function = "gpio_out";
                        };
                };
        };

        fragment@2 {
                target = <&spi0>;
                __overlay__ {
                        /* needed to avoid dtc warning */
                        #address-cells = <1>;
                        #size-cells = <0>;

                        M028C9341SD: M028C9341@0{
                                compatible = "mi,mi0283qt";
                                /* compatible = "ilitek,ili9341"; */
                                reg = <0>;

                                spi-max-frequency = <32000000>;
                                spi-cpol;
                                spi-cpha;
                                buswidth = <8>;
                                rotation = <0>;
                                reset-gpios = <&pio 0 201 0>; /* PG9 */
                                dc-gpios = <&pio 0 1 0>;    /* PA1 */
                        };
                };
        };
};

相手はNanoPi NEOなのでSPI0、それにD/C(RS)と、resetで使用するピン、それぞれPA1とPG9を使っていますが、それを宣言してやります。

これを適当な名前でsaveして、armbian-add-overlayし、rebootすると、TinyDRM関連ドライバおよびmi0283qtがロードされ、コンソールとしてブートメッセージが流れてくれるのを見たときには、ちょっと感動しました(笑)。

SPIを使用するLCDなら、それに合ったドライバを指定し直すことで、上記の構造はそのまま使えるはずです。このLCDモジュールにはSDカードコネクタもあるので、SPIモードであれば動かすことができると思いますし、もし、タッチパネル付きのものの場合は、それに応じた追加指定が必要です。NanoPiNEOの場合SPIは1ポートしかなく、armbian-configを使ってSPI1用のCSを追加してやれば、SPIの仕様的にはそれら更なるデバイスの追加は可能なように思えますが、LCDのパフォーマンス的にどうなのかな?とは思うところです。

 

さて、これを元に、 「箱」に仕立てる算段をすることにしましょう。キー入力とかどうしようかな…。