STM32驱动SG90舵机完成控制

举报
DS小龙哥 发表于 2024/08/15 10:15:19 2024/08/15
【摘要】 SG90舵机还分为180度和360度的类型,以及模拟舵机和数字舵机。模拟舵机需要不断的发送PWM信号才能旋转到指定的位置,而数字舵机只需要给一个目的地的PWM信号,就可以转动到指定的位置。

一、前言

SG90舵机的工作原理主要是基于PWM(脉冲宽度调制)信号来控制。 SG90舵机内部有一个基准电压,微处理器产生的PWM信号通过信号线进入舵机,产生直流偏置电压,与舵机内部的基准电压做比较获得电压差输出。电压差的正负输出到电机驱动芯片上,从而决定电机的正反转。当舵机开始旋转的时候,舵机内部通过急联减速齿轮带动电位器旋转,使得电压差为零,电机停止转动。

SG90舵机还分为180度和360度的类型,以及模拟舵机和数字舵机。模拟舵机需要不断的发送PWM信号才能旋转到指定的位置,而数字舵机只需要给一个目的地的PWM信号,就可以转动到指定的位置。

在控制SG90舵机时,PWM波形的频率是50HZ,即周期为20毫秒。在这个周期内,通过控制高电平的时长,就能够控制舵机旋转的角度。例如,高电平为0.5毫秒时,舵机旋转到0度;高电平为2毫秒时,旋转到135度;高电平为1.5毫秒时,旋转到90度。

视频讲解: https://www.bilibili.com/video/BV144421U7w7

SG90舵机的工作原理是通过接收PWM信号,控制电机的转动,从而带动舵机的旋转,实现精确的角度控制。

image-20240715151053366

下面是180°的SG90舵机商家给出的说明:写了高电平时间与转动的角度对应关系。

image-20240715150016656

什么样的波形是PWM波形? 下面的图片就是一个解释。

image-20240715150153403

对于舵机的驱动原理: 只需要产生一个周期为20ms,高电平宽度为0.5ms-2.5ms的PWM方波就能驱动舵机。

180°舵机 是一次PWM波形就可以转到指定的角度。

360°舵机需要持续发送PWM波形才可以转动。

一个完整的PWM是由高电平和低电平组成的。 也就是一个周期内,也就是这个20ms内。 可以自由分配 高低电平的占用时间。

这个分配 高低电平的占用时间的过程就叫:调整占空比。

只需要控制这个20ms的周期内。高电平的时间在 0.5ms-2.5ms 范围的内的PWM波形。 就可以任意控制舵机转动。 那么 0.5ms-2.5ms 之间不同的值是有什么不同的效果? 对于: 90°舵机、180°的舵机 是不一样的。

我当前是采用STM32F103单片机驱动的SG90舵机,采用的定时器1的通道1和通道4产生PWM波形,控制2个SG90转动。

定时器1的CCR1寄存器就是比较寄存器,定时器1的CNT寄存器在定时器启动之后就会不断的自增或自减(具体看配置),简单的说就是,CNT寄存器是一个时间基准;而输出的PWM占空比就是依靠CNT寄存器的值与CCR1寄存器的值进行相互比较。 比谁大谁小,从而控制当前的电平是低电平还是高电平,这个过程就是控制占空比的过程。 具体的代码表现形式就是: TIM1->CCR1=xxx 

STM32F103RCT6单片机定时器的运行频率是72MHZ; 如果我的定时器分频为720,重装载值填2000,这样的配置,输出的一个PWM周期就是50HZ,也就一个周期的总时间是20ms。

那么如何在代码里,如何实现控制 0.5ms-2.5ms 这个范围的高电平?

如果设置为: TIM1->CCR1=1860; 就表示 2000 -1860 = 140 = 1.4ms高电平。 如果设置为: TIM1->CCR1=1880; 就表示 2000 -1880= 120 = 1.2ms高电平。 ...... ...... ......

二、程序开发

2.1 逻辑分析仪测试

写好代码之后,可以先用逻辑分析仪检测一下单片机IO口输出的PWM情况。

image-20240715151236141

如果设置为: TIM1->CCR1=1860; 就表示 2000 -1860 = 140 = 1.4ms高电平。

看下面的逻辑分析仪测量的结果:

image-20240712204524403

image-20240712204335131

2.2 舵机的驱动问题

SG90舵机驱动的时候,要给外部电源。 如果采用开发板USB供电,是带不动2个以及2个以上的SG90舵机,需要外接稳压电源提供足够的电流才可以正常驱动舵机转动。 这个一定要注意。

2.3 完整代码


cpp
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include <string.h>
#include <stdlib.h>


/*


STM32F103C8T6可以用的IO口:PA0-PA15, PB0-PB15, PC13-PC15



STM32F103C8T6最小系统板的IO口。
PB11 PB10 PB1 PB0 PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 PC15 PC14 PC13 
PB12 PB13 PB14 PB15 PA8 PA9 PA10 PA11 PA12 PA15 PB3 PB4 PB5 PB6 PB7 PB8 PB9



PA13(SWDIO)和PA14(SWCLK): 用作STLNK-V2下载器的-SW模式的下载口。


【】摄像头云台舵机
GND----------->GND
VC------------->5V
PA8------------>IO(上下控制舵机)-定时器1的PWM-CH1
PA11---------->IO (左右控制舵机)-定时器1的PWM-CH4


*/



//舵机停止
void motor_Ctrl_Up_Down_stop(void)
{
    TIM1->CCR1=1850;	      //改变占空比
}

//舵机停止
void motor_Ctrl_Left_Right_stop(void)
{
    TIM1->CCR4=1850;	      //改变占空比
}


//舵机开始转动: 正向
void motor_Ctrl_Up_Down_1(void)
{
    TIM1->CCR1=1860;	      //改变占空比
}


//舵机开始转动: 反向
void motor_Ctrl_Up_Down_2(void)
{
    TIM1->CCR1=1840;	      //改变占空比
}


//舵机开始转动: 正向
void motor_Left_Right_Down_1(void)
{
    TIM1->CCR4=1860;	      //改变占空比
}


//舵机开始转动: 反向
void motor_Left_Right_Down_2(void)
{
    TIM1->CCR4=1840;	      //改变占空比
}



//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;	   
#define JTAG_SWD_DISABLE   0X02
#define SWD_ENABLE         0X01
#define JTAG_SWD_ENABLE    0X00		  
void JTAG_Set(u8 mode)
{
	u32 temp;
	temp=mode;
	temp<<=25;
	RCC->APB2ENR|=1<<0;     //开启辅助时钟	   
	AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]
	AFIO->MAPR|=temp;       //设置jtag模式
}

void set_pwm_1(float ms)
{
    if(ms >20)
    {
        ms=20;
    }
    TIM1->CCR1=2000-(ms*100);
}


void set_pwm_4(float ms)
{
    if(ms >20)
    {
        ms=20;
    }
    TIM1->CCR4=2000-(ms*100);
}


int main()
{
    //开启STLINK_SWD下载模式
    JTAG_Set(SWD_ENABLE);
    
    //串口1初始化,用于打印
    USART1_Init(115200);
    printf("STM32串口1初始化成功.\r\n");
      
    
    //初始化定时器1,输出PWM,通道1、4,控制SG90舵机
    //一个周期20ms 
    TIM1_PWM_Init(2000,720); //计数频率  单脉冲+重复计数模式	
    
    //转动到0°
    set_pwm_1(0.5);
    set_pwm_4(0.5);
    
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
   
   
    while(1)
    {  
        
        //转动到90°
        set_pwm_1(1.5); //第一个先转90
        set_pwm_4(2.5); //第二个再转180

        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);

        set_pwm_1(0.5); //之后第一个再转到0。
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        
        set_pwm_1(1.5); //然后第一个再赚到90。
        
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        
        set_pwm_4(0.5);//然后第二个再占到零。
        
        delay_ms(1000);
        delay_ms(1000);
         delay_ms(1000);
        delay_ms(1000);
        
        set_pwm_1(0.5); //然后第一个在转到零。
        
        delay_ms(1000);
        delay_ms(1000);
         delay_ms(1000);
        delay_ms(1000);
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。