舵机SG90详解
舵机,也叫伺服电机,在嵌入式开发中,舵机作为一种常见的运动控制组件,具有广泛的应用。其中,SG90 舵机以其高效、稳定的性能特点,成为了许多工程师和爱好者的首选,无论是航模、云台、机器人、智能小车中都有它的身影。
本文将深入探讨SG90舵机的技术规格、工作原理和使用方法,为您展现 SG90 舵机的功能和无限可能。
1. 源码下载及前置阅读
本文首发良许嵌入式网:https://www.lxlinux.net/e/ ,欢迎关注!
本文所涉及的源码及安装包如下(由于平台限制,请点击以下链接阅读原文下载):
https://www.lxlinux.net/e/stm32/sg90-tutorial.html
如果你是嵌入式开发小白,那么建议你先读读下面几篇文章。
- 了解不同的下载程序方法,为你的嵌入式开发提供更多选择:STM32下载程序的五种方法
- 手把手让你掌握MDK的使用方式和技巧,助你更高效地进行开发:一文教你使用MDK开发工具
- 从零开始轻松掌握STM32开发的必备指南:零基础快速上手STM32开发(手把手保姆级教程)
往期精彩教程,有兴趣的小伙伴可以看看。
从零开始轻松掌握STM32开发的必备指南:零基础快速上手STM32开发(手把手保姆级教程)
深入浅出,帮助您理解和应用MQTT协议:万字猛文:MQTT原理及案例
通俗易懂的 GPIO 介绍与实践:如何快速成为点灯大师?
| 作者简介 |
|---|
| 大家好,我是良许,博客里所有的文章皆为我的原创。 下面是我的一些个人介绍,欢迎交个朋友: · 211工科硕士,国家奖学金获得者; · 深耕嵌入式11年,前世界500强外企高级嵌入式工程师; · 书籍《速学Linux作者》,机械工业出版社专家委员会成员; · 全网60W粉丝,博客分享大量原创成体系文章,全网阅读量累计超4000万; · 靠自媒体连续年入百万,靠自己买房买车。 |
我本科及硕士都是学机械,通过自学成功进入世界500强外企。我已经将自己的学习经验写成了一本电子书,超千人通过此书学习并转行成功。现在将这本电子书免费分享给大家,希望对你们有帮助:
电子书链接:https://www.lxlinux.net/1024.html

2. SG90介绍
2.1 型号介绍
市面上常见的舵机型号有 SG90、MG90S、MG995、MG996R 等等,主要是扭矩大小、工作电压大小、齿轮材质塑料或金属的不同。
一般分为180度和360度:
- 180度:可以控制旋转角度、有角度定位。上电后舵机自动复位到0度,通过一定参数的脉冲信号控制它的角度。
- 360°舵机版本不可控制角度,只能控制顺时针旋转、逆时针旋转、停止和调节转速。
我们今天的主角是 SG90,180度版。

2.2 工作参数及引脚介绍
工作参数如下:
- 工作扭矩:1.6kg/cm
- 反应速度:0.12 - 0.13秒/60°
- 死区设定:5us
- 转动角度:常见0°、90°、180°、360°
- 齿轮材质:尼龙塑料齿
- 工作电压:3V - 6V
- 温度范围:-30° ~ +60°
引脚接线参考如下:
| SG90 | STM32 |
|---|---|
| PWM 信号线(橙色线) | 任意GPIO |
| VCC(红线) | 3.3/5V |
| GND(棕色线) | GND |
3. SG90原理
舵机的控制信号是通过脉冲宽度调制(PWM)来实现的。PWM 信号的周期通常为20ms,而脉冲宽度则在 0.5ms 至 2.5ms 之间变化。这个脉冲宽度与舵盘的位置呈线性关系,范围从0度到180度。
当给舵机提供特定宽度的脉冲信号时,输出轴会保持在相应的角度上,不受外界转矩的影响,直到接收到不同宽度的脉冲信号才会改变输出角度,使舵盘移动到新的位置。舵机内部有一个基准电路,产生周期为 20ms、宽度为 1.5ms 的基准信号。同时,还有一个比较器,用于将外部输入信号与基准信号进行比较,以确定转动方向和幅度,并生成驱动电机转动的信号。
控制电路板接收来自信号线的 PWM 控制信号,然后控制电机的转动。电机带动一系列齿轮组,在经过减速传动后,将力量传递到输出舵盘上。舵机的输出轴与位置反馈电位计相连,当舵盘旋转时,位置反馈电位计也会随之变化,向控制电路板输出电压信号进行反馈。控制电路板根据位置反馈信号判断当前位置,并决定电机的转动方向和速度,以实现目标停止。
为了控制舵机,需要使用单片机来生成周期为 20ms 的脉冲信号,并通过控制脉冲的高电平时间在 0.5ms 至 2.5ms 之间来控制舵机的角度。这样,我们可以通过调整 PWM 信号的脉冲宽度来精确控制舵机的位置和运动。
以 SG90,180度版为例,那么对应的控制关系是这样的:
| 脉冲高电平 | 角度 | 占空比 |
|---|---|---|
| 0.5ms | 0° | 2.5% |
| 1.0ms | 45° | 5.0% |
| 1.5ms | 90° | 7.5% |
| 2.0ms | 135° | 10.0% |
| 2.5ms | 180° | 12.5% |
4. 编程实战
现在我们就动手,让 SG90 每秒转动一下,0° -> 20° -> 40° -> 100° -> 180° 如此循环。
4.1 硬件接线
本教程使用的硬件如下:
- 单片机:STM32F103C8T6
- 舵机:SG90
- 烧录器:ST-LINK V2
接线如下:
| SG90 | STM32 |
|---|---|
| PWM 信号线(橙色线) | A0 |
| VCC(红线) | 3.3/5V |
| GND(棕色线) | GND |
烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【STM32下载程序的五种方法】。
| ST-Link V2 | STM32 |
|---|---|
| SWCLK | SWCLK |
| SWDIO | SWDIO |
| GND | GND |
| 3.3V | 3V3 |
接好如下图:
我用的是我自己打的板子,上官二号。大家可以用自己的板子,是 STM32F103C8T6 就行。

4.2 舵机初始化
将舵机 PWM 引脚进行一个初始化。
void SG_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0; /* PWM引脚 */
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; /* 复用推挽 */
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* 初始化PWM引脚 */
}
4.3 定时器初始化
我们 PWM 引脚接 A0,对应的是定时器2和通道1,以下是初始化代码。
void TIM2_Init(void)
{
//PA0 ------> TIM2_CH1
TIM_ClockConfigTypeDef sClockSourceConfig = {0}; /* 定时器设置结构体 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2; /* 通用定时器2 */
htim2.Init.Prescaler = 7199; /* 预分频系数 */
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */
htim2.Init.Period = 199; /* 自动装载值 */
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 时钟分频因子 */
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_Base_Init(&htim2);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);
HAL_TIM_PWM_Init(&htim2);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* 定时器2时钟使能 */
__HAL_RCC_TIM2_CLK_ENABLE();
}
}
4.4 舵机控制
已知 PWM 信号的周期为20ms;高电平 0.5ms 指向 0° 位置,2.5ms 指向 180° 位置。如果我们要指向 angle°:
2.5-0.5=2ms,对应于180°
CCRx / (199 + 1) * 20 = 0.5 +(angle / 180)× 2
于是 CCRx =(1.0 / 9.0) * angle + 5.0
void SG_Control(uint16_t angle)
{
float CCRx;
CCRx =(1.0 / 9.0) * angle + 5.0; //占空比值 = 1/9 * 角度 + 5
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (uint16_t )CCRx);
}
4.5 主函数
主函数如下:
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
TIM2_Init(); /* 定时器4初始化 */
SG_Init(); /* 舵机初始化 */
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
while(1)
{
SG_Control(0); //舵机旋转到0度
HAL_Delay(1000);
SG_Control(20); //舵机旋转到20度
HAL_Delay(1000);
SG_Control(40); //舵机旋转到40度
HAL_Delay(1000);
SG_Control(100); //舵机旋转到100度
HAL_Delay(1000);
SG_Control(180); //舵机旋转到180度
HAL_Delay(1000);
}
}
4.6 运行效果
SG90 每秒转动一下,0° -> 20° -> 40° -> 100° -> 180° 如此循环。

5. 总结
通过了解 SG90 舵机的工作原理和特点,我们可以更好地利用它的潜力,为我们的项目带来更多可能性和创新。无论是初学者还是专业工程师,SG90 舵机都是一个很不错的模块,它可以帮助我们实现精确的位置控制和稳定的运动性能。
希望本文能够让你对 SG90 舵机有更深入的了解,并且能够在你的项目中发挥出它的优势。感谢各位看官,peace and love!
舵机SG90详解的更多相关文章
- PID应用详解
PID应用详解 阅读目录 1.PID介绍及原理2.常用四轴的两种PID算法讲解(单环PID.串级PID)3.常用PID算法的C语言实现5.常用的四轴飞行器PID算法 PID介绍及原理 PID介绍 在工 ...
- ATmega328P定时器详解
写这篇文章,纯粹是想为博客拉点点击量.在博客园,游客访问好像是不计入阅读量的,而作为一个十八线博主,注册用户的访问应该以搜索引擎为主,博客园首页为次,个位数的粉丝就别谈了. 所以,希望各位从搜索引擎点 ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
随机推荐
- JS获取字符串长度的常用方法,汉字算两个字节
JS获取字符串实际长度(双字节字符.汉字算两个字符) //第一种 GetLength = function(str) { var realLength = 0; for (var i = 0; i & ...
- https证书一键自动续期,帮你解放90天限制
前言 前几天网站证书到期,发觉证书颁发每次只能90天有效期,这谁能忍受,于是乎发觉网上有免费的一键续期脚本,真正解放我们的双手.项目如下acme.sh. 期间由于"墙"的原因,踩了 ...
- C :文件
一直没有系统学习过该章节,现参考<C语言程序设计 (第四版)谭浩强> C文件基本知识 什么是文件 文件名 文件的分类 文件缓冲区 文件类型指针 typedef struct { short ...
- 从存钱罐到子数组:一个关于累加和的精妙问题|LeetCode 560 和为K的子数组
LeetCode 560 和为K的子数组 点此看全部题解 LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中) 生活中的算法 你有没有这样的经历:每天往存钱罐里存一些零钱,某一天突 ...
- 玩转云端 | 网络也i人?咋变显眼包?天翼云AccessOne边缘接入来了!
你是具有"社牛"属性的"e人" 还是"社恐"属性的"i人"? 在年轻群体中火起来的 "MBTI人格测试&quo ...
- .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
昨天线上有几个进程因为 StackOverFlowException 导致进程 Crash 了,但是 TCP 请求还是可以连接,具体可不可以连接一个出现StackOverFlowException的微 ...
- Flink流处理-简单案例-01
一.pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- JUC并发—3.volatile和synchronized原理
大纲 1.volatile关键字的使用例子 2.主内存和CPU的缓存模型 3.CPU高速缓存的数据不一致问题 4.总线锁和缓存锁及MESI缓存一致性协议 5.Java的内存模型JMM 6.JMM如何处 ...
- AI探索:通过宏脚本给小众编辑器EverEdit插上AI的翅膀!
1 AI探索:通过宏脚本给小众编辑器EverEdit插上AI的翅膀! 1.1 背景 在AI编程大行其道的背景下,各种AI编程工具:Cursor.VSCode的各种插件.Trae等等搞得不亦乐乎!您 ...
- [BZOJ3451] Normal 题解
这题分三步:葺网(期望).淀粉质(点分治).蓉翅(容斥),再佐以芬芳团(FFT),一道巨难无比的 luogu 黑题就诞生了. 期望 先考虑在淀粉树上,\(i\) 点在 \(j\) 点的子树里的概率.实 ...