用STM32F103单片机控制电调制动无刷电机

用电调控制无刷电机制作蓝牙遥控飞艇

【注:学习STM32总结做的笔记,大神勿喷。有不足之处还望不吝赐教,谢谢。工程代码在最后。】

蓝牙控制 调控电调 无刷电机 STM32F103单片机 用电调控制无刷电机制作蓝牙遥控飞艇

这是队友在某宝上买的无刷电机和电调,因为比赛需要,做了条飞艇出来。由于无刷电机质量问题(划重点),导致比赛失了败。
在这里插入图片描述
其实做出来是挺简单的,就是驱动电调去控制无刷电机,对于一些刚接触电调、无刷电机的人来说,有一定的难度(网上的教程很多,但很多都说得不明不白的)。下面我就完整的把我的讲一下吧,有不对的地方可以指出来,还望勿喷。

说之前还是要强调一下
注意事项:
1.调试要看紧点电机(安全问题,防止浆翼打伤手,能拿掉浆翼就拿掉)
2.防水措施一定要做好,不然进水会烧掉电路
3.电调要跟无刷电机接对线(电机有正反浆,接错会打转,或者不动。。电调只会往一个方向给信号)
4.船模设计要合理,要考虑船的承载能力和水位,不然飞艇会成潜艇(船头要轻,浮起来。不然前面太重,后面推动,飞艇还会成潜艇)
5.我这款无刷电机能下水,做船的建议电机浆翼到水就好(倾斜对水),不要整只下到水,阻力太大船就没动力了。
6.这些都是意见与经验之谈,觉得有用的就用。

我用的单片机是STM32F103电调是好盈的(HOBBYWNG)(材料型号规格要按实际要求选择,还要看它的说明书)无刷电机是三线的(不懂可百度)。
接线问题:黑线接GND(一定要和单片机共地接),红线接+5v(不接也没问题,还是建议接上),白线(信号线)接输出PWM的管脚另外两条粗粗的红黑线–自然是接电池电源

下图是电调的说明
在这里插入图片描述电调说明也可以参考这位博主的文章:https://blog.csdn.net/CalShell/article/details/44424347

电调驱动
驱动电调关键就是PWM频率,有的人用50Hz的PWM能驱动电调,也有的人用500Hz能驱动电调。这个要具体看电调的要求,以及PWM的输出(PWM设置分不分频会影响PWM的计数快慢,从而影响电调的控制),我下面的pwm设了分频,不理解PWM分不分频的可自行百度。如果按照我的这组数(1999,71)调不通,可以或者不分频多改改测测,接着就是解锁电调,电调第一次使用要设置量程,然后接上线就能动了,就是这么简单。
我这电调驱动的值在(5—500),5—速度最大;500—速度最小,无刷电机停止

TIM3_PWM_Init(1999,71);	 //不要问我怎么来的,这个数值的PWM频率是我测出来的((1999,71)这组数不唯一)。具体可以去理解一下PWM频率怎么计算	 
/*/////////////////////解锁电调////////////////////*/	 
/*电调第一次使用要设置量程,解锁两个电调步骤,先拉到最高油门,再拉到最低油门,这一步电机会动,一定要注意安全*/
TIM_SetCompare2(TIM3,10);
TIM_SetCompare3(TIM3,10);
delay_ms(1000);  //先延时
TIM_SetCompare2(TIM3,500);
TIM_SetCompare3(TIM3,500);	 
delay_ms(10);		//再延时
/*/////////////////////解锁电调////////////////////*/

在这里插入图片描述

电调PWM信号输出–示波器

电调驱动电机–第一次解锁和高速运行时的信号输出
在这里插入图片描述
电调驱动电机–电机停止时的信号输出
在这里插入图片描述

我做的飞艇用了三个电机–正反浆电机、加速喷水电机。正反浆无刷电机–控制前进左右方向,加速喷水电机–备用动力(终点快人一步)。

扫描二维码关注公众号,回复: 10749553 查看本文章

L298N驱动加速喷水电机就不多做解释了,接线如下图,代码也在最下面了。
接线图
在这里插入图片描述

调测–成品图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码区

mian.c

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "usart3.h" 
#include "timer.h"
	
 int main(void)
 {		
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级  

	uart_init(115200);	 //串口初始化为115200	 
	usart3_init(9600);//蓝牙的串口初始化 注意手机与单片机的蓝牙连接波特率是要9600	 
	TIM3_PWM_Init(1999,71);	 //不要问我怎么来的,这个数值的PWM频率是我测出来的。具体可以去理解一下PWM频率怎么计算
	 
/********************解锁电调**********************/
/*电调第一次使用要设置量程,解锁两个电调步骤,先拉到最高油门,再拉到最低油门,这一步电机会动,一定要注意安全*/
    TIM_SetCompare2(TIM3,10);
	TIM_SetCompare3(TIM3,10);	 
	delay_ms(1000);  //先延时
	TIM_SetCompare2(TIM3,500);
    TIM_SetCompare3(TIM3,500);
  delay_ms(10);		//再延时
/********************解锁电调**********************/		 
	 while(1)
	{
	
		if(USART3_RX_STA&0x8000)
		 {
	 
		 if(USART3_RX_BUF[0]=='l')//前进
				{			 			 
				 TIM_SetCompare2(TIM3,10);//电机1全速前进
				 TIM_SetCompare3(TIM3,10);//电机2全速前进		 
			  }
		 if(USART3_RX_BUF[0]=='h')//停止
			   {			 		 
			  	TIM_SetCompare2(TIM3,500);//电机1停止
			  	TIM_SetCompare3(TIM3,500);//电机2停止				
			   }
		  if(USART3_RX_BUF[0]=='z')//左转
			    {
			      TIM_SetCompare2(TIM3,100);//电机1减速
				  TIM_SetCompare3(TIM3,400);//电机2全速
			    }
			if(USART3_RX_BUF[0]=='y')//右转
			    {
                TIM_SetCompare2(TIM3,400);//电机1全速				 
                TIM_SetCompare3(TIM3,100);//电机2减速  
			    }
			if(USART3_RX_BUF[0]=='q')//备用电机启动
			    {
               TIM_SetCompare4(TIM3,10);//备用电机全速
			    }
			if(USART3_RX_BUF[0]=='t')//备用电机停止
			    {
               TIM_SetCompare4(TIM3,1999);//备用电机停止			  
			    }
								 			 
			 USART3_RX_STA=0;//清空接收标记
		 }
							
	}	
		 
 }

timer.c

#include "timer.h"
  	  
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	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_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
		LED1=!LED1;
		}
	
}

//TIM3 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
//PB5------TIM_SetCompare2------左边电机
//PB0------TIM_SetCompare3------右边电机
//PB1------TIM_SetCompare4------加速喷水电机
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5     
   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形	GPIOB.5
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
	GPIO_ResetBits(GPIOB,GPIO_Pin_1); 	//PB1要拉低,因为芯片默认高电平,而L298N一个脚接地,会形成回路,电机就默认驱动了的
	
   //初始化TIM3
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	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的时间基数单位
	
 	//初始化TIM3 通道2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
	
	 	//初始化TIM3 通道3 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

	 	//初始化TIM3 通道4 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC4Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
	
}

timer.h

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"

void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
#endif

蓝牙部分
usart3.c

#include "sys.h"
#include "usart3.h"

u8 USART3_RX_BUF[USART3_REC_LEN]; //数组用来存储接收到的数据,而USART3_REC_LEN为最多能接收的字节限度
u16 USART3_RX_STA=0;         		//接收状态标记	 0-14位为接收字节数,15位接收完成标志位

void usart3_init(u32 bound)
{ 
	  GPIO_InitTypeDef GPIO_InitStructure;
	  NVIC_InitTypeDef NVIC_InitStructurea;
	  USART_InitTypeDef USART_InitStruct;
	 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能串口3
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能GPIOB
	USART_DeInit(USART3);//串口3复位 不是必要的一步
	
	  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	  GPIO_Init(GPIOB,&GPIO_InitStructure);    //PB10设置为复用推挽输出

	  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
	  GPIO_Init(GPIOB,&GPIO_InitStructure);  //PB11设置为浮空输入	 
  
	  NVIC_InitStructurea.NVIC_IRQChannel=USART3_IRQn;
	  NVIC_InitStructurea.NVIC_IRQChannelCmd=ENABLE;
	  NVIC_InitStructurea.NVIC_IRQChannelPreemptionPriority=2;
	  NVIC_InitStructurea.NVIC_IRQChannelSubPriority=2;
	  NVIC_Init(&NVIC_InitStructurea);          //串口3中断的设置
		
		USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//串口3中断使能和中断类型设置
	    USART_InitStruct.USART_BaudRate=bound;//串口波特率
		USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件数据流控制
		USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Rx;//收发模式
		USART_InitStruct.USART_Parity=USART_Parity_No;//无奇偶校验位
		USART_InitStruct.USART_StopBits=USART_StopBits_1;//一个停止位
		USART_InitStruct.USART_WordLength=USART_WordLength_8b;//字长为8位数据格式
	    USART_Init(USART3,&USART_InitStruct);                 //串口3的一些参数设置		
		USART_Cmd(USART3,ENABLE);//串口3使能
		  
}
void USART3_IRQHandler()//串口3的中断
{ 
	 u8 res;//暂时缓存接收的数据
   if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)//判断是否为串口3接收中断
	 {
		   
	      res=USART_ReceiveData(USART3);//接收到数据放进res
		   USART3_RX_BUF[USART3_RX_STA&0x7FFF]=res;//数据放进数组中,则可以用到main函数中了
		   USART3_RX_STA++;                         //字节长度++
		   if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收	+; 
		   USART3_RX_STA|=0x8000;//串口3接收完成
		   USART_ClearITPendingBit(USART3,USART_IT_RXNE);//清除接收中断标志
		   
	  }
}


usart3.h

#ifndef USART3_H_
#define USART3_H_

#include "sys.h"
#include "stdio.h"	

#define USART3_REC_LEN  200  	//定义最大接收字节数 200

extern u8  USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节
extern u16 USART3_RX_STA;         		//接收状态标记	 0-14位为接收字节数,15位接收完成标志位
void usart3_init(u32 bound);
#endif

【注:文件源码是Keil uVision5–STM32工程文件】
参考文件源码下载链接:
https://download.csdn.net/download/qq_28056277/11232414
原创文章,转载请注明出处,谢谢。

发布了10 篇原创文章 · 获赞 30 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_28056277/article/details/91347436