一、运动控制基础:什么是运动控制?FPGA在运动控制中的角色与优势

1.1 先聊聊“运动控制”到底是个啥

说实话,我刚入行那会儿,觉得“运动控制”这个词挺唬人的。后来做项目多了,说白了就是——让机器按照我们想要的方式动起来

你想想看,一个电机要转多少圈、转到什么位置、用多快的速度转、什么时候加速什么时候减速……这些都属于运动控制的范畴。我习惯把它拆成三个核心问题:

  • 位置:要去哪儿?
  • 速度:多快去?
  • 加速度:怎么加/减速?

嗯,就这么简单。但真正做起来,你会发现这三个问题背后藏着不少坑。

1.2 一个典型的运动控制系统长什么样

我在调试一个三轴点胶机项目时,画过一张系统框图,大致是这样的:

上位机 (PC/工控机) 运动控制器 (FPGA核心) 轨迹规划+脉冲生成 驱动器 (伺服/步进) 电机 (执行机构) 编码器反馈 (位置/速度) 运动控制系统典型架构 FPGA 位于运动控制器位置,负责实时轨迹插补与脉冲输出

这张图我用了好多年。每次给新人讲,我都会指着中间那个框说:FPGA 就待在这儿,干最累的活——实时算轨迹、发脉冲。

1.3 FPGA 凭什么能干这活?

有人问我:用单片机或者 DSP 不行吗?当然行。但我在一个高速贴片机项目里吃过亏——用 MCU 做插补,到了 200kHz 以上的脉冲频率,CPU 就扛不住了,中断响应开始抖动,电机跟着“哆嗦”。

FPGA 的优势,说白了就三点:

特性 FPGA 怎么做 我踩过的坑
硬件并行 多轴同时算,不排队 用 MCU 做四轴联动,一轴插补时其他轴得等着
低延迟 纳秒级响应,脉冲抖动 < 10ns 某项目脉冲抖动 1μs,电机在低速时明显振动
确定性 每个时钟周期干固定的事 OS 调度延迟导致过冲,工件刮伤
我的习惯: 只要项目里要求三轴以上联动,或者脉冲频率超过 100kHz,我直接选 FPGA。省得后面调试时抓狂。

1.4 运动控制里的“三大件”

做运动控制项目,你绕不开这三个概念。我当年也是被它们折磨得够呛:

1.4.1 梯形加减速

最简单,也最常用。加速-匀速-减速三段。我在一个点胶机项目里就用这个,够用。

// 梯形加减速状态机(简化版)
typedef enum {
  ACCEL,    // 加速阶段
  CONSTANT, // 匀速阶段
  DECEL     // 减速阶段
} motion_state_t;

motion_state_t state = ACCEL;
uint32_t current_speed = 0;

void trapezoidal_step() {
  switch(state) {
    case ACCEL:
      current_speed += ACCEL_STEP;
      if (current_speed >= TARGET_SPEED) state = CONSTANT;
      break;
    case CONSTANT:
      // 保持速度
      if (remaining_steps <= DECEL_POINT) state = DECEL;
      break;
    case DECEL:
      current_speed -= ACCEL_STEP;
      if (current_speed <= 0) state = STOP;
      break;
  }
}

1.4.2 S 形加减速

比梯形更平滑。为什么?因为加速度本身也是逐渐变化的。我做过一个晶圆搬运项目,梯形加减速启动时工件会晃动,换成 S 形就好了。

1.4.3 插补算法

直线插补、圆弧插补。FPGA 里做插补,我习惯用 Bresenham 算法——只有加法和比较,没有乘除,硬件实现特别友好。

注意: 圆弧插补时,如果 FPGA 的乘法器资源不够,可以考虑用 CORDIC 算法替代。我曾经在一个低端芯片上硬算圆弧,结果逻辑资源爆了……后来换成 CORDIC,省了 40% 的资源。

1.5 FPGA 实现运动控制的常见架构

我一般把 FPGA 内部拆成这几个模块:

  • 通信接口:跟上位机打交道,SPI/UART/EtherCAT 都行
  • 指令解析:把上位机发的“走直线到 (100,200)”翻译成内部指令
  • 轨迹规划:算加减速曲线,决定每个时刻的速度
  • 插补器:把轨迹拆成每个轴要走的小步
  • 脉冲发生器:输出 PWM 或脉冲+方向信号给驱动器
  • 编码器接口:读回实际位置,做闭环

嗯,这个架构我用了五六年了,基本没大改过。每次新项目就是在这个框架上修修补补。

1.6 一个真实案例:为什么我选了 FPGA

前年做一个 六轴机械臂 的控制项目。要求每个关节独立控制,还要做笛卡尔空间轨迹插补。一开始用 DSP 做,结果发现:

  1. 六轴逆解算一次要 200μs
  2. 插补周期要求 1ms
  3. DSP 还要处理通信、IO 扫描……

算下来,留给插补的时间只有 300μs 左右。DSP 跑得满头大汗,还时不时丢一个脉冲。

后来换成 FPGA:

  • 逆解用硬件流水线,80μs 搞定
  • 插补器独立并行,不占 CPU 时间
  • 脉冲输出用专用硬件定时器,零抖动

效果? 同样的电机,同样的机械结构,运动平滑度提升了一个档次。

总结一下我的经验:

  • 单轴、低速(< 50kHz)→ MCU 够用
  • 多轴、中速(50-200kHz)→ DSP 可以试试
  • 多轴联动、高速(> 200kHz)、高精度 → 上 FPGA

1.7 避坑指南

最后分享几个我当年摔过的跟头:

  • 脉冲频率算错了:电机额定转速 3000rpm,编码器 2500 线,四倍频后就是 10000 脉冲/转。3000/60 × 10000 = 500kHz。嗯,我第一次算的时候少乘了个 4,结果电机死活跑不到目标速度。
  • 加减速时间设太短:梯形加速时间设了 5ms,电机直接过流报警。后来改成 50ms,稳了。
  • 忘记考虑机械谐振:FPGA 输出很完美,但机械结构有固有频率。某项目在 800rpm 时整个机器都在抖,最后加了陷波滤波器才解决。

这些坑,后面章节我会一个一个展开讲。今天先把基础打牢。


公众号:蓝海资料掘金营,微信deep3321