專題做好了,一支會計步、會開 Wi-Fi 讓手機看資料的小裝置。然後,他的電腦壞了。
原始碼只存在那台電腦裡。手上只剩一台還會動的裝置,沒有任何一行程式。
這篇記錄我們怎麼把它救回來:先完整備份,再把它重做成一套中文、可以在瀏覽器裡跑、學生能自己改的教材。後半段是實際拿在手上用了兩天之後,老師回報的四個問題,以及每一個問題背後的「失敗路徑」。
👉 介紹影片(13 分 23 秒,有章節):一台壞掉的電腦,和一支重生的計步器
🔗 瀏覽器模擬器+韌體+焊接短片:pedometer-lab 專案網站
📘 講義 PDF(81 頁,附 113 個名詞的白話解釋):下載講義

第一步:先備份,不要急著修
拿到別人的裝置,第一個動作不是燒新程式,而是把整片 4 MB 快閃記憶體唯讀備份下來,讀兩次,比對兩次的雜湊值完全一樣,才算備份成功。任何會寫入的動作,都要等到能完整還原之後才做。
從備份裡取回網頁、畫面上的英文字串、設定欄位,但機器碼要反推回原始碼,在 ESP32 上沒有可靠的方法證明「還原得對」。所以我們換一條路:把取回的文字當成「行為規格」(只寫它會做什麼、不寫它怎麼做),重新設計一個中文版。

可以直接拿去上課的觀念一:先在瀏覽器裡跑,再燒進板子
新版的核心是分層:計步、畫面、選單這些功能邏輯完全不碰硬體,中間隔一層「硬體抽象層」,上層只說「畫字」「讀加速度」,不管底下是真的板子還是瀏覽器。
結果是:同一份 C++ 程式,既能燒進 ESP32,也能編成 WebAssembly 在網頁裡跑成模擬器。學生不用每改一行就等兩分鐘燒錄,可以在模擬器裡拖傾斜盤、按「開始走路」、600 倍速快轉時間,馬上看到結果。
但要跟學生講清楚模擬器的極限:它測得到「邏輯對不對」,測不到「資源夠不夠」。下面兩條失敗路徑都是模擬器全過、真機卻出事。

硬體只有六條線:加速度計四條、蜂鳴器兩條。剝線、沾錫、焊接,每一條都是同樣三步,網站上有七段焊接短片可以直接放給學生看。

可以直接拿去上課的觀念二:沒有「真值」,就不能校正
第二輪改良裡最重要的一個問題,是老師回報「放在口袋走路,步數跳很快」。
要知道演算法準不準,需要真值,也就是「實際上走了幾步」。所以我們在裝置上做了「走路測試」:選好裝置放在哪裡、倒數三秒、邊走邊錄下每秒 50 筆加速度,走完再輸入自己數的步數。
老師走了「50 步」,裝置顯示 115。一問才知道,老師是同一隻腳落地才算一步;手機、手環則是左右腳每落地一次算一步。所以實際落地是 100 次,裝置多算了 15%。
課堂活動:請三位同學同時數同一位同學走路的步數,再比較每個人的數法。「一步」的定義不一樣,量出來的數字就不一樣——這就是為什麼校正前要先問清楚真值怎麼來的。
失敗路徑:頻譜最高的那根,不是步頻
這一條是我(AI)自己犯的錯。第一段錄音沒有真值,我看頻譜裡最強的頻率,就當成步頻,照它把演算法調成第二版。結果那其實是諧波(真正步頻的整數倍):放在口袋那條腿,同一步常常有兩三個波峰,頻譜就會被騙。第二版根本沒修好。
有了老師的真值之後,改用自相關:把最近 4 秒的訊號,和「自己往後挪一段時間」的版本比相似度,挪到剛好一個週期時最像,就知道每一步多久,不會被一步裡有幾個峰騙到。再加上「重新上膛」:算進一步後,訊號要先掉回 0 以下才接受下一個峰。



三段真機口袋錄音,第一版多算 13%~29%,第四版都在 ±3% 以內。三段錄音也存成回歸測試,以後誰改了演算法,跑一次就知道有沒有退步。
先量,再改:CPU 將近八成在空轉
老師另一個回報是「裝置會發燙」。我們先寫量測工具,才發現主程式每秒繞 18,000 圈,但真正在做事的時間只有兩成,其餘將近八成在空轉,像停紅燈還一直踩油門。
| 改了什麼 | 實測結果 |
|---|---|
| 主迴圈做完事就休息 | 時鐘畫面 CPU 活動比例 100% → 18.7% |
| 畫面沒變就不重送 | 設定畫面 CPU 11.5% |
| 加速度計自己先存 32 筆(FIFO),每 0.1 秒拿一次 | 不再漏資料 |
| 閒置關螢幕,輕敲兩下叫醒;螢幕關+用電池時進淺層睡眠 | 30 秒裡睡了 28 秒 |
| Wi-Fi 預設關閉,另加「完全關閉」開關 | 最大的發熱來源用到才開 |
失敗路徑:藍牙一開,板子就無限重開機
為了不開 Wi-Fi 也能用手機看步數,我們加了藍牙低功耗(BLE)。第一次用 Arduino 內建的藍牙程式庫,藍牙一開,記憶體只剩 9.7 KB,板子當機;而且「藍牙開」已經存進設定,每次開機都重來一次。
先燒一版沒有藍牙的韌體把板子救回來(步數與設定都還在),再換成小得多的 NimBLE,開著藍牙還剩 68 KB。現在打開藍牙,螢幕會出現 QR 碼,Android 手機用 Chrome 掃了就能連;iPhone 因為 Apple 的限制,要改用 Bluefy 瀏覽器。
教訓:評估「做不做得到」,不能只量程式放不放得進快閃記憶體,也要量執行時要多少 RAM。

失敗路徑:做了兩版的功能,最後拿掉
老師希望倒過來拿時畫面跟著轉。第一版在模擬器上轉得很順,燒進真機卻完全不會轉:轉動要先借一塊 65 KB 的記憶體,真機最大的一塊連續空間只有 57 KB。改用螢幕晶片的硬體旋轉之後,桌上自測正常,但老師實際拿在手上還是一直不能用。
最後的決定是:不再追查,整個功能拿掉。一個常常失靈的功能,比沒有這個功能更糟。「桌上自測通過」不等於「使用者拿在手上能用」,知道什麼時候該停損,也是專題要學的事。
還有一個小的:上下兩顆按鍵,程式一直是接反的。橫著拿時兩顆鍵在同一側上下排列,程式卻照「左鍵、右鍵」命名,把下面那顆當成「上一項」。老師用了兩天才提出來。按鍵的名字要照使用者實際看到的位置取,也要主動問使用者「哪裡用起來怪怪的」。
給老師的教材包
- 主選單一次一項:會動的小插圖+右側轉盤;番茄鐘、量角器依使用回饋刪掉,換成「音樂」(9 首公眾領域的兒歌與古典樂,用十二平均律換算頻率)。
- 瀏覽器寫程式、燒錄:學生改遊戲卡帶程式,模擬器自動重新載入;用 Web Serial 直接從 Chrome 燒錄,找不到裝置時網頁會提示要裝哪個驅動。編譯要在老師電腦上執行
make ide。 - 講義 81 頁:硬體、接線、演算法、模組選型、失敗路徑、逐步實作步驟,附錄 113 個名詞的白話解釋。

最後
這個專案想說的其實只有一句:原始碼要放進版本控制。而一個設計良好的系統,是可以被重建,也可以一直改得更好的。

🎬 13 分鐘介紹影片:YouTube 🔗 模擬器與所有教材:pedometer-lab 📘 講義 PDF
