2026 Hermes Agent 幫你寫程式 | ESP32 LED 程式
Hermes Agent 是 Nous Research 出品的開源 AI Agent——會用終端機、會讀寫檔案、會上網查資料,甚至會把踩過的坑寫成自己的技能筆記。這篇文章是一次完整實測:從一句「幫我偵測開發板」開始,到板上的 RGB LED 轉出彩虹,全程由 Hermes 代辦,人類只負責按批准、插板子、拍影片。
聽起來像按下按鈕就結束?實際過程精彩得多:AI 寫的程式有 bug、燒錄被板子的 USB 晶片擋了三小時、最後發現 PSRAM 是白牌相容顆粒且體質不佳——這條除錯長征,才是 AI Agent 時代寫韌體的真實樣貌,也是這篇文章最值得看的部分。

內容
為什麼用 Hermes Agent 寫韌體
嵌入式開發的第一顆 LED,卡住人的從來不是閃爍邏輯(那只是幾行程式碼),而是週邊的一切:
- 環境:ESP-IDF 版本、工具鏈、Python venv、環境變數——裝錯一步滿盤皆輸
- 硬體:這塊板子的 LED 接哪支腳?驅動方式是 GPIO 還是 WS2812?
- 燒錄:USB 轉接晶片的相容性、bootloader 進不了、莫名其妙的 checksum error
- 硬體體質:PSRAM 是否為白牌相容料件?時脈要設多少才不會崩潰?
AI Agent 的價值不是「替你寫那幾行閃爍程式」,而是把這些瑣事整包吃掉:它會上網查板型規格、翻 SDK 原始碼確認 API、讀 boot log 定位崩潰點、甚至去 GitHub issue 裡挖出跟你一模一樣的案例。人類的角色從「操作員」變成「審稿人+決策者」。
事前準備
| 項目 | 版本/內容 | 說明 |
|---|---|---|
| Hermes Agent | v0.21.6 | hermes update 一鍵升級,git 安裝 |
| 模型配置 | 雲端 z-ai/glm-5.3(NVIDIA NIM)+ 本地 Qwen3.8-27B 備援 | 雲端掛了自動切本地,無縫接手 |
| ESP-IDF | v5.5.5(含 esp32s3 工具鏈) | 用 Espressif 官方 eim 安裝器 |
| 開發板 | YD-ESP32-S3(DevKitC-1 相容板,16MB flash+8MB PSRAM) | 內建 WS2812 RGB LED 在 GPIO48 |
| 連接 | USB 資料線(CH343 轉接晶片) | 務必用資料線,充電線偵測不到 |
模型配置的重點:Hermes 支援 fallback 鏈——雲端模型(強、但偶爾逾時)掛掉時自動切到本機模型(快、離線可用)。這次實測中雲端反覆逾時,本地模型接手了好幾輪,全程無感。
一句話偵測板子
進入 Hermes CLI 後,第一句話:
幫我偵測目前接在電腦上的開發板:先看
/dev/cu.usb*有沒有序列埠,再用system_profiler SPUSBDataType看 USB 裝置型號;找得到埠的話,先啟動環境,再用 esptool 讀晶片 ID。
它做的事:列出序列埠 → 查出 USB 轉接晶片是 WCH CH343 → 連續兩次 esptool 連線失敗後自己換參數(--no_reset、指定晶片)→ 成功讀出身分:
晶片:ESP32-S3(rev v0.2,WiFi + BLE)
Flash:16MB · PSRAM:8MB(Octal)
MAC:fc:01:2c:d1:85:ec
這段有兩個值得注意的細節:偵測「失敗」時它不會強行瞎猜,會誠實回報「沒插板子」並給出排查建議(資料線 vs 充電線);連不上時會自己調整策略重試,而不是把錯誤丟回給你。
Hermes Agent 寫程式
第二句話把規格交代清楚:
板子確認是 ESP32-S3(16MB flash + 8MB PSRAM)。確認內建可程式 LED 腳位、建立 ESP-IDF v5.5.5 專案、寫 LED 閃爍程式、編譯。
Hermes 的做法相當專業:先上網查證板型(YD-ESP32-S3 官方規格表+電路圖),確認 WS2812 在 GPIO48(DevKitC-1 v1.0 佈局;v1.1 才是 GPIO38);接著翻本機 IDF 原始碼確認 RMT 驅動的 API 簽名,才開始撰寫程式碼。它選擇直接用 RMT 外設驅動 WS2812,不依賴第三方 led_strip 元件:
/* WS2812 wire order: G byte first, then R, then B — each byte MSB first */
static void encode_pixel(rmt_symbol_word_t *symbols, uint8_t r, uint8_t g, uint8_t b)
{
const uint8_t grb[3] = { g, r, b };
int i = 0;
for (int byte_idx = 0; byte_idx < 3; byte_idx++) {
for (int bit = 7; bit >= 0; bit--) {
bool one = (grb[byte_idx] >> bit) & 1;
symbols[i].level0 = 1;
symbols[i].duration0 = ns_to_ticks(one ? T1H_NS : T0H_NS);
symbols[i].level1 = 0;
symbols[i].duration1 = ns_to_ticks(one ? T1L_NS : T0L_NS);
i++;
}
}
}
AI 寫的程式也有 bug
第一次 build 之前,人類審查揪出第一個;後面兩個是編譯與硬體逼出來的:
| # | Bug | 徵狀 | 修復方式 |
|---|---|---|---|
| 1 | GRB 順序算反(bit 23 對到 B) | 彩虹照樣轉、紅燈照樣紅,但純綠會亮成藍——肉眼幾乎看不出來 | 人類審查發現,AI 重寫為顯式的 G→R→B 逐 byte |
| 2 | RMT 記憶體超配(64 symbols) | S3 每通道只有 48 words,rmt_new_tx_channel 會直接回錯 | AI 自查 SOC 常數後改 48 |
| 3 | API 欄位名錯(flags.loop_mode) | IDF 5.5 的 rmt_transmit_config_t 用 loop_count | 編譯器報錯後 AI 查標頭檔修正,並同步更新自己的技能筆記 |
第 1 題最值得深思:程式會動不代表程式是對的。GRB/BGR 顛倒的彩虹在人眼看來一樣是彩虹(色相反轉而已),只有審到資料協定那一層才會抓到。AI 能寫出「能動」的程式,但跨層一致性的最後一道防線,仍然是懂硬體的人類。
燒錄長征
程式編譯通過(200KB bin),真正的硬仗才開始。燒錄連環失敗:
- stub 模式:上傳 stub 時
0107: Checksum error - ROM 直寫(
--no-stub):第一個 flash block 就0105: format of the received message is invalid
Hermes 的排查流程完全是工程師做法:先排除變數(讀 flash OK、擦除 OK → 通訊是通的);換 USB 線、換埠重試 → 行為不變 → 排除實體層;掃過所有 baud rate → 全軍覆沒 → 排除速度;最後上網搜尋,在 Espressif 官方 issue #1178 找到一模一樣的案例(同顆 S3 rev v0.2),並從 Meta 的開源專案 muse-gadget-sdk 找到解法。
根因:這塊板子的 CH343 USB 轉接晶片沒有硬體流量控制。esptool 一口氣灌一整包資料,UART 來不及消化就掉封包——小量傳輸(讀/擦)剛好過關,大量傳輸(寫入、上傳 stub)必掛。
解法:paced 寫入——把資料切成 64 bytes 小包,按線速節流:
# tools/paced_esptool.py(節錄,源自 muse-gadget-sdk, Apache-2.0)
CHUNK = 64
def paced_write(self, data):
data = bytes(data)
n = 0
for i in range(0, len(data), CHUNK):
chunk = data[i : i + CHUNK]
n += _write(self, chunk)
self.flush()
time.sleep(len(chunk) * 10 / self.baudrate) # 10 bits a byte on the wire
return n
serial.Serial.write = paced_write # 補丁後再 import esptool
用它燒錄:三個 bin(bootloader / partition table / app)全部寫入成功、hash 驗證通過。
開機崩潰
燒進去了,新的坑:板子開機後無限重啟,log 斷在第二階段 bootloader 之後,app_main() 一步都沒跑到。
Hermes 的二分法乾淨俐落:
- 先驗證燒錄本身——把 flash 內容讀回來逐段比對,全部正確 ✅
- 再做煙霧測試——換一個「什麼都不做、只印一行字」的程式(彩虹版完整備份)→ 照樣崩 → 排除程式邏輯
- 關閉嫌疑犯——把 PSRAM 關掉重編 → app 跑到
app_main(),迴圈穩定運行 → 兇手現形
根因:這塊板子的 PSRAM(vendor 0x0d,白牌相容顆粒)在 80MHz Octal 模式初始化時必崩。降速到 40MHz 後完全穩定:
esp_psram: Found 8MB PSRAM device
esp_psram: Speed: 40MHz
esp_psram: SPI SRAM memory test OK
把 sdkconfig.defaults 永久改為 40MHz 並註明原因——這種「為什麼不是預設值」的註解,三個月後的自己會感謝現在的自己。
最終驗證
還原彩虹版、用 paced 工具做最終燒錄,完整開機 log 的關鍵三行:
I (197) esp_psram: Speed: 40MHz
I (1015) spi_flash: detected chip: boya
I (1055) led_demo: hermes_led_demo: rainbow cycle on WS2812 @ GPIO48
板上的 WS2812 開機先閃紅燈一下,然後以 HSV 色相每 10ms 轉 1° 的速度循環——紅、橙、黃、綠、青、藍、紫,3.6 秒一圈,永不停歇。
實戰心法
- 讓 Agent 做事,但保留審查權——AI 寫的程式「會動」不等於「是對的」。GRB 顛倒那題,人類審查的價值大於 AI 自查。看到可疑處直接指出,讓它自己修(它修得又快又好,還會記筆記)。
- 批准機制是安全網,別圖省事——Hermes 對危險指令(
python -c、rm -rf)會跳批准框,60 秒未回應自動拒絕。這個設計在整場實測中攔下了多條不必要執行的指令。方向鍵+Enter 的選單操作,記得先把終端機視窗點成焦點。 - 雲端+本地 fallback 是實用配置——雲端模型智商高但偶爾逾時,本地模型快且離線可用。整場除錯下來兩者無縫接手,體感近乎零中斷。
- 「錯誤碼全部列舉+排除法」是最強除錯模板——讀 OK/擦 OK/寫掛 → 排除實體層;換線無效 → 排除線材;全 baud 失敗 → 排除速度。每排除一個變數,嫌疑範圍就縮一圈,最後剩下的答案往往藏在 GitHub issue 裡。
- 相容開發板的晶片體質參差不齊是常態——標籤寫 16MB Flash+8MB PSRAM 不代表能跑滿官方最高時脈。PSRAM 降速至 40MHz 這種「規格打折換穩定」的妥協,正式量產或專案定案前務必實測。
- Agent 的自我進化是真的——這次它把「板子規格、WS2812 RMT 驅動配置、燒錄 0105/0107 解法、PSRAM 40MHz 坑」全部寫進了自己的技能庫。下次再開 ESP32 專案,它會先翻自己的筆記再動手。
結論
一次完整的「AI Agent 寫韌體」實測下來,分工其實很清楚:
| 角色 | 工作 |
|---|---|
| Hermes Agent | 偵測硬體、查證板型、寫碼、編譯、燒錄、讀 log、搜 issue、二分除錯、寫技能筆記 |
| 人類 | 插板子、按批准、審出 GRB bug、說「繼續」 |
| 板子本身 | 出難題(CH343 傳輸掉包、PSRAM 相容顆粒體質限制)——工程師永遠的朋友 |
AI Agent 沒有取代嵌入式工程師,但它把「第一顆 LED 從零到亮」的門檻從「一個週末的環境折騰」壓縮成「一場下午的對話」。真正卡住的兩關(燒錄時序、PSRAM 相容晶片體質限制),靠的是 AI 的窮舉耐心加上人類的跨層審查——這個組合,才是 2026 年寫韌體的正確姿勢。
下一顆 LED,你也來一句話試試?









