写点什么

STM32F103RCT6 驱动 SG90 舵机 - 完成正反转角度控制

作者:DS小龙哥
  • 2023-04-18
    重庆
  • 本文字数:2276 字

    阅读完需:约 7 分钟

一、SG90 舵机介绍

SG90 是一种微型舵机,也被称为伺服电机。它是一种小型、低成本的直流电机,通常用于模型和机器人控制等应用中。SG90 舵机可以通过电子信号来控制其精确的位置和速度。它具有体积小、重量轻、响应快等特点,因此在各种小型机械设备上得到了广泛应用。


SG90 舵机通常用于各种小型机械设备中,例如:


模型控制:SG90 舵机可以用于遥控汽车、飞机、船只和其他模型的转向、加速和刹车等控制。


机器人控制:SG90 舵机也广泛应用于机器人领域,例如可以控制机器人的头部旋转、臂部移动等。


相机云台:SG90 舵机可以用于控制相机的运动,例如实现云台的左右旋转和上下移动。


自动化系统:在一些自动化系统中,SG90 舵机可以用来控制小型机械臂或手指的运动。


总之,SG90 舵机适用于需要精确定位和紧凑设计的应用场景。



二、普通 IO 口模拟 PWM 驱动 SG90 舵机

以下是一个简单的示例代码,用于通过 PB5 普通 IO 口产生模拟 PWM 信号来控制 SG90 舵机正向旋转和反向旋转:


#include "stm32f10x.h"
#define PWM_FREQ 50 // 设置PWM信号频率为50Hz#define SERVO_MIN_PULSE_WIDTH 500 // 舵机最小脉宽500us#define SERVO_MAX_PULSE_WIDTH 2500 // 舵机最大脉宽2500us
void delay_us(uint32_t us) { uint32_t count = us * (SystemCoreClock / 1000000) / 9; while(count--);}
void servo_rotate(uint16_t pulse_width) { GPIO_SetBits(GPIOB, GPIO_Pin_5); // 设置PB5输出高电平 delay_us(pulse_width); // 延时等待脉宽结束 GPIO_ResetBits(GPIOB, GPIO_Pin_5); // 设置PB5输出低电平 delay_us(20000 - pulse_width); // 延时保持50Hz的PWM周期}
int main(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // PB5口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最大输出频率为50Mhz GPIO_Init(GPIOB, &GPIO_InitStructure);
while(1) { // 控制舵机正向旋转360° for (int i = SERVO_MIN_PULSE_WIDTH; i <= SERVO_MAX_PULSE_WIDTH; i += 10) { servo_rotate(i); } for (int i = SERVO_MAX_PULSE_WIDTH; i >= SERVO_MIN_PULSE_WIDTH; i -= 10) { servo_rotate(i); } // 控制舵机反向旋转360° for (int i = SERVO_MAX_PULSE_WIDTH; i >= SERVO_MIN_PULSE_WIDTH; i -= 10) { servo_rotate(i); } for (int i = SERVO_MIN_PULSE_WIDTH; i <= SERVO_MAX_PULSE_WIDTH; i += 10) { servo_rotate(i); } }}
复制代码


在这个代码中,我们首先定义了 PWM 频率以及舵机的最小和最大脉宽。然后,我们实现了一个延时函数delay_us(),用于产生指定微秒数的延时。接下来,我们实现了一个servo_rotate()函数,用于控制舵机的旋转。


servo_rotate()函数中,我们将 PB5 口设置为高电平,并延时等待一段时间,使得舵机旋转到相应的角度;然后将 PB5 口设置为低电平,延时保持 PWM 周期的长度,以达到模拟 PWM 信号的效果。


在主函数中,我们通过循环控制舵机旋转 360 度,并在正向和反向旋转之间进行切换。具体来说,我们通过循环执行servo_rotate()函数,并改变脉宽的值,实现舵机的旋转。


需要注意的是,这个示例代码只是一个简单的演示,实际使用中可能需要根据舵机的具体型号和应用场景进行调整。同时,由于使用的是延时产生模拟 PWM 信号,因此控制的精度可能会受到其他因素的影响,如果需要更高的控制精度,可以考虑使用硬件定时器来产生 PWM 信号。

三、通过定时器输出 PWM 控制 SG90 舵机

(1)配置定时器 4 的通道 1 为 PWM 模式,并且设置频率为 50Hz,占空比为 5%~10%。


代码如下:


// 开启TIM4时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// 定时器4 PWM模式配置TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = 1999; // 72M / (2*2000) = 18KHzTIM_TimeBaseStructure.TIM_Prescaler = 35; // 分频系数36TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
// 定时器4通道1 PWM输出配置TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 100; // 初始值TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OC1Init(TIM4, &TIM_OCInitStructure);
// 开启定时器4TIM_Cmd(TIM4, ENABLE);
复制代码


(2)使用定时器 4 的通道 1 输出 PWM 信号,使舵机正向旋转 360°,即将占空比由 5%~10%逐渐增加至 12.5%~2.5%。代码如下:


for (int i = 100; i <= 250; i += 10) {    TIM_SetCompare1(TIM4, i);    delay_ms(50);}
复制代码


(3)使用定时器 4 的通道 1 输出 PWM 信号,使舵机反向旋转 360°,即将占空比由 12.5%~2.5%逐渐减小至 5%~10%。代码如下:


for (int i = 250; i >= 100; i -= 10) {    TIM_SetCompare1(TIM4, i);    delay_ms(50);}
复制代码


在上面的代码中,delay_ms()函数是一个简单的延时函数,用于控制每次占空比变化后等待一段时间再进行下一步操作。需要自己实现这个函数。


另外,SG90 舵机正向旋转和反向旋转的具体占空比可能有所不同,需要根据实际情况调整代码中的占空比值。

发布于: 刚刚阅读数: 4
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022-01-06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
STM32F103RCT6驱动SG90舵机-完成正反转角度控制_三周年连更_DS小龙哥_InfoQ写作社区