stm32f103c8t6利用蓝牙控制180度舵机
关于蓝牙模块部分,如果不了解蓝牙模块的可以看我之前发的东西。
一般来说,舵机接收的PWM信号频率为50HZ,即周期为20ms。当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。以180度角度舵机为例,那么对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
关于舵机的话,本人用的是6~8.4V的的60KG大舵机,这里需要注意的是, 控制板上面只提供5V电压,满足不了这种舵机的电压,所以我利用12V的锂电池,让锂电池的正负极接在降压模块输入端的正负极,接着让降压模块输出端的正负极接舵机的正负极,也就是说舵机是独立供电的,最重要的一点就是舵机外接电源的GND需要和控制板的GND接在一起,也就是共地,这样舵机才能转动,否则是转动不了的,如果你用的是5V的舵机,虽然大多数情况直接接控制板的正负极可以让舵机转动,但是这样电压不稳定,会导致舵机转动一个角度后就卡死了,所以本人建议舵机最好都给他个独立的电源,这样舵机就能连续转动,不会产生卡死状态。以下是本人所用的降压模块和60K大舵机的图片及视频效果,这种大舵机速度比较慢,但是扭矩大。
以下的舵机VCC->降压模块的VCC
舵机的GND->降压模块的GND
舵机的信号线->stm32控制板的PB5(TIM3_CH2)
<iframe allowfullscreen="true" data-mediaembed="csdn" id="ODzJytkK-1606708112132" src="https://live.csdn.net/v/embed/110280"></iframe>
2.mp4
下面附上主程序:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
extern u8 res;
int main(void)
{
int len;
int t;
int i;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
My_USART2_Init();
TIM1_PWM_Init(199,7199); //不分频。T为20ms,这样的配置就是为了让输出的PWM信号达到舵机要求的20ms周期。
while(1)
{
if(res=='1'){TIM_SetCompare2(TIM3,175);delay_ms(1000);}对应180度
if(res=='2'){TIM_SetCompare2(TIM3,180);delay_ms(1000);}对应135度
if(res=='3'){TIM_SetCompare2(TIM3,185);delay_ms(1000);}对应90度
if(res=='4'){TIM_SetCompare2(TIM3,190);delay_ms(1000);}对应45度
if(res=='5'){TIM_SetCompare2(TIM3,195);delay_ms(1000);}对应0度
//在周期20ms的PWM信号中,不同的脉宽对应舵机不同的转动角度,在0.5ms-2.5ms间有效
// TIM_SetCompare2(TIM4,175);//总共计数200,前面设置的模式是计数在比较值之后才是高电平
//也就是高电平的时间是[(200-175)/200]*20ms=2.5ms,即转过360度,180度舵机依次类推
}
}
子程序:
#include "timer.h"
#include "led.h"
#include "usart.h"
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOA.8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//初始化TIM1
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_TimeBaseStructure.TIM_RepetitionCounter=0;//重复计数器的值
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM1 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
//TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
//TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;//输出通道空闲电平极性设置
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
//TIM_OC4Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器
// TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_Cmd(TIM3, ENABLE); //使能TIM1
//TIM_CtrlPWMOutputs(TIM1, ENABLE);//主输出使能,当使用的通用定时器时,这句不需要
}
如果在定时器初始化时TIM_OCInitStructure.TIM_OCMode配置的是PWM1模式那么main中的占空比就依次为25、20、15、10、5。下面解释一下模式PWM1和模式PWM2的区别:
假定TIM_OCInitTypeDef.TIM_OCPolarity = TIM_OCPolarity_High
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位。
本人用的是PWM2模式,在你们自己试验时,可以将占空比设置成各种不同的值,看看有什么不同的效果。
下面附上完整的程序:
stm32f103c8t6通过蓝牙控制180度舵机程序