Adafruit Product ID 1386をArduino経由で撮影するには
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > Adafruit Product ID 1386をArduino経由で撮影するには
JPEGシリアルカメラをつなぎたい
秋月電子で、小型TTLシリアルJPEGカメラ(NTSCビデオ出力付)として売られている物を購入。
Arduinoで撮影してSDカードに保存したかったので、https://github.com/adafruit/Adafruit-VC0706-Serial-Camera-Libraryを使って撮影できるようにしてみたが、うまくいかない。
うまくいかないのをうまくいくようにしたが、複数の問題点にさらされた。
- Adafruit Product ID 1386のボーレートは115200bpsである。解説されているAdafruit Product ID 397は38400bpsである。
- https://github.com/adafruit/Adafruit-VC0706-Serial-Camera-Libraryはソースコードを修正しないと115200bpsで接続することができない
- 115200としてArduinoにシリアル通信させても、何故か途中で途切れたり、撮影できなかったりする
- 不思議なのは、FTDIなどのシリアル変換ICを使うと普通に通信できる
うーん、VC0706のカメラ、撮影することはできるようになったのだけど、NFBufの初期化しないとダメかしらん? pic.twitter.com/1srgMVfp7z
— てきめん (@youkidearitai) 2017年10月22日
試したこと・できたこと
- FTDIなどのUSBシリアル変換器とJPEGカメラとを繋いでThe VC0706 CommTool softwareで撮影できる
- ただし、Adafruit Product ID 1386のボーレートは115200である。
- https://learn.adafruit.com/ttl-serial-camera?view=all#testing-the-cameraの「Using CommTool」で、Arduinoから直接カメラへ繋ぐとThe VC0706 CommTool softwareで撮影できる
ボーレートを修正する
https://github.com/adafruit/Adafruit-VC0706-Serial-Camera-Library/blob/master/Adafruit_VC0706.cpp#L50のbeginメソッドを見てみるとわかるが、引数のbaudに使われているuint16_tは65535が上限である。115200を引数として指定すると桁あふれがおこり通信できない。
そのため、直接リテラルに書き換えた。
boolean Adafruit_VC0706::begin(uint16_t baud) { // このbaudの上限は65535である。115200は桁あふれで渡せない
#if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_)
if(swSerial) swSerial->begin(115200); // baudを115200に書き換えている
else
#endif
hwSerial->begin(115200); // baudを115200に書き換えている。結局こっちも必要だった
return reset();
}
GitHubでプルリクエストを送ろうとしたがすでに送っている人が居た。
できないこと
ArduinoからSoftwareSerialを使って撮影を行い、ダウンロードしてきてSDカードへ書き出すことがうまくできない。できることにはできても、画像がかなり乱れる。
The VC0706 CommTool softwareで「Stop CFbuf」を選択しないまま「Save」を選んだ状態のようだ。
Stop CFbufとは
このThe VC0706 CommToolにある「Stop CFbuf」というボタンが、どうやらこの問題のキーのように思ったので、これが何を通信しているのかを調べたかった。
ArduinoでSerial hijickingをしらべていたのは、VC0706の「Stop CfBuf」がどのコマンドに属するかということで、それをシリアル通信からダンプすれば理解できるんじゃねと思ってダンプしたら 56 00 36 01 00 だった。明日試す pic.twitter.com/UHgyA91XEr
— てきめん (@youkidearitai) 2017年10月24日
そこで、PC -> Serial -> Arduino -> Serial -> VC0706の間にあるArduinoで通信の内容をキャプチャできないかと思って調べた。
このことを、hijackというらしい。
Hijackできる機種、できない機種
PC -> FT232XS -> VC0706
— てきめん (@youkidearitai) 2017年10月24日
ならつながるのに、
PC -> Arduino(HardwareSerial -> SoftwareSerial) -> VC0706
とするとたちまち繋がらなくなった。
UNOでJPEGシリアルカメラとSoftwareSerialでつなげて上記のことをやろうとしたが、画像をReadしてくる途中で何度やっても「Cmd Timeout」となった。LeonardoやMicroなどのATmega32u4ではHardwareSerialを2つ持っているので、持っているMicroを経由させることにした結果、問題なかった。
UNOでこのようなことをやりたい場合には、0番ピンにカメラのRXを、1番ピンにカメラのTXを挿してスケッチを空にして書き込めばうまくいけるが、HardwareSerialの余裕がなくなる。
結果、(ひとまず)Arduino Microでダンプに挑戦してみることにした。
ダンプしよう
肝心のシリアル通信によるSerial.printlnメソッドが使えないので、SDカードに保存することにした。
起動して、目的の「Stop Cfbuf」をクリックしたら、タクトスイッチを押してファイルをクローズ。SDカードをリーダーで差し込んでからVimでバイナリを読んだ。
そのときのスケッチはこのようになっている。
https://gist.github.com/youkidearitai/736b5d1547b88852b88bcc84400017b4
ダンプした結果、「56 00 36 01 00」だった。これは、「CAPTURE A IMAGE」である。まとめると以下。
VC0706 Comm Tool Fbuf Ctrlのボタン | コマンド(16進数) | PDF上のCommand Protocol |
---|---|---|
Stop CFbuf | 56 00 36 01 00 | CAPTURE A IMAGE |
Stop NFbuf | 56 00 36 01 01 | (なし、次のフレームを撮影) |
Resume | 56 00 36 01 03 | STOP CAPTURE |
ダンプした結果、PDF上の説明と相違がない。別に他のコマンドがあるわけではなかった。ここから、内容を推測すると。
- ArduinoとJPEGカメラとの通常の通信プロセスがおかしい
- Adafruitが提供しているライブラリ(AdaFruit_VC0706)は正しく実装されている
と考えた。そうなると、JPEGカメラとの通信にSoftwareSerialを使わないほうがよいだろうということで、Arduino MicroのSerial1を通信に使わせることにした。
結論
Arduino MicroでHardwareSerialを使ってJPEGシリアルカメラをキャプチャするかたちになった。
部品
- Arduino Micro
- 小型TTLシリアルJPEGカメラ(NTSCビデオ出力付)
- SDカードスロットDIP化モジュール
- 抵抗20kΩ × 3、5Vを3.3Vに落とすためにつかった
- 20kΩはなかったので10kΩ2つ使った
- 抵抗20kΩ × 3、5Vを3.3Vに落とすためにつかった
- タクトスイッチ
- デバッグ用
スケッチ
Snapshotのサンプルを編集したかたちのスケッチはこのようになった。
https://gist.github.com/youkidearitai/d4cf79508f5fb73dcd646fc84b620179
回路
- Arduino MicroとSDカードとは抵抗で分圧して3.3vくらいにしてる
- SDカードスロットが10kΩだったので20kΩを選択