STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N

STM32 舵机+超声波避障

  • 一.直流电机
  • 二.L298N模块

寒假由于时间较长,自己就想做一个智能车玩玩,第一个做的是蓝牙小车,不过比较简单,我就不打算具体另开一个部分,到时候挑一些与避障小车不一样的部分说一下。我这个小车行走速度比较慢,还是存在一定瑕疵,线也比较凌乱,大体功能可以实现。
先贴小车的图片:
STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N_第1张图片

STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N_第2张图片

小车主要分为几个部分:
1.STM32F103RCT6,当然用来执行各种命令的,因为用的是学习板,占地比较大,以后有时间改成C8T6的核心板,这样占地小一些。
2.L298N电机驱动模块,主要用来驱动左右两个电机,这个模块下面介绍。
3.电池,这里我买的是一款航模电池 1800mah 20c 焊接好T插头的电池,输出的是12V电压
4.分电板,主要是把电池的12V分成一个12V和一个5V输出
5.舵机,用的是SG90模拟舵机,这个舵机是花费时间最多的,因为总和我想要的结果不太一样
6.超声波测距模块,用的是HC-SR04模块,具体使用我上一篇说过了
7.蓝牙模块,用的HC-05这个蓝牙模块主要是用在蓝牙小车,后来放在避障小车上用来输出前方障碍物数据
8.小车底盘+电机,这个在某宝上一搜就有,而且驱动方法都差不多。我这里用的是直流电机。还有步进电机,但是我没有采用

这一篇我主要来说一下怎样让小车跑起来,就是电机怎么动。
想让小车跑起来,最重要的就是电机,电机驱动主要是需要两个接口。

一.直流电机


这个是我用的小车电机的说明,其中我们想要驱动电机就是在“电机线-”和“电机线+”一个高电压一个低电压,就会实现电机的转动,这里高低电压的接法没有要求接法不同只是影响正反转而已。至于其他的与编码器相关的可以不用连线,这些是测量电机转速的。在电压一定的情况下,电流越大,相应的转速也应该越快。
正常用L298N模块可以驱动电机并达到很高的转速,我这里尝试了一下直接用单片机驱动,发现也可以使电机转起来但是速度相比较用模块来说要慢很多,我猜测应该和电流有很大关系。

二.L298N模块

STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N_第3张图片
这个就是L298N驱动模块的样子
其中前面三个端子 ,中间的接地,注意要与单片机共地,否则将无法正常驱动电机,左面的端子是+12V输入,用来给L298N模块供电,就是电源输出的+12V电压,右面的端子是+5V输出,注意不要把这5V当作输入,建议不要用这个5V做为单片机的供电端。
左右两边各有两个端子,分别是OUT1,OUT2和OUT3,OUT4,用来驱动两路电机,这里只需要把OUT与电机的的电机线连接到一起即可完成。
在前面三个端子旁边有四个排针,这四个排针是用来控制左右两边的OUT,这四个排针分别是IN1 IN2 IN3 IN4 ,排针左右两边有两个用跳帽盖上的排针,分别是ENA ENB目的是使能那四个IN。用跳帽连接默认是已经使能,拔下跳帽另外加信号就可以继续使用。STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N_第4张图片

这是不同情况下的电机转动情况,后期可以用两种方法调节电机速度:
一.给EN使能,之后调节IN1 IN2 之间的电压差(通过调节PWM波占空比的方式实现)来控制速度。
二.是控制EN的电压也是通过条件PWM占空比来实现。我这里采用的就是这种方法。
这里我初始化四个IO口分别来控制四个IN端,来控制其正转反转。

void gpio_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);	 //使能PA,PB端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;				 //PA.4 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.4
// GPIO_SetBits(GPIOA,GPIO_Pin_4);						 //PA.4 输出高

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	    		 //PA.5 端口配置, 推挽输出
 GPIO_Init(GPIOA, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
 //GPIO_SetBits(GPIOA,GPIO_Pin_5); 						 //PA.5 输出高


 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	    		 //PB.10端口配置, 推挽输出
 GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
 

	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;	    		 //PB.11 端口配置, 推挽输出
 GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
 
 

 

}

这里我把几种电机转动情况来分类用函数来调用

void stop()
{
		PAout(4)=0;
		PAout(5)=0;
		PBout(10)=0;
		PBout(11)=0;//停止

}



void front()
	
{
		PBout(10)=0;
		PBout(11)=1;//前进
		PAout(4)=0;
		PAout(5)=1;
			



}


void left()
	
{
		PAout(4)=0;
		PAout(5)=1;
		PBout(10)=1;
		PBout(11)=0;//左转


}


void right()
{
		PAout(4)=1;
		PAout(5)=0;
		PBout(10)=0;
		PBout(11)=1;//右转

}	


void turnleft()
	
{

		PAout(4)=0;
		PAout(5)=1;
		PBout(10)=0;
		PBout(11)=0;//一电机停止 左转
		

}




void turnright()
	

{

		PAout(4)=0;
		PAout(5)=0;
		PBout(10)=0;
		PBout(11)=1;//一电机停止 右转

}
 

void back()
	

{

		PAout(4)=1;
		PAout(5)=0;
		PBout(10)=1;
		PBout(11)=0;//后退
		

}

这样就可以驱动轮胎转动,也就可以驱动小车任意方向运动。
下面是我设置了两路PWM波给两个EN信号,来控制电机速度,进而控制小车速度,我只用了普通的定时器来输出PWM波,没有用到高级定时器的刹车功能。
PWM1:

#include "pwm.h"


//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM4_Init(u16 arr,u16 psc)
{  
	 GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);  //使能GPIO外设时钟使能
	                                                                     	

   //设置该引脚为复用输出功能,输出TIM3 CH4的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM_CH4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 80K
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC4Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

  TIM_CtrlPWMOutputs(TIM3,ENABLE);	//MOE 主输出使能	

	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH4预装载使能	 
	
	TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
 
   
}

PWM2:

#include "pwm2.h"


//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM3_Init(u16 arr,u16 psc)
{  
	 GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);  //使能GPIO外设时钟使能
	                                                                     	

   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 80K
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

  TIM_CtrlPWMOutputs(TIM3,ENABLE);	//MOE 主输出使能	

	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH3预装载使能	 
	
	TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
 
   

两路PWM控制占空比

		TIM_SetCompare3(TIM3,2400);//左轮电机转速
		TIM_SetCompare4(TIM3,2530);//右轮电机转速

控制占空比函数数值越大转速越慢,在实际中,会遇到小车两个轮转速不一样,这里我没有用算法来调整,我采用手动调整到大概可以走直线,硬件的缺陷用软件来弥补。

到现在就可以用单片机+L298N模块来驱动电机,可以实现小车的任意方向行驶啦
具体代码之后上传

你可能感兴趣的:(STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N)