view
カメラ映像の表示
1280×720 の映像を5インチ画面へ。c 生 / s バイト入替 / b 2値画像 / g 明暗伸長 の4モードを切り替えられます。
sample program / for arduino ide
映像を表示し、QRコードを読み、暗い場所では画面そのものをライト代わりにする。 Tab5 のカメラは素の Arduino では素直に動いてくれないので、実機で確かめた設定を 1本のスケッチにまとめました。つまずきどころも全部書いてあります。
緑枠 解析範囲(720×720) 赤枠 QR候補 Z3 使用ズーム
ページを開くと、実機と同じ起動カラーバー(白→赤→緑→青)が流れます。
spec / できること
本体に組み込む前の切り分けを目的にしています。カメラだけを取り出して「どこまで動くか」を確かめられます。
view
1280×720 の映像を5インチ画面へ。c 生 / s バイト入替 / b 2値画像 / g 明暗伸長 の4モードを切り替えられます。
decode
quirc で解析し、読めた内容をシリアルへ QR,内容 で出力。中央を切り出して拡大するズームで、遠いQRにも当たります。
light
l キーで画面が真っ白に。5インチ・バックライト最大点灯の光を照明として使います。QRが読めたら自動で解除して結果を見せます。
b)、QR候補の赤枠、2値画像の黒の割合(blk)を画面に出します。
「なぜ読めないのか」が目で分かるので、切り分けが速くなります。
trace / 初期化の順序
コードもこの順で読めるように並べてあります。順序を入れ替えると動きません。とくに【1】と【4】は外せません。
M5.begin() より先に設定します。ESP32-P4 の LEDC は全タイマがクロック源を共有するため、後から設定すると M5GFX のバックライト用と衝突して24MHzが出せません。
backlightFix() で GPIO22 を素の出力として HIGH に固定します。M5GFX の調光が失敗して黒画面になるのを防ぎます。
E1.P6 = CAM_RST を解放します。これをやらないとカメラは SCCB に応答しません(0x36 が出てきません)。
csi.begin(cam_config, true) の true が必須です。MIPI PHY 用 LDO は画面と共用で、M5GFX が取得済みだからです。
captureBuffer() で RGB565 1280×720 を取得します。バッファは2枚で交互に返ってきます。
quirc_decode() は内部で約9KBのローカル配列を使うため、8KBの loopTask から呼ぶとスタック保護違反でリセットします。
g_lbuf)へコピーしてから pushImage()。PSRAMから直接DMAすると黒画面になることがあります。
build / コンパイル・実行に必要な注意点
実機で1つずつ確かめた項目です。症状と原因が対応するように書きました。
| 注意点 | 外すとどうなるか | 対処 |
|---|---|---|
XCLK を M5.begin() より先に設定 |
LEDC のタイマ衝突で24MHzが出ず、カメラが応答しない | xclkSetup() を setup の最初に置く。ログが 24MHz AUTO t3 : 24000000 Hz なら成功 |
csi.begin(cam_config, true)=dont_init_ldo |
LDO の取り合いで初期化失敗(画面が先に取得している) | 第2引数を必ず true にする |
IOエキスパンダの 0x01 に 0xFF を書かない |
LCD_RST / TP_RST まで戻り、画面が真っ黒になる | camPowerOn() の値(0x0D/0x0B/0x05/0x07/0x03)を変えない |
| GPIO22(バックライト)を直High に | M5GFX のLEDC調光が失敗し、画面が真っ黒のまま | backlightFix() を呼ぶ。setBrightness() だけでは直りません |
| QR解析は専用タスク(64KB)で行う | decode.c が約9KBのスタックを使い、loopTask(8KB)では保護違反でリセット |
xTaskCreatePinnedToCore(qrTask, "qrTask", 64*1024, ...) |
| 解析はバイト入替なしの輝度で行う | 画像が壊れ、どんなQRデコーダでも読めなくなる | 入替えるのは「画面表示用」だけ。解析と表示は別系統と覚える |
| 表示は16ラインずつ内蔵RAMを経由する | PSRAMから直接DMAしようとすると黒画面になることがある | g_lbuf[1280*16] にコピーしてから pushImage() |
このサンプルでは M5.update()・タッチを使わない |
内蔵I2C(G31/G32)とカメラSCCBが同じピンで clear bus failed が多発 |
モード切替はシリアル入力で行う |
s キー)。「解析用」と「表示用」は別物です。
setup / ライブラリとファイルの置き方
Arduino-ESP32 コア 3.3.11 以降には ESP_Video が同梱されていますが、環境によってはコア内の libraries\ESP_Video が見当たりません。その場合は配布しているZIPを次の形に展開してください。
# Windows の例 C:\Users\<ユーザー名>\Documents\Arduino\libraries\ESP_Video\src\ESP_Video.h ↑ この形になるように # NG: 1階層深くなっている ...\libraries\ESP_Video\ESP_Video\src\ESP_Video.h
展開後は Arduino IDE を再起動してください。スケッチ冒頭のマクロ定義(CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE など)は消さないでください。
スケッチの置き方 — フォルダ名と .ino 名は必ず一致させます。
Arduino/
└─ Tab5_CameraQR_Sample/
├─ Tab5_CameraQR_Sample_20261015.ino ← これを開く
├─ README.md
├─ quirc.h
├─ quirc.c
├─ quirc_internal.h
├─ decode.c
├─ identify.c
└─ version_db.c
Write timeout で失敗するときは、クラッシュ再起動ループでUSBが掴めなくなっています。
シリアルモニタを閉じる → リセットを約2秒長押し(内部の緑LEDが高速点滅=ダウンロードモード)→ 書き込み → もう一度リセット、の順で復帰します。USBケーブルはデータ通信対応のものをお使いください。
zoom / 小さく遠いQRのために
遠いQRは、画像の中で1モジュールが2〜3px しかありません。quirc はモジュールが小さいと見失います。
そこで中心の 720/Z px を切り出して 720 に拡大し、モジュールを Z 倍にします。
どれが効くかは、実機の生画像でシミュレーションして決めました。
| QRサイズ | モジュール | 従来 Z=1 | Z=2 | Z=3 | Z=4 |
|---|---|---|---|---|---|
| 200px | 5.1px | zx zb – | zx zb cv | zx zb cv | – zb – |
| 150px | 3.8px | – zb – | – zb – | zx zb cv | zx zb cv |
| 120px | 3.1px | – zb – | – zb – | – zb cv | zx zb cv |
| 100px | 2.6px | – zb – | – zb – | – zb – | – – cv |
keys / 操作
Arduino IDE のシリアルモニタを 115200bps で開き、1文字送るだけで切り替わります。
| キー | 動作 | 使いどころ |
|---|---|---|
c | COLOR(生) | そのままの映像 |
s | COLOR バイト入替 | 色化け(赤青反転)が直る。既定はこれ |
b | BINARY(quircが見ている画像) | 読めないときはまずこれ。QRの形が見えるか確認 |
g | GRAY(明暗を伸ばす) | 暗い・コントラストが弱いとき |
k | 先鋭化 ON/OFF | ぼやけているとき(既定OFF) |
z | ズーム:自動(Z=1..4巡回)⇔ 固定 Z=1..4 | 遠いQRは Z=3 / Z=4 に固定すると反応が速い |
a | 8秒ごとの表示自動切替 | 比較用 |
l | ライトモード ON/OFF | 暗い場所で画面を白くして照明にする |
h | ヘルプ | — |
画面の下のバーに、状態が1行で出ます。
COLOR byte-swap | Z3 | q720 | cand 1 | blk 47%
表示モード ズーム 入力サイズ QR候補数 2値画像の黒の割合
blk(黒の割合)は明るさの当たり外れが一目で分かります。5%未満=明るすぎ/白飛び、70%超=暗すぎ が目安です。
files / ダウンロード
まずはZIPを落として展開するのが早いです(中のフォルダ名と ino 名が一致しているので、そのまま Arduino で開けます)。中身は個別にも置いてあります。md5 を併記しているので、転送の確認に使えます。本体に組み込んだ版は body/ にあります。
quirc 同梱分(ZIPにも入っています。個別に欲しいとき用)
QUIRC_MAX_REGIONS 254 など)
download
# quirc.c に手を入れた1行(malloc を PSRAM に割り当てる)
#include <esp_heap_caps.h>
#define malloc(sz) heap_caps_malloc((sz), MALLOC_CAP_SPIRAM)
notes / 正直な記載
内蔵カメラの映像表示、QR読み取り、IOエクスパンダ経由の給電、ESP_Video の初期化手順は、 実機(Tab5)で動作を確認済みです。本サンプルは、その確認できた処理を1本に整理したもので、 整理後の全機能の通し確認はこれからです。差異があればお知らせください。
既知の制限
setSensorExposureTime() 等は未使用)。Tab5_CameraQR_Sample_20261015.ino / .zip へ改名。zip はフォルダ入り形式にして、展開してそのままビルドが通ることを実測で確認しました。