基于STM32與MPU6050的自平衡小車(chē):從PID控制到姿態(tài)解算的嵌入式實(shí)踐
1. 項(xiàng)目概述從零到一打造你的第一臺(tái)自平衡小車(chē)幾年前我第一次接觸平衡車(chē)項(xiàng)目時(shí)被那種“違反直覺(jué)”的穩(wěn)定感深深吸引。一個(gè)看似隨時(shí)會(huì)倒下的兩輪結(jié)構(gòu)竟然能通過(guò)電機(jī)和算法的配合穩(wěn)穩(wěn)立住甚至載人行駛。這背后是微控制器實(shí)時(shí)處理傳感器數(shù)據(jù)、快速做出決策并驅(qū)動(dòng)執(zhí)行機(jī)構(gòu)的經(jīng)典閉環(huán)控制案例。對(duì)于電子、嵌入式或自動(dòng)化領(lǐng)域的學(xué)習(xí)者來(lái)說(shuō)親手做一臺(tái)平衡車(chē)是理解PID控制、姿態(tài)解算、電機(jī)驅(qū)動(dòng)等核心概念的絕佳實(shí)踐。這個(gè)項(xiàng)目的主角是STM32和MPU6050。STM32作為意法半導(dǎo)體的主流ARM Cortex-M系列微控制器以其豐富的外設(shè)、強(qiáng)大的性能和活躍的社區(qū)生態(tài)成為眾多電子愛(ài)好者和工程師的首選。而MPU6050則是一款集成了三軸陀螺儀和三軸加速度計(jì)的六軸運(yùn)動(dòng)處理傳感器價(jià)格親民數(shù)據(jù)接口標(biāo)準(zhǔn)是獲取物體姿態(tài)信息的入門(mén)神器。將兩者結(jié)合我們就能搭建一個(gè)感知自身傾斜角度、并通過(guò)驅(qū)動(dòng)輪子來(lái)對(duì)抗傾斜、維持平衡的智能系統(tǒng)。整個(gè)制作過(guò)程你會(huì)經(jīng)歷硬件選型與焊接、傳感器數(shù)據(jù)采集與濾波、姿態(tài)角解算、PID控制器設(shè)計(jì)與調(diào)試、電機(jī)驅(qū)動(dòng)與PWM控制等多個(gè)環(huán)節(jié)。這不僅僅是焊幾根線(xiàn)、寫(xiě)幾行代碼那么簡(jiǎn)單它要求你對(duì)系統(tǒng)有一個(gè)整體的認(rèn)識(shí)并理解每個(gè)環(huán)節(jié)如何影響最終“站不站得穩(wěn)”這個(gè)結(jié)果。無(wú)論你是在校學(xué)生想做一個(gè)亮眼的畢業(yè)設(shè)計(jì)還是工程師想夯實(shí)自己的嵌入式控制功底亦或是純粹的硬件DIY愛(ài)好者這個(gè)項(xiàng)目都能帶給你滿(mǎn)滿(mǎn)的成就感和技術(shù)提升。2. 核心硬件選型與電路設(shè)計(jì)思路硬件是系統(tǒng)的骨架穩(wěn)定的硬件平臺(tái)是算法得以流暢運(yùn)行的基礎(chǔ)。在開(kāi)始焊接之前我們需要對(duì)每個(gè)模塊的選型理由和連接方式有清晰的認(rèn)識(shí)。2.1 主控芯片為什么是STM32在眾多單片機(jī)中我選擇了STM32F103C8T6也就是常說(shuō)的“藍(lán)色藥丸”核心板。這個(gè)選擇基于幾個(gè)現(xiàn)實(shí)的考量。首先它基于Cortex-M3內(nèi)核主頻72MHz對(duì)于需要每秒數(shù)百次循環(huán)讀取傳感器、計(jì)算PID并更新電機(jī)輸出的平衡車(chē)應(yīng)用來(lái)說(shuō)性能完全夠用且游刃有余。其次它擁有足夠多的定時(shí)器資源來(lái)生成多路高精度的PWM波驅(qū)動(dòng)電機(jī)同時(shí)其SPI和I2C接口方便與MPU6050通信。最重要的是它的生態(tài)極其豐富標(biāo)準(zhǔn)庫(kù)、HAL庫(kù)、LL庫(kù)以及各種第三方教程和開(kāi)源項(xiàng)目俯拾皆是極大降低了學(xué)習(xí)和調(diào)試的門(mén)檻。注意STM32F103系列有多個(gè)型號(hào)如C8T664K Flash20K RAM和RCT6256K Flash48K RAM。對(duì)于平衡車(chē)項(xiàng)目C8T6的資源已經(jīng)足夠。購(gòu)買(mǎi)時(shí)請(qǐng)認(rèn)準(zhǔn)正版芯片或信譽(yù)好的店鋪市面上有些劣質(zhì)仿冒芯片可能導(dǎo)致程序運(yùn)行不穩(wěn)定。2.2 姿態(tài)傳感器MPU6050的潛力與局限MPU6050是這個(gè)項(xiàng)目的“眼睛”。它通過(guò)I2C接口與主控通信實(shí)時(shí)提供三個(gè)軸的角速度陀螺儀和加速度數(shù)據(jù)。陀螺儀測(cè)量的是旋轉(zhuǎn)的角速度積分后可以得到角度變化但存在累積誤差漂移加速度計(jì)測(cè)量的是包括重力在內(nèi)的各軸加速度在靜止或勻速運(yùn)動(dòng)時(shí)可以通過(guò)反三角函數(shù)計(jì)算出相對(duì)于重力方向的傾斜角但對(duì)運(yùn)動(dòng)引起的加速度非常敏感動(dòng)態(tài)下誤差大。因此單一使用任一種數(shù)據(jù)都無(wú)法獲得穩(wěn)定、準(zhǔn)確的姿態(tài)角。這就需要我們進(jìn)行“傳感器融合”。MPU6050內(nèi)部自帶一個(gè)數(shù)字運(yùn)動(dòng)處理器DMP可以運(yùn)行官方的傳感器融合算法直接輸出解算好的四元數(shù)或歐拉角這大大簡(jiǎn)化了我們的工作。如果不用DMP我們也可以在STM32上實(shí)現(xiàn)互補(bǔ)濾波或卡爾曼濾波算法來(lái)融合數(shù)據(jù)。對(duì)于初學(xué)者強(qiáng)烈建議先從使用DMP開(kāi)始快速獲得穩(wěn)定角度數(shù)據(jù)把精力集中在控制算法上。2.3 動(dòng)力與執(zhí)行機(jī)構(gòu)電機(jī)、驅(qū)動(dòng)與電源平衡車(chē)的“手腳”是電機(jī)和驅(qū)動(dòng)電路。我推薦使用帶有減速箱的直流編碼電機(jī)。減速箱可以增大扭矩讓小車(chē)有足夠的力量對(duì)抗傾斜。而編碼器則用于測(cè)量電機(jī)的實(shí)際轉(zhuǎn)速為后續(xù)的速度環(huán)PID控制提供反饋是實(shí)現(xiàn)平穩(wěn)移動(dòng)和轉(zhuǎn)向的關(guān)鍵。電機(jī)驅(qū)動(dòng)芯片我選用的是TB6612FNG。相比傳統(tǒng)的L298NTB6612效率更高、發(fā)熱更小、體積更小巧并且支持大電流連續(xù)1.2A峰值3.2A。它只需要兩個(gè)PWM信號(hào)和一個(gè)方向信號(hào)就能控制一個(gè)電機(jī)的正反轉(zhuǎn)和速度接口非常簡(jiǎn)潔。電源部分至關(guān)重要且容易被忽視。整個(gè)系統(tǒng)包括STM323.3V、MPU60503.3V、TB6612邏輯部分3.3-5V電機(jī)部分需更高電壓和電機(jī)。一個(gè)常見(jiàn)的方案是使用一塊7.4V或11.1V的鋰電池作為總電源然后通過(guò)一個(gè)DC-DC降壓模塊如LM2596產(chǎn)生一個(gè)穩(wěn)定的5V電壓再通過(guò)AMS1117-3.3等LDO芯片為STM32和傳感器提供3.3V。TB6612的電機(jī)驅(qū)動(dòng)電壓VM直接接電池電壓以獲得最大驅(qū)動(dòng)力。2.4 電路連接與布局心得具體的引腳連接需要根據(jù)你的核心板型號(hào)來(lái)定但思路是通用的。以下是一個(gè)基于STM32F103C8T6的參考連接表模塊引腳/接口連接到STM32備注MPU6050VCC3.3V絕對(duì)不要接5VGNDGNDSCLPB6 (或其它I2C1 SCL)需配置為上拉模式SDAPB7 (或其它I2C1 SDA)需配置為上拉模式INT可選如PA0用于DMP中斷讀取TB6612 (左電機(jī))PWMAPA8 (TIM1_CH1)生成PWM波AIN1PB12方向控制1AIN2PB13方向控制2STBY接高電平(3.3V/5V)使能芯片AO1, AO2接左電機(jī)兩極VM接電池正極(如7.4V)電機(jī)驅(qū)動(dòng)電源VCC接5V邏輯電源GND接電源地TB6612 (右電機(jī))PWMBPA11 (TIM1_CH4)BIN1PB14BIN2PB15BO1, BO2接右電機(jī)兩極電機(jī)編碼器 (每路)VCC5V注意編碼器工作電壓GNDGNDA相如PA0, PA1 (配置為編碼器模式)接到定時(shí)器的CH1, CH2B相如PA6, PA7 (配置為編碼器模式)實(shí)操心得1布線(xiàn)時(shí)電機(jī)驅(qū)動(dòng)線(xiàn)連接TB6612 AO/BO到電機(jī)的線(xiàn)要盡量粗、短并且最好與信號(hào)線(xiàn)如I2C、編碼器線(xiàn)分開(kāi)走避免電機(jī)大電流開(kāi)關(guān)產(chǎn)生的噪聲干擾敏感的傳感器和編碼器信號(hào)。電源入口處記得并聯(lián)一個(gè)容量較大的電解電容如470uF/16V來(lái)緩沖電機(jī)啟動(dòng)時(shí)的電流沖擊。3. 軟件架構(gòu)與核心算法解析硬件搭建好后大腦軟件的設(shè)計(jì)決定了小車(chē)的“智商”。平衡車(chē)的軟件核心是一個(gè)多層閉環(huán)控制系統(tǒng)我們需要從底層到上層逐一實(shí)現(xiàn)。3.1 系統(tǒng)軟件框架設(shè)計(jì)一個(gè)穩(wěn)定可靠的平衡車(chē)程序通常采用“前后臺(tái)”或基于實(shí)時(shí)操作系統(tǒng)如FreeRTOS的結(jié)構(gòu)。對(duì)于初學(xué)者一個(gè)清晰的前后臺(tái)循環(huán)配合定時(shí)中斷就能很好地工作。我建議的軟件框架如下初始化層配置系統(tǒng)時(shí)鐘、GPIO、中斷、定時(shí)器、PWM、I2C、編碼器接口等所有外設(shè)。數(shù)據(jù)采集層在定時(shí)中斷如1ms一次中通過(guò)I2C讀取MPU6050的DMP數(shù)據(jù)解算出當(dāng)前車(chē)體的俯仰角Pitch和角速度。在另一個(gè)定時(shí)中斷或主循環(huán)中讀取編碼器數(shù)值計(jì)算電機(jī)的實(shí)際轉(zhuǎn)速。控制算法層這是核心。在一個(gè)固定的控制周期如5ms中斷中執(zhí)行控制算法。最內(nèi)環(huán)是直立環(huán)角度環(huán)根據(jù)目標(biāo)角度通常為0度即豎直和當(dāng)前角度偏差通過(guò)PID計(jì)算出一個(gè)基礎(chǔ)電機(jī)輸出值目的是讓車(chē)體保持直立。中間環(huán)是速度環(huán)根據(jù)目標(biāo)速度通常為0即靜止和編碼器測(cè)得的速度偏差通過(guò)另一個(gè)PID計(jì)算出一個(gè)補(bǔ)償值。這個(gè)補(bǔ)償值會(huì)疊加到直立環(huán)的輸出上目的是消除直立環(huán)的靜差讓小車(chē)能在靜止時(shí)真正站穩(wěn)而不是緩慢移動(dòng)。最外環(huán)是轉(zhuǎn)向環(huán)根據(jù)遙控器指令或自動(dòng)巡線(xiàn)等需求計(jì)算出左右電機(jī)的速度差實(shí)現(xiàn)轉(zhuǎn)向。輸出執(zhí)行層將最終計(jì)算出的左右電機(jī)PWM占空比和方向?qū)懭雽?duì)應(yīng)的定時(shí)器寄存器驅(qū)動(dòng)電機(jī)轉(zhuǎn)動(dòng)。通信與調(diào)試層通過(guò)串口將關(guān)鍵數(shù)據(jù)如角度、角速度、PWM值、PID參數(shù)發(fā)送到電腦上位機(jī)如匿名科創(chuàng)地面站、SerialPlot等方便實(shí)時(shí)觀察波形和調(diào)試參數(shù)。3.2 姿態(tài)解算獲取準(zhǔn)確的傾斜角如前所述使用MPU6050的DMP庫(kù)是最快最穩(wěn)的方式。你需要從官方或開(kāi)源社區(qū)獲取inv_mpu.c、inv_mpu_dmp_motion_driver.c等文件并移植到你的工程中。移植的關(guān)鍵是實(shí)現(xiàn)i2c_write和i2c_read函數(shù)以及提供準(zhǔn)確的延時(shí)函數(shù)。成功初始化DMP后你可以設(shè)置其輸出頻率如100Hz然后在中斷中調(diào)用dmp_read_fifo函數(shù)來(lái)獲取解算好的四元數(shù)。再將四元數(shù)轉(zhuǎn)換為歐拉角我們主要關(guān)心俯仰角pitch。// 示例從DMP讀取數(shù)據(jù)并計(jì)算Pitch角部分代碼 if (dmp_read_fifo(gyro, accel, quat, sensor_timestamp, sensors, more)) { // 讀取失敗處理 } if (sensors INV_WXYZ_QUAT) { // 將四元數(shù)轉(zhuǎn)換為歐拉角單位度 float q0 quat[0] / q30; // q30是DMP輸出數(shù)據(jù)的縮放因子 float q1 quat[1] / q30; float q2 quat[2] / q30; float q3 quat[3] / q30; // 計(jì)算俯仰角Pitch (繞Y軸旋轉(zhuǎn)) pitch asin(-2 * q1 * q3 2 * q0 * q2) * 57.3f; // 57.3是弧度轉(zhuǎn)度數(shù)的系數(shù) }實(shí)操心得2DMP輸出的數(shù)據(jù)穩(wěn)定性很高但上電后需要幾秒鐘的初始化時(shí)間。在程序開(kāi)始時(shí)確保小車(chē)靜止放置讓DMP完成自檢和校準(zhǔn)。此外安裝MPU6050時(shí)要確保其芯片平面與小車(chē)的主平面平行否則解算出的角度基準(zhǔn)會(huì)不對(duì)需要在你計(jì)算的pitch角上加上一個(gè)固定的安裝誤差補(bǔ)償值。3.3 控制核心PID算法的理解與實(shí)現(xiàn)PID控制器是平衡車(chē)的靈魂。它根據(jù)設(shè)定值Setpoint和實(shí)際值Feedback的偏差Error通過(guò)比例P、積分I、微分D三個(gè)環(huán)節(jié)的運(yùn)算得到控制輸出Output。比例P與當(dāng)前偏差成正比。P越大糾正偏差的力度越大響應(yīng)越快但過(guò)大會(huì)引起振蕩。積分I與偏差的累積和成正比。用于消除靜態(tài)誤差比如小車(chē)總是緩慢朝一個(gè)方向走但過(guò)大會(huì)導(dǎo)致系統(tǒng)反應(yīng)遲鈍和超調(diào)。微分D與偏差的變化率成正比。具有預(yù)見(jiàn)性能抑制振蕩提高穩(wěn)定性但對(duì)噪聲敏感。在平衡車(chē)中我們通常使用兩個(gè)串聯(lián)的PID直立環(huán)角度環(huán)和速度環(huán)。直立環(huán)是基礎(chǔ)它讓小車(chē)有站起來(lái)的趨勢(shì)速度環(huán)是修正它讓小車(chē)站住后不會(huì)偷偷溜走。typedef struct { float Target; // 目標(biāo)值 float Feedback; // 反饋值 float Kp, Ki, Kd; // PID參數(shù) float Error; // 當(dāng)前誤差 float LastError; // 上次誤差 float Integral; // 積分項(xiàng) float Output; // 輸出值 float IntegralLimit; // 積分限幅 float OutputLimit; // 輸出限幅 } PID_TypeDef; float PID_Calculate(PID_TypeDef *pid) { pid-Error pid-Target - pid-Feedback; // 比例項(xiàng) float p_out pid-Kp * pid-Error; // 積分項(xiàng)抗飽和處理 pid-Integral pid-Error; if (pid-Integral pid-IntegralLimit) pid-Integral pid-IntegralLimit; if (pid-Integral -pid-IntegralLimit) pid-Integral -pid-IntegralLimit; float i_out pid-Ki * pid-Integral; // 微分項(xiàng)常用不完全微分或?qū)Ψ答佒滴⒎?float d_out pid-Kd * (pid-Error - pid-LastError); pid-LastError pid-Error; // 總和并限幅 pid-Output p_out i_out d_out; if (pid-Output pid-OutputLimit) pid-Output pid-OutputLimit; if (pid-Output -pid-OutputLimit) pid-Output -pid-OutputLimit; return pid-Output; }直立環(huán)PIDTarget設(shè)為0度Feedback就是MPU6050解算出的pitch角。其輸出直接決定電機(jī)的力度和方向。速度環(huán)PIDTarget設(shè)為0期望靜止Feedback由編碼器測(cè)得的電機(jī)轉(zhuǎn)速經(jīng)過(guò)處理得到如左右輪速度的平均值。速度環(huán)的輸出不是直接給電機(jī)而是疊加到直立環(huán)的目標(biāo)值上或者作為一個(gè)修正量加到直立環(huán)的輸出上。這是一種“串級(jí)PID”的變體速度環(huán)的輸出改變了直立環(huán)的平衡點(diǎn)從而讓小車(chē)通過(guò)微微前傾或后仰來(lái)加速或減速最終使速度趨于零。4. 分步實(shí)現(xiàn)與調(diào)試全記錄理論需要實(shí)踐來(lái)驗(yàn)證。下面我們一步步完成從工程創(chuàng)建到小車(chē)站立的整個(gè)過(guò)程。4.1 工程創(chuàng)建與基礎(chǔ)外設(shè)驅(qū)動(dòng)首先使用STM32CubeMX工具初始化項(xiàng)目非常高效。選擇你的芯片型號(hào)STM32F103C8Tx在圖形化界面中配置SYS: Debug選擇Serial Wire用于ST-Link下載調(diào)試。RCC: HSE選擇Crystal/Ceramic Resonator如果你的板子有外部晶振。時(shí)鐘樹(shù): 將HCLK設(shè)置為72MHz。GPIO: 配置TB6612的方向控制引腳如PB12, PB13, PB14, PB15為輸出模式。定時(shí)器:配置TIM1的CH1和CH4為PWM Generation模式用于驅(qū)動(dòng)兩個(gè)電機(jī)。預(yù)分頻和自動(dòng)重載值設(shè)置為產(chǎn)生頻率在10-20kHz的PWM超出人耳聽(tīng)覺(jué)范圍電機(jī)噪音小。配置TIM2和/或TIM3為Encoder Interface模式用于讀取左右電機(jī)的編碼器。配置一個(gè)基本定時(shí)器如TIM4用于產(chǎn)生系統(tǒng)時(shí)基例如1ms中斷。I2C: 配置I2C1為標(biāo)準(zhǔn)模式100kHz或快速模式400kHz用于連接MPU6050。USART: 配置一個(gè)串口如USART1用于打印調(diào)試信息波特率115200。生成代碼后在Keil或STM32CubeIDE中打開(kāi)項(xiàng)目。首先確?;A(chǔ)功能正常編寫(xiě)測(cè)試代碼讓LED閃爍用邏輯分析儀或示波器檢查PWM波形是否正確讀取編碼器值是否隨電機(jī)轉(zhuǎn)動(dòng)變化通過(guò)I2C掃描函數(shù)確認(rèn)能檢測(cè)到MPU6050的地址0x68或0x69。4.2 MPU6050 DMP庫(kù)的移植與角度讀取這是關(guān)鍵一步。將DMP庫(kù)文件添加到你的工程并實(shí)現(xiàn)i2c_write和i2c_read函數(shù)通常直接調(diào)用HAL庫(kù)的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read。按照庫(kù)提供的示例流程進(jìn)行初始化初始化I2C。復(fù)位MPU6050。設(shè)置陀螺儀和加速度計(jì)量程例如陀螺儀±2000°/s加速度計(jì)±2g。加載DMP固件。配置DMP輸出速率如100Hz并啟用所需輸出如四元數(shù)。使能DMP。成功初始化后在定時(shí)中斷如1ms中調(diào)用讀取函數(shù)并計(jì)算pitch角。通過(guò)串口將pitch角實(shí)時(shí)發(fā)送到上位機(jī)軟件觀察波形。用手緩慢傾斜小車(chē)模塊看角度變化是否平滑、響應(yīng)是否及時(shí)。靜止時(shí)角度曲線(xiàn)應(yīng)是一條平穩(wěn)的直線(xiàn)噪聲越小越好。4.3 直立環(huán)PID的單獨(dú)調(diào)試在調(diào)試PID之前務(wù)必確保機(jī)械結(jié)構(gòu)牢固電池電量充足并將小車(chē)車(chē)輪懸空用架子架起來(lái)防止調(diào)試時(shí)小車(chē)突然失控沖出。首先只調(diào)試直立環(huán)。將速度環(huán)和轉(zhuǎn)向環(huán)的輸出置零。參數(shù)初始化將直立環(huán)PID的參數(shù)Kp,Ki,Kd全部設(shè)為0。速度環(huán)目標(biāo)Target設(shè)為0。先調(diào)P比例逐漸增大Kp。你會(huì)發(fā)現(xiàn)當(dāng)Kp小到一定程度時(shí)用手推動(dòng)車(chē)輪車(chē)輪會(huì)緩慢地朝你推的反方向轉(zhuǎn)動(dòng)試圖“抵抗”你的推動(dòng)但力度很弱。繼續(xù)增大Kp這個(gè)抵抗的力度和速度會(huì)變強(qiáng)。找到一個(gè)臨界點(diǎn)當(dāng)Kp增大到某個(gè)值時(shí)你一推車(chē)輪車(chē)輪會(huì)快速地來(lái)回振蕩幾次才停下。這個(gè)值就是臨界Kp。將最終使用的Kp設(shè)為這個(gè)臨界值的50%-70%。例如臨界Kp是120那么可以先設(shè)定Kp60。再調(diào)D微分微分項(xiàng)能抑制振蕩。在已有Kp的基礎(chǔ)上逐漸加入正的Kd。你會(huì)發(fā)現(xiàn)車(chē)輪的響應(yīng)變得更“沉穩(wěn)”用手快速撥動(dòng)時(shí)振蕩會(huì)明顯減弱。Kd能提高系統(tǒng)的阻尼。但Kd過(guò)大會(huì)導(dǎo)致系統(tǒng)反應(yīng)遲鈍。通常Kd的值在Kp的十分之一到幾十分之一之間試探。最后調(diào)I積分在平衡車(chē)直立環(huán)中積分項(xiàng)Ki通常很小甚至可以為0。因?yàn)槲覀兊哪繕?biāo)角度是0且傳感器有噪聲積分容易累積誤差導(dǎo)致系統(tǒng)不穩(wěn)定??梢韵仍O(shè)為0。調(diào)試時(shí)通過(guò)串口實(shí)時(shí)繪制pitch角、pitch角速度、直立環(huán)輸出Output的波形至關(guān)重要。觀察當(dāng)你給小車(chē)一個(gè)擾動(dòng)用手輕推時(shí)這些量的變化是否迅速且平穩(wěn)。4.4 加入速度環(huán)與參數(shù)整定當(dāng)直立環(huán)能讓小車(chē)在懸空時(shí)有明顯的“平衡反應(yīng)”后可以嘗試將小車(chē)放在地上做好保護(hù)防止跑飛。此時(shí)只有直立環(huán)的小車(chē)可能會(huì)朝一個(gè)方向加速跑出去直到倒下因?yàn)樗鼪](méi)有“想停下來(lái)”的意愿。此時(shí)加入速度環(huán)。速度環(huán)的Feedback是編碼器測(cè)得的轉(zhuǎn)速單位可以是編碼器計(jì)數(shù)/控制周期。速度環(huán)的Target設(shè)為0。速度環(huán)的Output不是直接給電機(jī)而是加到直立環(huán)的Target上。即直立環(huán)目標(biāo)角度 0 速度環(huán)輸出值這樣當(dāng)小車(chē)因?yàn)槲⑿∑铋_(kāi)始移動(dòng)時(shí)編碼器測(cè)到速度速度環(huán)輸出一個(gè)值這個(gè)值會(huì)改變直立環(huán)的平衡點(diǎn)。比如小車(chē)向前移動(dòng)速度環(huán)輸出一個(gè)負(fù)值使得直立環(huán)的目標(biāo)角度變成微微向后傾小車(chē)就會(huì)向后加速以糾正向前的速度最終達(dá)到靜止平衡。速度環(huán)的調(diào)試同樣遵循PID順序先調(diào)P從小開(kāi)始慢慢增大。目標(biāo)是讓小車(chē)在受到輕微推力后能自己慢慢回到原點(diǎn)停下而不是持續(xù)振蕩或跑飛。速度環(huán)的P通常比直立環(huán)的P小很多。再調(diào)I速度環(huán)的I項(xiàng)很重要用于消除靜態(tài)誤差。如果調(diào)好P后小車(chē)總是停不住有恒定的速度就需要加入I。I值也要從小加起過(guò)大會(huì)引起低頻振蕩。D項(xiàng)速度環(huán)的D項(xiàng)一般不加因?yàn)榫幋a器速度信號(hào)噪聲較大微分會(huì)放大噪聲。這個(gè)過(guò)程需要極大的耐心。一個(gè)實(shí)用的技巧是“階躍響應(yīng)法”用手將小車(chē)抬離地面然后突然放下觀察小車(chē)的反應(yīng)。理想情況是它輕微晃動(dòng)幾下就穩(wěn)穩(wěn)站住。如果倒下可能是直立環(huán)P不夠或D不夠如果持續(xù)前后擺動(dòng)可能是直立環(huán)P太大或速度環(huán)參數(shù)不合適如果朝一個(gè)方向勻速跑開(kāi)可能是速度環(huán)P太小或I不夠。5. 常見(jiàn)問(wèn)題排查與進(jìn)階優(yōu)化即使按照步驟操作你也一定會(huì)遇到各種問(wèn)題。下面是我在多次制作中踩過(guò)的坑和解決方案。5.1 硬件與基礎(chǔ)驅(qū)動(dòng)問(wèn)題排查現(xiàn)象可能原因排查方法MPU6050無(wú)法初始化/讀取1. I2C線(xiàn)路接觸不良2. 上拉電阻未接或失效通常模塊已集成3. 電源電壓不對(duì)必須3.3V4. I2C地址錯(cuò)誤AD0引腳電平?jīng)Q定1. 用萬(wàn)用表檢查連線(xiàn)。2. 使用I2C掃描程序檢查總線(xiàn)設(shè)備地址。3. 檢查MPU6050的VCC引腳電壓。4. 嘗試地址0x68和0x69。電機(jī)不轉(zhuǎn)或只振動(dòng)1. PWM頻率不對(duì)太低會(huì)聽(tīng)到嘯叫2. TB6612的STBY引腳未使能3. 電機(jī)驅(qū)動(dòng)電源VM電壓不足或電流不夠4. 電機(jī)損壞1. 用示波器或邏輯分析儀查看PWM引腳波形。2. 檢查STBY引腳是否接高電平。3. 檢查電池電量測(cè)量VM電壓。4. 直接給電機(jī)加電測(cè)試。編碼器讀數(shù)不變或亂跳1. 編碼器AB相接反2. 定時(shí)器未配置為編碼器模式3. 編碼器電源電壓不對(duì)4. 信號(hào)線(xiàn)受電機(jī)干擾1. 交換A、B相線(xiàn)序試試。2. 確認(rèn)TIMx的通道1、2配置為Encoder Mode。3. 檢查編碼器VCC電壓通常是5V。4. 編碼器線(xiàn)使用雙絞線(xiàn)或屏蔽線(xiàn)遠(yuǎn)離電機(jī)線(xiàn)。小車(chē)一上電就猛轉(zhuǎn)1. PID參數(shù)極不合理2. 角度傳感器數(shù)據(jù)異常如安裝方向反了3. 電機(jī)輸出極性接反1.務(wù)必懸空調(diào)試先調(diào)小所有PID參數(shù)。2. 通過(guò)串口打印角度值檢查靜止時(shí)是否接近0傾斜方向是否正確。3. 交換電機(jī)的兩根線(xiàn)或交換TB6612的AIN1/AIN2邏輯。5.2 軟件與算法調(diào)試技巧角度數(shù)據(jù)波動(dòng)大首先檢查MPU6050是否安裝牢固避免振動(dòng)。其次可以軟件上對(duì)DMP輸出的角度進(jìn)行低通濾波例如angle_filtered 0.9 * angle_filtered 0.1 * angle_new。但DMP本身已經(jīng)融合了數(shù)據(jù)通常不需要額外濾波。小車(chē)平衡點(diǎn)不在正中可能是機(jī)械重心不在兩輪軸線(xiàn)上??梢酝ㄟ^(guò)在軟件中給直立環(huán)的目標(biāo)角度Target加一個(gè)固定的偏移量來(lái)補(bǔ)償。例如小車(chē)總是向后倒就把Target設(shè)為0.5度前傾。響應(yīng)遲鈍或振蕩這是PID參數(shù)不匹配的典型表現(xiàn)。響應(yīng)遲鈍可能是P太小或D太大振蕩可能是P太大或D太小。使用上位機(jī)觀察波形至關(guān)重要。觀察當(dāng)你施加擾動(dòng)時(shí)角度偏差、輸出PWM的變化曲線(xiàn)。理想的響應(yīng)應(yīng)該是快速上升并平滑地回到零點(diǎn)超調(diào)量小。速度環(huán)引起低頻擺動(dòng)小車(chē)能站住但會(huì)以大約1-2秒的周期緩慢地前后擺動(dòng)。這通常是速度環(huán)的I值過(guò)大引起的。嘗試減小速度環(huán)的Ki或者給速度環(huán)的積分項(xiàng)加上一個(gè)泄漏系數(shù)即每次計(jì)算時(shí)讓積分項(xiàng)乘以一個(gè)略小于1的數(shù)如0.995防止其無(wú)限累積。5.3 從“能站”到“站得穩(wěn)”的進(jìn)階優(yōu)化當(dāng)小車(chē)基本能站立后還可以從以下幾個(gè)方面提升其性能控制周期優(yōu)化確保你的主要控制循環(huán)讀取傳感器、計(jì)算PID、更新電機(jī)在一個(gè)固定的、盡可能短的周期內(nèi)執(zhí)行如2ms或5ms。使用定時(shí)器中斷來(lái)觸發(fā)這個(gè)循環(huán)保證實(shí)時(shí)性。數(shù)據(jù)同步確保在同一個(gè)控制周期內(nèi)使用的角度、角速度、編碼器數(shù)據(jù)是同一時(shí)刻采集的避免使用“過(guò)時(shí)”的數(shù)據(jù)進(jìn)行計(jì)算否則會(huì)引入相位滯后影響穩(wěn)定性。輸出平滑對(duì)最終輸出給電機(jī)的PWM值進(jìn)行限幅和斜坡處理。突然的PWM大幅跳變會(huì)導(dǎo)致電機(jī)扭矩突變引起振動(dòng)??梢韵拗茊蝹€(gè)控制周期內(nèi)PWM的最大變化量。加入“死區(qū)”處理當(dāng)角度偏差和角速度都非常小時(shí)可以令電機(jī)輸出為零。這樣可以避免電機(jī)因微小的噪聲而持續(xù)嗡嗡作響也能節(jié)省電量。電池電壓補(bǔ)償電池電壓下降會(huì)導(dǎo)致電機(jī)在相同PWM下的轉(zhuǎn)速下降??梢詫?shí)時(shí)監(jiān)測(cè)電池電壓并對(duì)輸出的PWM值進(jìn)行比例補(bǔ)償使小車(chē)性能在不同電量下保持一致。最后機(jī)械結(jié)構(gòu)的對(duì)稱(chēng)性、重心的高低、輪胎的抓地力都會(huì)極大影響最終效果。一個(gè)重心低、結(jié)構(gòu)緊湊、輪子摩擦力適中的小車(chē)調(diào)試起來(lái)會(huì)事半功倍。這個(gè)項(xiàng)目最大的魅力在于它完美地體現(xiàn)了“軟硬結(jié)合”的思想。每一個(gè)參數(shù)的調(diào)整都能直觀地反映在小車(chē)的動(dòng)態(tài)行為上。當(dāng)你經(jīng)過(guò)無(wú)數(shù)次調(diào)試看到它終于穩(wěn)穩(wěn)立住的那一刻所有的努力都值了。

相關(guān)新聞

UniAda異構(gòu)計(jì)算框架:自適應(yīng)優(yōu)化原理與實(shí)戰(zhàn)

UniAda異構(gòu)計(jì)算框架:自適應(yīng)優(yōu)化原理與實(shí)戰(zhàn)

1. UniAda項(xiàng)目概述UniAda是一個(gè)面向異構(gòu)計(jì)算環(huán)境的自適應(yīng)優(yōu)化框架,它通過(guò)運(yùn)行時(shí)分析和動(dòng)態(tài)調(diào)優(yōu)技術(shù),實(shí)現(xiàn)了跨平臺(tái)性能的自動(dòng)優(yōu)化。這個(gè)框架特別適合處理需要同時(shí)部署在CPU、GPU和各類(lèi)加速器上的計(jì)算密集型任務(wù)。我在參與多個(gè)異構(gòu)計(jì)算項(xiàng)目時(shí)發(fā)現(xiàn)&#xff…

2026/7/29 7:26:08 閱讀更多
那些年,我們差點(diǎn)被細(xì)節(jié)坑掉的下午

那些年,我們差點(diǎn)被細(xì)節(jié)坑掉的下午

干了小二十年實(shí)驗(yàn)室管理,有個(gè)體會(huì)越來(lái)越深:實(shí)驗(yàn)室出事兒,從來(lái)不是因?yàn)槭裁锤呱罴夹g(shù)沒(méi)搞懂。全是細(xì)節(jié),全是那些你以為“差不多就行”的日常操作。 上個(gè)月翻我們?cè)獧zLIMS里的歷史不符合項(xiàng)統(tǒng)計(jì),我讓質(zhì)量主管拉了個(gè)數(shù)據(jù)——…

2026/7/29 7:16:08 閱讀更多
【C/C++】手寫(xiě) DPDK 協(xié)議棧(四):實(shí)現(xiàn) ICMP Echo Reply,讓 ping 通起來(lái)

【C/C++】手寫(xiě) DPDK 協(xié)議棧(四):實(shí)現(xiàn) ICMP Echo Reply,讓 ping 通起來(lái)

目錄 手寫(xiě) DPDK 協(xié)議棧(四):實(shí)現(xiàn) ICMP Echo Reply,讓 ping 通起來(lái)1. Echo 報(bào)文結(jié)構(gòu)2. 接收并定位協(xié)議頭3. 原地改包與重算校驗(yàn)和4. 實(shí)驗(yàn)結(jié)果小結(jié) 手寫(xiě) DPDK 協(xié)議棧(四):實(shí)現(xiàn) ICMP Echo Reply&am…

2026/7/29 7:16:08 閱讀更多
2026論文翻車(chē)真相[特殊字符]不是你不會(huì)寫(xiě),是工具選錯(cuò)了!okbiye才是隱形通關(guān)密碼?

2026論文翻車(chē)真相[特殊字符]不是你不會(huì)寫(xiě),是工具選錯(cuò)了!okbiye才是隱形通關(guān)密碼?

🌐 官方直達(dá):首頁(yè) - Okbiye智能寫(xiě)作Okbiye免費(fèi)論文查重檢測(cè)-首款免費(fèi)論文檢測(cè)軟件,為畢業(yè)生提供專(zhuān)業(yè)的論文重復(fù)率檢測(cè)、論文降重、Aigc檢測(cè)、智能排版 、論文寫(xiě)作等一站式服務(wù)。https://www.okbiye.com 同樣是寫(xiě)畢業(yè)論文,為什么有的人一次查…

2026/7/29 8:26:10 閱讀更多
布隆過(guò)濾器原理、特性及短信黑名單過(guò)濾業(yè)務(wù)實(shí)現(xiàn)方案

布隆過(guò)濾器原理、特性及短信黑名單過(guò)濾業(yè)務(wù)實(shí)現(xiàn)方案

一、 什么是布隆過(guò)濾器?(作用、組成、添加元素流程、查詢(xún)?cè)氐牧鞒?、特點(diǎn)(誤判、不支持刪除)布隆過(guò)濾器(Bloom Filter)是由Burton Howard Bloom于1970年提出的。我們可以把它看作由位數(shù)組和一組哈希函數(shù)組…

2026/7/29 8:26:10 閱讀更多
HDCP版權(quán)保護(hù)_橋接芯片科普05

HDCP版權(quán)保護(hù)_橋接芯片科普05

HDCP 版權(quán)保護(hù):橋接芯片里最容易被忽視的"隱形門(mén)禁" 龍迅橋接芯片科普系列 第 05 篇 系列文章:01 選型指南 | 02 DSC 顯示流壓縮 | 03 車(chē)載顯示橋接方案 | 04 Type-C 擴(kuò)展塢 | 05 HDCP 版權(quán)保護(hù) | 06 D-PHY vs C-PHY(待寫(xiě)&#xf…

2026/7/29 8:26:10 閱讀更多
3D打印與Arduino結(jié)合:從零打造會(huì)跳舞的仿生機(jī)器人

3D打印與Arduino結(jié)合:從零打造會(huì)跳舞的仿生機(jī)器人

1. 項(xiàng)目概述:當(dāng)3D打印遇上Arduino,一個(gè)會(huì)跳舞的機(jī)器人誕生了 如果你和我一樣,既沉迷于3D打印機(jī)“無(wú)中生有”的魔力,又對(duì)Arduino開(kāi)源硬件控制現(xiàn)實(shí)世界的能力著迷,那么“精舞堂BOB”這個(gè)項(xiàng)目絕對(duì)能讓你兩眼放光。這不僅僅…

2026/7/29 8:26:10 閱讀更多
基于ESP32-S3的3D裸眼風(fēng)扇:從視覺(jué)暫留原理到無(wú)線(xiàn)智能顯示實(shí)戰(zhàn)

基于ESP32-S3的3D裸眼風(fēng)扇:從視覺(jué)暫留原理到無(wú)線(xiàn)智能顯示實(shí)戰(zhàn)

1. 項(xiàng)目概述:從“風(fēng)扇”到“空中畫(huà)師”的蛻變 最近在創(chuàng)客圈和極客社區(qū)里,一個(gè)老項(xiàng)目又火了起來(lái),那就是“3D裸眼風(fēng)扇”。你可能在商場(chǎng)、科技展或者短視頻里見(jiàn)過(guò)它:一個(gè)高速旋轉(zhuǎn)的扇葉上,排列著一圈LED燈,當(dāng)它…

2026/7/29 8:16:09 閱讀更多
面試官大笑:“一個(gè)任務(wù)拆給 5 個(gè) Subagent 并行跑,不比 1 個(gè)快 5 倍?“我搖頭:“快不了,還可能更慢“

面試官大笑:“一個(gè)任務(wù)拆給 5 個(gè) Subagent 并行跑,不比 1 個(gè)快 5 倍?“我搖頭:“快不了,還可能更慢“

前兩個(gè)月,我在重構(gòu) AlgoMooc 網(wǎng)站過(guò)程中,發(fā)現(xiàn)一個(gè)問(wèn)題:在 Claude Code 里把一個(gè)任務(wù)拆給 5 個(gè) Subagent 并行跑,結(jié)果可能比 1 個(gè) agent 從頭干到尾還慢? 大多數(shù)人的第一反應(yīng)是反過(guò)來(lái)的:活是并行干的&#…

2026/7/29 0:15:24 閱讀更多
# 鴻蒙 HarmonyOS 應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號(hào)與動(dòng)畫(huà)渲染精講

# 鴻蒙 HarmonyOS 應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號(hào)與動(dòng)畫(huà)渲染精講

一、應(yīng)用概述 骰子(Dice Roller) 是一款經(jīng)典的休閑娛樂(lè)應(yīng)用,模擬了真實(shí)擲骰子的過(guò)程。應(yīng)用投擲兩個(gè)骰子(六面標(biāo)準(zhǔn)骰),使用 Unicode 骰面符號(hào)直觀展示每個(gè)骰子的點(diǎn)數(shù),并伴有快速滾動(dòng)的動(dòng)畫(huà)效果?!?/p>

2026/7/29 0:15:24 閱讀更多