亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

设计基于 FPGA 的 RC 舵机控制器:精准 PWM 实现

遥控 (RC) 舵机是模型飞机、车、船的核心。它们将遥控无线电指令转换为精确角度位置。由于 RC 系统已存在数十年,行业标准接口是脉宽调制 (PWM) 而非纯数字协议。凭借 FPGA 的确定性时序,实现高精度 PWM 易如反掌。本文演示一个通用 VHDL 舵机控制器,适用于任何使用 PWM 的 RC 舵机,含仿真测试平台和基于 Lattice iCEstick FPGA 板的实机实现。

RC 舵机 PWM 控制原理

PWM 基础另有介绍,RC 舵机略有不同。舵机忽略完整占空比,仅采样每个脉冲的高电平持续时间。标准脉冲间隔为 20 ms,对应 50 Hz 频率。在该 20 ms 窗口内,舵机读取脉宽,通常 1 ms(最小位置)到 2 ms(最大位置),具体值因厂商而异。

设计基于 FPGA 的 RC 舵机控制器:精准 PWM 实现

图示展示时序关系:20 ms 周期重复,每个脉冲的高电平时长直接映射到舵机角度位置。

VHDL 舵机控制器

我们将构建通用 VHDL 模块,接受时钟频率、PWM 脉冲频率、最小/最大脉宽(微秒)和极值间离散位置数等泛型参数。因 FPGA 时钟在兆赫兹级,整型计数器运算提供足够分辨率。为避免舍入歧义,使用 ieee.math_real 包的 round 函数,其始终远离零舍入。

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.round;

舵机模块实体声明如下:

entity servo is generic ( clk_hz : real; pulse_hz : real; -- PWM 脉冲频率 min_pulse_us : real; -- 最小位置脉宽(微秒) max_pulse_us : real; -- 最大位置脉宽(微秒) step_count : positive -- 离散位置数 ); port ( clk : in std_logic; rst : in std_logic; position : in integer range 0 to step_count - 1; pwm : out std_logic ); end servo;

position 输入驱动舵机从最小值 (0) 到最大值 (step_count‑1)。pwm 输出连接舵机信号线(通常黄/白)。多数 FPGA 输出 3.3 V 电平,需电平转换匹配舵机 5 V 输入。

声明区

先定义辅助函数,将微秒时间转为最近整数时钟周期数:

function cycles_per_us (us_count : real) return integer is begin return integer(round(clk_hz / 1.0e6 * us_count)); end function;

用该函数计算核心时序常量:

constant min_count : integer := cycles_per_us(min_pulse_us); constant max_count : integer := cycles_per_us(max_pulse_us); constant min_max_range_us : real := max_pulse_us - min_pulse_us; constant step_us : real := min_max_range_us / real(step_count - 1); constant cycles_per_step : positive := cycles_per_us(step_us);

建立按期望脉冲频率运行的 PWM 计数器:

constant counter_max : integer := integer(round(clk_hz / pulse_hz)) - 1; signal counter : integer range 0 to counter_max; signal duty_cycle : integer range 0 to max_count;

计数时钟周期

以下进程实现自由运行计数器:

COUNTER_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then counter <= 0; else if counter < counter_max then counter <= counter + 1; else counter <= 0; end if; end if; end if; end process;

PWM 输出进程

PWM 输出在计数器周期数小于当前 duty_cycle 时置高:

PWM_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then pwm <= '0'; else pwm <= '0'; if counter < duty_cycle then pwm <= '1'; end if; end if; end if; end process;

计算占空比

复位时 duty_cycle 默认为最小脉宽。否则根据 position 输入计算:

DUTY_CYCLE_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then duty_cycle <= min_count; else duty_cycle <= position * cycles_per_step + min_count; end if; end if; end process;

虽 cycles_per_step 四舍五入到整数,但因 FPGA 时钟比 50 Hz 脉冲率快数量级,误差可忽略。

舵机测试平台

为验证设计,构建简单测试平台手动遍历所有位置值并捕获波形。1 MHz 测试时钟加速仿真同时保持真实时序。

仿真常量

constant clk_hz : real := 1.0e6; constant clk_period : time := 1 sec / clk_hz; constant pulse_hz : real := 50.0; constant pulse_period : time := 1 sec / pulse_hz; constant min_pulse_us : real := 1000.0; constant max_pulse_us : real := 2000.0; constant step_count : positive := 5;

DUT 信号

signal clk : std_logic := '1'; signal rst : std_logic := '1'; signal position : integer range 0 to step_count - 1; signal pwm : std_logic;

时钟生成:

clk <= not clk after clk_period / 2;

DUT 实例化

DUT : entity work.servo(rtl) generic map ( clk_hz => clk_hz, pulse_hz => pulse_hz, min_pulse_us => min_pulse_us, max_pulse_us => max_pulse_us, step_count => step_count ) port map ( clk => clk, rst => rst, position => position, pwm => pwm );

测试平台定序器

定序器复位 DUT,然后遍历所有位置值,每次变化等待一个脉冲周期。序列完成后结束仿真。

SEQUENCER : process begin wait for 10 * clk_period; rst <= '0'; wait for pulse_period; for i in 0 to step_count - 1 loop position <= i; wait for pulse_period; end loop; report "Simulation done. Check waveform."; finish; end process;

舵机仿真波形

下图显示测试平台波形。PWM 输出仅在最早计数器周期内为高,匹配各位置值对应的预期脉宽。

设计基于 FPGA 的 RC 舵机控制器:精准 PWM 实现

下载完整工程文件复现仿真。

FPGA 实机实现示例

接下来从 Lattice iCEstick 板驱动真实 TowerPro SG90 舵机。舵机需 5 V 电平,故在 FPGA 引脚与舵机信号线间加电平转换。

顶层模块实体

entity top is port ( clk : in std_logic; rst_n : in std_logic; -- 上拉 pwm : out std_logic ); end top;

信号与常量

经实测校准舵机脉宽:0.5 ms 至 2.5 ms 可得完整 180° 扫动。以下常量匹配 iCEstick 时钟和舵机参数。

constant clk_hz : real := 12.0e6; -- iCEstick 时钟 constant pulse_hz : real := 50.0; constant min_pulse_us : real := 500.0; -- 0.5 ms constant max_pulse_us : real := 2500.0; -- 2.5 ms constant step_bits : positive := 8; -- 0 到 255 constant step_count : positive := 2**step_bits;

自由运行计数器 25 位,在 12 MHz 时钟下绕回周期约 2.8 秒。

constant cnt_bits : integer := 25; signal cnt : unsigned(cnt_bits - 1 downto 0);

模块连接:

signal rst : std_logic; signal position : integer range 0 to step_count - 1; signal rom_addr : unsigned(step_bits - 1 downto 0); signal rom_data : unsigned(step_bits - 1 downto 0);

舵机模块实例化

SERVO : entity work.servo(rtl) generic map ( clk_hz => clk_hz, pulse_hz => pulse_hz, min_pulse_us => min_pulse_us, max_pulse_us => max_pulse_us, step_count => step_count ) port map ( clk => clk, rst => rst, position => position, pwm => pwm );

自绕回计数器实例化

COUNTER : entity work.counter(rtl) generic map ( counter_bits => cnt_bits ) port map ( clk => clk, rst => rst, count_enable => '1', counter => cnt );

正弦 ROM 实例化

SINE_ROM : entity work.sine_rom(rtl) generic map ( data_bits => step_bits, addr_bits => step_bits ) port map ( clk => clk, addr => rom_addr, data => rom_data );

并发赋值连接计数器、ROM 和舵机:

position <= to_integer(rom_data); rom_addr <= cnt(cnt'left downto cnt'left - step_bits + 1);

在 Lattice iCEstick 上测试

整电路搭在面包板上:FPGA 3.3 V 输出经电平转换至 5 V 给舵机。PWM 信号接 iCEstick 引脚 119。上电后舵机在 0° 和 180° 间平滑摆动,极值处短暂停留。示波器上的 PWM 波形视频演示了正确时序。

设计基于 FPGA 的 RC 舵机控制器:精准 PWM 实现

结语

VHDL 实现 PWM 舵机控制器的方法很多,但用整型计数器可保持综合逻辑简单——仅计数器、寄存器和多路复用器。最常见陷阱是 32 位运算中的静默溢出,因此务必验证中间计算在所选参数下不越界。

注意此 PWM 风格专为 RC 舵机定制。对于占空比比频率更重要的应用(如模拟功率控制),另一种 PWM 策略更合适。

阅读关于使用 PWM 的模拟功率控制:
如何在 VHDL 中创建 PWM 控制器

想亲自试试?在下方表单填邮箱,下载包含完整 VHDL 代码、ModelSim 测试平台、iCEcube2 工程和编程器配置的 ZIP 包。

欢迎在评论区留言!

VHDL

  1. 为何销钉非机脚定位最佳选择——替代方案与实用对策
  2. 伺服控制器能修吗?专家洞见与高性价比方案
  3. 奥赛-普利马电伺服驱动器 97942050N “C轴驱动器不OK”错误修复实录
  4. 树莓派 ppDAQC 扩展板实时采集温度数据并上传至 InitialState
  5. 树莓派家庭温度监测仪表盘:实时图表展示
  6. 两块 Arduino 通过 Firebase 传递温湿度数据
  7. Arduino Uno 控制 25kHz 4 针 PWM 风扇 - 硬件、代码与测试
  8. PWM功率控制器:构建脉宽调制灯驱动器
  9. 基于安全FPGA SoC的可信执行环境,护航车载舱内AI
  10. 七步零代码提取PLC数据上云:IXON Cloud IIoT实战指南
  11. VHDL 实现 PWM 控制器:设计、仿真与 FPGA 演示
  12. 用 VHDL TEXTIO 库从文本文件初始化 FPGA 块 RAM