一 、舵机概述

方案中所测试两款180°舵机:MG996R 和 MG995 。

1、舵机的分类

  • 按旋转角度

180°舵机:能给定角度、固定转速。 只能在0度到180度之间运动,超过范围,舵机轻则齿轮打坏,重则烧坏内部电路.

360°舵机:能360度转动, 能控制转速。但不能调节转动的角度。

  • 按控制信号

模拟舵机:要持续提供PWM信号才能固定角度。优点:便宜。

数字舵机:只要给一次PWM信号就能固定角度。优点:高精度,响就快,抖动小,更大的角度固定力。

2、几个重要参数

  • 最大扭矩:如上面的MG996, 最大扭矩: 13KG/cm. 这个是在舵机堵转时测得的, 其时距离轴中心1cm处能挂起的重量.
  • 工作电压:如常用的3.0V~7.2V, 接入电压不同, 所能产生的工作扭矩自然不同. 直接影响角度固定力。

3、引脚接线说明

  • 红色:供电;电流比较大,除非测试, 真不建议在开发板上取电;

  • 粽色:地线;必须与控制器, 如SMT32芯片共地;

  • 橙色:PWM信号线;接芯片的TIMx外设的CHx脚;


二、舵机控制原理

以本次测试的180度模拟舵机为例进行笔记讲解。

1、原理简述

舵机接收的是PWM信号,能使舵机内部电路产生一个偏置电压,触发电机通过减速齿轮带动电位器移动,当电压差为零时,电机停转,从而达到伺服的效果。

即,给舵机提供一个特定的PWM信号,舵机就可以旋转到指定的位置。

2、PWM信号、角度

舵机接收的PWM信号频率为50HZ,即周期为20ms。当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。

为了更好地理解其信号,和编写代码,把PWM关键点转换如下:

  1. PWM信号周期:       20000us
  2. 0度时,高电平时长:    500us
  3. 180度时, 高电平时长:2500us
  4. 每增加1 °,需增加高电平时长:(2500-500)÷180 = 11.1us
  5. 某角度值A,需要的总高电平时长:(A x11.1 +500)us

特别地说明: 把所有ms值, 转换为us值, 是为了方便代码的编写和理解. 


三、STM32代码实现

工程代码: STM32F103RC + 标准库函数v3.5;

1、所用引脚的宏定义

/******************************************************************************* 移植配置
****************************************************************************/
// 舵机_1
#define SERVO_1_GPIO                GPIOB                     // GPIO
#define SERVO_1_PIN                 GPIO_Pin_8                // PIN
#define SERVO_1_TIM_PORT            TIM4                      // 定时器: TIMx
#define SERVO_1_TIM_CH              3                         // 通道: CHx
#define SERVO_1_ANGLE_RESET         90                        // 上电复位后的角度
// 时基配置, 适用20ms周期的舵机
#define SERVO_TIM_PSC               72                        // 计数器时钟=72000000/72=1000000次/秒=1us/次
#define SERVO_TIM_ARR               20000                     // 周期=20000*1us=20ms

为了加大代码移植的方便,取消时钟的宏定义,在初始化函数里根据所用端口做判断后使能各时钟.

2、GPIO初始化

// GPIO配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin   = PINx;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOx, &GPIO_InitStructure);

引脚配置要点:复用推挽模式(GPIO_Mode_AF_PP);

2、TIM初始化

void TIM_PwmInit(GPIO_TypeDef* GPIOx, u16 PINx, TIM_TypeDef* TIMx, u8 CHx, u16 PSC, u16 ARR, u16 CCR)
{TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;// TIM时基配置TIM_TimeBaseStructure.TIM_Prescaler= (psc-1);                // 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Period= (arr-1);                       // 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;          // 时钟分频因子 ,用于配置死区时间,没用到,随意TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;     // 计数器计数模式,设置为向上计数    TIM_TimeBaseStructure.TIM_RepetitionCounter=0;                // 重复计数器的值,没用到,可以随意设置TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);              // 初始化定时器        // 输出比较模式TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;            // 配置为PWM模式2TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  // 输出使能TIM_OCInitStructure.TIM_Pulse = ccr;                           // 设置占空比大小TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;       // 输出通道电平极性配置if(CHx==1)  TIM_OC1Init(TIMx, &TIM_OCInitStructure);if(CHx==2)  TIM_OC2Init(TIMx, &TIM_OCInitStructure);if(CHx==3)  TIM_OC3Init(TIMx, &TIM_OCInitStructure);if(CHx==4)  TIM_OC4Init(TIMx, &TIM_OCInitStructure);// CCR预装载if(CHx==1)  TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);   if(CHx==2)  TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);if(CHx==3)  TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);if(CHx==4)  TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);TIM_Cmd(TIMx, ENABLE);                                        // 使能计数器//TIM_CtrlPWMOutputs(TIMx, ENABLE);                             // 主输出使能,当使用的是通用定时器时,这句不需要
}

如果没有这几行 if 语句,代码简洁。

使用这些 if 进行判断的原因, 是因为我想把PWM的初始化函数, 做成更容易复用的代码, 这样以后要初始化某个TIM做PWM输出, 那只要传入相应的参数即可:

void TIM_PwmInit(GPIO_TypeDef* GPIOx, u16 PINx, TIM_TypeDef* TIMx, u8 CHx, u16 PSC, u16 ARR, u16 CCR);

上面的TIM初始化,是经这个函数传入参数的。

重点解释一下:PSC, ARR, CCR, CNT

  1. PSC:TIM时钟的分频系数:72;内部时钟经PSC值分频后, 传给CNT计数器使用;
  2. CNT:计数器,CNT每计数一次的脉冲时长为:1÷(CLK÷PSC)  =  1÷(72000000÷72) = 0.000001s/次 = 1us/次;
  3. ARR:自动重装载值:20000,CNT计数器经过多少次脉冲就重新开始计数。用这个值可控制需要的PWM信号周期:1us x 20000次  = 20 000us = 20ms
  4. CCR:用于控制周期内高电平时长, 当CNT<CCR时, 为有效电平. 而有效电平的高低, 则是通过CCER寄存器设置的, 默认的有效电平为高电平.

3、角度输出函数

// 舵机1#配置角度
// 【可选参数】 [angle]0.0°~180.0°;
void AnalogServo_1_Angle(float angle)
{u16 ccr_1=0;xServo.angleNow_1 = angle;if(xServo.angleNow_1>180)    xServo.angleNow_1 =180;                    // 限制最大值, 防止出错if(xServo.angleNow_1<  0)    xServo.angleNow_1 =2;                      // 限制最小值, 防止出错ccr_1 = xServo.angleNow_1*11.11 +500;                                   // 把角度值, 换算成CCR值TIM_SetCCR(SERVO_1_TIM_PORT, SERVO_1_TIM_CH, ccr_1);                    // 配置TIMx的CCR寄存器值
}// 控制TIMx的CCRx的值;【可选参数】 [TIMx]TIM1~8, [CHx]1~4, [CCR]0~65535;
void TIM_SetCCR(TIM_TypeDef* TIMx, u8 CHx, u16 CCR)
{    if(CHx==1)    TIMx->CCR1 = CCR;if(CHx==2)    TIMx->CCR2 = CCR;if(CHx==3)    TIMx->CCR3 = CCR;if(CHx==4)    TIMx->CCR4 = CCR;
}

哈,自己有个死穴,不管学习某个方面的知识时,理解得有多深刻,过一段时间后,总是会淡忘得一干二净的。

所以,这个代码做成调用时,直接传入角度即可,以后就不用回忆高电平与角度的关系了。


四、完整代码下载

工程所用STM32F103RC的核心版,完整代码,已分到CSDN的资料库。

完整代码下载: STM32_舵机PWM控制代码.zip

同时也分享了一份Q群 887199504 的文件夹,可自由下载的。

180°舵机角度控制(mg996 + stm32F1)相关推荐

  1. SG90 180°舵机的使用

    SG90 180°舵机的使用 SG90的介绍 舵机是一种位置(角度)伺服的驱动器,适用于需要角度不断变化并可以保持的控制系统,可以根据控制信号来输出指定的角度(常见的有0-90°.0-180°.0-3 ...

  2. 180°舵机如何控制?

    180°舵机最常见的是SG90舵机,用的也最多,非常便宜,某多多5.6块就可以买到一个,大概长这样: 前言 大二刚学单片机,觉得单片机很厉害,然后就想做一个宿舍智能开门装置.然后我就想其中最主要的问题 ...

  3. 基于stm32f103zet6控制180°舵机的详细使用及测试(keil5软件)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.代码 总结 前言 该文章适合于32单片机小白入手外设的一个代码篇章,主要通过按键来控制pwm占空比来控制舵机转动不 ...

  4. 180°舵机的使用步骤

    一.步骤 1.首先查看舵机的运行参数,包括工作的电压和电流,转1°(60°)需要的脉宽是多少. 2.根据舵机提供的参数,算出需要的PWM的周期和脉宽的范围. 3.通过单片机或者其他数字电路产生相应的P ...

  5. arduino的180度舵机与360度舵机控制

    文章目录 前言 一.180度舵机 二.360度舵机 三.区别于应用 1.区别 2.应用 总结 前言 许多时候我们都会用到舵机,目前市面上的舵机大致分为两种,一种是180度舵机,另一种是360度舵机,下 ...

  6. MG90S 舵机180°角度驱动

    MG90S简介 舵机: 是一种角度伺服电机,一般是由齿轮组.电位器.舵机控制电路.直流电机构成.由发送控制信号来控制输出轴的位置. 数字舵机与模拟舵机的区别: MG90S是一款常用的数字舵机,还有一款 ...

  7. 舵机分类和控制原理简述(180°模拟电机)SG90 MG996R

    -- 参考书目:<我的机器人 仿生机器人的设计与制作>罗庆生 北京理工大学出版社 舵机 舵机是一种位置(角度)伺服的驱动器,最早用于航模,相当于廉价版的伺服电机,但仅保留了位置环,适用于那 ...

  8. 学习 stm32(TTL)串口通信控制16路舵机控制板(维特智能)

    学习STM32Core平台串口2连接维特智能串口Normal协议,然后通过串口1直接连接舵机控制板(TTL),接收进行通信:需要看产品文档的可以直接官网搜索文档. 16路舵机控制板官方产品网址 在查看 ...

  9. 180°和360°伺服电机速度控制,转向控制Arduino代码与库(亲测可用)

    写在前面的话:如果你只想要我代码,建议你复制粘贴第一个和最后一个,试试.如果你想学习以后如何解决类似问题而不是仅仅的抄代码,建议你读完我啰嗦的话.希望对你有所帮助.你可以抄袭我代码,但请添加出处/引文 ...

最新文章

  1. 华为IPSEC-×××-典型配置举例1-采用手工方式建立IPsec 安全隧道
  2. Leetcode 383 Ransom Note
  3. 如何快速创建程序组_如何快速开发小程序
  4. Android 动态类加载实现免安装更新
  5. vue-beauty 的v-data-table数据单元不换行
  6. 【Python】体育竞技分析
  7. 《scikit-learn》通过GridSearchCV来进行超参数优化
  8. 浅谈深拷贝 与 浅拷贝
  9. NandFlash启动理解(S3C2410)
  10. Windows 1.0
  11. win64位下安装python的image支持
  12. 【推荐算法】今日头条、抖音推荐算法原理全文详解!
  13. OBS-Linux直播神器(录屏神器)
  14. 云和恩墨助力大地保险新核心业务系统上线,开启数字化保险4.0时代
  15. 群晖7.X关闭双重验证(OTP)的方法
  16. jquery鼠标经过水平180度翻转效果
  17. DxmCms自动过滤内容中的广告法违禁词功能
  18. 系统架构师(十四)信息系统
  19. 微软联合创始人保罗·艾伦因病离世,享年 65 岁
  20. 压测工具Jmeter下载及使用小解

热门文章

  1. 2022年陕西省中级工程师职称评审流程及申报条件
  2. One by wacom数位板安装及初步使用
  3. springcloud在 repository层通过sql语句实现查询功能
  4. Solidity概述及基本代码展示
  5. android 全局浮动球,Android仿360悬浮小球自定义view实现
  6. NUC 折腾笔记 - 储存能力测试
  7. 使用CH340串口模块对STM32进行程序下载
  8. 耳机插在电脑上怎么录音,在线录制音频的软件有什么?
  9. 数学建模学习笔记(十五)数据归一化
  10. Matlab实现的FEMIC的说明书