pico-jxgLABO は、USB ケーブル一本でマイコンボード RaspberryPi Pico の様々な機能を試すことができる実験プラットフォームです。
pico-jxgLABO に OV7670 カメラモジュール (FIFO メモリ無し) のサポートを追加しました。
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 にクロックを供給すれば、画像データの出力が開始されます。画像データ取得のフローは以下のようになります。
- VSYNC のパルスが一画面の開始を示します。VSYNC が Low の状態から High に変化する点を検出します
- HREF が High の間、1 ピクセルごとに PCLK の立ち上がりエッジ (Low から High に変化する点) で D0-D7 のデータを読み取ります。HREF が Low の間はピクセルデータは無効です
- 一画面のピクセル数分だけ手順 2 を繰り返します
レジスタの仕様などを記載したデータシートは、開発元のサイトには見当たりません。僕が参照したのは以下の PDF ファイルです1。特に、Implementation Guide は、混沌としたレジスタ群を機能ごとにカテゴリー分けしており、動作を理解するための参考になります。
▶️ Advanced Information Preliminary Datasheet
▶️ OV7670 Implementation Guide (V1.0)
ただし、これらのドキュメントはかなり不完全で、重要な情報が欠落しています。例えば、カラー画像を取得するにはレジスタの設定が必要なのですが、この操作は「レジスタ 0xB0 に 0x84 を設定する」というものになります。しかし、レジスタ 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 ボードに接続します。以下の配線例を参考にしてください。
接続する 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。
以下のコマンドを実行して、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 カメラモジュールからの動画ストリーミングを表示してみましょう。
-
ホスト PC と Pico ボードを USB ケーブルで接続します。
-
Pico ボードの
L:ドライブのルートディレクトリに.startupファイルを作成し、以下の内容を記述して保存します。L:ドライブは、ホスト PC からは USB マスストレージデバイスとして認識されるので、ホスト PC 上のテキストエディタで作成できます。.startupusbdev-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 ビデオデバイスとして認識されます。
-
ホスト PC で、タスクバーの検索ボックスに「カメラ」と入力してカメラアプリを起動します。正常に認識されていると、起動時に以下のように "pico-jxgLABO VideoTransmitter" と表示されます。
PC に複数のカメラデバイスが接続されている場合は、下図のようにカメラアプリの右上にカメラ選択ボタンが表示されるので、"pico-jxgLABO VideoTransmitter" が表示される画面に切り替えます。
-
ターミナルで以下のコマンドを実行して、OV7670 カメラモジュールからホスト PC に動画ストリーミングを開始します。
L:>camera video-transmit-startカメラアプリの画面に OV7670 カメラモジュールからの映像が表示されれば成功です。
camera fps コマンドを実行すると、現在のフレームレートを確認できます。
L:>camera fps
6 fps
画面サイズは QQVGA (160x120) に設定されているのですが、USB の転送速度がボトルネックになっているようで 6 fps とかなり遅いです。
実験 2: TFT ディスプレイへのリアルタイム表示
ST7789 TFT ディスプレイモジュールにカメラからのイメージをリアルタイム表示します。
-
以下の配線例を参考にして、OV7670 カメラモジュールと ST7789 TFT ディスプレイモジュールを Pico ボードに接続します。
-
以下のコマンドを実行して、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} -
TFT ディスプレイの動作確認を行います。以下のコマンドを実行して、ディスプレイモジュールの画面全体が赤色になれば OK です。
L:>draw fill {color:red} -
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 ファイルの例です。
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)。awbがonに設定されていると各ゲインは自動的に調整されますが、これを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 にクロスポストしています。







