CODESYS运动控制实战:从单轴定位到直线圆弧插补的路径规划

📅 2026/8/21 23:57:38
CODESYS运动控制实战:从单轴定位到直线圆弧插补的路径规划
1. 先搞清楚直线和圆弧插补到底解决什么问题在工业自动化特别是多轴协同运动的场景里直线和圆弧插补不是“锦上添花”的功能而是解决“路径规划”这个核心问题的必备手段。很多刚接触轴组编程的朋友容易把单轴定位和轴组插补搞混。单轴定位你只需要告诉每个电机“走多远、走多快”它们各走各的最终合成的路径是不可控的。而插补是让控制器来解算让两个或多个轴按照你指定的几何路径比如一条直线、一个圆弧协同运动末端执行器比如机械手、激光头、焊枪走的才是你想要的轨迹。所以这个主题的核心价值是让你从控制单个电机升级到控制一个运动轮廓。它适合已经会用 CODESYS 做单轴点动、回零、绝对定位但需要实现更复杂轨迹如切割、涂胶、焊接路径的工程师。最关键的实战点在于理解插补指令的“坐标系”和“数据流”而不是死记硬背函数块。很多人卡住的第一步是没想清楚“直线”和“圆弧”在程序里到底怎么描述。直线插补你需要的是起点和终点的坐标圆弧插补你需要起点、终点和圆心或中间点并且要明确旋转方向。CODESYS 的MC_MoveLinear和MC_MoveCircular这些功能块就是帮你把几何描述转换成各轴实时位置指令的“翻译官”。2. 动手前的环境与概念准备轴、轴组、坐标系在写第一行插补代码之前必须把三个概念理清物理轴Axis、轴组Kinematics、坐标系Coordinate System。这是后续所有操作的基础。2.1 物理轴与轴组的绑定物理轴就是你实际配置的伺服驱动器比如通过 EtherCAT 连接的汇川伺服。在 CODESYS 的“设备树”里你能看到一个个AXIS_REF对象。轴组则是一个逻辑容器它把多个物理轴“打包”在一起视为一个整体来规划运动。在 CODESYS 中通常使用MC_Kinematics相关的功能块来创建和管理轴组。一个常见的误区是以为配置好 EtherCAT 从站轴就能自动组队。实际上你需要显式地创建轴组对象并将物理轴添加进去。对于最常见的二维 X-Y 平台你需要创建一个“笛卡尔”类型的轴组然后将 X 轴和 Y 轴分别指定为组内的第一轴和第二轴。2.2 理解用户坐标系与轴组坐标系这是插补编程中最容易混淆的一点。当你用MC_MoveLinear指令说“移动到 (X100, Y50)”时这个坐标值是在哪个坐标系下轴组坐标系Group Coordinate System这是轴组内部的“自然”坐标系。对于 X-Y 笛卡尔轴组这个坐标系通常就直接是 (X, Y)。你程序里写的坐标默认就是指这个坐标系。用户坐标系User Coordinate System在实际设备中机械零点机械坐标系可能和你的工艺零点不一致。比如你可能希望以工件的某个角点为 (0,0) 点。这时就需要进行“坐标系偏移”或“旋转”。在 CODESYS 中可以通过设置轴组的Offset或使用MC_Transform等功能块来实现。我的建议是在学习和测试阶段先忽略用户坐标系变换。确保你的轴组坐标系定义清晰并且与机械的实际运动方向一致即程序命令 X 轴正方向移动平台确实向右移动。这一步可以通过单轴点动来验证。2.3 必备的软件与硬件环境清单要跑通接下来的实战你需要准备好这些软件CODESYS Development System (最新稳定版如 V3.5 SP18 或更高)。对应你硬件的设备描述文件GSDML 或 XML例如汇川伺服 AM600 系列或 SV660N 系列的 EtherCAT 从站文件。运动控制库确保你的 CODESYS 安装包含了Motion Control库。这是插补功能的基础。硬件一台支持 CODESYS Runtime 的控制器如倍福CX系列、施耐德M系列或树莓派CODESYS Control for Raspberry Pi。至少两个伺服驱动器如汇川SV660N及电机构成一个 X-Y 模组。稳定的 EtherCAT 网络。特别注意在配置 EtherCAT 主站时务必正确设置DC分布式时钟这是多轴同步精度的关键配置错误会导致插补路径抖动或变形。知识准备熟悉 CODESYS 基本编程ST语言。已完成单轴的使能 (MC_Power)、回零 (MC_Home)、点动 (MC_MoveVelocity) 和定位 (MC_MoveAbsolute) 操作。如果单轴还控制不稳直接上轴组会问题百出。3. 从零搭建一个二维直线插补任务我们从一个最简单的任务开始让 X-Y 平台从当前位置假设为 (0,0)以一定速度直线运动到目标点 (100 mm, 50 mm)。3.1 第一步创建轴组并添加物理轴在程序中你需要声明轴组对象和物理轴对象。PROGRAM MAIN VAR // 1. 声明物理轴引用关联到设备树中配置的实际轴 xAxis: AXIS_REF; yAxis: AXIS_REF; // 2. 声明轴组对象 xyGroup: MC_GROUP_REF; // 这是一个轴组引用需要初始化 // 3. 声明轴组配置结构体 groupConfig: MC_GROUP_CONFIGURATION; // 4. 声明插补运动相关的功能块 fbGroupPower: MC_GroupPower; fbGroupStop: MC_GroupStop; fbMoveLinear: MC_MoveLinear; END_VAR在PLC_PRG的初始化部分或一个专门的状态机中你需要配置并创建轴组// 配置轴组参数 groupConfig.AxisCount : 2; // 两个轴 groupConfig.KinematicsType : MC_KINEMATICS_TYPE_CARTESIAN; // 笛卡尔类型 groupConfig.pAxes : ADR(xAxis); // 指向物理轴数组的指针通常需要将轴放入数组 // 创建轴组这是一个一次性的初始化调用通常在启动时执行 MC_CreateGroup( Group : xyGroup, Configuration : groupConfig, Execute : TRUE, Done , // 输出参数创建完成信号 Busy , Error , ErrorID );关键点pAxes参数需要一个指向AXIS_REF数组的指针。你需要确保xAxis和yAxis在数组中的顺序与轴组坐标系中 X 轴和 Y 轴的对应关系一致。顺序错了运动方向就全乱了。3.2 第二步使能轴组和单轴一样轴组运动前必须先使能。使用MC_GroupPower功能块。// 使能轴组 fbGroupPower( Group : xyGroup, Enable : TRUE, // TRUE 为使能 EnablePositive : TRUE, EnableNegative : TRUE, Status , // 输出轴组状态 Error , ErrorID );只有当fbGroupPower.Status为 TRUE 时才表示轴组已准备就绪可以接收运动指令。务必在程序中判断这个状态而不是使能指令一执行就立刻发移动命令。3.3 第三步执行直线插补运动现在可以调用MC_MoveLinear来规划直线路径。// 触发一次直线插补运动 IF startMove AND fbGroupPower.Status THEN fbMoveLinear( Group : xyGroup, Execute : startMove, // 上升沿触发 Position : [100.0, 50.0], // 目标位置数组 [X, Y] Velocity : 50.0, // 路径速度 (mm/s 或 user units/s) Acceleration : 100.0, // 加速度 Deceleration : 100.0, // 减速度 CoordSystem : MC_COORDINATE_SYSTEM_GROUP, // 使用轴组坐标系 Done , // 运动完成信号 Busy , Active , CommandAborted , Error , ErrorID ); startMove : FALSE; // 防止重复触发 END_IF参数解读与避坑点Position这是一个数组长度等于轴组轴数。[100.0, 50.0]表示 X 轴到 100Y 轴到 50。Velocity这是合成速度即末端执行器沿直线运动的速度。不是单个轴的速度。Acceleration/Deceleration路径的加减速度。同样是指合成运动的加速度。CoordSystem这里我们使用MC_COORDINATE_SYSTEM_GROUP即轴组坐标系。这是最常用的设置。Execute信号必须使用上升沿触发。用一个布尔变量如startMove在条件满足时置 TRUE 一次然后在功能块调用后立即将其复位为 FALSE。这是运动控制功能块的通用规则用错了会导致指令重复执行或无法执行。3.4 第四步监控与停止运动过程中你可以通过fbMoveLinear.Active信号来判断是否正在移动。需要停止时使用MC_GroupStop。// 停止轴组运动 fbGroupStop( Group : xyGroup, Execute : stopCommand, // 上升沿触发停止 Deceleration : 200.0, // 紧急减速度可以设得比正常减速快 Done , // 停止完成 Busy , Error , ErrorID );测试顺序编译下载程序到控制器。在线后先单轴点动确认 X 轴和 Y 轴运动方向正确且单位如毫米符合预期。触发轴组使能 (fbGroupPower.Enable : TRUE)观察Status是否变为 TRUE。触发startMove信号观察平台是否沿直线运动到 (100, 50)。可以用一张白纸和笔固定在平台上直观地画出轨迹来验证。4. 实现圆弧插补关键在圆心与方向直线会了圆弧的核心就是多了一个“圆心”参数和“方向”参数。圆弧插补指令MC_MoveCircular需要你定义圆弧的“辅助点”Auxiliary Point或“圆心点”Center Point以及旋转方向。4.1 使用“圆心点”模式画圆弧这种模式最直观给定起点当前点、圆心点和终点就能唯一确定一段圆弧实际上有两种可能需要方向参数指定。假设我们要从点 (0, 0) 开始圆心在 (50, 0)画一个 90 度的圆弧到点 (100, 50)。VAR fbMoveCircular: MC_MoveCircular; startCircular: BOOL; END_VAR IF startCircular AND fbGroupPower.Status THEN fbMoveCircular( Group : xyGroup, Execute : startCircular, CircMode : MC_CIRCULAR_MODE_CENTER, // 使用圆心模式 AuxPoint : [50.0, 0.0], // 圆心坐标 [Cx, Cy] EndPosition : [100.0, 50.0], // 终点坐标 PathChoice : MC_PATH_CHOICE_DIRECTION, // 通过方向选择路径 Direction : MC_DIRECTION_POSITIVE, // 正方向通常为逆时针 Velocity : 30.0, // 圆弧路径速度 Acceleration : 100.0, Deceleration : 100.0, CoordSystem : MC_COORDINATE_SYSTEM_GROUP, Done , Busy , Active , CommandAborted , Error , ErrorID ); startCircular : FALSE; END_IF关键参数解析CircModeMC_CIRCULAR_MODE_CENTER表示AuxPoint参数是圆心坐标。AuxPoint圆心坐标数组[Cx, Cy]。PathChoice与Direction这两个参数共同决定了走哪一段圆弧。因为给定起点、圆心、终点在数学上对应两段互补的圆弧。MC_PATH_CHOICE_DIRECTION表示通过Direction正/负来选择。在大多数二维笛卡尔坐标系中MC_DIRECTION_POSITIVE对应逆时针CCW方向。这是最容易出错的地方务必通过画图或实际测试来验证方向是否符合你的工艺要求。4.2 使用“辅助点”模式画圆弧这种模式给定起点、中间点Auxiliary Point和终点。控制器会计算经过这三点的圆弧。// 从 (0,0) 经过 (50,25) 到 (100,50) 的圆弧 fbMoveCircular( ... CircMode : MC_CIRCULAR_MODE_RADIUS, // 注意有些版本库中辅助点模式可能是 MC_CIRCULAR_MODE_AUXILIARY AuxPoint : [50.0, 25.0], // 中间点坐标 EndPosition : [100.0, 50.0], PathChoice : MC_PATH_CHOICE_ALONG_PATH, // 沿着路径唯一 ... );注意不同版本的 CODESYS Motion Control 库对于辅助点模式的枚举命名可能略有不同需要查看库帮助文档确认。MC_PATH_CHOICE_ALONG_PATH通常用于辅助点模式表示路径是唯一的因为三点确定一个圆。4.3 圆弧插补的实战调试技巧先算后试在触发运动前最好在纸上或用绘图软件画出起点、圆心/中间点、终点。明确你期望的圆弧是哪一段。这能帮你快速判断Direction参数该选正还是负。小速度验证第一次跑圆弧时把Velocity设小一点比如 10 mm/s方便观察轨迹。同时确保加速度和减速度设置合理过大的加/减速度可能导致跟随误差报警。监控实际位置在线监控轴组对象xyGroup的ActualPosition数组。你可以看到 X 和 Y 轴的实际位置反馈与指令位置进行对比。如果偏差持续过大需要检查伺服驱动器的增益参数是否合适。错误处理MC_MoveCircular的Error信号需要重点监控。常见的错误 ID 可能指向“几何错误”如三点共线无法构成圆弧或“参数超出限制”。5. 进阶连续插补与路径队列单个直线或圆弧指令只能完成一段运动。在实际应用中比如切割一个复杂图形需要连续执行多段插补且段与段之间要平滑过渡这就需要用到路径队列Blending或连续插补功能。5.1 使用 MC_MoveLinear 的 Blending 参数高级的MC_MoveLinear功能块支持Blending参数。当一段运动尚未完成时提前触发下一段运动并设置一个融合距离或融合时间控制器会在前一段运动的末尾平滑地过渡到下一段运动而不是完全停止再启动。fbMoveLinear1( Group : xyGroup, Execute : startPath, Position : [100.0, 0.0], Velocity : 50.0, Blending : 10.0, // 融合距离单位与位置相同 ... ); // 在第一段运动尚未完成时例如通过定时器或位置判断触发第二段 fbMoveLinear2( Group : xyGroup, Execute : startSegment2, Position : [100.0, 100.0], Velocity : 50.0, Blending : 10.0, ... );关键点Blending值的大小决定了过渡的平滑程度。值太小过渡可能不平滑值太大可能导致实际路径偏离编程路径。需要根据工艺速度和精度要求进行调试。5.2 使用 MC_Path 功能块进行复杂轨迹规划对于非常复杂的轨迹包含大量直线和圆弧段更专业的做法是使用MC_Path系列功能块。你可以预先定义好一个“路径”Path其中包含一系列线段MC_Line和圆弧段MC_Arc的描述然后让轴组沿着整个路径一次性执行。VAR fbPath: MC_Path; myPath: REFERENCE TO MC_PATH_REF; pathElements: ARRAY[1..10] OF MC_PATH_ELEMENT; END_VAR // 1. 构建路径元素 pathElements[1].ElementType : MC_ELEMENT_TYPE_LINE; pathElements[1].EndPosition : [100.0, 0.0]; pathElements[1].Dynamic : ... // 动态参数速度、加速度等 pathElements[2].ElementType : MC_ELEMENT_TYPE_ARC_CENTER; pathElements[2].AuxPoint : [150.0, -50.0]; // 圆心 pathElements[2].EndPosition : [200.0, 0.0]; pathElements[2].Direction : MC_DIRECTION_POSITIVE; pathElements[2].Dynamic : ... // 2. 设置路径 MC_SetPath(Path : myPath, Elements : ADR(pathElements), ElementCount : 2, ...); // 3. 执行路径 fbPath( Group : xyGroup, Path : myPath, Execute : startComplexPath, Velocity : 50.0, ... );这种方式适合轨迹固定、需要高速高精度运行的场景比如激光切割机。它的优点是轨迹规划在运动前一次性完成整体性更好。6. 实战中必看的排查清单与经验当你写的插补程序跑不起来或者运动轨迹不对时不要急着改代码按这个顺序排查6.1 运动根本不执行轴组使能了吗检查MC_GroupPower.Status是否为 TRUE。单轴是否都已使能 (MC_Power.Status)指令触发了吗Execute信号是否是一个干净的上升沿用在线监控看触发瞬间。有报错吗检查MC_MoveLinear或MC_MoveCircular的Error和ErrorID。根据错误 ID 查手册。目标位置有效吗检查Position数组里的值是否在轴组的软限位范围内。6.2 运动轨迹不对比如走斜线不直圆弧变形物理轴与轴组映射顺序对吗确认在轴组配置中第一个轴对应 X 坐标第二个轴对应 Y 坐标。顺序反了轨迹就全错了。单轴方向对吗分别点动 X 轴和 Y 轴确认正方向移动与机械坐标系正方向一致。不一致需要在驱动器或轴配置中修改ScaleFactor的正负号。单位统一吗确保所有位置、速度、加速度参数使用相同的工程单位如毫米、毫米/秒。检查轴参数中的ScaleFactor每转脉冲数到工程单位的换算系数设置是否正确。EtherCAT 同步好吗检查 EtherCAT 主站配置确保 DC分布式时钟已正确启用并同步。同步不良会导致两轴运动不同步直线变曲线。伺服跟随性能够吗监控各轴的FollowingError跟随误差。如果误差持续较大特别是在拐角或高速时需要优化伺服驱动器的位置环增益、速度环增益和前馈参数。6.3 关于 ST 语言编程的提醒数组索引从 1 开始CODESYS ST 语言中数组默认索引从 1 开始。但在一些与 C 语言交互的底层库或直接操作内存时要注意区分。功能块实例化MC_MoveLinear、MC_GroupPower等都是功能块FB必须在 VAR 区声明为实例然后在程序循环中调用。不能像调用函数FC那样直接使用。状态机管理对于复杂的多段连续运动强烈建议使用状态机如 CASE OF 语句来管理运动流程空闲、使能、运动段1、运动段2、完成、错误处理而不是用一堆布尔变量做标志位逻辑会清晰很多。直线和圆弧插补是运动控制从“单轴”思维迈向“路径”思维的关键一步。我个人的经验是先把一个最简单的二维直线插补在实机上跑通画出轨迹验证。然后尝试一个 90 度的圆弧把圆心坐标、方向参数彻底搞明白。这两步稳了后续的连续插补、坐标变换、甚至是三维空间插补都是在此基础上叠加新的概念和参数。最忌讳的就是一开始就对着一个复杂的图形去编程问题会层层叠加无从下手。先从点到线再到弧一步步搭建你的运动控制能力。