2026 Hermes Agent 幫你寫程式 | ESP32 LED 程式


Hermes Agent 是 Nous Research 出品的開源 AI Agent——會用終端機、會讀寫檔案、會上網查資料,甚至會把踩過的坑寫成自己的技能筆記。這篇文章是一次完整實測:從一句「幫我偵測開發板」開始,到板上的 RGB LED 轉出彩虹,全程由 Hermes 代辦,人類只負責按批准、插板子、拍影片。

聽起來像按下按鈕就結束?實際過程精彩得多:AI 寫的程式有 bug、燒錄被板子的 USB 晶片擋了三小時、最後發現 PSRAM 是白牌相容顆粒且體質不佳——這條除錯長征,才是 AI Agent 時代寫韌體的真實樣貌,也是這篇文章最值得看的部分。

Hermes 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 Agentv0.21.6hermes update 一鍵升級,git 安裝
模型配置雲端 z-ai/glm-5.3(NVIDIA NIM)+ 本地 Qwen3.8-27B 備援雲端掛了自動切本地,無縫接手
ESP-IDFv5.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徵狀修復方式
1GRB 順序算反(bit 23 對到 B)彩虹照樣轉、紅燈照樣紅,但純綠會亮成藍——肉眼幾乎看不出來人類審查發現,AI 重寫為顯式的 G→R→B 逐 byte
2RMT 記憶體超配(64 symbols)S3 每通道只有 48 words,rmt_new_tx_channel 會直接回錯AI 自查 SOC 常數後改 48
3API 欄位名錯(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,你也來一句話試試?