STM32巡线小车是学习嵌入式控制和PID算法的经典项目。本文以STM32F103C8T6(蓝色魔法板)为例,做一台高速巡线小车。
一、硬件准备
主控:STM32F103C8T6最小系统板 × 1
下载器:ST-Link V2 或 USB转TTL串口模块
巡线传感器:5路红外巡线模块(TCRT5000)× 1
驱动:L298N 或 TB6612FNG电机驱动
电机:带编码器的直流减速电机 × 2(编码器用于测速,做闭环控制)
底盘:2WD小车底盘
电源:7.4V(2S)锂电池
二、5路巡线传感器原理
5路红外传感器排成一条直线,每个传感器检测到黑线时输出低电平(或高电平,取决于模块设计)。常见的传感器排列方式和对应数值:
传感器位置从左到右编号 1 2 3 4 5
当小车完全在黑线上方时,只有3号(中间)传感器检测到黑线,输出值为 00100。
当小车偏左时,左侧传感器检测到黑线,如 11000。
我们可以将5位二进制加权计算出一个位置偏差值:
偏差 = (-2×S1 + -1×S2 + 0×S3 + 1×S4 + 2×S5) / (S1+S2+S3+S4+S5)
偏差范围 -2 ~ +2,0表示居中。
三、PID巡线算法实现
// PID巡线核心代码(Keil MDK工程片段)
#include "stm32f10x.h"
#include "delay.h"
// PID参数(需要根据实际情况整定)
float Kp = 0.5; // 比例系数
float Ki = 0.01; // 积分系数
float Kd = 0.1; // 微分系数
// 读5路传感器值
uint8_t ReadSensors(void) {
return (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) << 0) |
(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) << 1) |
(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2) << 2) |
(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_3) << 3) |
(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) << 4);
}
// 计算偏差
float CalcError(uint8_t sensorVal) {
uint8_t s[5];
float error = 0;
float sum = 0;
for(int i=0; i<5; i++) {
s[i] = (sensorVal >> i) & 0x01;
}
error = (-2*s[0] + -1*s[1] + 0*s[2] + 1*s[3] + 2*s[4]);
sum = s[0]+s[1]+s[2]+s[3]+s[4];
if(sum == 0) return 0; // 没检测到线
return error / sum;
}
// PID控制器
float lastError = 0;
float integral = 0;
int PID_Control(float error) {
float proportional = error;
integral += error;
float derivative = error - lastError;
lastError = error;
return (int)(Kp*proportional + Ki*integral + Kd*derivative);
}
// 主循环
int baseSpeed = 60; // 基础速度 0-100
void main(void) {
while(1) {
uint8_t sensors = ReadSensors();
float error = CalcError(sensors);
int correction = PID_Control(error);
int leftSpeed = baseSpeed + correction;
int rightSpeed = baseSpeed - correction;
// 限幅
if(leftSpeed > 100) leftSpeed = 100;
if(leftSpeed < -100) leftSpeed = -100;
if(rightSpeed > 100) rightSpeed = 100;
if(rightSpeed < -100) rightSpeed = -100;
SetMotorSpeed(LEFT, leftSpeed);
SetMotorSpeed(RIGHT, rightSpeed);
delay_ms(10);
}
}
四、PID参数整定方法
1. 先将Ki和Kd设为0,只调Kp。从小到大增加Kp直到小车在线路上开始震荡。
2. Kp调到刚好震荡后稍微减小一点(取临界值的60%~80%)。
3. 加入Kd微分项,消除震荡,让小车走线更平滑。Kd通常取Kp的10%~20%。
4. 最后加一点点Ki积分项(Kp的1%~5%),消除直线段的稳态误差。
实际调试中,推荐串口输出偏差值和PID输出值,用曲线图观察效果。
五、常见问题
Q:小车在直线上左右摆动?
A:Kp太大或Kd太小。减小Kp或增大Kd。
Q:小车过弯时冲出轨道?
A:基础速度太高或者PID响应不够快。降低基础速度或增大Kp。
Q:传感器读数不稳定?
A:传感器高度调整到离地面约5-10mm。反光强的地面可能需要调节传感器上的电位器调灵敏度。

微信联系
淘宝联系