在前一篇測試中使用
cnadler86 提供的 ESP32-S3 CAM 韌體一直無法拍攝到正常完整的照片, 今天在 GitHub 上找到
shariltumin 的 repo, 發現裡面有 Gemini 強烈建議下載的 2022 年版韌體, 雖然是較舊的 MicroPython 1.20 版, 但能用才是王道, 於是下載來試試.
本系列之前的測試文章參考 :
雖然 repo 的標題是 2022, 但 2023 年有更新, 我是下載 20230717 的韌體 firmware.bin :
我將第一片燒錄到 GENERIC 那片板子拿來洗掉重燒 :
D:\ESP32-S3-CAM>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 4.6s
Hard resetting via RTS pin...
燒錄新版韌體 :
D:\ESP32-S3-CAM>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 0x00151fff...
Compressed 1383856 bytes to 913906...
Wrote 1383856 bytes (913906 compressed) at 0x00000000 in 79.8 seconds (effective 138.7 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
注意, 以上指令都需在下達出現 .... 時按住 BOOT 鍵才會生效. 燒錄完需拔掉 USB 斷電重開, 這樣 在 Thonny 按重新執行才能進入 Bootloader, 首先檢查 Flash 記憶體 :
MicroPython v1.20.0-206-g33b403dfb-kaki5 on 2023-07-10; ESP32S3-FREENOVE OV2640 w/BLE (KAKI5) with ESP32-S3
>>> import esp
>>> print(f"Flash 大小: {esp.flash_size() / 1024 / 1024:.2f} MB")
Flash 大小: 8.00 MB
N16R8 應該有 16MB 才對, 卻只能用到 8MB, 因為作者在製作這個韌體時為了相容性, 將分割表 (Partition Table) 設定為 8MB 之故. 8MB 足夠存幾千張照片或寫幾萬行程式, 剩下的 8MB 雖然看得到吃不到, 但也完全不影響效能.
接下來檢視 RAM 資訊 :
>>> import micropython
>>> micropython.mem_info()
stack: 736 out of 15360
GC: total: 6408320, used: 12560, free: 6395760
No. of 1-blocks: 282, 2-blocks: 36, max blk sz: 24, max free sz: 399722
GC 欄顯示有 6.4MB 的巨量 RAM, 與前一篇測試使用之韌體的 64K RAM 相比, 提升了 100 倍! 這對拍照與處理影像資料有如神助, 之前的綠色雜訊, 畫面撕裂, 與緩衝區溢位應該都會消失了.
先執行下列程式檢視 Flash 記憶體與 camera 模組 :
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)
輸出結果顯示有 camera 模組且 8MB PSRAM 有啟動 :
==============================
🚀 N16R8 Vibe Check
==============================
✅ 剩餘 RAM: 6.11 MB
-> 狀態:完美!Octal PSRAM 已啟用。
✅ Camera 模組版本: <module 'camera'>
-> 驅動載入成功。
==============================
接下來執行下列程式拍照 :
import camera
import time
import gc
# 1. 啟動與設定 (使用 Freenove 預設值)
gc.collect()
camera.init()
time.sleep(2.0) # 給相機一點時間適應光線
# 2. 拍照
buf = camera.capture() # 使用標準指令即可
# 3. 存檔
if buf:
with open("photo.jpg", "wb") as f:
f.write(buf)
print("拍照成功!")
# 4. 關閉
camera.deinit()
執行結果 :
這時重新整理 Thonny 左側的開發板資料夾, 會出現一個 photo.jpg 檔, 將其下載到 PC, 點擊開啟圖檔檢視軟體, 已成功拍攝了一張 800X600 的 JPG 照片 :
可見燒對韌體很重要, 雖然是 2023 年的版本, 且 MicroPython 是較舊的 v1.20, 但可以正常拍照就行. 上面的程式固定將拍攝的照片存成 photo.jpg 會蓋掉原檔案, 下面修正版則會自動編號為 photo_x.jpg :
import camera
import time
import os
import gc
# 1. 記憶體大掃除 (確保拍照順暢)
gc.collect()
print("========================================")
print("🚀 Vibe Cam - 22.0 純淨拍照版")
print(f"🧠 可用記憶體: {gc.mem_free() / 1024:.2f} KB")
print("========================================")
try:
# 2. 初始化相機
# Freenove 專用韌體不需要參數,它會自動載入正確設定
print("📷 初始化相機...")
camera.init()
# 【關鍵技巧】等待白平衡與自動曝光穩定
# 剛啟動的前幾秒畫面顏色可能會偏綠或偏暗,給它 2 秒適應光線
print("🔥 暖身中 (等待光線穩定)...")
time.sleep(2.0)
# 3. 拍照
print("📸 拍攝中...")
# 使用標準指令,Sharil 韌體會自動處理 JPEG 編碼
buf = camera.capture()
if buf and len(buf) > 0:
print(f"📦 取得影像: {len(buf)} bytes")
# 4. 智慧存檔 (存入內部 Flash)
# 自動尋找沒用過的檔名,避免覆蓋
i = 0
while True:
filename = f"photo_{i}.jpg"
try:
# 嘗試取得檔案資訊,如果檔案存在就不報錯,繼續下一號
os.stat(filename)
i += 1
except OSError:
# 檔案不存在 (報錯 ENOENT),代表這個名字可以用!
break
# 寫入檔案
with open(filename, "wb") as f:
f.write(buf)
print(f"💾 已儲存至內部空間: {filename}")
print("🎉 成功!請在 Thonny 左側檔案欄按右鍵 -> Refresh (重新整理) 查看。")
else:
print("❌ 拍照失敗 (數據為空)")
# 5. 釋放資源
# 養成好習慣,拍完就釋放,避免下次啟動衝突
camera.deinit()
print("✅ 相機已釋放")
except Exception as e:
print(f"❌ 發生錯誤: {e}")
# 嘗試強制釋放
try:
camera.deinit()
except:
pass
print("========================================")
輸出結果 :
========================================
🚀 Vibe Cam - 22.0 純淨拍照版
🧠 可用記憶體: 6225.03 KB
========================================
📷 初始化相機...
True
🔥 暖身中 (等待光線穩定)...
📸 拍攝中...
📦 取得影像: 51852 bytes
51852
💾 已儲存至內部空間: photo_0.jpg
🎉 成功!請在 Thonny 左側檔案欄按右鍵 -> Refresh (重新整理) 查看。
True
✅ 相機已釋放
========================================