賽開源:從電源設(shè)計(jì)到串級(jí)PID的完整硬件方案)
賽前我們約定的口號(hào)很簡(jiǎn)單“最后一圈跑完把能開的源全開了?!苯Y(jié)果真到了21屆智能車競(jìng)賽沖線那天代碼里還有一堆臨時(shí)patchPCB上還飛著兩根杜邦線。等到這周把 soberup 戰(zhàn)隊(duì)的開源目錄徹底整理出來(lái)已經(jīng)是賽后第四周中間還經(jīng)歷了補(bǔ)測(cè)、拆車、還焊臺(tái)三件事。這份開源目錄包含我們整個(gè)賽季的電路設(shè)計(jì)、底層驅(qū)動(dòng)、控制算法和調(diào)試工具主力平臺(tái)是 STM32 系的板卡比賽車模使用普通四輪車模組別是隊(duì)內(nèi)自己命名的“瘋狂電路組”。說(shuō)白了這就是一支把電源、傳感、驅(qū)動(dòng)、保護(hù)四塊電路全都自己啃下來(lái)的隊(duì)伍在用完了一個(gè)賽季的運(yùn)氣和炸掉的若干片MOS管之后把所有能交給下一屆的東西打包放在了一起。這篇博客就當(dāng)作開源目錄的導(dǎo)覽和說(shuō)明書寫給準(zhǔn)備打智能車、或者對(duì)嵌入式硬件開源項(xiàng)目感興趣的讀者看。1. 為什么一支“電路組”隊(duì)伍要公開全部家底1.1 從賽道邊的熬夜到實(shí)驗(yàn)室的炸板瘋狂電路組的來(lái)歷隊(duì)名叫 soberup中文意思是“清醒過(guò)來(lái)”但整個(gè)賽季我們做的事和這個(gè)詞基本無(wú)關(guān)。實(shí)驗(yàn)室的常態(tài)是凌晨三點(diǎn)有人在測(cè) Buck 電感的溫升有人在用示波器抓 IR2110 高端驅(qū)動(dòng)的自舉波形還有人一邊改攝像頭排線一邊罵賽道上那兩塊減速帶?!隘偪耠娐方M”不是官方組別名。我們學(xué)校車隊(duì)的組織架構(gòu)按賽道組劃分但隊(duì)內(nèi)又按職能拆了機(jī)械、電控、電路三攤。電路組負(fù)責(zé)的范圍很貪心整車的電源樹、傳感器信號(hào)調(diào)理、電機(jī)驅(qū)動(dòng)、可靠性保護(hù)電路、調(diào)試通信全都要沾手。于是我們就自嘲為瘋狂電路組因?yàn)閯e的組可能等代碼等設(shè)計(jì)我們每天等的是“別炸板”。這個(gè)背景和開源直接相關(guān)。賽季中期我們踩了很多坑但幾乎沒(méi)有系統(tǒng)的參考資料。B站和論壇上的開源項(xiàng)目大多是 18、19 屆的芯片型號(hào)老一代電路方案也比較傳統(tǒng)。當(dāng)時(shí)我就想著如果能把一整套 21 賽季實(shí)際跑通車的電路方案整理成開源項(xiàng)目至少下一屆學(xué)弟學(xué)妹就不用再經(jīng)歷一遍“照著舊方案改電感參數(shù)改了三個(gè)晚上”的日子。1.2 開源目錄里到底放了什么這次開源除了代碼倉(cāng)還有完整的硬件工程和文檔索引整體分五塊hardware/原理圖和 PCB 工程文件以及關(guān)鍵模塊的 BOM 表。我用的是立創(chuàng)EDA專業(yè)版工程同時(shí)導(dǎo)出了 PDF 原理圖和 Gerber 光繪文件方便沒(méi)有安裝 EDA 工具的同學(xué)直接看圖。firmware/嵌入式軟件工程分了driver/、algorithm/、task/三個(gè)目錄。driver 里是外設(shè)驅(qū)動(dòng)比如攝像頭 DCMI 采集、PWM 輸出、編碼器接口、陀螺儀 SPI 讀取algorithm 里是PID控制器、圖像處理、動(dòng)態(tài)閾值二值化task 里是調(diào)度邏輯。host/PC 上位機(jī)源碼主要負(fù)責(zé)實(shí)時(shí)顯示攝像頭畫面、賽道偏差曲線、陀螺儀角速度波形。后期調(diào)車我們大部分時(shí)間都在看這個(gè)上位機(jī)。doc/電路設(shè)計(jì)筆記、調(diào)試日志、賽場(chǎng)突發(fā)問(wèn)題記錄。這部分是我個(gè)人覺(jué)得最有價(jià)值的很多坑的完整排查鏈路都寫在里面。config/整車參數(shù)配置包括 PID 初始增益、賽道元素閾值、供電電壓標(biāo)定值每個(gè)參數(shù)后面都寫了修改理由。開源目錄的定位不是“給你一個(gè)能直接跑飛車的完整成品”而是“給你一套可復(fù)現(xiàn)的硬件方案和一整套調(diào)試方法論”。車這個(gè)東西每個(gè)隊(duì)的機(jī)械結(jié)構(gòu)、輪胎摩擦、賽道材質(zhì)都不一樣直接抄 PID 不可能一樣但電路基礎(chǔ)方案和調(diào)試思路是可以直接繼承的。1.3 你適合從這個(gè)開源里拿走什么如果你是新隊(duì)員可以對(duì)電路完全沒(méi)概念建議按doc/里的設(shè)計(jì)筆記配合hardware/的原理圖看。這里每塊電路都寫了我為什么選這個(gè)拓?fù)洹槭裁炊ㄟ@個(gè)參數(shù)而不是只丟給你一張圖。哪怕最后不用我們的板子這套分析思路也能幫你判斷別人開源項(xiàng)目的質(zhì)量。如果你是帶隊(duì)隊(duì)長(zhǎng)或者有一定經(jīng)驗(yàn)的隊(duì)員重點(diǎn)可以直接放在host/上位機(jī)和config/參數(shù)表里。我們花了大量時(shí)間做數(shù)據(jù)可視化有些問(wèn)題只有看到波形才能定位。你從波形里發(fā)現(xiàn)“這里怎么有一個(gè)不該有的震蕩”再回去翻硬件設(shè)計(jì)才知道是哪條地線惹的禍。如果你是純軟件方向的同學(xué)我希望你至少把hardware/里電源那一塊看一眼。因?yàn)橹悄苘囎畲蟮奶攸c(diǎn)就是“嵌入式軟件跑在臟電源上”電機(jī)一啟動(dòng)3.3V 上的紋波就能讓你的陀螺儀數(shù)據(jù)多出好幾度的漂移。不看電路軟件調(diào)死都調(diào)不出來(lái)。2. 電源鏈路設(shè)計(jì)Buck、Boost與每一步抗干擾取舍2.1 為什么智能車電源幾乎離不開Buck和Boost賽車上最穩(wěn)定的能量來(lái)源只有動(dòng)力電池組室內(nèi)賽用 7.4V 兩節(jié)鋰電的情況比較多。但板卡需要的電壓是 5V、3.3V攝像頭可能需要 5V 或 2.8V運(yùn)放要 5V 或者 3.3V 單電源驅(qū)動(dòng)芯片有時(shí)又要 12V 做外部供電。這么多電壓等級(jí)不可能每個(gè)都用線性穩(wěn)壓器去處理。線性穩(wěn)壓器的優(yōu)點(diǎn)是輸出紋波低、電路簡(jiǎn)單、價(jià)格便宜但它的效率在壓差大的時(shí)候慘不忍睹。7.4V 降到 3.3V壓差 4.1V即便是低壓差 LDO在 200mA 電流下也有接近 0.8W 的功耗變成熱量。車上空間就那么一點(diǎn)風(fēng)扇都沒(méi)有熱到最后傳感器都在溫漂。而 Buck 電路是開關(guān)電源理想情況下沒(méi)有線性區(qū)損耗用同步 Buck 拓?fù)湫首龅?90% 以上很輕松。Boost 電路在我們的方案里主要用來(lái)做局部電壓抬升比如把 5V 升到 12V 給無(wú)源蜂鳴器驅(qū)動(dòng)、風(fēng)扇和一些測(cè)試模塊用。它不是整車功率主干但少了它有些外圍模塊就是起不來(lái)。除了這些還有一個(gè)容易被忽略的原因Buck 和 Boost 的輸入范圍寬能容忍電池在滿電和欠壓之間波動(dòng)時(shí)保持輸出穩(wěn)定這一點(diǎn)對(duì)比賽穩(wěn)定性的價(jià)值遠(yuǎn)大于那零點(diǎn)幾伏的精度。2.2 Buck電路設(shè)計(jì)要點(diǎn)與紋波估算開源目錄里的主 Buck 方案選用的是同步降壓控制器方案不是集成模塊。集成模塊雖然省事但很難針對(duì)自己的負(fù)載特性去優(yōu)化紋波。我們實(shí)際遇到一個(gè)典型問(wèn)題電機(jī)堵轉(zhuǎn)瞬間電池電壓會(huì)拉低Buck 輸入電壓突變導(dǎo)致環(huán)路響應(yīng)不過(guò)來(lái)3.3V 上出現(xiàn)一個(gè) 200mV 的掉坑單片機(jī)直接復(fù)位。解決這個(gè)問(wèn)題的關(guān)鍵其實(shí)在輸入電容。很多人只關(guān)注輸出電容忽略了輸入電容承擔(dān)著高頻開關(guān)電流的回流。我在輸入側(cè)并了一個(gè) 22μF 陶瓷電容和 100μF 鋁電解電容的組合。陶瓷電容負(fù)責(zé)高頻瞬態(tài)鋁電解電容負(fù)責(zé)低頻能量緩沖。加完之后堵轉(zhuǎn)時(shí)輸入電壓的跌落明顯變小復(fù)位問(wèn)題消失。電感選值我用的是最??吹墓絃 (Vin - Vout) × Vout / (Vin × ΔI_L × fsw)其中 ΔI_L 取輸出電流的 30%。假設(shè)輸入 7.4V輸出 5V開關(guān)頻率 500kHz負(fù)載電流 1A那么 ΔI_L 0.3A算出來(lái)電感大概是 10.8μH我最終選了 10μH 的功率電感。輸出紋波電壓也可以用經(jīng)典公式粗算ΔVout ≈ ΔI_L / (8 × fsw × Cout) ΔI_L × ESR_Cout所以輸出電容我用了兩顆 22μF 的 X5R 陶瓷電容并聯(lián)順帶留了一個(gè)小的 0.1μF 高頻去耦電容。注意 X5R 陶瓷電容在直流偏壓下實(shí)際容值會(huì)下降比如 25V 耐壓的 22μF 電容在 5V 偏壓下可能只剩 60% 容量。選型時(shí)一定要看容壓曲線不然計(jì)算值和實(shí)測(cè)值差很多。2.3 供電網(wǎng)絡(luò)的抗干擾與防抖處理電源部分的“抗干擾”不只是加電容更關(guān)鍵的是地平面規(guī)劃和濾波網(wǎng)絡(luò)的擺放位置。我們的板卡是兩層板雖然不像四層板那樣有完整地平面但依然能通過(guò)“分區(qū)鋪銅單點(diǎn)連接”做出比較干凈的地。具體做法是把 Buck 電路的功率地、單片機(jī)數(shù)字地、模擬信號(hào)地分開然后在主控下方的某一點(diǎn)匯合。功率地上的高頻開關(guān)電流和電機(jī)驅(qū)動(dòng)回流不能流過(guò) MCU 的地平面否則 ADC 采樣和運(yùn)放輸出都會(huì)帶上毛刺。這個(gè)不是玄學(xué)是電流總是走低阻抗路徑如果路徑穿過(guò)傳感器地那傳感器地就被污染了?!胺蓝峨娐贰边@個(gè)說(shuō)法在熱詞里出現(xiàn)得挺多我們理解的防抖包含兩層含義。第一是電氣防抖供電線上串聯(lián)磁珠配合 π 型濾波器抑制電機(jī)火花和舵機(jī)瞬態(tài)電流對(duì)傳感器電源的干擾。第二是機(jī)械防抖攝像頭支架和 IMU 安裝位置之間用泡棉減震避免車過(guò)坡道和減速帶時(shí)瞬間沖擊影響圖像穩(wěn)定。這兩個(gè)都得做只做硬件濾波處理不了低頻機(jī)械振動(dòng)。調(diào)試時(shí)最滿意的改進(jìn)是把攝像頭供電單獨(dú)拉了一路 LC 濾波。攝像頭啟動(dòng)瞬間的電流尖峰會(huì)拉低共享的 5V 總線直接影響編碼器供電導(dǎo)致左右輪測(cè)速毛刺。加了一個(gè) 10μH 電感加 100μF 電容的 LC 濾波后圖像橫條紋徹底消失測(cè)速毛刺也基本清零。實(shí)測(cè)效果比改軟件濾波明顯得多這算是我在電源設(shè)計(jì)上收獲最大的一條經(jīng)驗(yàn)。3. 傳感器信號(hào)鏈路差分放大、運(yùn)放經(jīng)典電路與防抖3.1 信號(hào)調(diào)理是“電路組”的主場(chǎng)智能車上最需要電路組出力的地方其實(shí)是信號(hào)鏈路。攝像頭數(shù)字輸出還好但車模速度信號(hào)、陀螺儀模擬輸出、以及部分輔助傳感器信號(hào)都需要經(jīng)過(guò)運(yùn)放調(diào)理后才能進(jìn)單片機(jī) ADC。這部分電路看上去簡(jiǎn)單就是“放大-濾波-送ADC”但實(shí)際工程里每一步都有坑。比如運(yùn)放的供電軌單電源運(yùn)放輸出不能到負(fù)如果信號(hào)是雙極性的必須在輸入端加一個(gè)直流偏置把信號(hào)抬到量程中間。我們?cè)谠O(shè)計(jì)時(shí)把基準(zhǔn)電壓源設(shè)為 3.3V/2 1.65V所有單電源運(yùn)放都以這個(gè)電壓為虛擬地。偏置電路不是簡(jiǎn)單分壓就行。如果用兩個(gè)電阻分壓出 1.65V然后直接接運(yùn)放同相端電源噪聲會(huì)直接進(jìn)信號(hào)鏈路。我們的做法是用一個(gè)電壓跟隨器單獨(dú)緩沖基準(zhǔn)再接運(yùn)放。跟隨器輸出阻抗低帶載能力強(qiáng)而且隔離了分壓電阻熱噪聲。開源目錄里hardware/下專門有一個(gè)ref_bias.sch文件畫的就是這個(gè)。3.2 差分放大電路與共模噪聲的博弈賽場(chǎng)上常見(jiàn)的共模干擾有兩個(gè)來(lái)源電機(jī)換相產(chǎn)生的寬頻噪聲、無(wú)線模塊的地電勢(shì)差。單端放大電路很容易把共模噪聲一并放大所以差模信號(hào)必須用差分放大結(jié)構(gòu)。我們用的標(biāo)準(zhǔn)差分電路長(zhǎng)這樣一個(gè)四電阻差分放大器增益由反饋電阻和輸入電阻的比例決定Vout (Rf / Rin) × (V - V -)四顆電阻必須等差值配比否則共模抑制比 CM RR 會(huì)被電阻誤差拉低。計(jì)算很簡(jiǎn)單但真正的坑在選電阻。我用的是 0.1% 精度的精密電阻普通 5% 貼片電阻在溫差和焊接應(yīng)力下橋臂失配會(huì)超過(guò) 2%共模抑制性能直接廢掉。如果你實(shí)在沒(méi)有精密電阻也可以用集成差分放大器芯片比如 AD620 或者 INA 系列它們的內(nèi)部電阻已經(jīng)做了激光校準(zhǔn)。差分信號(hào)進(jìn)入運(yùn)放前我先接了一階 RC 低通截止頻率按實(shí)際信號(hào)帶寬來(lái)定我們?nèi)?10kHz 左右。這個(gè)前置濾波不是為了好看而是避免高頻共模噪聲通過(guò)運(yùn)放的非線性區(qū)混疊到低頻段。不加這個(gè)濾波你會(huì)發(fā)現(xiàn)示波器上放大后的信號(hào)滿是毛刺怎么換運(yùn)放都沒(méi)用。3.3 運(yùn)放偏置、濾波與電氣防抖開源doc/里我專門寫了“運(yùn)放11種經(jīng)典電路”的學(xué)習(xí)筆記這不是標(biāo)題黨是真的把同相放大、反相放大、電壓跟隨、差分放大、加法器、積分器、有源濾波這些電路逐個(gè)搭出來(lái)、用信號(hào)發(fā)生器實(shí)測(cè)過(guò)。我的體會(huì)是同一個(gè)電路仿真里完美不代表實(shí)板完美。板上任何一根走線的寄生電感、寄生電容都會(huì)在 1MHz 以上頻率改變運(yùn)放的實(shí)際響應(yīng)。以電壓跟隨器為例很多人以為把運(yùn)放輸出直接連反饋就行但在驅(qū)動(dòng)長(zhǎng)線時(shí)負(fù)載電容會(huì)引起輸出震蕩。我們用了一個(gè)低值串聯(lián)電阻33Ω放在輸出端把負(fù)載電容和運(yùn)放輸出隔開震蕩立刻消失。電氣防抖在信號(hào)鏈路上的體現(xiàn)也很有意思。攝像頭行中斷和場(chǎng)中斷信號(hào)是數(shù)字信號(hào)理論上不需要濾波但實(shí)際排線長(zhǎng)了以后電機(jī)噪聲會(huì)耦合進(jìn)來(lái)導(dǎo)致中斷誤觸發(fā)。我在信號(hào)線上加了 22Ω 串聯(lián)電阻加一小顆 33pF 電容到地構(gòu)成一個(gè)截止頻率大概 200MHz 的低通濾波既能濾掉高頻干擾又不影響行信號(hào)上升沿。硬件上犧牲一點(diǎn)點(diǎn)邊沿速率換來(lái)的是圖像采集不再隨機(jī)丟幀絕對(duì)值得。4. 驅(qū)動(dòng)與系統(tǒng)可靠性IR2110半橋、圖騰柱和看門狗4.1 電機(jī)驅(qū)動(dòng)為什么選擇IR2110半橋方案車模電機(jī)尤其是主驅(qū)電機(jī)瞬間電流可以從幾安到十幾安。普通集成電機(jī)驅(qū)動(dòng)芯片輸出能力有限炸芯片是家常便飯。所以我們的驅(qū)動(dòng)板用了“MCU 柵極驅(qū)動(dòng)芯片 大功率 MOSFET”的分立方案柵極驅(qū)動(dòng)芯片選的是 IR2110。IR2110 是一款半橋驅(qū)動(dòng)器可以同時(shí)驅(qū)動(dòng)一個(gè)高邊 MOSFET 和一個(gè)低邊 MOSFET自帶自舉供電結(jié)構(gòu)邏輯輸入兼容 3.3V這對(duì) STM32 來(lái)說(shuō)很方便。我們用兩個(gè) IR2110 搭成一個(gè)全橋驅(qū)動(dòng)有刷電機(jī)四個(gè) N-MOSFET 構(gòu)成 H 橋。為什么不直接用集成的全橋驅(qū)動(dòng)器集成驅(qū)動(dòng)芯片雖然板子小但散熱差、電流上限低而且一旦燒毀往往整個(gè)芯片連邏輯部分一起報(bào)廢。分立 MOSFET 方案的好處是驅(qū)動(dòng)芯片壞了只需要換 IR2110功率管壞了只需要換 MOSFET而且可以按整車需求自由選擇更大封裝的管子。對(duì)于比賽這種高強(qiáng)度運(yùn)行場(chǎng)景可維護(hù)性就是戰(zhàn)斗力。4.2 圖騰柱與自舉電容那些坑IR2110 驅(qū)動(dòng)高邊 MOSFET 用的自舉電容一定要認(rèn)真選。自舉電容負(fù)責(zé)在高端管導(dǎo)通時(shí)給上管柵極提供能量如果容量太小上管柵極電壓維持不住管子會(huì)進(jìn)入線性區(qū)發(fā)熱量劇增。計(jì)算公式大概可以參考C_boot Qg / ΔVQg 是所選 MOSFET 的總柵極電荷ΔV 是允許的電壓跌落一般取 0.5V 左右。我們用的 MOSFET 的 Qg 在 30nC 量級(jí)取 ΔV0.5V算出來(lái)需要至少 60nF我留了余量選了 100nF 低 ESR 陶瓷電容實(shí)際工作正常。另一個(gè)容易翻車的地方是圖騰柱驅(qū)動(dòng)。IR2110 本身自帶驅(qū)動(dòng)能力但如果你用的是不帶驅(qū)動(dòng)芯片的邏輯電平 MOSFET或者想直接用小 MOSFET 驅(qū)動(dòng)大 MOSFET 的情況就需要用圖騰柱結(jié)構(gòu)。圖騰柱就是兩個(gè)互補(bǔ)的三極管或者 MOSFET一個(gè)拉電流一個(gè)灌電流共同組成推挽輸出。MCU 引腳直接驅(qū)動(dòng)大 MOS 的柵極由于柵極電容大上升沿會(huì)變緩開關(guān)損耗暴增。加了圖騰柱以后上升沿從 400ns 縮短到 80ns開關(guān)損耗小了非常多。最痛苦的一個(gè)坑和死區(qū)有關(guān)。H 橋上下兩個(gè) MOS 管如果同時(shí)導(dǎo)通就是直通短路電流瞬間幾百瓦地把管子打穿。IR2110 自身不生成死區(qū)時(shí)間必須在程序 PWM 里設(shè)置互補(bǔ)帶死區(qū)輸出。我們?cè)缙谠诖a里只設(shè)置了 100ns 死區(qū)結(jié)果換了一個(gè)柵極電荷更大的 MOS 管后關(guān)斷時(shí)間變長(zhǎng)實(shí)際死區(qū)不夠又燒了兩片管。后來(lái)直接在定時(shí)器里配置了 500ns 死區(qū)同時(shí)把驅(qū)動(dòng)芯片的輸入波形在示波器上看了確認(rèn)無(wú)交疊才算穩(wěn)定。4.3 看門狗、復(fù)位與485調(diào)試電路讓系統(tǒng)更耐跑跑場(chǎng)地時(shí)最怕的不是算法寫錯(cuò)而是系統(tǒng)跑到一半“莫名其妙”進(jìn)入死循環(huán)。智能車賽道路況復(fù)雜靜電、干擾、電源瞬態(tài)都可能讓單片機(jī)跑飛。我們的兜底方案是硬件看門狗加復(fù)位芯片雙組合。STM32 的獨(dú)立看門狗IWDG用內(nèi)部 LSI 時(shí)鐘時(shí)鐘頻率約 40kHz。它的超時(shí)時(shí)間大約可以算T (預(yù)分頻系數(shù) × 重裝載值) / 40000預(yù)分頻系數(shù)取 64重裝載值取 625超時(shí)就是 1 秒。我們?cè)谥餮h(huán)里喂狗同時(shí)把喂狗放在任務(wù)調(diào)度的最低優(yōu)先級(jí)意味著如果低優(yōu)先級(jí)任務(wù)能跑說(shuō)明系統(tǒng)大體沒(méi)卡死如果卡在高優(yōu)先級(jí)中斷里太久看門狗超時(shí)復(fù)位車自動(dòng)重啟。這里要特別提醒看門狗復(fù)位之后車立馬上賽道如果沒(méi)有妥善處理“復(fù)位后初始狀態(tài)”車會(huì)在原地轉(zhuǎn)圈。我們的做法是復(fù)位后先強(qiáng)制停車 200ms同時(shí)重新讀取賽道信息等圖像穩(wěn)定后再啟動(dòng)。復(fù)位電路方面我們用了類似 MAX809 的上電復(fù)位芯片它在 VDD 上升到閾值前保持復(fù)位防止上電瞬間程序亂飛。有些同學(xué)直接用 10μF 電容加電阻做 RC 復(fù)位省成本但電源上升斜率慢時(shí)會(huì)出問(wèn)題芯片復(fù)位不徹底。485 電路則是調(diào)試階段的生命線。我們用 SP3485 做了一路 RS-485 接口通過(guò) USB-485 轉(zhuǎn)換器連電腦上位機(jī)實(shí)時(shí)傳送圖像和傳感器數(shù)據(jù)。485 用差分信號(hào)傳輸抗干擾能力比 UART TTL 電平強(qiáng)很多。硬件上注意 A/B 兩根線要加 120Ω 終端電阻A 線上拉 1kΩ 到 3.3VB 線下拉 1kΩ 到 GND這樣總線空閑時(shí)狀態(tài)確定不會(huì)亂幀。無(wú)源蜂鳴器驅(qū)動(dòng)電路也在開源目錄里。小蜂鳴器直接用三極管驅(qū)動(dòng)就行但續(xù)流二極管一定要加否則關(guān)斷瞬間的反向電動(dòng)勢(shì)會(huì)擊穿三極管基極。我們驅(qū)動(dòng)頻率選擇 4kHz效果比默認(rèn)的 2kHz 更響。5. 電路與代碼的交點(diǎn)PID輸出角速度與攝像頭循跡5.1 為什么我要輸出“角速度”而不是PWM很多人寫轉(zhuǎn)向環(huán)外環(huán)拿攝像頭偏差算出一個(gè) PWM 直接給舵機(jī)這叫位置式單環(huán)。我們第二年改成了串級(jí)結(jié)構(gòu)外環(huán)用圖像偏差計(jì)算“期望角速度”內(nèi)環(huán)再用陀螺儀實(shí)時(shí)角速度做反饋輸出 PWM 給舵機(jī)。為什么輸出角速度因?yàn)橹苯铀?PWM 有一個(gè)問(wèn)題同一份 PWM車速不同時(shí)轉(zhuǎn)向角速度完全不同。低速時(shí) 50% PWM 可能只轉(zhuǎn) 10°/s高速時(shí)可能轉(zhuǎn) 30°/s。如果外環(huán)期望的是角速度那么內(nèi)環(huán)就會(huì)自動(dòng)補(bǔ)償車速帶來(lái)的變化整車轉(zhuǎn)向特性更接近線性。內(nèi)環(huán)頻率要足夠高。我們控制周期 1ms陀螺儀數(shù)據(jù)用 SPI 讀取經(jīng)過(guò)零漂校準(zhǔn)和低通濾波后計(jì)算的角速度非常平滑。外環(huán)頻率 20ms因?yàn)閿z像頭采集一幀圖像加處理的時(shí)間在 10~20ms跑低頻沒(méi)有問(wèn)題。這個(gè)結(jié)構(gòu)在直道入彎和彎道出坡時(shí)表現(xiàn)尤其穩(wěn)不會(huì)出現(xiàn)“同一個(gè)偏差值時(shí)靈時(shí)不靈”的情況。5.2 攝像頭信號(hào)與單片機(jī)的中斷配合攝像頭組里硬件和軟件的交界線就在信號(hào)同步那里。我們用的數(shù)字灰度攝像頭輸出場(chǎng)中斷、行中斷、像素時(shí)鐘和 8bit 數(shù)據(jù)。主控用 DCMI 接口采集但行中斷需要注意時(shí)序。電路設(shè)計(jì)上攝像頭排線要短數(shù)據(jù)線盡量等長(zhǎng)并且用接插件固定不然車震動(dòng)時(shí)會(huì)傳輸錯(cuò)誤數(shù)據(jù)。我額外加了一路施密特觸發(fā)器對(duì)場(chǎng)中斷信號(hào)整形避免長(zhǎng)線上沿不陡導(dǎo)致中斷觸發(fā)抖動(dòng)。前期沒(méi)有這個(gè)整形圖像偶爾會(huì)上下跳動(dòng)換了施密特緩沖器之后一場(chǎng)比賽跑下來(lái)再也沒(méi)有出現(xiàn)圖像撕裂。圖像數(shù)據(jù)處理方面我們做了動(dòng)態(tài)閾值二值化而不是固定閾值。因?yàn)橘惖涝诓煌瑹艄庀缕骄叶炔詈艽蠊潭ㄩ撝禃?huì)在過(guò)暗時(shí)把賽道和背景混在一起。二值化后提取每一行賽道邊界和中心線偏差這個(gè)偏差就是外環(huán) PID 的輸入。5.3 聯(lián)合調(diào)試中的幾個(gè)真實(shí)翻車點(diǎn)聯(lián)調(diào)時(shí)最經(jīng)典的翻車是軟件顯示偏差巨大但實(shí)際車走得很正。看著上位機(jī)控方向盤跟蹤最終發(fā)現(xiàn)是攝像頭安裝角度偏了機(jī)械基準(zhǔn)和圖像中心差了兩個(gè)像素軟件再怎么調(diào) PID 都沒(méi)用。另一個(gè)翻車點(diǎn)在內(nèi)環(huán)參數(shù)。角速度環(huán)的 P 太大時(shí)車會(huì)走蛇形P 太小時(shí)轉(zhuǎn)向響應(yīng)慢入彎推頭。尤其換新輪胎后同樣的參數(shù)手感完全不同。我寫了一個(gè)簡(jiǎn)單腳本在調(diào)試模式下給舵機(jī)一個(gè)階躍角速度指令記錄車模實(shí)際角速度響應(yīng)曲線從曲線上讀延遲和超調(diào)代替“盲調(diào)”。還有一個(gè)我特別想強(qiáng)調(diào)的編碼器測(cè)速受電源干擾時(shí)會(huì)跳動(dòng)帶著跳動(dòng)會(huì)讓速度環(huán)產(chǎn)生高頻振蕩。我們后來(lái)給編碼器供電加了電感濾波再用 10ms 窗口求平均輪速數(shù)據(jù)才終于平滑。這個(gè)問(wèn)題的排查鏈路是速度環(huán)嘯叫 - 看速度波形有毛刺 - 用示波器抓編碼器 VCC 有 50mV 紋波 - 加 LC 濾波 - 解決。所以遇到軟件行為異常第一件事永遠(yuǎn)是查電源不是查代碼。6. 開源目錄的打開方式復(fù)現(xiàn)、避坑與擴(kuò)展6.1 目錄結(jié)構(gòu)與文件對(duì)應(yīng)關(guān)系整理開源目錄時(shí)我費(fèi)了很大勁才把文檔和工程文件對(duì)應(yīng)清楚。如果你下載下來(lái)后覺(jué)得“文件好多不知道從哪開始”可以參考我的閱讀順序。第一步看doc/00_start_here.md這是一篇 2000 字左右的導(dǎo)讀把整車架構(gòu)、供電樹、信號(hào)流和數(shù)據(jù)流畫成了表格說(shuō)明。第二步看hardware/block_diagram.pdf這是我手畫的整板模塊劃分圖里面有每一塊電路之間的電氣連接關(guān)系。第三步對(duì)照hardware/BOM.csv核對(duì)元器件。我在 BOM 里寫了替代料列表比如某顆電阻可以用哪個(gè)封裝的相近阻值替代。第四步打開firmware/README.md里面寫清楚了每個(gè)外設(shè)驅(qū)動(dòng)的初始化和接線引腳對(duì)應(yīng)關(guān)系。必須承認(rèn)我們的工程不是一塵不染的整齊代碼。firmware 里有些驅(qū)動(dòng)文件是賽季中改的注釋不全但 README 里記錄了每個(gè)文件的“最后一次修改原因”。比如有一行寫著“ov7725.c最后改動(dòng)解決行中斷抖動(dòng)加入邊沿濾波”這就是一條很好的索引線索。6.2 復(fù)現(xiàn)時(shí)必須注意的元器件與布局細(xì)節(jié)復(fù)現(xiàn)我們的硬件時(shí)最不建議做的就是“隨手換料”。原理圖里有些電阻值是經(jīng)過(guò)波形實(shí)測(cè)確定的比如運(yùn)放反饋電阻 10k 搭配輸入電阻 4.7k看著像隨便取值但這是把帶寬、噪聲、穩(wěn)定性綜合考慮后的結(jié)果。你換成 100k 和 47k放大倍數(shù)一樣但運(yùn)放輸入偏置電流帶來(lái)的失調(diào)會(huì)變大輸出零點(diǎn)可能偏到 ADC 量程外面。布局方面建議嚴(yán)格參考我們的 PCB 工程。我在關(guān)鍵位置做了絲印注釋比如“功率地單點(diǎn)連接點(diǎn)”、“自舉電容靠近芯片”這些不是裝飾。兩層板下如果不按這個(gè)布局寄生電感會(huì)讓開關(guān)節(jié)點(diǎn)產(chǎn)生振鈴輕則噪聲大重則在壞溫度下打壞驅(qū)動(dòng)芯片。焊接順序也有講究。先焊電源部分確認(rèn) Buck 輸出正常再焊主控再焊驅(qū)動(dòng)。千萬(wàn)別一次性全焊完再上電否則短路都不知道是哪個(gè)模塊燒的。團(tuán)隊(duì)后勤把“分模塊上電”寫進(jìn)了實(shí)驗(yàn)規(guī)范后面的故障排查效率高了很多。6.3 下一屆可以繼續(xù)做深的方向開源不是終點(diǎn)。我們留下的這套目錄只代表 21 賽季的一種最優(yōu)解很多方向還有明顯的提升空間。首先是電源效率。我們的 Buck 方案用了同步降壓控制器但還有進(jìn)一步提升的空間比如負(fù)載點(diǎn)電源設(shè)計(jì)把 3.3V 分成數(shù)字 3.3V 和模擬 3.3V中間用磁珠隔離能進(jìn)一步降低 ADC 噪聲。其次是驅(qū)動(dòng)電路的智能保護(hù)。我們現(xiàn)在只有硬件過(guò)流保護(hù)沒(méi)有實(shí)時(shí)的電流閉環(huán)。下一屆可以考慮在 MOSFET 源極加采樣電阻用運(yùn)放放大后送 ADC軟件做限流。這樣電機(jī)堵轉(zhuǎn)時(shí)不會(huì)硬頂而是自動(dòng)降功率。然后是 485 調(diào)試鏈路可以做無(wú)線化。雖然沒(méi)有必要把整車數(shù)據(jù)無(wú)線化但在現(xiàn)場(chǎng)調(diào)車時(shí)一根調(diào)試線繞著賽道走真的很痛苦。用常見(jiàn)無(wú)線模塊轉(zhuǎn)發(fā) 485 數(shù)據(jù)或者直接走無(wú)線串口會(huì)舒服很多。最后是控制算法層面?,F(xiàn)在串級(jí) PID 已經(jīng)很穩(wěn)定但未來(lái)可以引入模型預(yù)測(cè)或者模糊自適應(yīng)參數(shù)。前提是先對(duì)車的動(dòng)力學(xué)模型做離線辨識(shí)不然一堆高級(jí)算法不如把內(nèi)環(huán)帶寬調(diào)到位更有效。整理開源目錄本身也讓我重新看了一遍自己畫的每一張?jiān)韴D、寫的每一段驅(qū)動(dòng)。有些當(dāng)時(shí)靠“試出來(lái)”的參數(shù)這回通過(guò)計(jì)算和推導(dǎo)終于理解了為什么會(huì)是這個(gè)值。這就是開源最大的收獲不只是給別人看更是逼著自己把閉環(huán)過(guò)程想明白。如果你也正在打智能車或者準(zhǔn)備在未來(lái)做一個(gè)開源硬件項(xiàng)目我特別建議一邊做項(xiàng)目一邊寫文檔不要等到比賽結(jié)束再補(bǔ)。當(dāng)時(shí)的直覺(jué)、波形和翻車原因過(guò)兩個(gè)月回頭看已經(jīng)模糊了大半而記錄下來(lái)的那部分才是真正能被下一支 soberup 繼承的財(cái)富。