作者:c72586051 | 来源:互联网 | 2023-10-16 10:39
基于STM32的智能循迹小车设计(基础版)硬件准备1、小车底盘+四直流电机(带轮)2、STM32F103C8T6核心板3、12V8700mAh锂电池(可以用几节18650锂电池)4
基于STM32的智能循迹小车设计(基础版)
硬件准备
1、小车底盘+四直流电机(带轮)
2、STM32F103C8T6核心板
3、12V 8700mAh锂电池(可以用几节18650锂电池)
4、循迹模块
选择的是TCRT500L,五路集成在一起,集成度比较高,但是可能不如五个单独的循迹模块好用
5、L298N电机驱动模块
四驱车为啥用L298N电机驱动模块?
可以把左边的两个电机并联,用输出A控制。把右边的两个电机并联,用输出B控制。
12V供电接电源正极,供电GND接电源负极和核心板GND,5V供电接核心板5V和循迹模块5V,然后循迹模块GND接核心板GND,所有设备就都可以上电了。(最好设置几个开关,安全且方便调试)
另外,接线最好先试触,避免短路。
6、杜邦线、开关若干
软件设计
1、电机调速
通过输出PWM控制电机转速
PWM初始化(以A1为例)
void TIM2_CH2_PWM_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;//定义三个结构体
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//开启相关时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//A1 GPIO初始化
TIM_TimeBaseStructure.TIM_Period = 199;
TIM_TimeBaseStructure.TIM_Prescaler =7199;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 定时器初始化
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
//定时器通道初始化
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
//预装值初始化
TIM_Cmd(TIM2, ENABLE);
//打开定时器
}
初始化完后,输出PWM控制电机转速,注意,TIM_SetCompare2(TIM2,n);n越小占空比越大,点假转速越快,一下代码就是A1输出PWM占空比更大,它所对应的电机转速就越快。 具体的数据是多少,需要自己根据不同的场地去摸索,不停地调试。
void left()
{
TIM_SetCompare2(TIM2,20);
TIM_SetCompare3(TIM2,120);
}
2、循迹模块检测
GPIOB初始化,同时将B4 B5 B6 B7 B8设置为上拉输入
void GPIOB_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7| GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
宏定义,少打字,B4 B5 B6 B7 B8 分别对应L1 L2 M R2 R1
#define L1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)
#define L2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)
#define M GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)
#define R2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)
#define R1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8) // L1 L2 M R2 R1
读取函数
void Read_Date(void)
{
L1;
L2;
M;
R2;
R1;
}
3、主函数(用读取的循迹数据控制电机)
用了一个比较笨的但是很直接的方法,将所有的情况都罗列出来。
思路:如果L1检测到,那必须bigright;如果R1检测到,那必须bigleft;
那中间的那三位,还有8种,将这8种枚举就可。
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART1_Init(9600);
GPIOB_Init();
TIM2_CH2_PWM_Init();
TIM2_CH3_PWM_Init();
while(1)
{
Read_Date();
if(L1==0&&L2==0&&M==0&&R2==0&&R1==0)
{
go();
delay_ms(10);
}
if(L1==0&&L2==1&&M==1&&R2==1&&R1==0)
{
go();
delay_ms(10);
}
if(L1==0&&L2==0&&M==1&&R2==0&&R1==0)
{
go();
delay_ms(10);
}
if(L1==0&&L2==1&&M==0&&R2==0&&R1==0)
{
right();
delay_ms(10);
}
if(L1==0&&L2==0&&M==0&&R2==1&&R1==0)
{
left();
delay_ms(10);
}
if(L1==0&&L2==1&&M==1&&R2==0&&R1==0)
{
right();
delay_ms(10);
}
if(L1==0&&L2==1&&M==0&&R2==1&&R1==0)
{
go();
delay_ms(10);
}
if(L1==0&&L2==0&&M==1&&R2==1&&R1==0)
{
left();
delay_ms(10);
}
if(R1==1)
{
bigleft();
delay_ms(10);
}
if(L1==1)
{
bigright();
delay_ms(10);
}
}
}
工程文件现已上传到资源,2积分即可下载。