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

您所在的位置:网站首页 无刷电机调速电路图 用STM32F103单片机控制电调制动无刷电机

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

2024-07-09 18:09| 来源: 网络整理| 查看: 265

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

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3