動(dòng)TT馬達(dá):從PWM配置到差速小車實(shí)戰(zhàn)指南)
1. 從點(diǎn)燈到轉(zhuǎn)輪為什么STM32小車的入門任務(wù)都選TT馬達(dá)我到現(xiàn)在還記得第一次用STM32把TT馬達(dá)轉(zhuǎn)起來(lái)的那個(gè)晚上和之前點(diǎn)燈的體驗(yàn)完全不一樣。點(diǎn)LED只是GPIO拉個(gè)電平本質(zhì)還在“數(shù)字世界”里打轉(zhuǎn)當(dāng)TT馬達(dá)接入電路、輪子真正開(kāi)始旋轉(zhuǎn)之后你開(kāi)始面對(duì)電流、功率、機(jī)械扭矩、電源噪聲這些和現(xiàn)實(shí)物理強(qiáng)相關(guān)的問(wèn)題。STM32 控制 TT 馬達(dá)直流電機(jī)之所以被看作嵌入式入門“第二課”不是因?yàn)樗?jiǎn)單而是因?yàn)樗鼊偤貌仍谶壿嬇c物理的交界線上把你學(xué)的定時(shí)器、PWM、GPIO、中斷全部激活。這篇文章我會(huì)從電機(jī)本體、驅(qū)動(dòng)電路、接線規(guī)范、CubeMX配置、HAL庫(kù)代碼、經(jīng)典故障排查一路講到差速小車擴(kuò)展中間穿插大量實(shí)測(cè)中踩過(guò)的坑。適合已經(jīng)跑通開(kāi)發(fā)環(huán)境、準(zhǔn)備做小車底盤的同學(xué)也適合正在被“電機(jī)一轉(zhuǎn)單片機(jī)就復(fù)位”折磨的玩家對(duì)照排查。1.1 TT馬達(dá)到底是個(gè)什么東西減速箱、額定參數(shù)與堵轉(zhuǎn)電流TT馬達(dá)這個(gè)名稱并不是嚴(yán)格意義上的工業(yè)型號(hào)而是國(guó)內(nèi)電子市場(chǎng)上的一種通用叫法。它通常由三部分構(gòu)成一個(gè)空心杯有刷直流電機(jī)、一組塑料齒輪減速箱、一根3mm輸出軸。因?yàn)闇p速比不同市面常見(jiàn)規(guī)格有1:48、1:90、1:120等數(shù)值越大輸出轉(zhuǎn)速越低、扭矩越大。我做項(xiàng)目時(shí)最常用的是1:48版本空載轉(zhuǎn)速大約200到300rpm之間搭配直徑65mm輪子做桌面小車正合適。參數(shù)表里最需要盯住的是電流數(shù)據(jù)很多新手恰恰栽在這上面參數(shù)典型值額定電壓3V ~ 6V空載轉(zhuǎn)速90rpm ~ 320rpm由減速比決定空載電流100mA ~ 250mA堵轉(zhuǎn)電流0.8A ~ 2A輸出軸3mmD形或圓軸一片STM32的GPIO引腳輸出能力通常只有幾到十幾毫安。而電機(jī)空載時(shí)就要100mA以上堵轉(zhuǎn)時(shí)電流能瞬間沖到1A甚至更高。這已經(jīng)不是一個(gè)“夠不夠”的問(wèn)題而是“GPIO根不是用來(lái)做功率輸出”的問(wèn)題。所以我一直強(qiáng)調(diào)控制TT馬達(dá)的實(shí)質(zhì)不是讓單片機(jī)去推電機(jī)而是讓單片機(jī)去控制一路“比它大得多的功率通路”這個(gè)通路就是后面的驅(qū)動(dòng)電路。1.2 有刷直流電機(jī)的控制本質(zhì)通斷、方向與占空比先把有刷直流電機(jī)的控制模型建立起來(lái)。它本質(zhì)上就是一個(gè)直流負(fù)載給它正向電壓就正轉(zhuǎn)反向電壓就反轉(zhuǎn)不給電壓就靠慣性滑行。所謂控制拆解下來(lái)只有三件事要不要通電、電流方向往哪走、一個(gè)周期里通電時(shí)間占多少。方向由H橋電路負(fù)責(zé)轉(zhuǎn)速由PWM波的占空比負(fù)責(zé)。很多初學(xué)者把“調(diào)速”想復(fù)雜了以為要輸出一個(gè)“可變的直流電壓”。實(shí)際上STM32輸出的PWM波是用高低電平的占空比去等效平均電壓。占空比50%平均電壓就是電源電壓的一半轉(zhuǎn)速大約也是空載轉(zhuǎn)速的一半左右。這個(gè)理解一旦建立后面寫代碼時(shí)你操作的每個(gè)寄存器就都有了明確意義設(shè)置比較值就是設(shè)置占空比拉高或拉低兩個(gè)方向引腳就是改變電流方向兩根引腳同時(shí)拉高或同時(shí)拉低則是剎車或滑行。記住這個(gè)映射關(guān)系你會(huì)少走很多彎路。2. 驅(qū)動(dòng)電路選型H橋與驅(qū)動(dòng)芯片誰(shuí)才是TT馬達(dá)的正確搭檔直接給結(jié)論TT馬達(dá)必須經(jīng)過(guò)驅(qū)動(dòng)電路不能直連STM32。市面上常見(jiàn)的驅(qū)動(dòng)方案有三類L298N模塊、TB6612模塊、DRV8833模塊另外還有自制分立H橋。很多人第一反應(yīng)是“L298N最經(jīng)典就選它”我也確實(shí)走過(guò)這條路但實(shí)測(cè)下來(lái)它并不是TT馬達(dá)的最好選擇。下面把每條路都拆開(kāi)聊透。2.1 GPIFO不能直接驅(qū)動(dòng)電機(jī)的根本原因除了輸出電流能力不足之外另一個(gè)被忽略的問(wèn)題是電機(jī)感性負(fù)載帶來(lái)的反電動(dòng)勢(shì)。TT馬達(dá)內(nèi)部有線圈電流突變時(shí)會(huì)產(chǎn)生反向電動(dòng)勢(shì)如果不做續(xù)流處理這個(gè)尖峰電壓可以沖到幾十伏直接擊穿單片機(jī)的引腳保護(hù)二極管。驅(qū)動(dòng)芯片內(nèi)部集成了續(xù)流二極管或MOSFET體二極管能在PWM關(guān)斷期間給感性電流提供泄放回路這是“驅(qū)動(dòng)電路能保護(hù)單片機(jī)”的第二個(gè)關(guān)鍵能力。如果你選用的是沒(méi)有集成續(xù)流橋的L298N裸板或自制H橋那么外部必須額外并接續(xù)流二極管通常采用快恢復(fù)二極管或肖特基二極管。很多模塊板上已經(jīng)畫好了二極管但廉價(jià)模塊有時(shí)會(huì)為了省成本省掉買回來(lái)先對(duì)著原理圖驗(yàn)證一下這點(diǎn)很值得養(yǎng)成習(xí)慣。2.2 TB6612、L298N、DRV8833三款模塊實(shí)測(cè)對(duì)比我也在同一個(gè)TT馬達(dá)上分別接過(guò)了這三款模塊差別真的能明顯感覺(jué)到。L298N用的是雙極性晶體管導(dǎo)通時(shí)內(nèi)部壓降大約1.5V到2V。TT馬達(dá)額定電壓本來(lái)就只有3V到6V如果給5V電源L298N自己先吃掉2V電機(jī)實(shí)際分到的電壓可能只有3V多轉(zhuǎn)速會(huì)明顯偏低而且模塊發(fā)燙嚴(yán)重。L298N更適合6V到12V電壓區(qū)間的中型直流電機(jī)對(duì)TT馬達(dá)來(lái)說(shuō)有些“殺雞用牛刀”性能卻不占優(yōu)。TB6612FNG是我現(xiàn)在最推薦給純新手的一款。它內(nèi)部是MOSFET H橋?qū)▔航敌〉枚嚯姍C(jī)電壓范圍2.7V到13.5V最大持續(xù)電流1.2A峰值3.2A夠TT馬達(dá)在堵轉(zhuǎn)邊緣使用。模塊引腳也簡(jiǎn)單VM、VCC、GND、PWMA、AIN1、AIN2、STBY接線清爽邏輯電壓支持3.3V能直接和STM32 GPIO對(duì)接。DRV8833則更適合追求低電壓和低壓降的場(chǎng)景。它工作電壓2.7V到10.8V每通道1.5A導(dǎo)通電阻非常低單節(jié)鋰電池3.7V供電時(shí)表現(xiàn)尤其是它好。它還帶有輸出電流限制功能對(duì)防止小學(xué)生級(jí)別的“以為轉(zhuǎn)不動(dòng)就用手去捏”這類短路場(chǎng)景有奇效。如果你計(jì)劃做一個(gè)手持設(shè)備或迷你小車DRV8833的板子尺寸比TB6612還要小一圈。三款模塊的選型結(jié)論其實(shí)很簡(jiǎn)單默認(rèn)選TB6612如果你只有3.7V單節(jié)電池且在意外形尺寸選DRV8833L298N留給你以后做中型機(jī)器人時(shí)再用。我不建議新手一上來(lái)就囤L298N不是因?yàn)樗鼔亩撬膲航岛腕w積會(huì)讓調(diào)試體驗(yàn)下降不少。2.3 自制H橋 vs 模塊什么階段才值得自己搭很多教程會(huì)教人用兩個(gè)三極管或四個(gè)MOSFET搭H橋這種精神值得鼓勵(lì)但不適合作為“第一個(gè)TB6612都沒(méi)玩熟”階段的方案。自制H橋涉及P溝道和N溝道MOSFET的搭配、柵極驅(qū)動(dòng)電壓是否夠高、死區(qū)時(shí)間控制、續(xù)流二極管布局等復(fù)雜問(wèn)題。如果只是想讓TT馬達(dá)轉(zhuǎn)起來(lái)模塊的集成度和穩(wěn)定性遠(yuǎn)比自制方案高。我自己的路線是先用TB6612把電機(jī)控制整個(gè)流程跑通之后再回去補(bǔ)H橋原理和PCB設(shè)計(jì)那樣基礎(chǔ)會(huì)更扎實(shí)也不至于一開(kāi)始就受挫。3. 接線與供電電機(jī)和單片機(jī)要“分居”但地線必須連在一起接線部分看似簡(jiǎn)單其實(shí)是翻車率最高的一關(guān)。很多同學(xué)一接上程序點(diǎn)擊下載電機(jī)沒(méi)轉(zhuǎn)電腦卻彈出“no stm32 target found”第一反應(yīng)以為是調(diào)試器壞了、驅(qū)動(dòng)沒(méi)裝好真正的原因往往是供電系統(tǒng)出了問(wèn)題。這部分我把接線原則和細(xì)節(jié)一次講清楚。3.1 電機(jī)電源、邏輯電源要分離但GND必須共地先說(shuō)核心原則電機(jī)電源和STM32邏輯電源最好分開(kāi)供電但兩塊電源的GND必須連在一起。為什么電機(jī)啟動(dòng)和堵轉(zhuǎn)時(shí)會(huì)讓電源電壓劇烈波動(dòng)如果單片機(jī)的供電線直接和電機(jī)電源走同一條線路瞬間的壓降可能導(dǎo)致STM32斷電復(fù)位。分開(kāi)供電后單片機(jī)和電機(jī)各自有穩(wěn)定電源噪聲就不容易串過(guò)去。但共地同樣不能省。PWM控制信號(hào)屬于邏輯信號(hào)它的“0”和“1”參考的是單片機(jī)的GND而驅(qū)動(dòng)芯片內(nèi)部判斷邏輯電平參考的是模塊的GND。如果兩套地不連通GPIO輸出的3.3V高電平在驅(qū)動(dòng)芯片看來(lái)可能是懸空的邏輯完全亂掉。所以接線順序應(yīng)該是電池/電源正極接到驅(qū)動(dòng)模塊的VM電機(jī)電源端單片機(jī)開(kāi)發(fā)板的5V或3.3V單獨(dú)接到驅(qū)動(dòng)模塊的VCC邏輯電源端電池負(fù)極和開(kāi)發(fā)板的GND一起接到驅(qū)動(dòng)模塊的GNDSTBY引腳接3.3V或5V讓它脫離待機(jī)。3.2 一套完整的TB6612接線表直接抄作業(yè)我舉個(gè)例子。假設(shè)你手里是一塊STM32F103C8T6核心板加上一塊TB6612FNG模塊按照下面的引腳對(duì)應(yīng)關(guān)系接線TB6612引腳接到STM32或電源VM電機(jī)電源正極建議3V ~ 6VVCC3.3V也可接5V邏輯電平有區(qū)別GND電源負(fù)極與STM32的GNDPWMAPA0TIM2_CH1AIN1PA1AIN2PA2STBY3.3V或STM32 GPIO拉高AO1/AO2電機(jī)一的兩根線保險(xiǎn)起見(jiàn)電機(jī)電源并聯(lián)一個(gè)100uF到470uF的電解電容位置越靠近VM引腳越好。這個(gè)電容的作用是吸收堵轉(zhuǎn)瞬間的電流沖擊防止電壓塌陷。我實(shí)測(cè)過(guò)很多次加了電容后系統(tǒng)穩(wěn)定性提升非常明顯尤其是使用普通電池盒時(shí)這個(gè)電容幾乎是必需品。也有些封裝模塊已經(jīng)帶了比較大的穩(wěn)壓電容你看一下板子背面如果沒(méi)有自己補(bǔ)焊一個(gè)最穩(wěn)妥。3.3 電源選型別讓TT馬達(dá)超壓或憋屈TT馬達(dá)額定電壓在3V到6V之間超過(guò)6V不是不能轉(zhuǎn)但長(zhǎng)時(shí)間低速堵轉(zhuǎn)時(shí)發(fā)熱嚴(yán)重很容易燒壞線圈。常見(jiàn)供電方案有三種兩節(jié)AA電池共3V轉(zhuǎn)速偏平穩(wěn)適合桌面小車一節(jié)18650電池3.7V理論上可以但需要確認(rèn)電池能輸出足夠的瞬時(shí)電流兩節(jié)18650串聯(lián)7.4V則明顯超壓不能直接接到電機(jī)的VM端。我在調(diào)試時(shí)發(fā)現(xiàn)一個(gè)項(xiàng)項(xiàng)目常用的做法是動(dòng)力系統(tǒng)用電池直接供電給驅(qū)動(dòng)模塊STM32則通過(guò)獨(dú)立的AMS1117穩(wěn)壓板從同一電池降壓到3.3V。這樣做既保持了電機(jī)電源波動(dòng)不影響單片機(jī)又能用一個(gè)電池給整機(jī)供電市面上的智能小車底盤大多是這個(gè)架構(gòu)。4. STM32軟件實(shí)現(xiàn)CubeMX定時(shí)器PWM與方向GPIO的全套配置軟件部分我以STM32F103C8T6加HAL庫(kù)為例這套流程在F407、F722上幾乎一樣只是引腳編號(hào)和定時(shí)器通道會(huì)有變化。標(biāo)準(zhǔn)庫(kù)用戶也別覺(jué)得被落下原理完全互通只需要把末尾我給的函數(shù)名對(duì)應(yīng)替換成標(biāo)準(zhǔn)庫(kù)寫法即可。4.1 定時(shí)器PWM頻率怎么算PSC、ARR和死區(qū)的關(guān)系PWM頻率由定時(shí)器時(shí)鐘、預(yù)分頻器PSC和自動(dòng)重裝載值A(chǔ)RR共同決定。公式是PWM頻率 定時(shí)器時(shí)鐘 ÷ ((PSC 1) × (ARR 1))定時(shí)器時(shí)鐘按72MHz計(jì)算。如果PSC3ARR999那么頻率 72MHz ÷ ((31)×(9991)) 18kHz占空比分辨率是1000級(jí)。這個(gè)配置我實(shí)測(cè)下來(lái)比較推薦頻率超過(guò)人耳敏感區(qū)的上限聽(tīng)不到高頻嘯叫1000級(jí)分辨率也足夠平滑。如果把PSC改成71、ARR保持999頻率就會(huì)降到約1kHz占空比仍然有1000級(jí)但這時(shí)候電機(jī)運(yùn)轉(zhuǎn)時(shí)你會(huì)聽(tīng)到非常明顯的“吱吱”聲那是PWM的開(kāi)關(guān)頻率落在音頻范圍內(nèi)線圈鐵芯在磁場(chǎng)變化下發(fā)出機(jī)械振動(dòng)。頻率并不是越高越好頻率越高M(jìn)OSFET和電機(jī)的開(kāi)關(guān)損耗都會(huì)增加頻率太低電流紋波變大低速扭矩會(huì)明顯不穩(wěn)。18kHz對(duì)TT馬達(dá)來(lái)說(shuō)是一個(gè)甜點(diǎn)區(qū)間大家可以直接抄這個(gè)配置。CubeMX里的操作流程是選擇對(duì)應(yīng)定時(shí)器比如TIM2把Channel1設(shè)置為PWM Generation CH1然后在參數(shù)配置里把Prescaler設(shè)為3、Counter Period設(shè)為999Pulse初始值可以留一個(gè)占空比如500。注意檢查時(shí)鐘樹(shù)是否已經(jīng)是72MHz很多工程的HSE配置不同實(shí)際頻率對(duì)不上會(huì)讓計(jì)算失真。4.2 可復(fù)用的驅(qū)動(dòng)函數(shù)封裝正轉(zhuǎn)、反轉(zhuǎn)、剎車、滑行PWM配置完成之后接下去把方向控制函數(shù)封裝起來(lái)。PCB上我把PWMA接到了PA0對(duì)應(yīng)的TIM2_CH1AIN1接PA1AIN2接PA2?;诖送暾尿?qū)動(dòng)函數(shù)代碼如下// 啟動(dòng)PWM輸出占空比由CCR寄存器控制 HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); // 設(shè)置速度speed取值范圍0~1000 void Motor_SetSpeed(uint16_t speed) { __HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, speed); } // 正轉(zhuǎn) void Motor_Forward(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); } // 反轉(zhuǎn) void Motor_Reverse(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); } // 剎車快速停轉(zhuǎn) void Motor_Brake(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1 | GPIO_PIN_2, GPIO_PIN_SET); } // 滑行斷電依靠慣性 void Motor_Coast(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1 | GPIO_PIN_2, GPIO_PIN_RESET); }方向邏輯需要結(jié)合TB6612FNG的真值表來(lái)理解AIN1AIN2電機(jī)狀態(tài)01正轉(zhuǎn)10反轉(zhuǎn)11剎車短接制動(dòng)00滑行不驅(qū)動(dòng)使用時(shí)先調(diào)用Motor_Forward()設(shè)置方向再調(diào)用Motor_SetSpeed()給一個(gè)速度值電機(jī)就會(huì)轉(zhuǎn)動(dòng)起來(lái)。切換方向時(shí)務(wù)必先調(diào)用Motor_Brake()或Motor_Coast()停一下而不是直接從正轉(zhuǎn)切到反轉(zhuǎn)原因放在下一節(jié)講。如果你用的是標(biāo)準(zhǔn)庫(kù)函數(shù)對(duì)應(yīng)關(guān)系也就是TIM_SetCompare1(TIM2, speed)以及GPIO_WriteBit之類的調(diào)用邏輯完全一致可以參考著替換。4.3 換向時(shí)為什么必須先剎車再反接直接從一個(gè)方向切到另一個(gè)方向最直觀的后果是電源電流瞬間沖擊很大。因?yàn)殡姍C(jī)有慣性轉(zhuǎn)子的反電動(dòng)勢(shì)方向還在維持原轉(zhuǎn)向此時(shí)強(qiáng)行反向通電相當(dāng)于把一臺(tái)正在全速轉(zhuǎn)動(dòng)的電機(jī)瞬間變成發(fā)電機(jī)并短路電流會(huì)極致地沖到堵轉(zhuǎn)值以上。對(duì)TT馬達(dá)來(lái)說(shuō)這會(huì)加劇減速箱齒輪的沖擊對(duì)驅(qū)動(dòng)模塊來(lái)說(shuō)則是一次電流高峰有可能觸發(fā)模塊過(guò)流保護(hù)還可能把電源電壓打出一個(gè)深坑導(dǎo)致MCU復(fù)位。我習(xí)慣在換向函數(shù)里強(qiáng)制加一個(gè)5到20ms的剎車窗口。比如要做反轉(zhuǎn)先拉高兩個(gè)IN引腳讓電機(jī)短接制動(dòng)等轉(zhuǎn)速真正降下來(lái)再設(shè)置反轉(zhuǎn)方向的GPIO并恢復(fù)PWM。這個(gè)操作在紙面上只是多幾行代碼但實(shí)測(cè)下來(lái)模塊的溫度和成功切換的果斷程度都有明顯改善。不要讓電機(jī)“硬擰”著反轉(zhuǎn)這是寫驅(qū)動(dòng)函數(shù)時(shí)最容易忽略的細(xì)節(jié)。5. 實(shí)測(cè)高頻故障排查電機(jī)一轉(zhuǎn)MCU復(fù)位、下載失敗這些坑的根因軟件和硬件都接通之后接下去的調(diào)試階段才是真正的試煉場(chǎng)。我把這幾年踩過(guò)以及幫朋友排查過(guò)的高頻問(wèn)題總結(jié)成四個(gè)方向每個(gè)都給出排查鏈路和最終處理辦法。5.1 電機(jī)一轉(zhuǎn)STM32立刻復(fù)位下載報(bào)“no stm32 target found”這個(gè)故障的典型表現(xiàn)是程序里只要啟動(dòng)電機(jī)開(kāi)發(fā)板上的LED閃一下隨后板子掉電、程序從新開(kāi)始跑或者你在下載程序時(shí)根本識(shí)別不到芯片調(diào)試器報(bào)“no stm32 target found”。很多人第一反應(yīng)是驅(qū)動(dòng)板或者電機(jī)短路但我遇見(jiàn)的絕大多數(shù)情況是電源問(wèn)題。電機(jī)啟動(dòng)瞬間的電流抽走了電源線上的電壓STM32的VDD跌到復(fù)位閾值以下芯片瞬間重啟SWD調(diào)試鏈路也隨之?dāng)嚅_(kāi)。排查鏈路是這樣的先斷開(kāi)電機(jī)電源單獨(dú)給單片機(jī)供電并下載程序確認(rèn)下載器沒(méi)問(wèn)題再用獨(dú)立電源給電機(jī)供電并把兩塊電源的地連好最后在驅(qū)動(dòng)模塊VM端并聯(lián)一個(gè)大電解電容同時(shí)在STM32的3.3V引腳靠近處并聯(lián)100nF陶瓷電容。做完這三步絕大多數(shù)復(fù)位問(wèn)題會(huì)消失。如果仍然出現(xiàn)“no stm32 target found”還有一種容易忽略的情況你把電機(jī)的兩根線接在了STM32的3.3V和GND上測(cè)試導(dǎo)致芯片瞬間過(guò)流或引腳損壞。這不是驅(qū)動(dòng)問(wèn)題是硬件連接問(wèn)題所以我再次強(qiáng)調(diào)驅(qū)動(dòng)電路的必要性。5.2 電機(jī)吱吱響PWM頻率選低了電機(jī)運(yùn)轉(zhuǎn)時(shí)發(fā)出高頻刺耳聲響大概率是PWM頻率落在人耳可聽(tīng)范圍。那個(gè)“吱吱”聲并不是電機(jī)壞掉而是定子鐵芯在交變磁場(chǎng)作用下產(chǎn)生的磁致伸縮振動(dòng)頻率等于PWM開(kāi)關(guān)頻率或其諧波。解決方式很直接提高PWM頻率到18kHz以上或者低于可聽(tīng)范圍也可以但通常不好用因?yàn)榈陀趲装俸掌澓笈ぞ夭▌?dòng)會(huì)非常厲害。但是提高頻率會(huì)帶來(lái)一個(gè)副作用頻率越高相同定時(shí)器時(shí)鐘下ARR就越小占空比分辨率就降低。74kHz下100步分辨率和18kHz下1000級(jí)分辨率給人的手感完全不一樣。所以更合理的做法是保持PWM頻率在17kHz到20kHz之間通過(guò)調(diào)小PSC來(lái)盡量提高分辨率。我在前面給出的PSC3、ARR999就是一個(gè)兼顧兩頭的配置。5.3 低速時(shí)轉(zhuǎn)速忽快忽慢“占空比死區(qū)”現(xiàn)象轉(zhuǎn)速調(diào)低以后電機(jī)出現(xiàn)斷斷續(xù)續(xù)或者完全停轉(zhuǎn)的現(xiàn)象這是有刷電機(jī)的死區(qū)效應(yīng)。當(dāng)占空比很低時(shí)平均電壓不足以克服電刷接觸電阻和齒槽轉(zhuǎn)矩電機(jī)表現(xiàn)為不轉(zhuǎn)或抖動(dòng)。在這個(gè)區(qū)域里占空比微調(diào)1%可能完全沒(méi)反應(yīng)再調(diào)大一點(diǎn)又突然加速給人感覺(jué)“非線性非常強(qiáng)”。處理這個(gè)問(wèn)題的常用手段是軟件死區(qū)處理把0到某個(gè)下限值我常用10%全部映射為停止?fàn)顟B(tài)從10%開(kāi)始才允許PWM實(shí)際輸出同時(shí)在10%附近用線性插值把曲線拉緩。這樣處理之后小車低速行駛時(shí)手感會(huì)平順很多。另外有刷電機(jī)的碳刷磨損也會(huì)讓低速品質(zhì)下降TT馬達(dá)的電機(jī)壽命相對(duì)有限不要長(zhǎng)時(shí)間堵轉(zhuǎn)虐待它。5.4 調(diào)速還是不平滑查一下定時(shí)器的時(shí)鐘配置有些同學(xué)按教程把PSC和ARR一改結(jié)果轉(zhuǎn)速依然一卡一卡。排查思路回到時(shí)鐘樹(shù)CubeMX中如果APB1預(yù)分頻不是1那么掛在APB1上的定時(shí)器時(shí)鐘會(huì)是APB1時(shí)鐘的兩倍很多教程默認(rèn)72MHz但如果你改了外部晶振或HSE配置實(shí)際定時(shí)器時(shí)鐘可能不是72MHz。你用一個(gè)錯(cuò)誤的時(shí)鐘頻率去反推PSC和ARR自然不準(zhǔn)確。遇到這種情況我建議打開(kāi)CubeMX的Clock Configuration頁(yè)面直接看TIM2的時(shí)鐘數(shù)值。也可以用調(diào)試器在線讀RCC時(shí)鐘寄存器的值或者暴力一點(diǎn)輸出一個(gè)已知PWM用示波器或邏輯分析儀實(shí)測(cè)頻率反推實(shí)際時(shí)鐘。沒(méi)有示波器的讀者用一根杜邦線把PWM引腳接到另一個(gè)定時(shí)器的輸入捕獲通道用捕獲模式直接測(cè)出頻率這也是一招很有用的“窮辦法”。6. 從驅(qū)動(dòng)一個(gè)TT馬達(dá)到驅(qū)動(dòng)一臺(tái)兩輪小車編碼器、差速與閉環(huán)的進(jìn)階路線聊完了單電機(jī)的控制細(xì)節(jié)最后把它放到真實(shí)場(chǎng)景里也就是兩輪差速小車。這也是STM32模塊教程里最常見(jiàn)的最終目標(biāo)。當(dāng)你把第一顆電機(jī)調(diào)順之后第二顆電機(jī)的加入會(huì)帶來(lái)一個(gè)嶄新的問(wèn)題兩個(gè)電機(jī)的轉(zhuǎn)速先天就存在差異開(kāi)環(huán)跑不直。你想讓它走直線它卻總往一邊偏這幾乎是每個(gè)小車愛(ài)好者都經(jīng)歷過(guò)的“幽靈跑偏”。6.1 兩路PWM加方向GPIO如何拼出差速轉(zhuǎn)向驅(qū)動(dòng)兩個(gè)電機(jī)只需要在驅(qū)動(dòng)模塊上再?gòu)?fù)用一組通道TB6612的另一路PWMB、BIN1、BIN2正好對(duì)應(yīng)第二個(gè)電機(jī)。初始化時(shí)再開(kāi)一個(gè)定時(shí)器通道比如TIM2_CH2然后對(duì)左右輪分別設(shè)置速度值。差速轉(zhuǎn)向的邏輯很簡(jiǎn)單左輪速度大于右輪車體右轉(zhuǎn)右輪速度大于左輪車體左轉(zhuǎn)一正一反就能原地旋轉(zhuǎn)。差速大小決定了轉(zhuǎn)彎半徑兩者速度相同才是直行。但這個(gè)“直行”只有在理論中成立?,F(xiàn)實(shí)中因?yàn)閮蓚€(gè)電機(jī)的繞組差異、輪胎半徑差、地面阻力不一致即使兩個(gè)PWM占空比完全相同轉(zhuǎn)速也會(huì)存在幾個(gè)百分點(diǎn)的偏差。想讓它自動(dòng)跑成直線光靠開(kāi)環(huán)PWM是不夠的這才有了閉環(huán)控制的必要。6.2 帶霍爾編碼器的TT馬達(dá)測(cè)速原理與PID閉環(huán)的下一步我建議下一步直接換成帶霍爾編碼器的TT馬達(dá)也就是市面上常見(jiàn)的“黃皮編碼器減速電機(jī)”。它內(nèi)部在電機(jī)轉(zhuǎn)軸上裝了霍爾傳感器和磁性碼盤能夠輸出A、B兩相脈沖通過(guò)STM32的外部中斷或定時(shí)器編碼器模式就能測(cè)出實(shí)際轉(zhuǎn)速。A、B兩相之間有90度相位差不僅能測(cè)速還能通過(guò)誰(shuí)先跳變判斷轉(zhuǎn)向這就是正交編碼器的優(yōu)勢(shì)。測(cè)速代碼的思路非常簡(jiǎn)單對(duì)每個(gè)上升沿觸發(fā)一次外部中斷在一個(gè)固定時(shí)間窗口內(nèi)統(tǒng)計(jì)脈沖數(shù)再結(jié)合減速比和每圈脈沖數(shù)換算成rpm。有了實(shí)時(shí)轉(zhuǎn)速之后就可以用增量式PID對(duì)左右輪做閉環(huán)控制。具體來(lái)說(shuō)設(shè)定一個(gè)目標(biāo)轉(zhuǎn)速PID根據(jù)實(shí)際轉(zhuǎn)速和目標(biāo)的誤差調(diào)整PWM占空比讓兩個(gè)輪子始終跟蹤各自的目標(biāo)。到了這一步車跑直就再也不是“調(diào)參數(shù)碰運(yùn)氣”而是變成了一套可控的反饋系統(tǒng)。我在實(shí)際做小車時(shí)的習(xí)慣是先在桌面把單個(gè)電機(jī)的測(cè)速和PID調(diào)好再把左右輪合起來(lái)做差速閉環(huán)。一次只增加一個(gè)變量出問(wèn)題時(shí)也更容易定位。比如先驗(yàn)證編碼器計(jì)數(shù)是否準(zhǔn)確再用手動(dòng)給定占空比觀察轉(zhuǎn)速是否穩(wěn)定最后才進(jìn)入PID整定避免比例、積分、微分三個(gè)參數(shù)和硬件問(wèn)題攪在一起。這里也常出現(xiàn)新的坑比如編碼器模塊上還有VCC、GND、A、B之外的引腳注意它們是否和電機(jī)端子共地不接共地的話A相脈沖會(huì)完全讀不到。最后再分享一個(gè)我調(diào)試小車時(shí)的習(xí)慣永遠(yuǎn)在代碼里保留一個(gè)“測(cè)試模式”上電后先用固定占空比轉(zhuǎn)動(dòng)電機(jī)再在串口打印實(shí)時(shí)的編碼器脈沖數(shù)。這套自檢流程在每次改裝完車架、換電池之后都能幫你快速判斷是硬件原因還是代碼原因省下來(lái)的時(shí)間非??捎^。TT馬達(dá)本身不復(fù)雜但把它真正調(diào)順這個(gè)過(guò)程值得你多花心思慢慢磨。