マイコン工作実験日記

Microcontroller を用いての工作、実験記録

JPEG取得成功

2016-08-20 22:53:32 | CMOSカメラ
部品箱から74HC00を探し出したので、次のようにカメラとの接続を変更。


前回同様、PCLK 5MHz, 画像サイズQVGAで実験したところ、JPEG画像の取得に成功しました。



試行錯誤しながら実験してみてわかったかのは
  • タイマーの設定においてFilterを0に設定していると しばしば正常に画像がキャプチャできないことがあったので、フィルタ値として1を設定したところ安定して画像が取得できるようになった。
  • CLKRCの値を変更してPCLK周波数を6MHz以上にあげてみると、正しく画像データが取得できないみたい。
  • カメラからはSOIに始まってEOIで終わる完全なJPEGフォーマットが出力されるので、そのままファイルに落としてやれば画像ファイルとして使える。

タイマーキャプチャのクロックがHREFでゲートされたので、DMAバッファには綺麗にSOIで始まるデータが取得できるようになりました。



PCLKを早くすると、DMAでデータを取得するタイミングがうまく合わなくなるのか、データが正しく取得できないようです。74HC00を入れたためにPCLKにゲート遅延が生じてしまいキャプチャするタイミングがそれだけ遅くなってしまうことも悪影響を与えていると思われます。5MHzのPCLKでは、4フレーム弱程度の速度でしか画像を取得できないので動画撮影には遅すぎます。7フレーム/秒程度の動画撮影は出来るんじゃないかと想像していたので、ちょっと残念な実験結果です。
コメント
この記事をはてなブックマークに追加

JPEG出力信号を確認する

2016-08-19 00:13:18 | CMOSカメラ
OV2640の出力する信号を確認するために、SaleaeのLogic 8を接続。8chなので、VSYNC, HREF, PCLKに加えてD7..D3の5ビット分のデータをキャプチャしてみました。

まずはJPEGモードではない、通常形式での出力の場合。



ひとつのVSYNC区間の間に、HREFがライン数回変化していることがわかります。PCLKは出っぱなし。
出力形式をJPEGに変更すると次のようになりました。



通常形式とは全く異なる、なんだかちょっと不思議なところもある信号です。
  • VSYNCにはひとつヒゲが出ていますが、SYSCLKよりも短いようなので無視しても大丈夫そうです。
  • HREFにもヒゲのように見える部分がありますが、こちらは10us程度の長さがあり、無視はできません。
  • HREFがLの時にPCLKが続けて出ていますが、この時のデータは無視しなければいけないようです。
  • HREFがHでもPCLKがでていない時の方が多い。


JPEG出力の始まりの部分をズームしてみると...



HREFが立ち上がって、すぐにSOI (0xFF, 0xD8) と APP0 (0xFF, 0xE0)がでているようです。
HREFでヒゲのように見えている部分も拡大してみると...



PCLKがしっかりと出ているので、この部分のデータは読み捨てなければいけないようです。GitHubにあった参考コードでは、HREFの変化を割り込みで検出してタイマーのキャプチャ動作を許可/禁止する仕掛けになっていましたが、PCLKの速度に比べてMCUのクロックが充分に早くないと処理が間に合いません。5MHzのPCLKでも画像がきちんと取得できなかったのは、これが原因ではないかと思われます。

HREFがLの期間のPCLKを無視するために、TIMERにはHREFとPCLKの論理積(AND)をとった信号を入れてやれば、問題を解決できるように思われます。
コメント
この記事をはてなブックマークに追加

Arduino PRIMO

2016-08-18 09:47:22 | Weblog


Arduino PRIMOというのが出るらしい。nRF52(BLE)+ESP8266(WiFi)という組み合わせをSTM32F103がお助けするという構成のようです。知名度高いものの組み合わせではありますが、なんかもう少しスッキリして欲しい気もするんですが。。。
コメント
この記事をはてなブックマークに追加

頭は見つかったものの...

2016-08-17 21:55:58 | CMOSカメラ
今回, OV2640を使ってみようと思い立ったのは、こちらの記事にて、「DCMIを使わずにSTM32にOV2640をつなぐ」というアイデアが紹介されていたのを見つけたのがきっかけです。また、STからはAN4666というAPノードが出ていることもわかりました。TIMERのインプットキャプチャ機能を使って、画素クロックの立ち上がりを検出してDMA要求を出させるというアイデアに、「なるほど、その手があったか!!」と感心したので、ぜひとも自分でも試してみたくなったのです。この記事では仕組みの概要やSTM32F4のコードも示されているものの、実際に取得してみた画像は示されておらず、あくまでもコンセプトを実証してみたという扱いにとどまっていることもちょっと気になったので、自分で確認してみようと思い立ったのです。わたしの場合、下図のようにつなげています。

  • PB6/PB7はもともとI2Cとして使っていましたが、OVとの相性が悪いことがわかったので、GPIOとして使い、ソフトI2Cにてレジスタ操作を行うことになりました。
  • PA8はMCOとして使い、SYSCLKの80Mhzを分周した20Mhzをカメラに供給。
  • PCLKからはカメラの設定に応じてXCLKを分周したものが出力されますが、TIM2をInput Captureモードで使うことで、その立ち上がりを検出します。
  • PB4とPB5はEXTIに設定して、同期信号の立ち上がり/立ち下がりを割り込みで検出します。
  • 実際にはPWDNとRESET信号もつないでいますが、図では省略。


ソフトI2Cにしたら、OV2640のレジスタアクセスは問題なく動作するようになったので、サンプルのコードを参考にしてSTM32CubeMXで生成したHALとFreeRTOSで動作するコードを作成。TIM2の入力キャプチャ動作を開始しておいて、VSYNCの立ち上がりを検出したらDMAでGPIOCの読みとりを開始させまます。JPEG画像情報の出力が終わるとVSYNCが落ちるのでDMAを止めて取得できたJPEG情報を確認するという具合です。

PCLKが5MHzになるようにOV2640のCLKRCレジスタを設定、画像サイズはQVGAに設定してやって、カメラから出力されるJPEGデータを取り込んだところ、次のようにJPEGファイルの頭の部分を見つけることができました。



0x2000135E番地からの 0xFF, 0xD8の2バイトがJPEGファイル構造の始まりを示すSOIになっており、続く2バイトの0xFF, 0xE0がAPP0の始まりになっています。そして、その後には量子化テーブルとハフマンテーブル定義が続いていますので、実際のフレーム情報はさらにその後ろに続いているだろうと思わます。DMAでメモリに読み込んだデータをファイルに落としてやれば、JPEGファイルとなるはずです。しかし、まだSDカードへの書き込みは作っていないので、確認のためにデバッガーを使ってメモリの内容をファイルに書き出してやることにしました。近頃、お気に入りのOzoneを使えばメモリ表示ウインドウからメニューを出してダンプしてやることができます。こんな手順で、JPEG画像ファイルが取得できるはずだったのですが....







何度試してみても綺麗な画像が取得できません。画像の途中でズレが生じてしまっています。途中で画素情報の取りこぼしが生じてしまっているように思われます。どうやら、1枚の画像情報を出力している間に何度かHREF信号が変化するらしく、この信号により画素情報の有効期間が通知されているようなのですが、その処理がうまくできていないようです。

そもそもカメラからどんな信号が出力されているのかを、ちゃんと確認しておかねばいけませんね。何しろ、ネットで入手できるOV2640のデータシートではそのあたりの詳細は説明されていませんので。
コメント
この記事をはてなブックマークに追加

I2Cとの相性

2016-08-12 21:16:52 | CMOSカメラ
OV2460とNucleo-L476RGをつなぐための最低限の配線ができたので、続いてソフトの準備です。

まずはカメラのレジスタの読みとりができることの確認から。よく知られているようにOmnivisionのカメラの制御信号はSCCBと呼ばれていますが、物理的なインタフェースはI2Cと同じです。そこでSTM32L476側のI2CとつないでCubeMXのHAL_I2C_Mem_Read() APIを使ってアクセスを試みたものの、レジスタの読みとりができません。調べてみると、カメラに対してデバイスアドレスを送ったのに、ACKが返ってこないのでエラーとなっているようです。これがSCCBとI2Cの規格の違いで、I2Cにおいて ACKを返すべきところがSCCBではDon't careになっているために、このような不都合が生じます。この違いは想定内だったので、このエラーは無視して続いてレジスタの番号を送ろうとしたのですが、送信することができません。

マニュアルを読んで確認してみると、STM32L476のI2Cはアドレス指定の際にスレーブからのNAKを検出した時点で自動的にSTOPを送ってI2Cの動作を停止してしまうことが判明。確かにI2Cの機能としては便利な機能なんですが、これではSCCBとの接続には使えません。世の中にはSTM32とOminivionのカメラを接続している例はゴマンとあるので、みんなどうやっているのだろうかと思いSTM32F0やSTM32F4のマニュアルを確認してみると、I2C_CR1やI2C_CR2の構成が全然違います。HALレベルで使っていると、ハードの差異が隠蔽されてしまって気がつきませんが、どうやらこれまでのシリーズのI2CとSTM32L4のI2Cは別物と考えた方が良いようです。

こんなワケで、I2Cを使うのは断念して、GPIOを使ってのソフトI2Cでつなげることにします。
コメント
この記事をはてなブックマークに追加