小车PID算法跑直线

#include<stm32f10x.h>
#include"sys.h"


extern unsigned char Rec_Dat_U1;
extern unsigned char Rec_String_U1[200];
extern int conut_flag_1;


#define in_1(x)    x?GPIO_ResetBits(GPIOC , GPIO_Pin_0): GPIO_SetBits(GPIOC , GPIO_Pin_0)
#define in_2(x)    x?GPIO_ResetBits(GPIOC , GPIO_Pin_1): GPIO_SetBits(GPIOC , GPIO_Pin_1)
#define in_3(x)    x?GPIO_ResetBits(GPIOB , GPIO_Pin_10): GPIO_SetBits(GPIOB , GPIO_Pin_10)
#define in_4(x)    x?GPIO_ResetBits(GPIOB , GPIO_Pin_11): GPIO_SetBits(GPIOB , GPIO_Pin_11)
#define key_1   GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12) 
#define key_2   GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_13) 
#define key_3   GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_14) 
#define key_4   GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_15) 


float  Kp_l =                0.82  ; //比例常数
float  Ti_l =                0.09 ; //微分时间常数
float  Td_l =                0.015 ; //采样周期


float  Kp_r =                0.20  ; 
float  Ti_r =                0.09 ;
float  Td_r =                0.015 ;


#define T                  0.02 
#define Ki_l                Kp_l*(T/Ti_l)        // Kp Ki Kd 
#define Kd_l                Kp_l*(Td_l/T)


#define Ki_r                Kp_l*(T/Ti_l)        // Kp Ki Kd 
#define Kd_r                Kp_l*(Td_l/T)


#define left_b in_1(1); in_2(0);
#define left_f in_1(0); in_2(1);
#define right_f in_3(1); in_4(0);
#define right_b in_1(0); in_2(1);


extern float pwm_l;
extern float pwm_r;


void CAR_GPIO_INIT(void);


int main()
{


// int speed=50;
SYS_CONFIG();
CAR_GPIO_INIT();
pwm_init(TIM3_1);
pwm_init(TIM3_2);
TIM4_PWMINPUT_INIT(0xffff,31);  //1M速度采样率
TIM5_PWMINPUT_INIT(0xffff,31);
incPIDinit();
  PID_set(Kp_l,Ki_l,Kd_l,Kp_r,Ki_r,Kd_r);   
//void PID_set(float pp_1,float ii_1,float dd_1,float pp_2,float ii_2,float dd_2)
  right_f
left_f
// set_pwm_percent(TIM3_1,50) ;
// set_pwm_percent(TIM3_2,50) ;
PID_setpoint(&PID_l, 160);
PID_setpoint(&PID_r, 160);
while(1)
{
printf("%d\r\n",(int)pwm_l);
delay_ms(200);
}
}
void CAR_GPIO_INIT() 
{


  GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD, ENABLE); 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP; 
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);           

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;  
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;  
GPIO_Init(GPIOB, &GPIO_InitStructure);        

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;    
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
GPIO_Init(GPIOC, &GPIO_InitStructure);          

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;  
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
GPIO_Init(GPIOC, &GPIO_InitStructure);         

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;   
GPIO_Init(GPIOD, &GPIO_InitStructure);          

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;  

GPIO_Init(GPIOD, &GPIO_InitStructure);     
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;   
GPIO_Init(GPIOD, &GPIO_InitStructure);          

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;  
GPIO_Init(GPIOD, &GPIO_InitStructure);   
}

 

前言: 开始之前先要说为什么要采用PID算法控制小车。玩过小车的DIY爱好者们都会碰到这样一种情况:为什么本该直线行驶的小车着轨迹就会发生偏移,即所谓的“不直”。 小车不直的原因有:两个电机本身的驱动特性不可能完全相同,两个电机外形大小不可能是完全一致,组装时精度也会出现差异,另外轮胎在滚动时打滑、遇到细小的障碍物等因素都会造成左右轮的速度出现差异,从而不直。开环控制是无法消除左右轮的速度误差的,因为上述的扰动是随机的。 要想小车一条直线,唯有实现闭环控制,当小车受到扰动时能对左右轮及时给予反馈,修正两轮的速度偏差,从而可以出一条直线PID算法就是一种闭环控制算法,实现PID算法需得从硬件上实现闭环控制,即存在反馈,所以我采用的是带测速装置的电机。 项目简介: 本项目采用的是PID控制算法来修正小车时两轮的速度偏差,实现小车可以直线小车是使用一个安卓App来控制小车的行路径,App通过App Inventor2来进行编写。 完成作品图: 需要用到的材料: 1. Arduino Uno 2. Arduino Uno的扩展板 3. DFRobot L298 双路2A直流电机驱动板 4. HC-05或HC-06的蓝牙模块 5. 坦克小车底盘 6. 两个带霍尔传感器的电机 7. 锂电池 8. 杜邦线若干 软件部分: 1. Arduino IDE 2. App Invent 附件内容截图:
### 使用PID控制器使小车保持直行路径 #### 设定目标位置 为了确保小车能够沿着预定的直线路径行驶,需要预先设定好目标位置。此目标位置通常依据规划好的路线来决定[^3]。 #### 获取实际位置数据 实际位置信息可以通过安装于车辆底部的一系列灰度传感器获取。这些传感器负责探测地面颜色变化情况,从而判断当前所处的具体方位以及相对于理想轨迹是否存在偏移现象。 #### 计算偏差值 一旦获得了期望的位置坐标与实时测量所得的数据之后,就可以计算两者之间的差异即误差`e(t)`。该误差反映了当前位置同预期路径间的差距程度,并作为后续调整的基础输入信号传递给PID 控制器处理[^4]。 #### 调整控制参数 对于四轮驱动的小车型号而言,在编写用于维持其沿直线前进逻辑时,可以借鉴两轮自平衡车型的设计思路——采用分段式的PID策略来进行方向修正操作。当处于较宽裕路段时适当降低敏感度;而在接近转弯区域前则应逐步提升响应速度以便更好地适应曲率变化需求[^2]。 #### 实现代码示例 下面给出一段Python伪代码表示如何应用上述理论构建一个简单的基于增量型PID 的自动导航系统: ```python class PidController: def __init__(self, kp=0.1, ki=0.05, kd=0.01): self.kp = kp self.ki = ki self.kd = kd self.last_error = 0 self.integral = 0 def compute(self, setpoint, measured_value): error = setpoint - measured_value derivative = error - self.last_error self.integral += error output = (self.kp * error + self.ki * self.integral + self.kd * derivative) self.last_error = error return output def main(): pid = PidController(kp=1.2, ki=0.002, kd=0.8) while True: target_position = get_target_position() current_position = read_sensor_data() steering_angle = pid.compute(target_position, current_position) adjust_steering(steering_angle) if __name__ == '__main__': main() ```
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道亦无名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值