てきとうなさいと べぇたばん

Adafruit Product ID 1386をArduino経由で撮影するには

Adafruit 1386のJPEGシリアルカメラ。このカメラを使えるようにした Arduinoからとうとう撮影できた最初の写真。これを撮るために色々やることになる。 VC0706 Comm Toolの「Stop CFbuf」「Stop NFbuf」「Resume」が何のコマンドなのかどうしてもわからなかった。 VC0706 Comm Toolの通信の内容をhijackingを利用してキャプチャし、SDカードで取得したファイルをバイナリエディタで覗いている図。 できたときの全体写真。 回路図概略。

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を使うと普通に通信できる

試したこと・できたこと

  • 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」というボタンが、どうやらこの問題のキーのように思ったので、これが何を通信しているのかを調べたかった。

そこで、PC -> Serial -> Arduino -> Serial -> VC0706の間にあるArduinoで通信の内容をキャプチャできないかと思って調べた。

このことを、hijackというらしい。

Hijackできる機種、できない機種

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」である。まとめると以下。

参考にしてるデータシート(PDF)

VC0706 Comm Tool Fbuf Ctrlのボタンコマンド(16進数)PDF上のCommand Protocol
Stop CFbuf56 00 36 01 00 CAPTURE A IMAGE
Stop NFbuf56 00 36 01 01 (なし、次のフレームを撮影)
Resume56 00 36 01 03 STOP CAPTURE

ダンプした結果、PDF上の説明と相違がない。別に他のコマンドがあるわけではなかった。ここから、内容を推測すると。

  • ArduinoとJPEGカメラとの通常の通信プロセスがおかしい
  • Adafruitが提供しているライブラリ(AdaFruit_VC0706)は正しく実装されている

と考えた。そうなると、JPEGカメラとの通信にSoftwareSerialを使わないほうがよいだろうということで、Arduino MicroのSerial1を通信に使わせることにした。

結論

Arduino MicroでHardwareSerialを使ってJPEGシリアルカメラをキャプチャするかたちになった。

部品

スケッチ

Snapshotのサンプルを編集したかたちのスケッチはこのようになった。

https://gist.github.com/youkidearitai/d4cf79508f5fb73dcd646fc84b620179

回路

  • Arduino MicroとSDカードとは抵抗で分圧して3.3vくらいにしてる
    • SDカードスロットが10kΩだったので20kΩを選択