基于PID算法下STM32控制的坡道行驶电动小车(2020年电赛)

这篇具有很好参考价值的文章主要介绍了基于PID算法下STM32控制的坡道行驶电动小车(2020年电赛)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本题源于2020年TI杯大学生电子设计竞赛C题-----坡道行驶电动小车

由于手上没有MSP430/MSP432 板子,所以本篇采用stm32实现

一、题目设计

任务
利用 TI 的 MSP430/MSP432 平台,设计制作一个四轮电动小车。要求小车能沿着指定路线在坡道上自动循迹骑线行驶。小车必须独立运行,车外不能使用任何设备(包括电源)。小车(含电池)重量小于 1.5kg,外形尺寸在地面投影不大于 25cm×25cm。坡道用长、宽约 1m 的细木工板制作,允许板上有木质本色及自然木纹。木工板表面铺设画有 1cm×1cm 黑白间隔的纸条(以下简称为标记线)作为路线指示;标记线起始段为直线,平行于木板两边;标记线在坡顶转向 90°,转弯半径 20cm;标记线平行坡顶距≥30cm,距坡顶距离≤20cm;标记线总长度为 1m。停车标记为宽 1cm 长 5cm 的黑色线条,垂直于坡顶标记线。小车坡度

角示意及行驶线路顶视图如图 1 所示。
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库

要求

(1) 坡度角 θ=0°,电动小车能够沿标记线自动骑线行驶,在停车点停车; 小车上标记点到停车标记中心线的垂直距离误差≤2cm。停车时立即发出声音提示。小车行驶过程中,其地面投影不得脱离标记线。(15 分)

(2) 在完成(1)的基础上,电动小车能够设定行驶时间,自动控制小车匀速通过 1 米长的线路,在停车点停车。行驶时间可在 10s~20s 间设定。误差绝对值≤1s。行驶过程中不得碾压、脱离标记线。时间误差每超过1s 扣 1 分。 (20 分)

(3) 坡度角 θ=10°,完成要求(2)的动作。 (20 分)

(4) 可任意指定坡度角 θ 在 11°~30°,完成要求(2)的动作。 (20 分)

(5) 在完成(4)后,尽量增加坡度角 θ,完成要求(2)动作。 (20 分)

(6) 其他。 (5 分)

(7) 设计报告: (20 分)

二、硬件选择

1. 主控芯片
采用STM32F103c8t6作为主控芯片
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
2. 电机
采用霍尔编码器电机(4个)
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库

3. 电机驱动
需要采用2个TB6612电机驱动,分别控制左前轮左后轮、右前轮右后轮
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库

4. 轮胎
选用黑色轮胎 海绵内胎,软橡胶外胎,金属轮毂(4个)
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
5. 红外传感器
采用三路循迹模块
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
6. 小车底板
采用铝合金底板
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
7. 电池
采用7.4v 3600mah锂电池
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
8. 面包板
插接导线,搭建电路
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
9. 下载器
采用ST-LINK V2仿真器
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
10. 其余工具零件
若干杜邦线、螺母、铜柱、螺丝刀、剥线钳等
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库

实物图:
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库
电赛坡道小车,STM32的简单应用,stm32,算法,单片机,嵌入式硬件,嵌入式实时数据库

三、软件设计

1. stm32最小系统板
插在面包板上,方便引脚连接。由于stm32最小系统板没有基本定时器,所以最多可采用4个定时器( 1个高级定时器TIM1和3个通用定时器TIM2、TIM3、TIM4 ),在这里需要全部用上。

2. 定时器
TIM1:配置四个电机的PWM输出
左前:PA8 左后:PA9 右前:PA10 右后:PA11

TIM2:配置编码器模式,通道1和通道2分别作为小车左后轮编码器A、B相
PA0、PA1

TIM3:配置编码器模式,通道1和通道2分别作为小车右后轮编码器A、B相
PA6、PA7

TIM4:在中断读取TIM2、TIM3计数器(cnt)的值,设置TIM4每隔5ms溢出一次,每向上计数四次cnt的值加1,并且在中断函数中读取完cnt的值后就清零,那么每次进入TIM4溢出中断时,cnt的值都不会太大,可直接将cnt的值作为小车的当前速度。

3. 三路红外传感器
Vcc和GND连接TB6612模块上的Vcc和GND
红外输出: 左 中 右 分别接线PA2、PA3、PA4
(1) 当左右均未踩到黑线时,小车匀速直行
(2) 当左没踩到,右踩到黑线时,小车右转
(3) 当左踩到,右没踩到黑线时,小车左转
(4) 当左中右都踩到黑线时,小车停止

4. TB6612驱动
逻辑输入:
左前轮 配置为通道1 连接PB12,PB13
左后轮 配置为通道2 连接PB10,PB11
右前轮 配置为通道3 连接PB14,PB15
右后轮 配置为通道4 连接PB0,PB1

用锂电池给TB6612模块供电,即锂电池的正负极连接TB6612的Vin+和-;然后用该TB6612模块的Vout+和-连接另一块TB6612的Vin+和-,相继再用Vcc和GND与面包饭上的Vcc和GND相连,实现供电。

四、程序设计

1. 红外传感设计

void GPIOB_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	/*红外out引脚:PA2,PA3,PA4*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	/*初始为低电平*/
	GPIO_ResetBits(GPIOB,GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

}

void Change_Target(int t_l,int t_r)
{
	target_left = t_l;
	target_right = t_r;
}

void forward(int t)
{
	Change_Target(t,t);
	GPIO_SetBits(GPIOB,GPIO_Pin_1| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_15);
	GPIO_ResetBits(GPIOB,GPIO_Pin_0| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_14);
}

void back(int t)
{
	Change_Target(t,t);
	GPIO_SetBits(GPIOB,GPIO_Pin_0| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_14);
	GPIO_ResetBits(GPIOB,GPIO_Pin_1| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_15);
}

void turn_left(int t_l,int t_r)
{
	Change_Target(t_l,t_r);
	GPIO_SetBits(GPIOB,GPIO_Pin_1| GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_15);
	GPIO_ResetBits(GPIOB,GPIO_Pin_0| GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_14);
}

void turn_right(int t_l,int t_r)
{
	Change_Target(t_l,t_r);
	GPIO_SetBits(GPIOB,GPIO_Pin_1| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14);
	GPIO_ResetBits(GPIOB,GPIO_Pin_0| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_15);
}

void stop(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
}

2. 定时器

void TIM1_PWM_Init(u16 per,u16 psc)
{
	/*使能TIM4时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	
	/*使能GPIO*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	/*使能AFIO*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*配置GPIO*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 |GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	/*设置重映射*/
	//GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//部分重映射	
	
	/*初始化定时器参数*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频为1分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数模式为向上计数
	TIM_TimeBaseInitStructure.TIM_Period = per;//配置周期(ARR自动重装器的值)
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//配置PSC预分频器的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计数器才需配置
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
	//TIM_ClearFlag(TIM4,TIM_FLAG_Update);//先清除标志位,避免刚初始化就进入中断
	
	/*初始化PWM参数*/
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;   //选择空闲状态下的非工作状态 低电平
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;  //选择互补空闲状态下的非工作状态 低电平
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择PWM1模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性:高电平有效
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //输出比较使能
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;  //互补输出比较使能
	TIM_OC1Init(TIM1,&TIM_OCInitStructure);
	TIM_OC2Init(TIM1,&TIM_OCInitStructure);
	TIM_OC3Init(TIM1,&TIM_OCInitStructure);
	TIM_OC4Init(TIM1,&TIM_OCInitStructure);
	
	/*使能TIMX在CCRX上的预装载寄存器*/
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
	TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);
	
	/*使能TIMX在ARR上的预装载寄存器允许位*/
	//TIM_ARRPreloadConfig(TIM4,ENABLE);
	
	/*开启定时器*/
	TIM_Cmd(TIM1,ENABLE);
}

void TIM2_Init(u16 per,u16 psc)
{
	/*开启通用定时器TIM2和GPIO时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	/*配置时基单元*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频为1分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数模式为向上计数
	/*
	定时频率 = 72M / (PSC+1) / (ARR+1)
	*/
	TIM_TimeBaseInitStructure.TIM_Period = per;//已知编码器线数:线数*4-1
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计数器才需配置
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*选择时钟源,配置正交解码*/
	TIM_ICInitTypeDef TIM_ICInitStructure;  
    TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,  TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//TI12:A、B项都计数
    TIM_ICStructInit(&TIM_ICInitStructure);//缺省输入
    TIM_ICInitStructure.TIM_ICFilter = 10;  //滤波器
    TIM_ICInit(TIM2, &TIM_ICInitStructure);
	
	TIM_SetCounter(TIM2,0X7FFF); //TIM4->CNT=0X7FFF(65536的一半)
	/*启动定时器*/
	TIM_Cmd(TIM2,ENABLE);
}

void TIM3_Init(u16 per,u16 psc)
{
	/*开启通用定时器TIM2和GPIO时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	/*配置时基单元*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频为1分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数模式为向上计数
	/*
	定时频率 = 72M / (PSC+1) / (ARR+1)
	*/
	TIM_TimeBaseInitStructure.TIM_Period = per;//已知编码器线数:线数*4-1
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;

	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计数器才需配置
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
	
	/*选择时钟源,配置正交解码*/
	TIM_ICInitTypeDef TIM_ICInitStructure;  
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);//TI12:A、B项都计数
    TIM_ICStructInit(&TIM_ICInitStructure);//缺省输入
    TIM_ICInitStructure.TIM_ICFilter = 0;  //滤波器
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_SetCounter(TIM3,0X7FFF); //TIM4->CNT=0X7FFF(65536的一半)
	/*启动定时器*/
	TIM_Cmd(TIM3,ENABLE);
}

void TIM4_Init(u16 per,u16 psc)
{
	/*1、开启通用定时器TIM4时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
	
	/*2、选择时钟源为内部时钟*/
	//TIM_InternalClockConfig(TIM4);//默认为内部时钟
	
	/*3、配置时基单元*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频为1分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数模式为向上计数
	/*
	定时频率 = 72M / (PSC+1) / (ARR+1)
	*/
	TIM_TimeBaseInitStructure.TIM_Period = per;//配置周期(ARR自动重装器的值)
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//配置PSC预分频器的值
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
	
	/*4、使能更新中断*/
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
	
	/*5、配置NVIC*/
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//选择中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//开启中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级
	NVIC_Init(&NVIC_InitStructure);	
	
	/*6、启动定时器*/
	TIM_Cmd(TIM4,ENABLE);
}

3. PID设计

int target_left,target_right;
int err_now1,err_now2;
int err_last1,err_last2;
int err_last_last1,err_last_last2;
int spd_now1,spd_now2;
int jisuan1,jisuan2;
int out_left,out_right;
int cnt_left,cnt_right;

float Kp=0.5;
float Ki=0.4;
float Kd= 0.1;
		
		cnt_left = abs((TIM2->CNT)-0X7FFF);
		cnt_right = abs((TIM3->CNT)-0X7FFF);
		
		TIM2->CNT = 0X7FFF;
		TIM3->CNT = 0X7FFF;

		
		//左电机	
		spd_now1 = cnt_left;
		err_now1 = target_left - spd_now1;
		jisuan1 = Kp*(err_now1-err_last1) + Ki*err_now1 + Kd*(err_now1+err_last_last1-2*err_last1);
		out_left += jisuan1;
		if(out_left<0)  out_left = 0;
		if(out_left>100)  out_left = 100; 
		TIM_SetCompare1(TIM1,out_left);	   //左前
		TIM_SetCompare2(TIM1,out_left);	  
		err_last_last1 = err_last1;
		err_last1 = err_now1;
		
		//右电机
		spd_now2 = cnt_right;
		err_now2 = target_right - spd_now2;
		jisuan2 = Kp*(err_now2-err_last2) + Ki*err_now2 + Kd*(err_now2+err_last_last2-2*err_last2);
		out_right += jisuan2;
		if(out_right<0)  out_right = 0;
		if(out_right>100)  out_right = 100; 	
		TIM_SetCompare3(TIM1,out_right);	 //右前轮
		TIM_SetCompare4(TIM1,out_right);
		err_last_last2 = err_last2;
		err_last2 = err_now2; 
		
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);

4. main文章来源地址https://www.toymoban.com/news/detail-562043.html

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组
	GPIOB_Init();
	
	TIM1_PWM_Init(100-1,72-1);
	TIM2_Init(65535,9);
	TIM3_Init(65535,9);
	TIM4_Init(5000,72-1); 
	int i;
	
	while(1)
	{
		if(L==0 && R==0)  i=0;
		
		if(L==1 && R==0)  i=1;
		
		if(L==0 && R==1)  i=3;
		
		if(L==1 && M==1 && R==1)  i=5;
		
		switch(i)
		{
			case 0:
				forward(4);
			  break;
			
			case 1:
				turn_left(4,10);	
			  break;

			case 3:
				turn_right(10,4);
			  break;

			case 5:
				stop();
				delay_ms(1000);
			  break;
		}		
	}
}

到了这里,关于基于PID算法下STM32控制的坡道行驶电动小车(2020年电赛)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32写的PID算法温度控制程序示例

    使用STM32写的PID算法温度控制程序示例,该程序通过读取温度传感器的数据,并采用PID控制算法,输出PWM信号来控制加热器的工作,以实现温度的稳定控制。  以上代码基于STM32F10x的单片机实现,使用了定时器来输出PWM信号,以控制加热器的加热功率。同时,该程序还实现了

    2024年02月15日
    浏览(9)
  • 基于stm32的智能小车(远程控制、避障、循迹)

    学完stm32,总是想做点东西“大显身手”一下,智能小车就成了首选项目,其核心只是就是PWM输出,I/O口引脚电平判断。 制作智能小车的硬件名单: 由于我们做的控制功能可以使用2.4G控制,也可以使用蓝牙进行控制, 两种传输方式所需购买的模块不同,已在硬件名单中加以

    2024年02月03日
    浏览(14)
  • 基于stm32F1的蓝牙控制小车 全硬件代码开源

       “基于stm32F1的蓝牙控制小车”由L898N电机驱动模块、电源管理模块、stm32f1主控模块、蓝牙串口通信模块。电机驱动模块使用了两个L298N芯片来驱动4路电机,使能端连接4路来自主控板的电平信号;电源管理模块使用了LM2940-5.0芯片进行12V到5V的转换,12V用于电机模块的供电,

    2023年04月20日
    浏览(16)
  • STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

    PID是什么,P,I,D的分别功能 你和PID调参大神之间,就差这篇文章! P(比例): 简单来说,P就是凉了加热水,热了加凉水。 比目标值小 ,我就 增加 一点, 比目标值大 ,我就 减小 一点。 (现在) P可能出现的问题: 1.P太小,达到目标值需要花费很长的时间,而且会有

    2024年02月03日
    浏览(14)
  • 四轮两驱小车(四):STM32驱动5路灰度传感器PID循迹

    目录 前言: 小车效果展示: 5路数字灰度传感器: 巡线思路: 加入PID调节的代码:         之前买了一批5路灰度传感器,想用这传感器进行循迹,无奈网上和官方的资料提供的还是比较少,这里还是做一下当初的学习记录。 STM32RCT6主控,5路灰度寻迹,超声波HC_SR04中断式

    2024年02月03日
    浏览(18)
  • 基于STM32F103的树莓派ROS小车——全局路径规划之Dijkstra算法

    Dijkstra Dijkstra算法概念: 基本思想:由近到远把所有点的最短路径算出来。 算法解析:从起点向四周辐射,由近到远一层一层遍历所有的点,直到包含目标点所在层级。然后将所有可行路径进行计算比较,筛选出绝对最佳路径。 优点:最终得到的路径一定是最佳路径。 缺点

    2024年02月15日
    浏览(9)
  • 单相逆变电路实战!(基于STM32F103C8T6的单相逆变电路,PID控制输出额定电压)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 我建了一个群,分享我个人做项目的经历和资源,纯个人爱好,一切免费,看自己空闲时间答疑,有想法的可以加QQ群280730348 本篇文章是对单相逆变电路进行实战演练的一次项目,主要实现功能为: 直

    2023年04月08日
    浏览(22)
  • Arduino毕业设计——基于Arduino+PID+AI的自动驾驶小车控制系统设计与实现(毕业论文+程序源码)——自动驾驶小车控制系统

    大家好,今天给大家介绍基于Arduino+PID+AI的自动驾驶小车控制系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报告PPT模板及论文答辩PPT模板等的小伙伴,可以进入我的博客主页查看左侧最下面栏目中的自助下载方法哦 文章目录: 近年来,各

    2024年02月06日
    浏览(16)
  • STM32 HAL库PID控制电机 第三章 PID控制双电机

    注:本文含全部PID控制代码,保证可以运行,如不能运行可以留言回复 1 基础配置 1.1 编码器电路图及配置 引脚 定时器通道 PA0 TIM2_CH1 PA1 TIM2_CH2 PB6 TIM4_CH1 PB7 TIM4_CH2 因此需要把TIM2、TIM4配置为编码器模式。在STM32CubeIDE中找到定时器2与定时器4,进行模式配置。以下以定时器2为

    2024年02月16日
    浏览(11)
  • 100、基于STM32单片机自动跟随小车 红外遥控控制小车避障模式 跟随模式设计(程序+原理图+PCB源文件+流程图+硬件设计资料+元器件清单等)

    智能小车通过各种感应器获得外部环境信息和内部运动状态,实现在复杂环境背景下的自主运动,从而完成具有特定功能的机器人系统。而随着智能化电器时代的到来,它们在为人们提供的舒适的生活环境的同时,也提高了制造智能化电器对于人才要求的门槛。智能小车是集

    2024年02月15日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包