共计 1510 个字符,预计需要花费 4 分钟才能阅读完成。
开环与闭环控制波形对比
用示波器观察开环控制时(图 1),电机脉冲信号与实际位置存在明显相位差,当负载突变时会出现明显丢步。而带编码器反馈的闭环控制(图 2)波形显示:编码器信号(黄色)实时矫正驱动脉冲(蓝色),400PPR 分辨率下每转可检测 1600 个边沿信号(4 倍频),理论定位精度达 360°/1600=0.225°。

硬件系统搭建
关键组件清单
- 42 步进电机(1.8°/ 步)
- 增量式编码器(400PPR)
- Arduino Uno + CNC Shield 扩展板
- SN754410 电机驱动芯片
- 6N137 光电隔离器
光电隔离电路设计
[编码器 A 相] ---[1kΩ]---+---[6N137 输入端]
|
[编码器 B 相] ---[1kΩ]---+---[6N137 输入端]
|
[GND]
输出端接 10kΩ 上拉电阻至 Arduino 的 2 / 3 引脚(外部中断口),注意电机电源与逻辑电源需完全隔离。
Arduino 代码实现
PlatformIO 项目配置
[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps =
madhephaestus/AccelStepper@^1.61.0
PID 位置控制核心代码
#include <AccelStepper.h>
#define ENCODER_A 2 // 中断 0
#define ENCODER_B 3 // 中断 1
volatile long encoderPos = 0;
float Kp = 0.5, Ki = 0.01, Kd = 0.1; // PID 参数
void setup() {attachInterrupt(0, readEncoderA, CHANGE);
attachInterrupt(1, readEncoderB, CHANGE);
stepper.setMaxSpeed(1000);
stepper.setAcceleration(500);
}
void loop() {
int32_t target = 1600; // 1 圈位置
int32_t error = target - encoderPos;
// PID 计算
static float lastError = 0, integral = 0;
float output = Kp*error + Ki*integral + Kd*(error-lastError);
stepper.move(output);
stepper.run();
lastError = error;
integral += error;
}
// 4 倍频解码
void readEncoderA() {encoderPos += (digitalRead(ENCODER_A)==digitalRead(ENCODER_B))?1:-1;
}
关键参数计算
-
脉冲当量:
步距角(1.8°) / 微步数 / (编码器 PPR×4) 例如 16 细分时:1.8/16/(400×4) = 0.0000703°/ 脉冲 -
最大跟踪误差:
(电机最大速度×采样周期) / 脉冲当量 若采样周期 10ms,速度 300rpm:(300×1600 脉冲 / 转)/60×0.01 / 0.0000703 ≈ 1138 脉冲
避坑指南
信号干扰解决方案
- 使用双绞线传输编码器信号
- 在电机电源并联 100μF 电解电容 +0.1μF 陶瓷电容
- 避免与电机线平行走线,交叉时保持 90°
机械安装校准
- 使用千分表检测电机轴径向跳动,应 <0.02mm
- 联轴器安装时先预紧 30% 力度,手动旋转测试无卡滞再完全紧固
- 空载运行时用频闪仪观察轴标记,确认无周期性抖动
进阶思考
-
卡尔曼滤波应用:
在encoderPos更新时融合加速度计数据,状态方程需考虑电机转动惯量 -
多电机中断优化:
- 给每个编码器分配独立定时器
- 使用 PinChange 中断库扩展中断引脚
- 在 RTOS 中创建专用中断服务线程
正文完
发表至: 未分类
近一天内
