ホームページmini2440>その6・CMOSカメラモジュールを使う

その6・CMOSカメラモジュールを使う

目次
 はじめに

 mini2440用のCMOSカメラモジュール(モジュール名:C-130、チップ名:OV9650)の利用について、試行しました。

 なお、今回は主にUbuntu 14.04マシンを使用しました。(MacはQtアプリ作成のみ:Mac mini mid 2010、OSX 10.11.3、Qt 4.8.6、Qt Creator 3.2.1)
 また、各バージョンは試行時のもので、最新版とは異なる場合があります。


 経緯

 オリジナルのQtopiaではカメラモジュールが使えていたことと、現用カーネルの起動オプションにカメラがあったことから、当初は簡単に考えていました。

 ですが、カメラオプションを指定しただけでは使えない、というより、現用カーネルがカメラに対応していないことが判明して、結局、オリジナルカーネルとのハイブリッド版にした上に、サードパーティ製のカメラドライバを導入することで、ようやく使えるようになりました。

 なお、今回はカーネルに特化した話であり、ファイルシステムは全ケースとも、前回作成したDebian 7.0 wheezyを使っています。
注) 現用カーネル:参考サイト(1)からダンロードさせて頂いたもの。
オリジナルカーネル:本体同梱のDVD収録のもの。または参考サイト(2)で公開されているもの。

 現用カーネルとオリジナルカーネルを使う(失敗)

 まずは順序として、現用カーネルの利用を試みました。
 オリジナルカーネルでは、カメラモジュールはデバイスドライバとして/dev/cameraを使用するのですが、現用カーネルで確認してみるとこれがありません。
 カーネルのソースを調べると、カメラモジュール関連のソース一式がありませんでした。

 あれ、と思って、オリジナルカーネルを見てみると、ソース一式がありました。
 この時、初めて現用カーネル(のソース)がオリジナルカーネル(のソース)と異なることに気付きました。(道理で、ググった時に見慣れないコードが引用されていた訳だ。)
 現用カーネルの起動コマンドには、カメラを有効にするオプションがあるのに何故?と思って当該ソースを見ると、TODOと書いてありました。
 どうも現用カーネルは、カメラを使うことができなそうな雰囲気です。

 ということで、続いてはオリジナルカーネルを試してみることにしました。
 オリジナルカーネルはW35にも対応しているので「cp config_mini2440_w35 .config」してから、menuconfigを起動後、Device Drivers>Multimedia supportと辿ると、現用カーネルにはなかった「OV9650 on the s3c2440 driver」オプションが表示されるようになったので、yesに設定しました。
 あと、オリジナルカーネルのファイルシステムはYAFFS2になっていますので、これをext3に変更しました。(この辺は、現用と両方のメニューを表示して合わせ込むのが簡便です。)

 ビルド後に動かしてみると、カーネル自体には問題がありましたが、/dev/cameraがあることが確認できました。
カーネル自体の問題(というよりファイルシステムとの齟齬?)は、(1)tty端末がログイン可能状態にならない、(2)ネットワーク接続できない、というもので、本体に接続したUSBキーボードからは操作可能。
 早速、カメラテスト用に作成したQtアプリを起動すると、以下のメッセージが表示されました。
root@mini2440:/root# Camera1: page allocation failure. order:10, mode:0xd1
(以下、ダンプメッセージ)
 単純に解釈すると「メモリが足りない」となりますが、カメラが必要とするメモリ量は300KB程度の筈なので、額面通りに受け取ってよいものか、よく分からない状況となりました。


 ハイブリッドカーネルと代替ドライバを使う(成功)

 カメラドライバについてこれ以上調べるのに、本体ディスプレイとキーボードしか使えないのはあまりに不便なので、まずはここから手をつけることにしました。

 この件(と、あわよくばカメラドライバの両方)を解決する(可能性のある)最も手っ取り早い方法は、現用カーネルとオリジナルカーネルのハイブリッド版を作ってみることです。
 即ち、現用カーネルのkernel/mini2440/drivers/media/以下を、オリジナルカーネルのmediaで置き換える、というものです。
(mediaを選択した理由は、ここのKconfigがカメラモジュール関連のオプション情報を持っているため。)

 この状態でmenuconfigを起動すると、「OV9650 on the s3c2440 driver」オプションが「M」になっていました。
 Mはモジュールの事で、ドライバがカーネル内部にビルトインされて常時起動するのではなく、外部に置かれて必要な時に読み込まれる、ということのようです。
(今回の件では、Mしか選択できなかったのですが、必要に応じてというより、依存関係が解決されて、可能であれば読み込まれる、ということのようです。後述)
 モジュール化されることは特に問題ない(というか、これも後述しますが、実はそうでないと困る)ので、そのままビルドしました。
この時、もう一点気をつけることがあって、それはmenuconfigのDevice Drivers>Multimedia supportにある「Video For Linux」が「M」になっていること。(多分、最初からMになっている筈。これも後述)
 実機に持って行って起動したところ、tty端末/ネットワーク接続とも、問題なく使えることを確認しました。
 肝心のドライバはというと、/dev/cameraが見当たりません。どうもデフォルトではモジュールが起動しないようです。
 そこで、ドライバのディレクトリに入って、「insmod s3c2440camera.ko」としてやると、起動はしました。(/dev/cameraも出来ました。)

 もしかして、と思って上述のカメラアプリを起動してみたのですが、やはりというか、同じメッセージが表示されて動きませんでした。
 オリジナルカーネルはもともと、YAFFS2と組み合わせて本体内のNAND Flashに載せて使うものなので、メモリの使い方が異なる可能性もあります。
 何れにしても、これ以上はメモリマップの確認等、ドライバ内部の検証に入らざるをえず、自分にとってはなかなかハードルが高いです。

 という訳で、ここは先人達を頼らさせて頂こうとググってみたところ、以下がヒットしました。

 参考サイト(3):s3c2440camera - Linux driver for S3C2440 camera interface - Google Project Hosting

 これは、代替ドライバモジュールで、純正ドライバモジュールと差し替えて使うものです。
 これですと、ソースを変更したい時も、モジュールをリビルドするだけで、カーネル本体はノータッチで済む訳です。
(幸いというか、ハイブリッドカーネルは既にカメラドライバがモジュール化されているので、そのまま使える。)

 このドライバは、純正がキャラクタドライバである(日昇テクノロジー2011/08/25版マニュアル、P89)のに対し、V4L2準拠のようで、異なる結果が期待できます。
 早速、これを使わせて頂いてテストしてみました。
 上記サイトでは使い方も説明されていますが、端折られている部分もあるので、改めて手順を纏めておくことにしました。
  1. カーネルは上述のハイブリッド版(のコピー)を使用。(カメラドライバとVideo For Linuxをモジュールで組み込む設定済のもの)
  2. 参考サイト(3)からs3c2440camera-r5.tar.gzをダウンロードして解凍。(解凍先ディレクトリ名:s3c2440camera-r5)
  3. s3c2440camera-r5ディレクトリをカーネルのkernelディレクトリ内に置く。(mini2440ディレクトリと同じ階層)
  4. mini2440ディレクトリ内で、カーネルをmakeする。(念のため実行しておいた。なお、コンフィグは既に実行済なので、mini2440_defconfigは行わない。)
    CROSS_COMPILE=arm-linux- ARCH=arm make prepare O=../kernel-bin/
    CROSS_COMPILE=arm-linux- ARCH=arm make O=../kernel-bin/
    
  5. s3c2440camera-r5ディレクトリに移動し、makeする。(ポイントはKERNELDIRをソースディレクトリではなく、O=で指定したバイナリの方にする点)
    KERNELDIR=../kernel-bin CROSS_COMPILE=arm-linux- make
    
  6. テストアプリが同梱されているので、同様にmakeする。(自分の環境では素直にmakeすると、ホスト用の実行ファイルが作られてしまうので、CCを変更した。)
    KERNELDIR=../kernel-bin CC=arm-linux-cc make test_capture
    
  7. 出来上がったs3c2440camera.koとtest_captureを実機にコピー。(場所はどこでも。ここでは/root)
  8. 起動の順番は以下の通り。(s3c2440camera.koはvideodev.koに依存し、videodev.kはv4l1-compat.koに依存しているので、順に起動する。)
    insmod /lib/modules/2.6.32-rc8/kernel/drivers/media/video/v4l1-compat.ko
    insmod /lib/modules/2.6.32-rc8/kernel/drivers/media/video/videodev.ko
    insmod s3c2440camera.ko
    
  9. /devにvideo0ができていることを確認。(このドライバではcameraではなく、video0が作られる。)
 同梱のテストアプリを起動したところ、正常終了して、輝度のファイルと色相彩度のファイルが作成されました。
 このうち、輝度のファイルはホスト上の画像ビュアーで表示できました。(輝度だけなのでモノクロ)

 以上、例によってのドタバタでしたが、ひとまず動作する環境は整えられました。


 Qtでカメラアプリ(簡易版)を作ってみる

 カメラにアクセスできるようになったので、簡単なQtアプリを作ってみることにしました。

 デバイスドライバからのデータの取得は今までやったことがなかったので、どうやるかが不明だったのですが、調べてみると、基本的にファイルから読むのと同じ、ということ(前項のテストアプリもそんな感じ)でしたので、まずこの点はクリアできました。
 次は取得データのフォーマットですが、以下のデータシートに記載されていました。

 参考サイト(4):[PDF] OV9650 Color CMOS SXGA(PDFファイルへのリンク)

 これによると、「YUV/YCbCr / GRB / RGB565 / RGB555 / Raw RGB」とのこと。
 扱いやすいのはRaw RGBと思われますが、それにはレジスタの操作が必要で、不確定要素が増えてしまうため、これは次に回すとして、まずは(前項のテストアプリ同様)デフォルトのYUV/YCbCrでいくことにしました。
 なお、YUV/YCbCr(YUV422p)のバイトストリームは、以下に示されています。

 参考サイト(5):V4L2_PIX_FMT_YUV422P ('422P')

 モノクロでよければ、前半の輝度部分のみをそのまま書き出せばよい(前項のテストアプリがそうしている)のですが、カラーの場合はYUV/YCbCrをRGBに変換する必要があります(注1)。この辺は、画像処理の一般的なマターなので情報は充実していて、例えば以下が参考になります(注2)。

 参考サイト(6):YUV - Wikipedia
注1:今回使用するQImageクラスはYUVに対応していない。(QVideoFrameクラスは対応しているようだが。)
注2:細かく見ていくと、いくつかバリエーションがあるようだが、あくまでテストなのでここでは深入りせず、アプリとしてまとめることを優先する。
 あとは、QtのAPIを使ってPNGやJPEGに書き出す処理を追加してやれば、簡単なキャプチャアプリが出来上がりそうです。
 取り敢えず、以下の仕様で作ってみました。
 起動と同時にキャプチャするだけのアプリですが、動作はしました。

注)50%縮小後にJPEGに変換している。


 おわりに

 OV9650には様々なオプションがあるようで、それらをいじってみるのも面白そうです。
 それと、これはカメラ自身のことではありませんが、
  1. ACアダプタだと室内しか撮れないので、外に持ち出すためのバッテリシステム
  2. カメラの向きを逆にするための延長ケーブル(本体に直付けだと、カメラがディスプレイと同じ方を向いてしまって使い勝手が悪い。)
があると便利なのですが、さて、どうするか。
(モバイルバッテリとUSB-DCplugケーブル、2mmピッチのピン/ソケットは手に入るようなので自作すれば、なんとかなりそうではありますが…)


 お世話になったサイト

 有用なソフトウェアおよび貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)

 参考サイト(1):mini2440にDebian環境をインストール
 参考サイト(2):Index of /download/ARM9-2440-DVD/Linux
 参考サイト(3):s3c2440camera - Linux driver for S3C2440 camera interface - Google Project Hosting
 参考サイト(4):[PDF] OV9650 Color CMOS SXGA(PDFファイルへのリンク)
 参考サイト(5):V4L2_PIX_FMT_YUV422P ('422P')
 参考サイト(6):YUV - Wikipedia
 参考サイト(7):qt - How can I decrease the amount of time it takes to save a png using QImage? - Stack Overflow


 更新履歴

 2016.02.10 章番号を変更。
 2016.01.30 新規作成


[Home]  [MacSoft]  [Donation]  [History]