Yutaka Yasuda / 2018.12.31 (2019.9.28 追記)
(オリジナルの文書はこちらにあります)
概要
- Lepton FLIR Camera Module を Raspberry Pi Zero で動作させる際の注意点
- 継続的に絵が出てこない(しばらくすると赤い四角表示になる)問題の原因と対処
作ったもの
Lepton FLIR Thermal camera を天井に貼り付け、部屋の中の状態をサーモグラフィ画像としてドア前に提示するシステムを作りました。
Lepton FLIR Camera Module を Raspberry Pi Zero で動作させる際の注意点
基本的には以下の作例情報と、そこで参照されていたソフトウェアを利用しました。
- [FLIR Lepton Hookup Guide]
(https://learn.sparkfun.com/tutorials/flir-lepton-hookup-guide) (sparkfun, 何年も前のもの?) - FLiR Dev Kit を試す その2 (上記 sparkfun のチュートリアルに沿った報告, 2017/12)
- LeptonModule (GitHub, 何年も前のもの)
この段階で注意すべきことが一点あります。結論から書くと、上記作例に沿うなら、カメラモジュールのCSピンはRaspberry Pi の pin #26 ではなく pin #24 に接続する必要があります。
上記二つの作例では FLIR module の CS ピンに接続すべき Raspberry Pi 側 SPI インタフェイスの CE ピンは、CE0 (#24)ではなくCE1 (#26)に接続するように書かれています。しかし実際にはそれでは動作せず(上記二例に書かれている赤い四角が左上に出る状態になる)、CE0 ピンに接続する必要がありました。
私は SPI などについて今回初めて調べた程度の理解しかありませんが、ざっと調べたところでは、
- Raspberry Pi にはSPIインタフェイスが2つあり
- それぞれに CE0, CE1 ピンがある=最大四つのSPIデバイスが接続でき
- 上記LeptonModule Software の raspberry_video のコードは /dev/spi0,0 にアクセスするように書かれている
(LeptonThread.cpp は SpiOpenPort(0); とあり、それは SPI.cpp では open(std::string("/dev/spidev0.0").c_str(), O_RDWR) を呼び出すことになる) - 作例にある pin #26 は SPI0 CE1 で、それは /dev/spidev0.1 に相当する
(see; Raspberry Pi Pinout ) - しかし spidev0.0 に当たるはずの SPI0 CE0 は pin #24 のはず
です。そして実際に #24 に接続すると赤四角画像ではなく、きちんとサーモグラフィ画像が出ます。おそらく私の理解は間違ってないでしょう。
実際には現場で一緒に作業していたN君がCE1でなくCE0につないでみることを提案して動作し、後で上記のことを調べました。N君に感謝。なお画面左上に赤い四角が出るだけの状態は、映像をSPIインタフェイス(カメラ)から取得できていないことを示しています。上記ソフトウェアのmain.cppの前の方に、80x60範囲をredで埋めるコードがあります。
継続的に絵が出てこない問題の原因と対処
Shortcut
結果だけに興味のある方は、以下の「主たるコード変更箇所」セクションまで飛ばすと良いかもしれません。
問題と原因
さて前節のようにピンさえ間違えなければ動作はするのですが、連続的に動作させてみると何時間、あるいはそれより短い時間で、カメラから映像が出てこない(raspberrypi_video ソフトウェアでは絵が最後に更新されたままになるので、止まっているように見える)状態に繰り返し陥りました。というか、丸一日以上動作したことがほとんどありません。なお私の環境だけかも知れませんが、Raspberry Pi Zero のCPU温度($ vcgencmd measure_temp などとして表示可能)が高くなればなるほど、発生頻度が高まるように思われました。
面白いことに Raspberry Pi をソフトウェア・リブート($ sudo reboot)してもこの状態から戻れません(raspberrypi_video ソフトウェアでは赤四角が表示される)。唯一の解決方法はハード・リセット、つまり電源を切って入れ直すことでした。
これは以下のことを想像させます。
- Lepton FLIR Breakout board あるいは Camera Module が何らかの状態を保持しており、これがおかしくなる
- システム再起動、つまりドライバの再ロードで解決しないので、
- つまりドライバにあるはずのデバイス初期化コードはその状態をリセットしない
- しかしBreakout board あるいは Camera Module は電源の再投入によって自分自身をハード・リセットする
となると、ソフトウェアからこのハード・リセットが呼び出す方法があるかどうかが問題です。
そこで FLIR の Datasheetを見ると、p.12 の Pin Layout に RESET_L なるピンがあります。p.20 にリセットシーケンスが、p.24 辺りにやはり pin #23, #24 に PWR_DWN_L, RESET_L ピンなどがあることが示されています。しかしこれらのピンはブレイクアウトボードのピンには出ていません。つまり Breakout board 上の回路がこのあたりを制御してスタートアップシーケンスを実行していると思われます。
対処
SDKのコードやドキュメントをかなりたくさん読んで理解を整理して、ざっと検索し直したところ、これが自分だけでなく一般的な現象であることがわかりました。
Lepton common issue, but no solution (2017/3)
"However, after 5-10 minutes of continuous operation, the Lepton stops transmitting data." (b...@labyrinthlabs.ca)
However, even with this approach - eventually the thing goes off the rails and wont come back without a hard reset. (JeffW)
ここでもやはり PWR_DWN_L, RESET_L ピンが Breakout board に出ていないことが指摘されています。読み進むと、最終的に LEP_RunOemReboot() 関数が再起動をしてくれて、これによって再びデータを出してくれるようになる、と報告されています。
ところが私が参照していた FLIR Software Interface Description Document (IDD) は2014年のもので、PowerOn コマンドなどが含まれていません。それらのものは後に追加されたようです。FLIR LEPTON Software Interface Description Document (IDD) Rev 303 には 2018年の情報もあり、こちらには PowerOn や Reboot 関連の記述があります。
また冒頭に引用した Lepton Software も古く、この OEM 関連のコードがライブラリに含まれていません。ざっと検索すると、 PureThermal 1/2/Mini Reference Firmware にには LEPTON_OEM.c が含まれており、そこには LEP_RunOemReboot() があります。周囲のファイル群を自分が使っていた古い Lepton Software と較べて問題が無さそうだったので、私はこの LEPTON_OEM.c を自分の環境にバックポートして build しました。
この Google Group で正解を出した Ben Kluwe も恐らく同じ対処をした raspberrypi_libs/leptonSDKEmb32PUB を用意しているようですから、他の人はこれを利用すると良いと思います。ただ、例えば raspberrypi_video ソフトウェアなどの中に、状態がおかしくなったときに LEP_RunOemReboot() を呼び出して問題を解決するようなコードは含まれていません。プログラマが自分自身で適切なところで Reboot させるコードを追加する必要があります。下の方に私が行った rapberrypi_video ソフトウェアに対するコード追加の例を示しておきます。
注意
なお LEP_RunOemReboot() は普通、return code は -26 を返します。LEPTON_ErrorCodes.h を見ると -26 は以下のように定義されています。
LEP_ERROR_I2C_FAIL = -26, /* I2C Bus Error - General Failure */
まあリブートして I2C の接続が切れてしまった(正しい終了手続きを踏めなかった)からでしょう。これで問題無くリブートしています。ただ、LEP_RunOemReboot() を呼び出した直後に何らかのアクセス、たとえば LEP_RunSysPing() を呼び出すなどすると、恐らくはレスポンスが無いためにそこでスタックし、永遠に戻ってきません。上の Google Groups でも同様の議論があり、Reboot させてからしばらく待つようにとあります。私の実験範囲では 0.5sec の待ち時間ではダメで、0.75sec では問題ありませんでした。
主たるコード変更箇所
GitHub Repository yyasuda/LeptonModule に、そのように修正したraspberrypi_video アプリケーションが得られる状況を作っています。
つまり上記リポジトリからファイルを取得して、以下のようにすると対策した raspberrypi_video アプリケーションが得られます。
$ cd software/raspberypi_video
$ qmake && make
Comparing changes を見ると、修正箇所が分かるでしょう。大きな修正点を以下に列挙しておきます。
- LEPTON_OEM.c, .h を追加
- Lepton_I2C.cpp/h に lepton_reboot() を追加
- LeptonThread.cpp に lepton_reboot() 呼び出し記述を追加
なおこの Repository に含まれているドキュメント(IDD)は 2015 年のもので、そこには OemReboot に関する記述がありません。
FLIR LEPTON Software Interface Description Document (IDD) Rev 303 には 2018年の情報もあり、こちらには PowerOn や Reboot 関連の記述がありますので、こちらを参照することをお勧めします。
注意
この文書が参照している groupgets/LeptonModule Lepton Module は古いもので、恐らくgroupgets/purethermal1-firmware を利用する方が良いと思います。つまり sparkfun の作例 FLIR Lepton Hookup Guide は古いのですが、しかし多くの人は前者にしか含まれない raspberrypi_video アプリケーションに魅力を感じるでしょう。
その意味で BenKluwe/LeptonModule も同じことをやろうとしているように見えます。
私自身はまだこれで本当に安定して FLIR camera module が長時間連続動作できることを確認しきれていませんが、ともあれ現時点での情報としてあげておきます。
追記
このドキュメントを書くために調べていたら、なんと 2018.8 に同じ問題を同じように対処している人がいたのを発見しました。novacoast/Lepton-3-Module を見ると、おかしくなったらボタンをクリックして OEM Reboot を掛けるようにしています。うーん、気づかなかった。なんでもとりあえず検索するって大事ですね。(なんというオチ)
追記2
上のドキュメントは2018年の暮れに書いたので、その時点では「長時間連続動作できることを確認しきれていませんが」とする他ありませんでした。が、それ以来 2019年1月25日現在まで、何度かソフトウェア修正のためのリブートを行った以外は連続稼働させて、問題なく動作し続けている状態です。うまく問題を解決できていると思います。
追記3
2019年の9月に @higuchi-toshio-intec さんが Lepton 3 Module 対応の修正と機能追加をされています。参考になると思います。(近日中に取り込み予定)
https://qiita.com/higuchi-toshio-intec/items/da4f12e3e09426f45812
9/28 に @higuchi-toshio-intec さんのコードをマージしました。ありがとうございます!raspberrypi_video はいま撮影されている範囲での最高・最低温度を対象にヒートマップの色を割り付けるのですが、これを固定するためのオプションが追加されており、実用性が上がっています。
https://github.com/yyasuda/LeptonModule/pull/1