电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车

我的第一辆智能车—电磁循迹智能车

提示:本文适用于初学,想完成一个基础四轮车练练手者,大佬还请勿喷,不过欢迎提出意见,有纰漏之处我将及时纠正。
:工程代码链接已贴在文末。

电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车_第1张图片

前言:

所用到的硬件平台:
stm32f103c8t6,舵机,电机,L298N驱动模块,OLED,电磁杆,干簧管,基础四轮车模。

所用到软件部分:
PID算法,ADC多路采集配置DMA,OLED驱动程序,环岛处理,普通GPIO口使用。

智能车图片
电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车_第2张图片

进入正题

一、舵机模块

1)舵机,三条线路,一条GND,一条VCC,一条给予PWM波输入。
控制舵机角度主要是控制PWM波的大小,不同的PWM对应不同的角度。中间角度的占空比为7.5%。这个值上下加减对应控制舵机左右角度。

2)一个对应的PWM确定一个对应的角度。注意的是时间周期应配为20MS,频率50HZ。

3)在设置最大主频72MHZ的情况下,计数值设为2000-1,预分频系数设为720-1。CUBEMX注意通道使能。工程代码中可以直接操纵寄存器TIM1->CCR3 = 143。(143是我设置的中间值,正常情况下应该是150)
二、电机、L298N驱动模块

1)电机引出的两条线路不分正负,表现出来只是正反转,之后用代码普通GPIO口控制即可。LM298N左右端子分别接电机的引脚。

2)中间排针四个口接普通GPIO口,用于stm32单片机控制其正反转。

3)两边的口接PWM,设置占空比控制电机的转速。

三、PID算法

add.c文件中的PID控制部分

使用的是位置式PID
电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车_第3张图片
代码如下:

void Control(void)
{
    static float EP,PWM,ISUM,LAST_EP,a = 0,sum,EP_H,LAST_EP_H,k = 0,y,z;
	float  L_value_shuzhi,L_value,R_vlaue_shuzhi,R_value,J;
	
	L_value_shuzhi =adc(2);// adcbuf[0];
	L_value = adc(3);//adcbuf[1];
	R_value = adc(4);//adcbuf[2];
	R_vlaue_shuzhi = adc(0);//adcbuf[3];
	EP = R_value  - L_value;//传入PID控制器的差值										
    ISUM += EP;                                //积分
	PWM = P*EP + I*ISUM + D*(EP - LAST_EP);   //PID控制部分
	LAST_EP = EP;                             //记录上一次的差值
}

传入主函数控制

void main(void)
{
	while(1)    //用户理想值
	{
		TIM1->CCR3 =143+Control();  //转向控制系统,核心部分
	}
}

P:proportion,比例,就是用户期望值,与传感器返回值的差值,偏差。
I:integral,积分,记录了从某一时刻开始,所有的偏差的累积。
D:derivative,微分,是偏差的偏差,相当于偏差的导数,偏差变化的速率。

四、OLED

(1)对于OLED来说一般网上有很多相关的驱动文件,和其能调用的子函数。直接加入工程,修改一下引脚就可以调用了。使用CUBEMX配置使能硬件IIC驱动IIC。

(2)链接:https://download.csdn.net/download/cubejava/21518138

五、电磁杆

1)电磁杆我们组硬件员是自己画板去某创开板拿回来自己制好了的,但是在使用时发现两边对称的电感值不一样,相差很大。这个情况是也许是可以用卡尔曼滤波算法解决的,但是由于我目前的技术太菜,无法实现,所以很遗憾,我们不能用自己的电磁感进行循迹,而这恰恰是这个比赛最关键的一步。

2)我们最后只能买了某龙的电磁杆,说实话,买的电磁杆质量那叫一个好。可以直接拿来用,完全可以不用滤波,效果贼好。六个电感,我们只用了4个,两个水平的用于检测直道和弯道,两个竖直的用于检测环岛。(电感检测电磁场的变化,转化为电压—电磁感应,用多路ADC采集值传回)。

3)所以如果是初次参加比赛建议买现成的电磁杆,可用省去很多麻烦,把精力放在代码优化上。

六、ADC多路采集配置DMA

以下为cubeMX的配置

电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车_第4张图片

在程序中添加以下代码即可使用

uint16_t adcbuf[5];//五路ADC存储数组。
HAL_ADCEx_Calibration_Start(&hadc1 );//开启ADC。 
HAL_ADC_Start_DMA (&hadc1 ,(uint32_t *)adcbuf,5);//开启五路DMA

后面使用数组数据即可,如电感一的值则是adcbuf[0],电感二的值则是adcbuf[1],以此类推。

八、干簧管(用于检测停车)

1)提到干簧管是比较难受的(不是因为难,很简单),我真的直接裂开。比赛时干簧管没有检测到。

2)干簧管模块一般有三条线路,一条VCC(用3.3V即可,之前我接的5V,多用几次芯片就烧坏了),一条GND,还有一条信号线,用于检测电平变化。若没有检测到永磁铁时,处于高电平,检测到永磁铁后处于低电平。程序控制的方式是用一路ADC检测其传回来的值,判断其高低电平,进而写对应的用户代码。

3)而我当时比赛时干簧管为什么没有检测到,因为我把我的干簧管检测程序写在了子函数里,并设置了一个标志位,当检测到时标志位计数,加到我的预设值后实现相应的用户代码。思路是没有问题,但是我的子函数有问题!!!原因是每次进去我的子函数里,变量值就会被刷新为0,根本达不到我的预设值!所以根本进不去我的用户代码。

4)比赛结束后那天晚上我一直睡不着在想为什么会检测不到,最后我发现我忘记加static,静态变量了(变量只初始化一次)。所以平时写代码要多多灵活应用static啊!static,static,static,重要的东西说三遍。

八、普通GPIO口使用

这个也不用多说了,直接在cubeMX使能配置就好了。
程序里需要调用的函数一般就三个:

HAL_GPIO_WritePin (GPIOX ,GPIO_PIN_X , x(01);
HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
HAL_GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

九、环岛处理

1)环岛处理部分我使用的是比较容易想到的思路——闭环控制,即检测到标志点则卡死程序强行打角度进入环岛,好处是程序简单,容易理解,效果明显。坏处时会出现一些偶然性,受环境影响大。

2)如图环岛的关键点,我分为四个点,刚到,即将入,刚出,即将出。分设相应的检测值范围和标志位。
电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车_第5张图片

具体程序处理见工程代码。

总结

1)怎么说呢,这次比赛也还是算尽力了吧,一个月来天天去赛道调车,基本上都是晚上11:00左右才依依不舍离开实验室。最后比赛时轮胎打滑,速度没来得及提上去,只得了三等奖,能力还不够啊!不足的地方还很多,需要学的东西还有很多,在这里就不多说了。路漫漫其修远兮,吾将上下而求索!
电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车_第6张图片

2)以上写的很多只是我自己片面的想法,而且能力有限,有不足的地方欢迎指出。

3)最后,因为自己也是花了时间和心血一点一点才完成的工程、写出的代码,所以不太想被人白嫖,故设置了付费,还请大家理解。不过博文中大部分已经进行了详细说明,只要稍微会一点stm32应该就能独立完成整个智能车了。欲速则不达,加油!

工程代码链接:https://download.csdn.net/download/cubejava/41879499

你可能感兴趣的:(智能车,单片机,编程语言,stm32)