前回からの続きです。
EdisonのI2Cハードを使わずにI2C通信する
数日間ずっと暗い気持ちでモヤモヤしていたのですが、ふと、全く別のアプローチを思いつきました。Edisonが提供しているI2Cハードを使うのをやめて、汎用のデジタルIOピン上でI2C通信する処理を自前で実装するのです。(Bit Bangingと呼ばれる手法です)
基本的な実装は思ったほど難しくなかったのですが、いざ動かしてみると、ここにも一つ落とし穴がありました。
通常、汎用のI/Oピンは、データの方向(INPUT/OUTPUT)を設定してから、電圧レベル(HIGH/LOW)を読み書きします。今回はI2C通信をエミュレートするため、データ方向を頻繁に切り替える必要がありました。(I2Cは、データの送受信を1本の線でまかないます)
データ方向の切り替えはArduino互換ライブラリのpinMode関数を使って行ったのですが、この関数を呼び出すと、なんと、切り替えと関係ない「他のIOピン」の電圧が一瞬上下に振れます。I2Cプロトコルに準じた波形を作るために苦労している中で、こんな副作用があっては困ってしまいます。
試行錯誤した結果、今回は、pinMode関数を呼び出すタイミングを調整することで、なんとか副作用を抑えることができました。
Bit Bangingが救いの神だった
Bit Bangingの実装が終わったところで、デモプログラムのI2C処理を置き換えて、動作確認してみました。どうせダメでしょ・・・くらいに思っていたのですが、なんとなんと、全てのパラメーター書き込みに成功しました!
結局、EdisonのI2CハードとArduCAMの相性が悪かったんですね・・・。
カメラモジュールを1台繋げた状態でうまくいったので、今度は、2台繋げて検証してみました。いろいろ試した結果、2kHz程度のクロック周波数なら、複数台繋いでもうまくいくことが分かりました。(10kHzだと、一方は正常に動作するものの、他方はパラメーター設定に失敗して変な画像が出力されたりしました)
2kHzと言うと、I2C仕様の中で最も低速なスタンダードモードの100kHzより50倍遅いことになります。とはいえ、今回の自作カメラにおいては、I2C通信はカメラモジュールの初期化時に1回走るだけです。初期化後のシャッター制御や画像読み取りは高速なSPI通信で制御されるので、実用上の問題はありません。
ようやく、自作カメラがまともに動く
幾多の困難を乗り越えて、ようやくArduCAMがEdison上で動くようになりました。
動かし始めた頃は、EdisonからSDカードを抜き、自機のMAC OS Xに差し、画像を確認し、Edisonに再び差し直す・・・という作業を繰り返していました。ただ、これを数十回も繰り返しているうち、いい加減面倒になってきました。
そこで、Expressというnode.js用のWebサーバーAPIを使って、SDカードのJPEG画像を自機のWebブラウザから直接見られるようにしました。
$ vi app.js
var express = require(‘express’);
var app = express();// Edisonは、SD Card を /media/sdcardにマウントする
app.use(‘/sdcard’, express.static(‘/media/sdcard’));app.listen(3000, function () {
console.log(‘Example app listening on port 3000!’);
});$ node app.js #webサーバ起動
特にトラブることなく、あっさり成功。I2Cの苦労を思えば、まさに瞬殺です。こういうことがサクッとできるところに、Edisonの凄さを感じます。
今後の予定
冒頭でも述べた通り、本当にやりたい事はカメラから画像出力した先の処理なのですが、今回は、画像出力までで力尽きました。
でも、これでようやくスタートラインに立てました。これから色々試してみて、随時、本ブログに結果報告していきたいと思います。