view
カメラ映像の表示
1280×720 の映像を5インチ画面いっぱいへ。c 生 / s バイト入替 / g 明暗伸長 の3モード。既定は色化けの直る s です。
sample program / for arduino ide
素の Arduino では素直に動いてくれない M5Stack Tab5 のカメラを、 映像が出るところまで確実に立ち上げるための1本です。 初期化の順序、黒画面の直し方、色化けの直し方、暗い場所で画面をライトにする使い方まで。 実機で確かめた設定と、つまずいた理由をそのまま書いてあります。
fps 実測 ms 1フレームの表示時間 LIGHT L 左半分が照明(白)exp 露出時間
ページを開くと、実機と同じ起動カラーバー(白→赤→緑→青→CAM INIT OK)が流れます。
spec / できること
本体に組み込む前の切り分けを目的にしています。カメラだけを取り出して「どこまで動くか」を確かめられる形にしました。
view
1280×720 の映像を5インチ画面いっぱいへ。c 生 / s バイト入替 / g 明暗伸長 の3モード。既定は色化けの直る s です。
light
l キーで画面が真っ白に。5インチ・バックライト最大点灯の光を照明として使います。ライト中もカメラは止まりません。
half light
起動直後から、左半分が白(照明)/右半分がカメラ映像。暗い場所で白い面を照明や証明写真の背景にしながら、被写体を確認できます。t で全面映像、r で左右反転。
exposure
e/E で露出時間、-/+ でゲイン。自動露出がハンチングして明るさが脈打つときの、追い込みの足がかりです。
trace / 初期化の順序
コードもこの順で読めるように並べてあります。順序を入れ替えると動きません。とくに【1】と【4】は外せません。
M5.begin() より先に設定します。ESP32-P4 の LEDC は全タイマがクロック源を共有するため、後から設定すると M5GFX のバックライト用と衝突して24MHzが出せません。
backlightFix() で GPIO22 を素の出力として HIGH に固定します。M5GFX の調光が失敗して黒画面になるのを防ぎます。
E1.P6 = CAM_RST を解放します。これをやらないとカメラは SCCB に応答しません(0x36 が出てきません)。0x01 に 0xFF は禁止。
csi.begin(cam_config, true) の true が必須です。MIPI PHY 用 LDO は画面と共用で、M5GFX が取得済みだからです。
cap.begin(name, 3) → setFormat(RGB565) → startCapture()。バッファは3枚。表示中に1枚取られても余裕を持たせます。
captureBuffer() で RGB565 1280×720 を借用します。変数が消えると自動でドライバに返る(RAII)ので、長く握ると次のフレームが来ません。
g_lbuf)へコピーしてから pushImage()。PSRAMから直接DMAすると黒画面になることがあります。
setSensorExposureTime() / setSensorGain() で手動調整(実験的)。
build / コンパイル・実行に必要な注意点
実機で1つずつ確かめた項目です。症状と原因が対応するように書きました。
| 注意点 | 外すとどうなるか | 対処 |
|---|---|---|
XCLK を M5.begin() より先に設定 |
LEDC のタイマ衝突で24MHzが出ず、カメラが応答しない | xclkSetup() を setup の最初に置く。ログが 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() だけでは直りません |
| 表示は16ラインずつ内蔵RAMを経由する | PSRAMから直接DMAしようとすると黒画面になることがある | g_lbuf[1280*16] にコピーしてから pushImage() |
| フレームバッファを長く握らない | 次のフレームが来ず、fps が落ちる/止まる | 重い処理の前に、必要な分だけコピーして手放す |
表示はバイト入替をする(s) |
赤と青が入れ替わって見える(色化け) | 表示は入替、解析は入替なしが原則。用途で別系統と覚える |
このサンプルでは M5.update()・タッチを使わない |
内蔵I2C(G31/G32)とカメラSCCBが同じピンで clear bus failed が多発。fps も 6→1.7 に低下(実測) |
モード切替はシリアル入力で行う。タッチが要るなら 250ms 間隔に間引く |
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_Camera_Basic_20261106/
├─ Tab5_Camera_Basic_20261106.ino ← これを開く
└─ README.md
ino と M5Unified だけでビルドできます。コマンドラインなら次の1行。
arduino-cli compile -b esp32:esp32:m5stack_tab5 Tab5_Camera_Basic_20261106
Write timeout で失敗するときは、クラッシュ再起動ループでUSBが掴めなくなっています。
シリアルモニタを閉じる → リセットを約2秒長押し(内部の緑LEDが高速点滅=ダウンロードモード)→ 書き込み → もう一度リセット、の順で復帰します。USBケーブルはデータ通信対応のものをお使いください。
keys / 操作
Arduino IDE のシリアルモニタを 115200bps で開き、1文字送るだけで切り替わります。
| キー | 動作 | 使いどころ |
|---|---|---|
c | COLOR(生) | そのままの映像 |
s | COLOR バイト入替 | 色化け(赤青反転)が直る。既定はこれ |
g | GRAY(明暗を伸ばす) | 暗い・コントラストが弱いとき |
t | 半分照明 ON/OFF | 既定はON(左半分が白/右半分が映像)。OFFで全面映像 |
l | 全面ライト ON/OFF | 画面全体を白くして照明にする(従来のライト) |
r | 白い側を左右反転 | カメラの位置に合わせて、照らしたい側へ(1=左/0=右) |
e / E | 露出時間を 1段下げる / 上げる | 自動露出がハンチングするとき |
- / + | ゲインを 1段下げる / 上げる | 暗いとき(ノイズと引き換え) |
0 | 露出・ゲインを初期値へ | 元に戻す |
h | ヘルプ | — |
画面のバーに、いまの状態が1行で出ます。半分照明のときは映像側の下端、全面表示のときは画面の下端です。
半分照明: SWAP | 26.1 fps | exp 1000 全面表示: COLOR swap | 26.1 fps | 16 ms | exp 1000 | gain 0 表示モード 実測fps 表示時間 露出時間 ゲイン
* が付いているときは「手で動かした(手動)」の印です。
exposure / 明るさが脈打つとき
本体に組み込んだ版では、映像が白っぽく、明るさが脈打つ現象が残っています。 カメラ側の AE(自動露出)が行ったり来たりしている疑いが濃いのですが、 ESP_Video の公開 API には AE を止める手段が見当たりません。 そこで、露出時間とゲインを直接投げる道具を入れておきました。
// ESP_Video.h にある V4L2 拡張コントロール cap.setSensorExposureTime(int32_t); // V4L2_CID_EXPOSURE_ABSOLUTE cap.setSensorGain(int32_t); // V4L2_CID_GAIN cap.setSensorExposure(int32_t); // V4L2_CID_EXPOSURE cap.setSensorAETargetLevel(int32_t); // V4L2_CID_CAMERA_AE_LEVEL
| 段 | 露出時間 | ゲイン |
|---|---|---|
| 初期値 | 1000 | 0 |
| 下限 | 100 | 0 |
| 上限 | 20000 | 64 |
OK が出ても暗さが変わらないことがあります。
その場合はドライバの AE が優先されています。値の単位(マイクロ秒相当か、行数相当か)も実装依存です。
e/E を押しながら、g モードの見え方と fps を見て決めてください。
files / ダウンロード
まずはZIPを落として展開するのが早いです(中のフォルダ名と ino 名が一致しているので、そのまま Arduino で開けます)。md5 4813f2e3b7ed3c4e6d78e0c9ad03683a body/ にあります。
# ビルド確認(この版を作ったときの実測)
Arduino-ESP32 コア 3.3.12 / esp32:esp32:m5stack_tab5
Flash 1,075,612 bytes (16%)
RAM 70,052 bytes (21%)
warning 0 / error 0
notes / 正直な記載
内蔵カメラの映像表示、IOエキスパンダ経由の給電、ESP_Video の初期化手順は、 実機(Tab5)で動作を確認済みです。本ライブラリは、その確認できた処理に 露出・ゲイン操作と fps 表示を足したものです。2026.11.06 に実機で書き込み・起動・カメラ初期化まで確認しました。左半分が白・右半分が映像の状態で 26.0 fps / I2Cエラー0 / AEエラー0。全面表示(1280×720)では 6〜7 fps なので、律速は表示転送です。 差異があればお知らせください。
既知の制限