1.舵机到底要的是什么信号?

想象舵机就像一个“听秒表的工人”:

这个工人每隔 20ms 就抬头看看秒表一次。

秒表上的 高电平持续多久,他就把这个时间当成“指令角度”。

高 1ms → 转到最左(0°)
高 1.5ms → 转到中间(90°)
高 2ms → 转到最右(180°)

所以:舵机只关心“脉宽多少微秒”,不关心占空比,也不关心电平是多少次。
它就像在量高电平的时间长度。

为什么舵机用 PWM 控制?

舵机的内部

常见 3 线舵机(信号、VCC、电源地)内部是:电机 + 减速齿轮 + 电位器反馈 + 控制器。
外部只给它一个周期固定、脉宽可变的控制脉冲,舵机内部会把“脉宽”当作目标角度,做闭环去转到位。

舵机“吃”的信号

帧周期:通常 20 ms(50 Hz)最通用;很多舵机允许 40–300 Hz,数字舵机还能更高,但50 Hz 是最安全默认。

脉宽:常见 1.0 ms ≈ 0°、1.5 ms ≈ 90°、2.0 ms ≈ 180°(具体要以舵机说明书/实测为准;有些是 0.5–2.5 ms)。

注意:这是“定周期的脉宽控制”,不是单纯追求占空比。我们用定时器 PWM 正是为了精准到微秒地生成这个脉宽。

为什么用 PWM?

PWM(脉宽调制)就是 MCU 内部“定时器”自动帮我们生成一个方波信号:

周期固定:20ms 一次。

高电平可调:可以是 1000us、1500us、2000us……

不用自己 while(1) 里 delay 搞波形,定时器硬件自动输出,非常精准。

所以我们用 定时器 + PWM 模式,就是为了让 MCU 硬件替我们“定点报时”。

2.在 STM32 里怎么做?

MCU 的“定时器”就像一个秒表:

PSC(预分频器):决定秒表走得快还是慢。

ARR(自动重装载):决定多少数后清零 → 就是周期。

CCR(比较寄存器):决定在哪个数的时候翻转电平 → 就是脉宽。

举例(假设 STM32 主频 72MHz):

让秒表每 1 微秒加 1(PSC=71)。

设置 ARR=20000 → 秒表数到 20000 就清零 → 周期 20ms。

设置 CCR=1500 → 秒表数到 1500 的时候输出翻转 → 高电平 1.5ms。

这样我们就得到了一个“周期 20ms、高电平 1.5ms”的 PWM,舵机看到它,就会乖乖转到 90°。

把角度变成脉宽

角度和脉宽是线性映射:
脉宽(us)=1000+(角度/180)×(2000−1000),比如:

0° → 1000us

90° → 1500us

180° → 2000us

所以我们只要给定一个角度,就能算出对应的脉宽,然后设置到 CCR 寄存器。

为什么必须这样做?

因为舵机内部的电路就是按照“高电平时间长度”来解码的。
如果你给它随便一个 PWM(比如频率 1kHz,占空比 10%),它根本不懂,会乱抖。
只有20ms 周期 + 特定的脉宽,舵机才能正确理解。

举个直观的比喻

想象你和舵机在玩手电筒信号:每 20 秒我都给你亮一次手电筒。如果亮 1 秒,你就走到左边。如果亮 1.5 秒,你就走到中间。如果亮 2 秒,你就走到右边。舵机就是这么傻,但很稳定。

3.举例具体代码案例

主函数 main.c

OLED_Init();       // 初始化 OLED 显示屏
Servo_Init();      // 初始化舵机(其实就是初始化 PWM)
Key_Init();        // 初始化按键OLED_ShowString(1,1,"Angle:");while (1)
{KeyNum = Key_GetNum();  // 读按键if(KeyNum == 1){Angle += 30;        // 每按一下 +30°if(Angle > 180){Angle = 0;      // 超过180°回到0°}}Servo_SetAngle(Angle);               // 把角度换成 PWM 脉宽OLED_ShowNum(1, 7, Angle, 3);        // 显示角度
}

按一次按键 → Angle += 30 → Servo_SetAngle(Angle) → 改 PWM 脉宽 → 舵机转动。

PWM_Init()

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;       // TIM2_CH2 -> PA1
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

STM32 主频 72 MHz

PSC=72-1 → 72 分频 → 定时器时钟 = 1 MHz(1 tick = 1us)

ARR=20000-1 → 每数到 20000 清零 → 周期 = 20000us = 20ms 20ms 就是舵机需要的 PWM 周期。

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   // PWM1 模式
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;                  // CCR 初值
TIM_OC2Init(TIM2, &TIM_OCInitStructure);

输出 PWM1 模式:计数器 < CCR → 高电平

计数器 ≥ CCR → 低电平

这样一来,高电平的长度就取决于 CCR。

PWM_SetCompare2()

void PWM_SetCompare2(uint16_t Compare)
{TIM_SetCompare2(TIM2, Compare);
}

直接改 CCR2,控制高电平时间。

比如 Compare=1500 → 高电平 1500us → 舵机转到 90°。

Servo_SetAngle()

void Servo_SetAngle(float Angle)
{PWM_SetCompare2(Angle/180.0f*2000 + 500);
}

把角度(0°~180°)映射到脉宽:

Angle=0 → CCR=500 → 500us

Angle=180 → CCR=2500 → 2500us

这就是一个 500~2500us 的范围。
(有些舵机要求 1000~2000us,我这里用了 500~2500us,表示支持的角度范围更大,实际可能会超出舵机物理限制,要注意一下)。

总结一下

参数/函数作用对应舵机需求
PSC=72-1定时器分频,得到 1MHz 计数频率1 tick = 1us
ARR=20000-1自动重装载,周期 20000us20ms 周期
CCR2捕获比较寄存器控制高电平时间(us)
PWM1 模式输出模式高电平持续到 CCR,符合舵机信号
Servo_SetAngle()角度→脉宽换算0°=500us,180°=2500us
PA1 (TIM2_CH2)PWM 输出引脚信号送到舵机

4.注意:普通舵机(角度型) vs 连续旋转舵机(360°型)

特性普通舵机(角度舵机)连续旋转舵机(360°舵机)
控制信号周期20ms(50Hz)20ms(50Hz)
PWM脉宽含义表示目标角度表示旋转方向和速度
典型控制范围0.5ms ~ 2.5ms ≈ 0°~180°1.0ms ~ 2.0ms = 速度控制(1.5ms停止)
1.0ms信号接近 0°位置反转(中速)
1.5ms信号中间角度(≈90°)停止
2.0ms信号接近 180°位置正转(中速)
反馈机制内部电位器 → 有角度反馈无反馈,类似直流电机
能否定位可以,转到角度后会自动停不可以,只能连续旋转
控制目标绝对角度转速 + 方向
主要用途机械臂、云台、模型舵面小车驱动轮、电机替代
代码实现公式PWM = (Angle/180)*2000 + 500PWM = 1500 + speed*5(speed=-100~100)

具体连续旋转舵机,之后会详细说明(这边可以留意一下)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94400.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94400.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/94400.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动态带宽扩展(DBE):下一代Wi-Fi性能提升的关键技术

动态带宽扩展(DBE):下一代Wi-Fi性能提升的关键技术 引言 在无线通信技术快速发展的今天,用户对网络带宽和传输速率的需求呈指数级增长。为了满足这种需求,IEEE 802.11标准不断演进,引入了多项创新技术。其中,动态带宽扩展(Dynamic Bandwidth Expansion, DBE) 作为80…

Seaborn数据可视化实战:Seaborn数据可视化基础-从内置数据集到外部数据集的应用

Seaborn数据集探索与图表绘制实践 学习目标 通过本课程&#xff0c;你将学习如何使用Seaborn库中的内置数据集&#xff0c;了解如何加载这些数据集&#xff0c;并掌握使用这些数据集绘制图表的基本方法。此外&#xff0c;你还将学习如何导入外部数据集&#xff0c;并在Seaborn中…

漫谈《数字图像处理》之经典空域边缘检测Canny与LOG

在《数字图像处理》的图像分割领域&#xff0c;Canny 边缘检测与 LOG&#xff08;高斯拉普拉斯&#xff09;边缘检测是两款极具代表性的先进空域算法。不同于深度学习驱动的方法&#xff0c;它们通过对图像像素的直接计算提取边缘&#xff0c;下面用更贴近日常认知的语言&#…

抢红包案例加强版

加join的功能是保证线程全部运行完毕&#xff0c;之后好统计构造器刚开始为空列表&#xff0c;利用这个方法返回每个成员列表&#xff08;把每个员工弄成一个列表里面写他们抢到的红包大小&#xff0c;索引代表抢到的个数。&#xff09;

曲面方程的三维可视化:从数学解析到Python实现

在三维几何建模中,我们经常遇到需要将隐式方程可视化的需求。本文将深入探讨一个特定的曲面方程: XH−YH2+ZH2tan⁡(θ)−H2πarcsin⁡(YHYH2+ZH2)=0 X_H - \frac{\sqrt{Y_H^2 + Z_H^2}}{\tan(\theta)} - \frac{H}{2\pi} \arcsin\left( \frac{Y_H}{\sqrt{Y_H^2 + Z_H^2}} \r…

当GitHub宕机时,我们如何协作

引言简述GitHub在全球开发协作中的重要性提出假设性问题&#xff1a;当GitHub不可用时&#xff0c;如何确保团队协作不中断常见的GitHub宕机场景服务完全不可用&#xff08;如DNS问题、全球性故障&#xff09;部分功能受限&#xff08;如API速率限制、仓库访问失败&#xff09;…

如何确定哪些层应添加适配器(Adapter)?(58)

“它如何确定哪些层应添加适配器(Adapter)?是否只有量化层符合条件?我能否也将适配器添加到常规(非量化)线性层上?” 这个问题提得很好,我会逐一为你解答。首先,先给出简洁结论: • 主流模型架构会预配置目标层列表,适配器将应用于这些列表中的层。 • 无论目标层…

【内网渗透】CVE-2025-21420 利用cleanmgr本地提权

目录 原理 POC 复现 一个windows本地提权漏洞 这是一个存在于Windows磁盘清理工具&#xff08;cleanmgr.exe&#xff09;中的权限提升漏洞。攻击者可以利用该系统组件在处理特定目录时的逻辑缺陷&#xff0c;通过精心构造的符号链接&#xff08;Symbolic Link&#xff09;&a…

什么是JSON-RPC 2.0,在项目中应该怎么使用

它是什么 JSON-RPC 2.0 是一种超轻量、与传输无关的远程调用协议&#xff1a;用 JSON 表达“方法名 参数 → 结果/错误”。可跑在 HTTP、WebSocket、Unix 管道&#xff0c;甚至 stdio 上&#xff08;很多开发协议如 LSP 就用它&#xff09;。 报文长这样 • 请求&#xff1a; …

基于CentOS7:Linux服务器的初始化流程

文章目录前言一、服务器初始化1.1 配置国内 Yum 源&#xff08;加速软件安装&#xff09;1.1.1 使用阿里云源1.1.2 使用清华源&#xff08;可选&#xff09;1.2 更新系统与安装必备工具1.3 网络连接验证1.4 配置主机名1.5 同步时间1.6 配置iptables防火墙1.6.1 手动配置iptable…

如何避免MyBatis二级缓存中的脏读

避免 MyBatis 二级缓存中的脏读问题&#xff08;即缓存数据与数据库实际数据不一致&#xff09;&#xff0c;需要从缓存更新机制、配置策略、业务设计等多维度入手。以下是经过实践验证的解决方案&#xff0c;结合底层原理和具体实现&#xff1a;一、理解二级缓存脏读的根源脏读…

Python实现RANSAC进行点云直线、平面、曲面、圆、球体和圆柱拟合

本节我们分享使用RANSAC算法进行点云的拟合。RANSAC算法是什么&#xff1f;不知道的同学们前排罚站&#xff01;(前面有)总的来说&#xff0c;RANSAC&#xff08;Random Sample Consensus&#xff09;是一种通用的迭代鲁棒估计框架&#xff0c;无论拟合何种几何模型&#xff0c…

实验2 天气预报

实验1 天气预报一、实验目标二、实验步骤&#xff08;一&#xff09;准备工作&#xff08;二&#xff09;小程序开发项目创建页面配置视图设计逻辑实现三、程序运行结果四、问题总结与体会主要问题及解决方案主要收获chunk的博客地址一、实验目标 1、掌握服务器域名配置和临时…

【CVE-2025-5419】(内附EXP) Google Chrome 越界读写漏洞【内附EXP】

前言 近日,奇安信CERT监测到Google Chrome中曝出一枚高危安全漏洞(CVE-2025-5419,QVD-2025-21836),该漏洞属于越界读写问题,攻击者只需通过构造恶意网页,就可能触发漏洞,从而绕过Chrome的沙箱防护,直接实现远程代码执行,最终完全控制用户设备。目前,安全社区已确认…

【科研绘图系列】R语言在海洋生态学中的应用:浮游植物糖类组成与溶解性有机碳的关系

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍 数据准备 数据处理 糖类组成随年龄的变化 糖类组成与DOC含量的关系 数据可视化 加载R包 数据下载 导入数据 数据预处理 画图 总结 系统信息 介绍 本教材通过R语言及其强大的数据…

webpack文件指纹:hash、chunkhash与contenthash详解

文件指纹就是打包后输出文件的后缀&#xff0c;每次构建都会生成不同的文件后缀&#xff0c;这样可以防止浏览器的默认缓存&#xff0c;使客户端代码可以及时修改。文件指纹的三种方式&#xff1a;‌ hash ‌&#xff1a;基于整个项目构建内容生成全局哈希值&#xff0c;任何文…

Pytest 插件怎么写:从0开发一个你自己的插件

概述 你用过 pytest-html 生成报告,或用 pytest-xdist 并行运行测试吗?这些强大的功能,其实都是 Pytest 插件 这些都是我们引入项目后直接使用的,当然 你也可以自己写一个 Pytest 插件 基本原理 Pytest 的强大,源于它的 插件系统。它允许你通过定义特定的函数(称为 H…

Java:IO流——基础篇

目录 前言 一、File 类 1、概述 ①构造方法 ②实例对象 2、使用 ①查看名称、路径、长度 ②判断、创建和删除操作 ③目录遍历操作 二、IO流 1、流的概念 2、流的分类 ①按数据流向 ②按数据类型 ③按功能 3、字节流 ⑴FileInputStream——文件输入流 ⑵FileOutputStream——文件…

数据挖掘 5.1~5.2 PCA——前言

5.1 Twelve ways to fool the masses 5.1 愚弄大众的十二种方法 5.2.1 Prelim: Old MacDonald meets Lagrange 5.2.1 前言&#xff1a;老麦克唐纳遇见拉格朗日 5.2. Prelim: Meet stubborn vectors 5.2. 前言&#xff1a;遇见顽固向量 5.2.3 Prelim: Covariance and its friend…

DeepSeek分析

(非走向数字时代,融入数字生活,构建数字生态的分解,只是感觉可以分享给大家---因此现设置VIP,旺海涵) 这是deepseek刚爆的时候,春节紧急对其做的分析。 内容还是私藏状态,做了初步评估,感觉可以分享给大家!!! 但是非共享的构建数字生态的核心,因此添加了vip设置…