2019-01-19 20:06:48 qq_40732054 阅读数 826

 

通过32单片机输出特定pwm波,驱动电调进而控制推进器。

  1. 对于单个的推进器进行控制,有时候数据手册提供的控制条件范围不准确;
  2. 明确速度变化pwm波的输出区间;
  3. 整体程序编写。

推进器的选取,如图1所示推进器型号为T200水下推进器,图2为此次使用电调,资料在对应论坛下载http://forum.bluerobots.cn/t/topic/261下载。

 

                                                                          图1 T200推进器 

                                                                         图2 ESC30电调 

 电调一般是需要特定的频率波形才能进行驱动。32产生pwm波可以自己设定定时器模拟,也可以进行库里面的pwm波通道输出。

(1) 主函数代码(测试用,通过按键逐步增加占空比)

int main(void)
 {        
     u16 led0pwmval=0;
    int dir=0;              
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  
    uart_init(115200);    //串口配置
     LED_Init();               
     KEY_Init();    //按键初始化
     TIM3_PWM_Init(19999,71); //输出制定的电调要求的50HZ频率波        
       while(1)
    {                                     
  
    switch(KEY_Scan(0))
        {
            case 1:
            {
                dir++;
                TIM_SetCompare2(TIM3,1100+100*dir);//根据资料数据提供
                USART_SendData(USART1,'2');//为了便于检测是否按键执行正确,其实是通过看有几个2来确定输出的占空比
            }   break;
            default:break;
        }            
    }    
    
 }

(2)按键检测(直接用的正点原子的,象征性的贴出代码)

u8 KEY_Scan(u8 mode)
{     
    static u8 key_up=1;//
    if(mode)key_up=1;  //     
    if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
    {
        delay_ms(10);//
        key_up=0;
        if(KEY0==0)return KEY0_PRES;
        else if(KEY1==0)return KEY1_PRES;
        else if(KEY2==0)return KEY2_PRES;
        else if(WK_UP==1)return WKUP_PRES;
    }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;         
     return 0;// 
}

(3) PWM波输出配置

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);    //
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //
    
    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //  
 
    GPIO_InitStructure.GPIO_Pin = 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);
 
   //TIM3
    TIM_TimeBaseStructure.TIM_Period = arr; //
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //
    
    //TIM3 Channel2 PWM 
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);  
    
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //
    TIM_Cmd(TIM3, ENABLE); 
}

(4)而后不确定的就可以先通过示波器看输出的pwm波的频率与占空比是否正确,通过论坛资料吧输出的高电平需要为3.3V,在接推进器时,实现进行板子pwm输出测试,如图3所示。

                                                                (a)输出电平 

                                                                (b)输出占空比情况 

                                                                       图3 测试情况

在测试时,我设置的基PWM高电平时间为1100us,通过按键当PWM高电平时间为1600us时,推进器运行。在高电平时间为1400时,推进器第二次声响,但是没有转动,当为1600us时启动。

待更新中。。。1.19

 

添加一位同学的补充:

2019.4.20

 

2019-08-06 19:01:05 qq_35701387 阅读数 360

单片机通过电调控制无刷电机

单片机输出一定的频率和一定脉宽的PWM波,模拟飞控的油门控制,从而解锁电调,通过调节PWM脉宽,控制电调,从而控制无刷电机的转速。

电调接线

在这里插入图片描述
我这里使用过的是XXD 新西达 30A 的电调。

	如图中,电调上有8根线,
	蓝色的三根线 与 无数电机的三根线链接;
	黑色和红色为电源的正负极,红色为正极,黑色为负极,接至电源即可,电源供电电压范围根据自己购买的电调属性确认,我这款供电范围为:4 ~ 16V,一般供电12V;
	三根细线为控制信号线,其中黄色-信号线,输入PWM;红色-电源线,接至5V;棕色-地线。
	注意:两处供电需要共地

无数电机接线

在这里插入图片描述
如上图,无数电机三根线与电调三根蓝色线接即可,接线方式任意,若发现电机旋转方向相反,只要调整上述三根的任意两根线即可。

电调的解锁与调速

第一次使用电调时,需要识别飞控的最大行程和最小行程,即解锁。方法如下:

输入PWM 频率为 50HZ,脉宽为2ms(10%占空比),电调上电,会听到“BB”两声;
调整脉宽为1ms(5%占空比),会听到“BBB”三声,解锁完毕。

电调解锁完毕后,只需要在1ms ~ 2ms(5% - 10%占空比)之间,调整脉宽,即可调整无刷电机转速,1ms为停止,2ms为最大转速。

输入PWM可以通过信号发生器输入,也可通过单片机PWM模块配置输入。

2017-08-02 10:29:22 gin_love 阅读数 2267

最近刚接触四旋翼,主控用的是瑞萨的RX23T系列,表示以前从来没有接触过瑞萨的单片机,所以拿到手一脸的懵逼。在我好不容易搞懂了开发环境的使用,把在某宝上寻得的资料烧写到单片机上,期待电机嗡嗡转起来,可是只听到了循环的滴滴叫声。
网上一查,电调要先解调之后,才能控制无刷电机。

针对我自己的情况,我们用的是好盈20A的电调,2212无刷电机,瑞萨R5F523T5ADF。(以下所提方法和参数可能会因为电调型号和电机不同而不同)

ps:此篇博客主要是我用来记录我们小组成员解调电调的过程,对于博文中提到的一些关于瑞萨单片机的使用上或是理解上有错误的地方(实在是小白一只)欢迎大家热心提出并指正。

可略过此版块直接看第二板块

我首先根据资料配置好MTU来实现四路PWM的输出从而控制四路无刷电机,文件r_cg_main.c中的主函数中调整占空比即可,初始状态:200Hz,四路占空比50%。

R_MTU3_C0_Start(); //PWM OUT The initial value is 200Hz
R_MTU3_C2_Start(); //PWM OUT The initial value is 200Hz
MTU0.TGRB = 5000; //change duty PB2
MTU0.TGRC = 5000; //change duty PB1
MTU0.TGRD = 5000; //change duty PB0
MTU2.TGRA = 5000; //change duty PA3

简单说下我对以上代码理解,首先是配置MTU,MTU0和MTU2配置为PWM模式2,然后分别配置MTU0和MTU2模块,重点在PWM的输出设置上。
这里写图片描述

此处配置PWM输出周期为5ms(即PWM的频率为200Hz),相应的初始化寄存器值在0~9999之间,所以设置为5000即为占空比50%
(注意,给比较寄存器配置的初始值是低电平占整个周期的值,从波形图上也能够看出)。
但是就是把这段代码烧写到单片机中并不能让电机转动。

重点在这里

好了,重点来了,知道了电调是需要先解调之后才能控制电机,所以在网上各种贴吧挖坟找了一下解调的方法。这里就直接说我最后采用的可行的方法吧。

  • 首先了解基本原理

    单片机发送一定频率和脉宽范围的PWM给电调,电调进入编程设置模式,通过给出的脉宽的不同完成不同的设置。此时就要参考不同电调的使用说明书了。

  • 然后在此处我参考了另一个博主以前发的一篇博文

    http://blog.csdn.net/CalShell/article/details/44424347

  • 查到了好盈电机的使用说明书

这里写图片描述

这里写图片描述

这里写图片描述

参照了博主给出的设置电调的方法,起初我们采用将PWM频率设置为50Hz,即pwm输出周期为20ms,采用5%~10%的油门行程。
同上设置,在PWM的输出周期设置为20ms的情况下,寄存器的最大配置值为39999,所以最高油门设置时,寄存器应配置为40000-40000*0.1 = 36000,同理最低油门设置为38000。知道配置参数设置,我们就开始了实际调试的过程。

1、首先,我们将油门先设置到最高,然后给个延时(20ms左右)。
2、紧接着给寄存器赋值相应的值,将油门打到最低。但是电机仍然不会转动,电调仍然只是响启动音。
3、然后我们尝试延长延时的时间,新的现象就是电调在发出了哔哔两声之后,循环滴滴,嘀嘀嘀,嘀嘀嘀嘀(询问客服说是进入了电调调试模式了)。
4、然后我们陷入了卡死的状态,在这期间我们找到了其他人写的用arduino控制好盈电机的示例代码,烧进arduino板子上接上我们的电调确实可以驱动电机。
5、我们发现我们实现原理几乎一致,用示波器测试波形也几乎一致,唯一的区别就是频率有些不同,arduino中的PWM频率是用代码模拟的,只有40多赫兹不足50赫兹。
6、在这里我们就很魔性的把我们的频率设置为了40Hz,然后油门行程还是设置在5%~10%。并且加大了延时时间,这次将代码烧写进去也是先是听到了哔哔两声,然后就进入了哔哔哔哔的急促断音。
7、查看了好盈电机说明书,故障快速处理表格。出现我们的这种现象可能是油门未归零或者是油门行程设置过小,所以我们就尝试将油门行程增大到3%~10%。并且魔性的在代码里不断设置重复油门最高,延时(增大/减小),油门最低,延时(增大/减小)。
8、最后经过数次调试,终于找到了一个可行的延时时间。

最后可运行代码

void R_MAIN_UserInit(void)
{
    /* Start user code. Do not edit comment generated here */


    R_MTU3_C0_Start(); //PWM OUT   The initial value is 200HZ
    R_MTU3_C2_Start(); //PWM OUT   The initial value is 200HZ
    MTU0.TGRB = 45000;  //change duty PB2
    MTU0.TGRC = 45000;  //change duty PB1
    MTU0.TGRD = 45000;  //change duty PB0
    MTU2.TGRA = 45000;  //change duty PA3
    delay_ms(2500);     
    MTU0.TGRB = 48500;  //change duty PB2
    MTU0.TGRC = 48500;  //change duty PB1
    MTU0.TGRD = 48500;  //change duty PB0
    MTU2.TGRA = 48500;  //change duty PA3
    delay_ms(7000);

    /* End user code. Do not edit comment generated here */
}
void main(void)
{
    R_MAIN_UserInit();
    /* Start user code. Do not edit comment generated here */

    while (1U)
    {
        MTU0.TGRB = 48000;  //change duty PB2
        MTU0.TGRC = 48000;  //change duty PB1
        MTU0.TGRD = 48000;  //change duty PB0
        MTU2.TGRA = 48000;  //change duty PA3
    }
    /* End user code. Do not edit comment generated here */
}

pwm周期设置

这里写图片描述

附上示波器波形图

  • 采用40Hz的频率,占空比为10%,也就是设置油门最高操作

采用40Hz的频率,占空比为10%,也就是设置油门拉高操作

  • 频率40Hz,占空比为3%,也就是设置油门最低操作

频率40Hz,占空比为3%,也就是设置油门最低操作

  • 解调成功后通过PWM控制电机,范围在油门行程范围之类(即PWM占空比在3%~10%之间)

这里写图片描述

ps:我们尝试过将频率重新设置为50Hz,油门行程设置为3%~10%,然后电调并没有解调成功(其中我们也尝试过设置不同的延时时间或者是再将最低油门设置低一点,可是电调还是处于哔哔哔长叫中),小组成员也都很无语,。但是因为还要弄其他的模块,所以其中原因我们也不想深究了。写篇博文记录,以后有时间再深究吧!如果各位有知道原因的请不吝告知。

2019-06-09 18:26:18 qq_28056277 阅读数 1599

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

【注:学习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信号输出–示波器

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

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

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
原创文章,转载请注明出处,谢谢。

2016-08-03 11:29:18 zjzto 阅读数 3130

电调的控制方法——PWM

    单片机输出1ms~2ms的方波脉冲,根据航模标准,PWM信号线的频率应该是50Hz,对应的每个周期20ms,一般白色为油门线。如果是单向电调,1ms表示0%的油门,2ms表示100%的油门。如果是双向电调(有正、反转和刹车),标准1.5ms是0点,1ms是反向油门最大(100%油门),用于刹车或反转;2ms正向油门最大(100%油门),用于正转。这是无线遥控模型比例控制的一个标准。对于其它电调也一样。注意,电调转速只与1ms~2ms的脉宽有关,与脉冲重复率无关。1~2ms的方波脉宽渐变过程对应油门的从小到大,从负到正的渐变。 脉宽的幅度2.5V~6V;所以3~5V工作电压的单片机都适用。

默认接线都是正确OK,如下图示。


第一次使用电调需要配置,参考下图。



首先设定油门行程,代码如下

<span style="white-space:pre">	</span>
/*使用TIM2 channel1作为PWM输出口,频率50Hz定时器参考配置如下
#define  PERIOD_VALUE       (40000 - 1)  /* Period Value  */
#define  PULSE1_VALUE       2100        /* Capture Compare 1 Value  */
#define  PULSE2_VALUE       3000        /* Capture Compare 2 Value  */
#define  PULSE_MAX <span style="white-space:pre">	</span>    4000        /* 按照电调要求 1%即2ms  */
#define  PULSE_MIN          2000         /* 0.5%即1ms  */
uhPrescalerValue = (uint32_t) (SystemCoreClock / 2000000) - 1;
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* TIM2 init function */
static void MX_TIM2_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = uhPrescalerValue;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = PERIOD_VALUE;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim2);
} 

油门行程设置解释,置于main 函数初始化阶段
        HAL_Delay(1000);
	sConfigOC.Pulse = 4000;  //满油门
	HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); //启动
	HAL_Delay(3000); //延时3秒,实际可调整,确保能听到最高油门确认音
	sConfigOC.Pulse = 2000;//最高油门确认音后,油门至最低
	HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//确认
	HAL_Delay(2000);//延时,会有锂电节数音及最终确认音


注意上电顺序,先上单片机,再给电调供电!!

油门设定完成后即可进行正常上电,main 函数参数时,将占空比设置为5%(1ms)最低油门即可,再通过按键或者串口更改占空比进行调速。



完整代码:https://git.oschina.net/zjzto/XXDdriver.git

电调的总结

阅读数 1476

好盈电调使用

阅读数 3933

航模的遥控与电调

阅读数 4673

没有更多推荐了,返回首页