0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プログラム不要! コマンド操作で Pico ボードと OV7670 カメラを簡単接続

Posted at

pico-jxgLABO は、USB ケーブル一本でマイコンボード RaspberryPi Pico の様々な機能を試すことができる実験プラットフォームです。

pico-jxgLABO に OV7670 カメラモジュール (FIFO メモリ無し) のサポートを追加しました。

ov7670.jpg

OV7670 は Omnivision が開発した VGA 解像度 (640x480) のカメラモジュールです。とてもポピュラーなカメラモジュールで、一個 500 円程度で購入できる手軽さから多くの電子工作プロジェクトで利用されています。でも、汎用的に使えるよう実装されたプログラムはそれほど多くなく、自分のプロジェクトに組み込むにはある程度のプログラミングスキルが必要です。

pico-jxgLABO では、コマンド操作で OV7670 カメラモジュールをセットアップできるようにしました。これにより、プログラムを作成しなくてもカメラの動作確認や実験が簡単に行えます。解像度の変更やパラメータの設定・確認もコマンドで実行できるので、いろいろ試してから応用的なプログラムの作成に進むことができます。

この記事では、このカメラモジュールを使った以下の実験を行います。

実験 1 Pico ボードと USB で接続されたホスト PC (Windows) でカメラアプリを起動して、OV7670 カメラモジュールからの動画ストリーミングを行います。OV7670 カメラモジュールと Pico ボード (+ ホスト PC) だけでできる実験です。

実験 2 TFT LCD ディスプレイモジュール ST7789 を追加し、カメラ画像をこのディスプレイにリアルタイム表示します。

なお、開発や動作確認をするホスト PC は Windows を想定しています。

OV7670 カメラモジュールについて

OV7670 は、FIFO メモリが無いモジュールの場合、クロックで同期を取りながら 8 ビットのパラレルデータバス経由で画像データの取得を行います。また、I2C インターフェースを使用してレジスタを操作し、各種設定を行います。

OV7670 カメラモジュールの信号は以下の通りです。

信号名 説明
3.3V, GND 電源
PWDN パワーダウン制御。GND に接続して動作状態にします
RESET リセット入力。Low でアクティブになります。3.3V に接続して通常動作させます
D0-D7 8 ビットのパラレルデータバス
XCLK 外部クロック入力。通常 24 MHz の方形波を供給します
PCLK ピクセルクロック出力。1 ピクセルごとにパルスを出力します
HREF 水平同期信号。この信号がアクティブの間、ピクセルデータが有効です
VSYNC 垂直同期信号。フレームの開始を示します
SDA I2C データライン
SCL I2C クロックライン

レジスタの設定をしなくても、XCLK にクロックを供給すれば、画像データの出力が開始されます。画像データ取得のフローは以下のようになります。

  1. VSYNC のパルスが一画面の開始を示します。VSYNC が Low の状態から High に変化する点を検出します
  2. HREF が High の間、1 ピクセルごとに PCLK の立ち上がりエッジ (Low から High に変化する点) で D0-D7 のデータを読み取ります。HREF が Low の間はピクセルデータは無効です
  3. 一画面のピクセル数分だけ手順 2 を繰り返します

レジスタの仕様などを記載したデータシートは、開発元のサイトには見当たりません。僕が参照したのは以下の PDF ファイルです1。特に、Implementation Guide は、混沌としたレジスタ群を機能ごとにカテゴリー分けしており、動作を理解するための参考になります。

▶️ Advanced Information Preliminary Datasheet
▶️ OV7670 Implementation Guide (V1.0)

ただし、これらのドキュメントはかなり不完全で、重要な情報が欠落しています。例えば、カラー画像を取得するにはレジスタの設定が必要なのですが、この操作は「レジスタ 0xB00x84 を設定する」というものになります。しかし、レジスタ 0xB0 が何を制御しているのか、0x84 という値が何を意味するのかドキュメントには記載されていないのです。このあたりは、過去の開発者達がおそらくリバースエンジニアリングで解析して作ったであろうプログラムを参考にして、実装を進める必要があります。

pico-jxgLABO の書き込み

Pico ボードへの pico-jxgLABO の書き込みと基本的な使い方はこちら。特別なハードウェアは必要なく、Pico や Pico 2 ボードを USB ケーブルで PC に接続するだけで始められます。ターミナルソフトを使ってコマンドを入力し、Pico ボードを操作します。

この記事で説明する実験を行うには、バージョン 0.6.2 以降の pico-jxgLABO が Pico ボードに書き込まれている必要があります。ターミナルソフトで about-me コマンドを実行すると pico-jxgLABO のバージョンを確認できます。

L:/>about-me
Program Information
 name:              pico-jxgLABO
 version:           0.6.2
     :
     :

OV7670 カメラモジュールの接続

OV7670 カメラモジュールは、I2C インターフェースと複数の GPIO ピンを使用して Pico ボードに接続します。以下の配線例を参考にしてください。

ov7670-wiring.png

接続する GPIO ピンはコマンド操作でカスタマイズができます。その際、以下の点に留意してください。

  • 3.3V と GND を電源に接続します
  • PWDN を GND、RESET を 3.3V に接続します
  • D0 から D7 までの 8 本のデータラインを連続した GPIO ピンに接続します
  • XCLK, PCLK, HREF, VSYNC を任意の GPIO ピンに接続します
  • SDA と SCL は Pico ボードの I2C0 またh I2C1 のいずれかの I2C インターフェースに接続します

信号線にはかなり高い周波数の電流が流れ、最も周波数の高い XCLK 端子で 24 MHz になります。配線をできるだけ短くすることが望ましいのですが、それほど神経質になる必要もないようで、手元の実験では 16 cm 程度のジャンパーワイヤーで接続して問題なく動作しています2

ov7670-wiring-photo.jpg

以下のコマンドを実行して、I2C インターフェースとカメラモジュールをセットアップします。

L:>i2c0 -p 16,17 --baudrate:100000
L:>camera-ov7670 setup {i2c:0 d0:2 xclk:10 pclk:11 href:12 vsync:13}
  • i2c0 コマンドで I2C0 インターフェースを GPIO16 (SDA), GPIO17 (SCL) に設定し、通信速度を 100 kHz に指定しています
  • camera-ov7670 setup コマンドで OV7670 カメラモジュールの各種接続ピンを指定しています。I2C として I2C0 インターフェースを選択しています。D0 は GPIO2 に接続し、D1 から D7 までは連続した GPIO3 から GPIO9 に自動的に割り当てられます。XCLK, PCLK, HREF, VSYNC はそれぞれ GPIO10, GPIO11, GPIO12, GPIO13 に接続しています。

これで、OV7670 カメラモジュールが使用可能になります。camera-ov7670 コマンドで dump サブコマンドを実行して、カメラモジュールのレジスタ設定を確認してみましょう。

L:/>camera-ov7670 dump
00  3C 80 80 00 01 0B 61 40 9D 00 76 73 04 00 01 02
10  7F 01 04 EF 20 02 00 11 61 03 7B 00 7F A2 04 00
20  04 02 01 00 75 63 A5 80 80 07 00 00 80 00 00 61
30  08 30 80 08 11 1A 00 3F 01 00 00 08 68 C0 19 00
40  11 08 00 14 F0 45 61 51 79 00 00 01 00 00 00 80
50  80 00 22 5E 80 00 40 80 1E 00 00 01 00 00 00 F0
60  F0 F0 00 00 04 20 05 80 80 01 80 4A 0A 55 11 9A
70  3A 35 11 F1 11 0F C1 10 00 00 20 1C 28 3C 55 68
80  76 80 88 8F 96 A3 AF C4 D7 E8 00 00 00 0F 00 00
90  00 00 00 00 04 08 01 01 10 40 40 20 00 99 7F 78
A0  68 03 02 00 00 05 DF DF F0 90 94 07 00 00 00 00
B0  84 04 00 82 00 20 00 66 00 06 00 00 00 00 00 00
C0  00 00 00 00 00 00 00 00 06 CE

実験 1: ホスト PC への動画ストリーミング

Pico ボードと USB 接続されたホスト PC (Windows) 上でカメラアプリを起動して、OV7670 カメラモジュールからの動画ストリーミングを表示してみましょう。

  1. ホスト PC と Pico ボードを USB ケーブルで接続します。

  2. Pico ボードの L: ドライブのルートディレクトリに .startup ファイルを作成し、以下の内容を記述して保存します。L: ドライブは、ホスト PC からは USB マスストレージデバイスとして認識されるので、ホスト PC 上のテキストエディタで作成できます。

    .startup
    usbdev-video-transmitter setup
    i2c0 -p 16,17 --baudrate:100000
    camera-ov7670 setup {i2c:0 d0:2 xclk:10 pclk:11 href:12 vsync:13}
    

    usbdev-video-transmitter setup コマンドは、Pico ボードを USB ビデオデバイスとして動作させるためのセットアップを行います。残りのコマンドは OV7670 カメラモジュールのセットアップを行います。

    USB ケーブルを抜き差しして、Pico ボードを再起動します。これにより、Pico ボードが USB ビデオデバイスとして認識されます。

  3. ホスト PC で、タスクバーの検索ボックスに「カメラ」と入力してカメラアプリを起動します。正常に認識されていると、起動時に以下のように "pico-jxgLABO VideoTransmitter" と表示されます。

    windows-camera-app.png

    PC に複数のカメラデバイスが接続されている場合は、下図のようにカメラアプリの右上にカメラ選択ボタンが表示されるので、"pico-jxgLABO VideoTransmitter" が表示される画面に切り替えます。

    windows-camera-app-select.png

  4. ターミナルで以下のコマンドを実行して、OV7670 カメラモジュールからホスト PC に動画ストリーミングを開始します。

    L:>camera video-transmit-start
    

    カメラアプリの画面に OV7670 カメラモジュールからの映像が表示されれば成功です。

    windows-camera-app-ov7670.png

camera fps コマンドを実行すると、現在のフレームレートを確認できます。

L:>camera fps
6 fps

画面サイズは QQVGA (160x120) に設定されているのですが、USB の転送速度がボトルネックになっているようで 6 fps とかなり遅いです。

実験 2: TFT ディスプレイへのリアルタイム表示

ST7789 TFT ディスプレイモジュールにカメラからのイメージをリアルタイム表示します。

  1. 以下の配線例を参考にして、OV7670 カメラモジュールと ST7789 TFT ディスプレイモジュールを Pico ボードに接続します。

    ov7670-st7789-wiring.png

    ov7670-st7789-wiring-photo.jpg

  2. 以下のコマンドを実行して、OV7670 カメラモジュールと ST7789 TFT ディスプレイモジュールをセットアップします。

    L:>i2c0 -p 16,17 --baudrate:100000
    L:>camera-ov7670 setup {i2c:0 d0:2 xclk:10 pclk:11 href:12 vsync:13}
    L:>spi1 -p 14,15 --baudrate:50000000
    L:>display-st7789 setup {spi:1 rst:18 dc:19 cs:20 bl:21 dir:rotate90}
    
  3. TFT ディスプレイの動作確認を行います。以下のコマンドを実行して、ディスプレイモジュールの画面全体が赤色になれば OK です。

    L:>draw fill {color:red}
    
  4. camera コマンドの display-start サブコマンドを実行すると、OV7670 カメラの映像を TFT ディスプレイにリアルタイム表示します。

    L:>camera display-start
    

camera fps コマンドを実行すると、現在のフレームレートを確認できます。

L:>camera fps
27 fps

OV7670 のスペック上の最大フレームレートが 30 fps ですから、ほぼフルスピードで動作していることになります。

出力先を TFT ディスプレイモジュールにした場合、解像度の変更も可能です。camera-ov7670 コマンドの resolution サブコマンドを使って、以下の解像度に変更できます。

解像度名 ピクセル数 使用する RAM サイズ
qvga 320 x 240 153.6 kB
qqvga 160 x 120 38.4 kB
qqqvga 80 x 60 9.6 kB

例えば、解像度を QQVGA (160x120) に変更するには、以下のコマンドを実行します。

L:>camera-ov7670 resolution:qqvga

OV7670 カメラモジュールの最大解像度は VGA (640x480) なのですが、画像データが 614.4 kB となり Pico ボードの RAM サイズ (Pico: 264 kB, Pico2: 520 kB) を超えてしまうため指定できません。

.startup ファイルによる初期化処理の自動化

OV7670 カメラモジュールのセットアップコマンドは少し長いので、.startup ファイルに記述しておくとボードを起動したときに自動的に実行されて便利です。

以下は USB ビデオデバイスと OV7670 カメラモジュール、ST7789 TFT ディスプレイモジュールのセットアップを行う .startup ファイルの例です。

.startup
usbdev-video-transmitter setup

i2c0 -p 16,17 --baudrate:100000
camera-ov7670 setup {i2c:0 d0:2 xclk:10 pclk:11 href:12 vsync:13}

spi1 -p 14,15 --baudrate:50000000
display-st7789 setup {spi:1 rst:18 dc:19 cs:20 bl:21 dir:rotate90}

各種パラメータの設定

camera-ov7670 コマンドでは、サブコマンドを使って各種パラメータを設定できます。--help オプションを指定すると、利用可能なサブコマンドの一覧が表示されます。

L:/>camera-ov7670 --help
Usage: camera-ov7670 [OPTION]... [SUBCMD...]
Options:
 -h --help prints this help
Sub Commands:
 setup                              setup a OV7670 camera module with the given parameters:
                                     {i2c:BUS d0:PIN xclk:PIN pclk:PIN href:PIN vsync:PIN [pwdn:PIN] [reset:PIN] [freq:FREQ]}
 reso:RESO                          gets/sets resolution: vga, qvga, qqvga, qqqvga
 format:FORMAT                      gets/sets format: rgb565, yuv422
 dump                               dumps all OV7670 registers
 ccir656:[on|off]                   enables/disables CCIR656 mode
 scale:[on|off]                     enables/disables scaling
 dcw:[on|off]                       enables/disables DCW
 color-bar:[on|off]                 enables/disables color bar
 agc:[on|off]                       enables/disables AGC
 awb:[on|off]                       enables/disables AWB
 aec:[on|off]                       enables/disables AEC
 mirror:[on|off]                    enables/disables mirror
 vflip:[on|off]                     enables/disables vertical flip
   :
   :

以下に、主なサブコマンドの使い方を示します。

  • mirror: ミラー表示 (左右反転) の有効/無効を設定します

    L:>camera-ov7670 mirror:on
    
  • vflip: 上下反転の有効/無効を設定します

    L:>camera-ov7670 vflip:on
    
  • brightness: 明るさ調整の値を設定します (-127 から +127、デフォルトは 0)

    L:>camera-ov7670 brightness:-4
    
  • contrast: コントラスト調整の値を設定します (0 から 255、デフォルトは 64)

    L:>camera-ov7670 contrast:15
    
  • sharpness: シャープネス調整の値を設定します (0 から 31、デフォルトは 0)

    L:>camera-ov7670 sharpness:7
    
  • awb, awb-red, awb-blue, awb-green: 自動ホワイトバランス (AWB) の有効/無効と各色のゲインを設定します (0 から 255、デフォルトは 128)。awbon に設定されていると各ゲインは自動的に調整されますが、これを off に設定すると awb-red, awb-blue, awb-green で指定した値が使用されます。

    L:>camera-ov7670 awb:off
    L:>camera-ov7670 awb-reds:120 awb-blue:140 awb-green:180
    

まとめ

OV7670 カメラモジュールを pico-jxgLABO で簡単にセットアップし、画像キャプチャ、動画ストリーミング、TFT ディスプレイへのリアルタイム表示を行う方法を紹介しました。これにより、Raspberry Pi Pico を使ったカメラアプリケーションの開発が手軽に始められます。ぜひ試してみてください!

追記

この記事は Zenn と Qiita にクロスポストしています。

  1. 変な電波をまき散らしているかもしれないので、注意は必要です

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?