蝦皮買的 ESP32-CAM 上周到貨, 周末帶回鄉下將接腳焊上, 並把攝影鏡頭 OV2640/OV5640 裝上去, 方法參考之前 ESP32-WROOM-DEV 開發板的筆記 :
開啟命令提示字元視窗, 先查詢 Flash 資訊 :
D:\ESP32>esptool --port COM4 flash_id
esptool.py v4.6.2
Serial port COM4
Connecting.............
Detecting chip type... ESP32-S3
Chip is ESP32-S3 (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
MAC: e0:72:a1:d7:dd:d4
Uploading stub...
Running stub...
Stub running...
Manufacturer: 68
Device: 4018
Detected flash size: 16MB
Flash type set in eFuse: quad (4 data lines)
Hard resetting via RTS pin...
可見 Flash 確實是 16MB. 用下列指令清除 Flash :
D:\ESP32>esptool --chip esp32s3 --port COM4 erase_flash
esptool.py v4.6.2
Serial port COM4
Connecting..................
Chip is ESP32-S3 (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
MAC: e0:72:a1:d7:dd:d4
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 3.6s
Hard resetting via RTS pin...
然後到 cnadler86 的 Camera API (目前社群首推) repo 庫, 下載有 OCTAL 字眼的 S3 韌體, 這款才能使用到 8MB PSRAM (N16R8 中的 8 是指 PSRAM/SPI RAM). 注意, ESP32 和 ESP32-S3 的 CPU 架構不同 (Xtensa LX6 vs LX7), 韌體完全不通用, ESP32-S3 若燒錄 ESP32, 板子可能會完全無法開機, 就算能開機也抓不到那 8MB 的 PSRAM 記憶體.
解開下載的 mpy_cam-v1.27.0-ESP32_GENERIC_S3-SPIRAM_OCT.zip 會得到映像檔 firmware.bin. 檔名中的 mpy_cam 表示內建 camera 模組, GENERIC_S3 表示適用於標準 ESP32-S3 開發板, SPIRAM_OCT 代表支援 Octal SPI RAM, 這正是 N16R8 (R8=8MB Octal RAM) 必須要有的驅動. 沒有 OCTAL 的是一般 SPIRAM (Quad) 的版本, 雖然能開機, 但只會抓到 2MB 或更少的記憶體且速度較慢.
接下來參考之前 ESP32-S3 開發板燒錄韌體指令將此 MicroPython 韌體燒錄到 Flash 中 :
D:\ESP32>esptool --chip esp32s3 --port COM4 write_flash -z 0 firmware.bin
esptool.py v4.6.2
Serial port COM4
Connecting...................
Chip is ESP32-S3 (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
MAC: e0:72:a1:d7:dd:d4
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x001dbfff...
Compressed 1948272 bytes to 1238576...
Wrote 1948272 bytes (1238576 compressed) at 0x00000000 in 108.1 seconds (effective 144.1 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
燒錄成功後在 Thonny 點選 "執行/停止-重新啟動" 出現 "not in bootloader mode" 訊息 :
Device is busy or does not respond. Your options:
- wait until it completes current work;
- use Ctrl+C to interrupt current work;
- reset the device and try again;
- check connection properties;
- make sure the device has suitable MicroPython / CircuitPython / firmware;
- make sure the device is not in bootloader mode.
按 RST 鍵 (左鍵) 出現 "waiting for download" :
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x20 (DOWNLOAD(USB/UART0))
waiting for download
我詢問 Gemini, 它說這個訊息的意思是 "我現在處於下載模式 (Download Mode), 因為有人按著我的 BOOT 鍵 (右鍵), 所以我正在等待電腦傳送新的程式給我", 板子根本沒有試著去讀取剛燒進去的 MicroPython, 而是以為還要繼續燒錄, 所以一直停在門口發呆, 這通常是由硬體原因造成的, 最常見的兇手是鏡頭模組, 相機的某些腳位可能與 Strapping Pins (決定開機模式的腳位) 共用, 當插著 OV2640/OV5640 開機時, 鏡頭內部的電路可能會把板子上的 GPIO 0 拉低, 導致晶片誤以為 BOOT 鍵被按著不放.
拔掉電源拆下鏡頭後重新插入 USB 槽, 果然就順利進入 MicroPython 執行環境了 :
MPY: soft reboot
MicroPython v1.27.0-dirty on 2026-01-12; Generic ESP32S3 module with Octal-SPIRAM with ESP32S3
Type "help()" for more information.
>>> import esp
>>> print(f"Flash 大小: {esp.flash_size() / 1024 / 1024:.2f} MB")
Flash 大小: 16.00 MB
然後用下列程式檢查是否可載入 camera 模組, 以及 PSRAM 是否啟用 :
>>> import gc
import camera
import micropython
# 分配記憶體與整理
gc.collect()
print("="*30)
print("🚀 N16R8 Vibe Check")
print("="*30)
# 1. 檢查 RAM (關鍵指標)
# N16R8 成功驅動後,這裡應該要顯示 4MB ~ 8MB 之間的數值
free_ram_mb = gc.mem_free() / 1024 / 1024
print(f"✅ 剩餘 RAM: {free_ram_mb:.2f} MB")
if free_ram_mb > 4:
print(" -> 狀態:完美!Octal PSRAM 已啟用。")
else:
print(" -> 警告:RAM 過少,可能燒錄成 Non-Octal 版本。")
# 2. 檢查 Camera 模組
try:
print(f"✅ Camera 模組版本: {camera}")
print(" -> 驅動載入成功。")
except Exception as e:
print(f"❌ Camera 模組載入失敗: {e}")
print("="*30)
==============================
🚀 N16R8 Vibe Check
==============================
✅ 剩餘 RAM: 7.93 MB
-> 狀態:完美!Octal PSRAM 已啟用。
✅ Camera 模組版本: <module 'camera'>
-> 驅動載入成功。
==============================
可見 8MB 的 PSRAM 已成功啟用, 剩餘 PSRAM 為 7.93MB.
做完上述測試確認可讀到 8MB PSRAM 後拔除 USB, 將鏡頭插回去, 找了一片 8GB TF 卡插入背板的卡槽, 重新插上 USB, 這次居然順利進入 MicroPython 環境, 沒有卡在等待 Bootloader 那邊 (萬一出現此情況, 可以試著多按幾次 RST 鍵, 按一下 RST 等 2 秒再按一下; 或者按住 BOOT 鍵不放, 按一下 RST 鍵然後放開, 繼續按著 BOOT 鍵等待 1-2 秒再放開).
先用 Gemini 建議的程式測試看看能否讀取 TF 卡 :
MicroPython v1.27.0-dirty on 2026-01-12; Generic ESP32S3 module with Octal-SPIRAM with ESP32S3
Type "help()" for more information.
>>> import machine
import os
def mount_sd():
try:
# 針對 Generic ESP32-S3 CAM,通常使用 SDMMC Slot 1
# width=1 (1-bit mode) 比較省腳位且常見,若失敗可改 width=4
# 注意:不同板子的 clk/cmd/d0 腳位可能不同,請查閱您的板子 Schematic
# 以下是常見的 Freenove/Generic S3 CAM 預設腳位:
sd = machine.SDCard(slot=1, width=1,
clk=39, cmd=38, d0=40)
# 若上面的腳位報錯,試試不指定腳位: machine.SDCard(slot=1, width=1)
os.mount(sd, "/sd")
print("✅ SD Card mounted at /sd")
# 檢查容量
fs_stat = os.statvfs('/sd')
free_mb = (fs_stat[0] * fs_stat[3]) / 1024 / 1024
print(f"📦 Free space: {free_mb:.2f} MB")
return True
except Exception as e:
print(f"❌ Failed to mount SD: {e}")
return False
# 測試
mount_sd()
❌ Failed to mount SD: extra keyword arguments given
False
回報給 Gemini, 它說 extra keyword arguments given 意思是 "您給了我一個我不認識的參數名稱", 原因是上面的程式碼中使用了 clk 這個參數名稱, 但在 MicroPython 的標準 machine.SDCard 函式庫中, 時鐘腳位的標準參數名稱通常是 sck (Serial Clock) 而不是 clk, 它建議使用標準 ESP32-S3 的寫法, 將 clk 改為 sck 並明確使用 Pin() 物件, 程式修正如下 :
>>> import machine
import os
from machine import Pin
def mount_sd():
try:
# 修正點:
# 1. clk 改為 sck
# 2. 建議加上 Pin() 包裝 (比較保險)
sd = machine.SDCard(slot=1, width=1,
sck=Pin(39),
cmd=Pin(38),
d0=Pin(40))
os.mount(sd, "/sd")
print("✅ SD Card mounted at /sd")
# 檢查容量
fs_stat = os.statvfs('/sd')
free_mb = (fs_stat[0] * fs_stat[3]) / 1024 / 1024
print(f"📦 Free space: {free_mb:.2f} MB")
return True
except Exception as e:
print(f"❌ Failed to mount SD: {e}")
return False
mount_sd()
❌ Failed to mount SD: extra keyword arguments given
False
結果還是不行, 回報 Gemini, 它說可能是韌體底層把 cmd 和 d0 對應到了 mosi 和 miso 的參數位置 (這是某些 S3 移植版的怪癖), 叫我試試看下面這個版本測試程式 :
>>> import machine
import os
from machine import Pin
def mount_sd():
try:
# 修正點:
# 1. clk 改為 sck
# 2. 建議加上 Pin() 包裝 (比較保險)
sd = machine.SDCard(slot=1, width=1,
sck=Pin(39),
mosi=Pin(38), # 對應 CMD
miso=Pin(40)) # 對應 D0
os.mount(sd, "/sd")
print("✅ SD Card mounted at /sd")
# 檢查容量
fs_stat = os.statvfs('/sd')
free_mb = (fs_stat[0] * fs_stat[3]) / 1024 / 1024
print(f"📦 Free space: {free_mb:.2f} MB")
return True
except Exception as e:
print(f"❌ Failed to mount SD: {e}")
return False
mount_sd()
❌ Failed to mount SD: invalid config: SDMMC slot with SPI pin arguments
False
錯誤訊息變成 invalid config 了, Gemini 綜合上面測試結果, 認為是軟硬體不匹配問題, 目前燒錄的這版 cnadler86 "Generic" 韌體為了維持通用性鎖住了 SDMMC 的腳位設定功能, 它強制使用 ESP32-S3 的官方預設腳位 (CLK=14, CMD=15, D0=2), 不允許透過 Python 程式碼 (clk=39...) 去修改它. 但這塊開發板 (N16R8 CAM) 的硬體線路是 (CLK=39, CMD=38, D0=40), 軟體想走東但硬體在西所以讀不到卡.
Gemini 認為我的板子應該是 Freenove ESP32-S3 開發板的仿板, 建議我改燒錄 Freenove 專為 S3 WROOM (N16R8) 設計的韌體才能解決此問題, 還好這塊開發板我買了三塊, 打算用另一塊來燒錄 Freenove 的韌體, 等測試 OK 再洗掉目前這塊重新燒錄.



沒有留言 :
張貼留言