基于STM32的智能循迹避障小车运动部分实验
写在前面
这个实验是关于智能小车的实验,现在的想法就是先做出一个循迹和避障功能,后续可能会再添加一些其他的模块。
我在做这个实验之前基本了解了F1系列开发板的大部分模块,如果没有学习之前的模块,建议先学习下开发板的基本模块。
实验所需的硬件
本来是想在网上直接买成套的,但是碍于手头实在紧张,所以分开买的配件。
所有配件均从淘宝购入,适合动手能力强的人。
1 |
STM32F103C8T6最小系统板 |
2 |
智能小车底板 |
3 |
L298N电机驱动模块 |
4 |
舵机SG90云台和超声波模块HC-SR04 |
5 |
4节5号电池 |
6 |
TCRT5000循迹模块2个 |
7 |
面包板和杜邦线若干 |
8 |
下载器 |
9 |
5v转3.3v DC-DC模块 |
附上它们的图片
主芯片我当时也买了但是没用上,因为c8t6最小系统板是不带TTL串口下载功能的,如果要下载还需要一个下载器,我因为着急做,所以就用我自己的开发板了。
电路连接部分这里不再展开,可以在网上找些视频讲解,比较通俗易懂。
硬件整理完后就可以开始程序的书写了。
让小车动起来
让小车动起来的原理也非常简单, 看图:!!!!
这个图中标注了这些每个引脚的功能,将我们小车的电源线连接到12V供电,完后供电GND接入我们板子上的GND。这里再附上L298N工作原理图:
图表 1电机转动示意图
这个图翻译成人话就是一共有4个输入引脚,引脚12控制电机1,也就是图上的输出A,引脚34控制电机2,也就是图上的输出B,当两个引脚输出的电平不同时,电机就会工作,反之电机就停止工作。所以我们可以用普通GPIO口输出高低电平来使它工作。
接下来我们就利用GPIO口来控制小车动起来:
CobeMX配置
首先先进行CobeMX的配置:选择你自己喜欢的GPIO口进行配置,然后根据你的配置来连线,之后选择将所有的GPIO初始值都拉低。
图表 2GPIO选择
我这里选择的是GPIOG2、4、6、8四个接口,将它们配置成GPIO_OutPut模式。
具体每个IO口的配置如图
图表 3GPIO配置
代码实现部分
上述配置完成后就可以生成代码了。这部分我们先实现简单的让小车可以动起来,
根据图表1,我们知道当IN1和IN2的电平不同时就可以使OUT1的电机转起来,
所以这里先试着让一个电机转动:
HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
在主函数中让IN1的电平改变为高电平,烧录进开发板,如果车轮可以正常转动,说明之前配置和硬件电路的连接都是正常的。接下来我们将前进、后退、左转、右转都封装成函数:
// 前进
void Car_Go(void)
{
HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, GPIO_PIN_SET);
}
// 后退
void Car_Back(void)
{
HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN4_GPIO_Port, IN4_Pin, GPIO_PIN_SET);
}
// 左转
void Car_Left(void)
{
//HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, GPIO_PIN_SET);
}
// 右转
void Car_Right(void)
{
//HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, GPIO_PIN_SET);
}
这里的几个代码是相对于我这个接线方法的,如果使用这个代码的出现轮子转的方向不对,最简单的方法就是将线反接一下,或者改下代码中的接口也可以。
最后,就可以在主函数中测试刚才实现的几个功能了。
有兄弟可能会问这个正接、反接、1输出高还是2输出高最后导致的电机转动方向不同,这个问题可以自己到时候试几次,就可以试出来了,我现在说这些正接反接,到时候你一个线接反了就全反了,所以倒不如到时候自己试几次。
PWM驱动电机
我们只是实现了简单的运动,但是这样的运动有些局限性,我们不能调节小车的速度,转动的时候小车基本不向前移动,针对这个问题,我们可以使用PWM调波方式实现小车转速降低,也可以在转动时转弯半径增大。
实现原理:通过通用定时器控制PWM输出占空比不同的PWM波,来实现施加在电机上电压的时间,进而改变电机转动的速度。
通过查看手册,可以知道通用定时器可以生成PWM波。所以我们这里采用通用定时器实现PWM波的生成。
接线方法:在L298N的示意图上,我们可以看到有通道A使能和通道B使能,这两个本来是用跳帽和正极短接,现在我们将跳帽拔下,然后连接到开发板的PWM使能引脚(可以先用CobeMX进行使能,然后看对应使能的接口来连线)。
让我们回到CobeMX进行设置:在设置定时器之前我们首先得先开启RCC的时钟:这里配置为高速外部时钟。然后打开时钟树,将HCLK配置成最高的72MHz。
完成时钟配置后,打开TIM2的通道1和2,将它们配置成PWM模式。
完成后配置下方的具体配置,具体配置这里就不展开描述。
图表 4PWM配置
只需注意:
1.PSC是预分频器,它可以对时钟进行预分频:也就是一次计时的计数次数,如果配置为7199,实际分频就为7200,这里因为影响不大,所以直接配置为7200。配置完后从分频器输出的时钟频率为(72MHz/7201)=1000,当计数值达到这个值就会触发中断然后计数器又归零重新计数(这里不需要中断)。
2.Counter Period是计数周期,这里配置为200,也就是计时200ms。
3.Pulise是PWM高低电平的时间,这里设置为高电平50ms,低电平150ms。
配置完成后就可以生成代码了。
代码实现:
// 前进
void Car_Go(void)
{
HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, GPIO_PIN_SET);
}
// 后退
void Car_Back(void)
{
HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN4_GPIO_Port, IN4_Pin, GPIO_PIN_SET);
}
// 左转
void Car_Left(void)
{
HAL_TIM_Base_Start_IT(&htim2);
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,50);
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);
HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, GPIO_PIN_SET);
}
// 右转
void Car_Right(void)
{
HAL_TIM_Base_Start_IT(&htim2);
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,50);
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);
HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, GPIO_PIN_SET);
}
__HAL_TIM_SET_COMPARE()这个函数是修改PWM占空比的函数,也就是修改Pulise。可以通过使转弯时一个轮子的转速下降来实现转弯,也可以整体调整小车行驶速度。这里需要注意:主函数调用这个函数时每次调用完都得回调PWM的占空比。如下:
while (1)
{
/* USER CODE END WHILE */
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,199); // 回调PWM
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,199);
Car_Go();
HAL_Delay(10);
/* USER CODE BEGIN 3 */
}
由于篇幅原因,在下一篇文章中我们再实现小车的循迹模块。
最后附上整个项目的HAL库源码:
提取码:1234