1. 项目缘起与整体方案设计1.1 为什么要在树莓派上跑CODESYS SoftMotion最早动了这个念头是因为手头有个小型自动化项目需要控制三根轴做同步运动——一根主轴带两根从轴从轴要按凸轮曲线跟随主轴的位置变化。传统做法是上PLC加运动控制模块一套下来少说大几千甚至上万。而树莓派4B现在几百块就能拿下CODESYS Runtime在ARM平台上又是免费授权的SoftMotion的凸轮表功能恰好能满足多轴同步的需求这个组合的性价比实在让人难以拒绝。CODESYS SoftMotion本质上是在软PLC层面实现运动控制算法它不依赖专用的运动控制芯片而是通过实时任务周期性地计算轴的位置、速度和加速度再通过总线或GPIO把指令发出去。树莓派4B的四核Cortex-A72跑在1.5GHz配合PREEMPT_RT实时补丁跑一个中等复杂度的多轴同步任务完全够用。我实测下来三轴同步、周期1ms的情况下CPU占用率大概在40%到55%之间波动留有余量。这个方案适合谁呢如果你在做小型自动化设备、教学实验平台、或者个人DIY项目需要多轴协调运动但又不想投入太多硬件成本那这套方案值得认真考虑。当然如果你需要控制十几根轴、或者对同步精度要求达到微秒级那还是老老实实上专用运动控制器。1.2 硬件选型与系统架构硬件清单其实很简洁树莓派4B4GB内存版本、一张质量靠谱的32GB以上的TF卡、官方电源、网线。如果要做实际的轴控制还需要搭配伺服或步进驱动器通过EtherCAT或者脉冲方向信号连接。我这里用的是EtherCAT方案因为CODESYS SoftMotion对EtherCAT的支持最成熟同步性也最好。系统架构上树莓派运行的是Raspberry Pi OS with RT patch也就是带实时内核的版本。CODESYS Development System装在PC上通过网线与树莓派上的CODESYS Runtime通信。Runtime负责执行运动控制程序PC端负责编程和调试。实际运行时树莓派不接显示器完全作为嵌入式控制器使用。注意树莓派4B的以太网口和WiFi共用一条内部总线如果同时使用可能会影响实时性。建议做运动控制时只用有线网口WiFi关掉。1.3 软件栈的搭建逻辑软件层面分三块底层是带RT补丁的Linux系统中间是CODESYS Runtime for Raspberry Pi上层是CODESYS Development System。Runtime的安装包在CODESYS官网可以下载到选择ARM64版本即可。安装过程不复杂但有几个关键点容易踩坑后面会详细说。SoftMotion是CODESYS的一个选件需要在Development System里安装对应的库。凸轮表编辑器和在线调试工具都集成在开发环境里用起来比较顺手。整个软件栈的搭建时间如果顺利的话一个下午能搞定如果不顺利可能要在驱动和权限问题上折腾一两天。2. 系统环境搭建与Runtime部署2.1 树莓派系统安装与实时内核配置树莓派4B装系统这一步没什么特别的用Raspberry Pi Imager烧录Raspberry Pi OS Lite64位就行。选Lite版本是因为不需要桌面环境省资源。烧录之前在Imager的高级设置里把SSH打开、WiFi配好虽然最终不用WiFi但初次配置方便主机名设成好记的名字。系统起来之后第一件事是换源。国内访问官方源速度不稳定换成清华或者中科大的镜像源会快很多。编辑/etc/apt/sources.list和/etc/apt/sources.list.d/raspi.list把raspbian.raspberrypi.org替换成mirrors.tuna.tsinghua.edu.cn/raspbian然后sudo apt update sudo apt upgrade。实时内核是重点。Raspberry Pi OS默认内核没有RT补丁需要自己编译或者找现成的RT内核包。我试过两种方式一种是直接用rpi-source拉源码自己打补丁编译耗时大概两三个小时另一种是找社区维护的RT内核deb包直接安装省事但版本可能不是最新的。推荐后者除非你有特殊的内核定制需求。编译RT内核的关键配置项CONFIG_PREEMPT_RTy、CONFIG_HIGH_RES_TIMERSy、CONFIG_NO_HZ_FULLy。编译完成后用uname -a确认内核版本带-rt后缀。装好RT内核后还需要把/boot/cmdline.txt里的isolcpus参数加上把CPU核心3隔离出来专门跑CODESYS的实时任务避免被系统进程干扰。# 查看当前内核是否支持RT uname -a # 输出中应包含 PREEMPT RT 字样 # 隔离CPU核心3给实时任务 # 编辑 /boot/cmdline.txt在末尾添加 isolcpus3 nohz_full3 rcu_nocbs32.2 CODESYS Runtime安装与授权CODESYS Runtime for Raspberry Pi的安装包是一个.deb文件从CODESYS官网下载后通过SCP传到树莓派上用sudo dpkg -i安装。安装完成后Runtime会作为系统服务自动启动默认监听端口1217。授权方面CODESYS Runtime在树莓派上可以免费运行但SoftMotion是需要授权的选件。不过CODESYS提供了试用授权每次可以激活一段时间对于学习和测试来说够用了。在Development System里通过“授权管理器”把试用授权分配给树莓派设备即可。安装完成后在PC上的CODESYS Development System里添加设备选择“Raspberry Pi”作为设备类型填入树莓派的IP地址。如果连接成功设备图标会变成绿色。连不上的话先检查树莓派上Runtime服务是否在运行sudo systemctl status codesys。提示CODESYS Runtime默认使用root权限运行这在安全上不是最佳实践但为了访问GPIO和EtherCAT网卡暂时只能这样。如果在意安全性可以配置sudo规则让特定用户以受限权限运行Runtime。2.3 网络配置与EtherCAT主站设置树莓派的以太网口eth0要同时承担两个角色一是与PC上的Development System通信二是作为EtherCAT主站与从站设备通信。这两个角色可以共用一个网口但需要配置虚拟网络接口或者VLAN。我的做法是让eth0走EtherCAT协议另外用一个USB转以太网口与PC通信这样最省心。EtherCAT主站需要在CODESYS里配置。在设备树中添加“EtherCAT Master”节点然后扫描从站。扫描之前要确保树莓派的网口已经正确识别并且没有其他网络服务占用。如果扫描不到从站大概率是网卡驱动的问题——树莓派4B的genet网卡对EtherCAT的支持需要额外配置。# 检查网卡状态 ip link show eth0 # 确认网卡处于UP状态 # 关闭NetworkManager对eth0的管理避免干扰EtherCAT sudo nmcli dev set eth0 managed noEtherCAT从站的ESI文件需要导入到CODESYS的设备仓库中。每个品牌的伺服驱动器都有自己的ESI文件从官网下载后通过“设备仓库”导入即可。导入后扫描从站CODESYS会自动识别并添加到设备树中。3. SoftMotion多轴同步的核心配置3.1 轴的基本配置与参数设置在CODESYS里添加SoftMotion轴每个轴需要配置几个关键参数最大速度、最大加速度、最大减速度、急动度Jerk。这些参数不是随便填的要根据实际机械系统的能力来设定。比如你用的步进电机最高只能跑到1000rpm那最大速度就设成对应值设高了也没用反而可能导致丢步。轴的参考系统也要选对。线性轴选毫米旋转轴选度。如果做凸轮同步主轴和从轴的单位要统一否则凸轮表的比例会乱掉。我一般习惯把所有旋转轴都设成度线性轴设成毫米然后在凸轮表里做单位换算。// 轴参数配置示例在轴对象的属性中设置 VAR AxisMain : AXIS_REF; // 主轴 AxisSlave1 : AXIS_REF; // 从轴1 AxisSlave2 : AXIS_REF; // 从轴2 END_VAR // 在程序初始化时设置参数 AxisMain.MaxVelocity : 3000.0; // 单位度/秒 AxisMain.MaxAcceleration : 10000.0; AxisMain.MaxDeceleration : 10000.0; AxisMain.MaxJerk : 100000.0;急动度这个参数容易被忽略但它对运动的平滑性影响很大。急动度设得太小加减速会显得很生硬机械冲击大设得太大又起不到平滑作用。经验值是从轴急动度设为主轴的1.5到2倍这样从轴跟随的时候不会因为急动度限制而跟不上。3.2 凸轮表的创建与编辑凸轮表是SoftMotion里做同步的核心工具。它的本质是一张“主轴位置-从轴位置”的对应关系表系统根据这张表实时计算从轴应该在哪里。CODESYS的凸轮表编辑器支持图形化编辑可以直接拖拽控制点也可以导入CSV数据。创建凸轮表的步骤在Application里右键添加“Cam”对象然后打开编辑器。编辑器的横轴是主轴位置0到360度或者0到主轴周期长度纵轴是从轴位置。你可以添加多个控制点每个控制点定义主轴在某个位置时从轴应该在的位置。控制点之间的曲线类型可以选直线、多项式或者样条曲线。我一般先用多项式曲线做粗调再用样条曲线做微调。多项式曲线的好处是数学上连续可导速度和加速度都不会突变样条曲线更灵活但控制不好容易出现局部振荡。对于大多数应用5次多项式就够用了。注意凸轮表的控制点不是越多越好。控制点太多会导致曲线在点之间产生不必要的波动反而影响同步精度。一般5到10个控制点就能描述一条复杂的凸轮曲线。凸轮表编辑完成后需要编译并下载到树莓派。在程序里通过MC_CamIn功能块把从轴耦合到主轴上指定使用的凸轮表对象。耦合的时候可以设置偏移量和缩放比例方便做微调。3.3 多轴同步的程序框架程序框架我习惯分成三层初始化层、运动控制层、状态监控层。初始化层负责轴的使能、参数设置、回零运动控制层负责凸轮耦合、齿轮同步、位置指令的生成状态监控层负责读取轴的实际位置、速度、错误状态并做安全处理。PROGRAM PLC_PRG VAR // 轴引用 AxisMain : AXIS_REF; AxisSlave1 : AXIS_REF; AxisSlave2 : AXIS_REF; // 功能块实例 PowerMain : MC_Power; PowerSlave1 : MC_Power; PowerSlave2 : MC_Power; HomingMain : MC_Home; CamIn1 : MC_CamIn; CamIn2 : MC_CamIn; // 状态变量 bEnable : BOOL : FALSE; bHomed : BOOL : FALSE; bCamActive : BOOL : FALSE; END_VAR // 轴使能 PowerMain(Axis : AxisMain, Enable : bEnable, bRegulatorOn : TRUE, bDriveStart : TRUE); PowerSlave1(Axis : AxisSlave1, Enable : bEnable, bRegulatorOn : TRUE, bDriveStart : TRUE); PowerSlave2(Axis : AxisSlave2, Enable : bEnable, bRegulatorOn : TRUE, bDriveStart : TRUE); // 回零 IF bEnable AND NOT bHomed THEN HomingMain(Axis : AxisMain, Execute : TRUE, Position : 0.0); IF HomingMain.Done THEN bHomed : TRUE; END_IF END_IF // 凸轮耦合 IF bHomed AND NOT bCamActive THEN CamIn1( Master : AxisMain, Slave : AxisSlave1, Execute : TRUE, CamTableID : CamTable1, MasterOffset : 0.0, SlaveOffset : 0.0 ); CamIn2( Master : AxisMain, Slave : AxisSlave2, Execute : TRUE, CamTableID : CamTable2, MasterOffset : 0.0, SlaveOffset : 0.0 ); IF CamIn1.InSync AND CamIn2.InSync THEN bCamActive : TRUE; END_IF END_IF这个框架的好处是逻辑清晰每个功能块的状态都能单独监控。MC_CamIn的InSync输出很重要它表示从轴已经进入同步状态只有InSync为TRUE之后才能认为同步真正建立。3.4 同步精度的影响因素与优化同步精度受好几个因素影响任务周期、总线周期、轴的PID参数、凸轮曲线的平滑度。任务周期和总线周期要匹配一般设成一样比如都是1ms。如果任务周期比总线周期快会出现空转如果慢会丢帧。轴的PID参数对同步精度影响很大。位置环的P增益设得太低从轴跟不上主轴设得太高又会振荡。我一般先用默认参数跑起来然后用CODESYS的示波器功能观察主轴和从轴的位置差逐步调整P增益直到位置差最小且不振荡。凸轮曲线的平滑度也很关键。如果曲线在某处有尖角从轴在那个位置会产生很大的加速度可能导致跟随误差超限。用多项式曲线可以避免这个问题因为多项式曲线天然是光滑的。实操心得调试同步的时候先把主轴速度降到额定值的10%到20%观察从轴的跟随情况。低速下没问题了再逐步提速。直接全速跑很容易出问题而且不容易判断是参数问题还是机械问题。4. 在线调试与问题排查实录4.1 在线调试工具的使用技巧CODESYS的在线调试功能很强大但要用好需要一些技巧。最常用的是“示波器”功能可以同时抓取多个变量的波形。调试多轴同步的时候我把主轴位置、从轴位置、位置差、从轴速度都加到示波器里采样周期设成1ms这样能清楚看到同步的动态过程。示波器的触发条件设置很重要。如果只是自由运行很难抓到瞬态过程。我一般把触发条件设成“主轴速度超过某个值”或者“位置差超过阈值”这样能自动捕获异常时刻的波形。另一个好用的工具是“在线修改”。调试的时候经常需要改参数如果每次都停下来改完再下载效率太低。CODESYS支持在线修改改完直接生效不用停机。但要注意不是所有参数都支持在线修改轴的最大速度、最大加速度这些参数改了之后需要重新初始化轴才能生效。// 在线监控变量示例 VAR fMasterPos : LREAL; // 主轴实际位置 fSlavePos : LREAL; // 从轴实际位置 fPosError : LREAL; // 位置跟随误差 fSlaveVel : LREAL; // 从轴实际速度 END_VAR fMasterPos : AxisMain.fActPosition; fSlavePos : AxisSlave1.fActPosition; fPosError : fMasterPos - fSlavePos; // 注意这里需要根据凸轮关系换算 fSlaveVel : AxisSlave1.fActVelocity;4.2 常见问题速查与解决方法调试过程中遇到的问题不少我整理了一个速查表方便快速定位。问题现象可能原因排查方法解决方法从轴不跟随主轴凸轮未耦合成功检查MC_CamIn的InSync输出确认凸轮表ID正确重新执行耦合位置跟随误差大PID参数不合适用示波器观察位置差波形调整位置环P增益或降低主轴速度轴使能失败驱动器未就绪检查驱动器的状态字确认驱动器供电正常无报警同步时有异响凸轮曲线不光滑检查凸轮曲线是否有尖角改用多项式曲线增加控制点Runtime频繁重启实时性不足检查CPU隔离和RT内核确认isolcpus配置正确关闭无关服务EtherCAT扫描不到从站网卡驱动问题检查dmesg中的网卡信息更新网卡驱动或换用USB网卡这个表里的问题我都实际遇到过其中“Runtime频繁重启”最让人头疼。后来发现是树莓派的温度过高导致CPU降频实时任务超时Runtime就重启了。加了个散热风扇之后问题解决。所以如果你也遇到类似情况先检查散热。4.3 实时性问题的深度排查实时性是树莓派跑SoftMotion最大的挑战。Linux本身不是实时操作系统即使打了RT补丁也不能保证100%的实时性。我遇到过几次因为实时性不足导致的同步失败排查过程比较曲折。排查实时性问题的第一步是看CPU占用率。用top命令观察如果CODESYS Runtime的CPU占用率持续超过70%那实时性肯定受影响。第二步是看中断延迟用cyclictest工具可以测量系统的最大中断延迟。正常情况下RT内核的最大延迟应该在100微秒以内如果超过500微秒说明系统有干扰。# 安装cyclictest sudo apt install rt-tests # 运行延迟测试持续60秒 sudo cyclictest -t1 -p80 -n -i1000 -l60000 # -t1: 1个线程 # -p80: 优先级80 # -n: 使用clock_nanosleep # -i1000: 间隔1000微秒 # -l60000: 循环60000次如果延迟超标常见的干扰源有WiFi模块、蓝牙、USB设备、系统日志服务。我的做法是把这些全部关掉sudo systemctl disable bluetooth、sudo systemctl disable wpa_supplicant、sudo systemctl stop rsyslog。另外把CODESYS Runtime的进程优先级调到最高用chrt -f 99启动。注意关闭系统服务的时候要小心别把SSH也关了否则就连不上了。建议在本地终端操作或者确认网络配置没问题再关。4.4 凸轮同步的精度验证方法同步精度怎么验证最直接的方法是用外部编码器或者激光位移传感器测量从轴的实际位置然后和指令位置对比。如果没有这些设备可以用驱动器自带的位置反馈虽然精度差一些但也能说明问题。我一般做两个测试静态测试和动态测试。静态测试是让主轴停在某个位置观察从轴是否停在凸轮表对应的位置误差应该在几个脉冲以内。动态测试是让主轴以不同速度运行观察从轴的跟随误差。动态误差一般比静态误差大因为存在动态滞后。测试数据我习惯用CSV格式记录下来然后用Python或者Excel画图分析。CODESYS的示波器支持导出CSV很方便。分析的时候重点看几个指标最大跟随误差、平均跟随误差、误差的周期性。如果误差有周期性说明凸轮曲线或者机械传动有问题如果误差是随机的说明是实时性或者PID参数的问题。import pandas as pd import matplotlib.pyplot as plt # 读取CODESYS示波器导出的CSV data pd.read_csv(sync_data.csv) # 计算跟随误差 data[error] data[master_pos] - data[slave_pos] # 绘制误差曲线 plt.figure(figsize(12, 6)) plt.plot(data[time], data[error]) plt.xlabel(Time (s)) plt.ylabel(Following Error (deg)) plt.title(Cam Synchronization Error) plt.grid(True) plt.show() # 统计指标 print(f最大跟随误差: {data[error].abs().max():.4f} deg) print(f平均跟随误差: {data[error].abs().mean():.4f} deg)这套验证方法我用了很多次能比较全面地评估同步性能。如果最大跟随误差在应用允许的范围内那这套系统就算调通了。5. 性能优化与扩展思路5.1 提升同步性能的几个关键手段同步性能的提升没有捷径就是一点点抠细节。除了前面提到的CPU隔离、RT内核、PID调参之外还有几个手段效果比较明显。第一个是优化凸轮表。凸轮表的控制点位置和曲线类型对同步精度影响很大。我试过用遗传算法自动优化控制点位置效果比手动调好不少但计算量大适合离线做。实际项目中手动调加上经验判断就够用了。第二个是使用前馈控制。SoftMotion支持速度前馈和加速度前馈开启之后能显著减小跟随误差。前馈系数的整定需要一些技巧一般从0.8开始试逐步增加到误差最小。第三个是调整任务周期。任务周期不是越短越好太短了CPU扛不住反而导致抖动。我试过0.5ms、1ms、2ms、4ms几个档位1ms是树莓派4B上的甜点值。树莓派5的话可以试试0.5ms性能更强。// 开启前馈控制 AxisSlave1.bEnableVelocityFeedForward : TRUE; AxisSlave1.fVelocityFeedForward : 0.9; // 速度前馈系数 AxisSlave1.bEnableAccelerationFeedForward : TRUE; AxisSlave1.fAccelerationFeedForward : 0.85; // 加速度前馈系数5.2 从三轴扩展到更多轴的可行性三轴跑通了自然会想能不能扩展到更多轴。理论上是可以的但有几个限制。首先是CPU算力每增加一根轴运动控制的计算量就增加一份。树莓派4B跑三轴已经占了40%到55%的CPU加到五轴可能就到80%以上了实时性会变差。树莓派5的CPU性能大概是4B的两到三倍跑五轴应该没问题。其次是EtherCAT总线的带宽。EtherCAT的带宽很高100Mbps的速率下跑十几根轴都够用所以总线不是瓶颈。瓶颈在CPU和实时性。再就是授权问题。CODESYS SoftMotion的授权是按轴数算的轴数越多授权费用越高。不过对于学习和测试试用授权可以覆盖。我的建议是如果确实需要控制很多轴可以考虑用多台树莓派做分布式控制每台负责几根轴通过EtherCAT或者网络同步。这样每台树莓派的负载都不会太高实时性有保障。5.3 实际项目中的经验教训这个项目做下来踩的坑不少有几个教训值得分享。第一个教训是不要忽视散热。树莓派4B跑满负载的时候发热很厉害不加散热片和风扇的话几分钟就降频了。降频之后实时性直接崩掉同步误差大到没法看。我后来加了一个铜散热片加5V小风扇温度控制在60度以下就稳定了。第二个教训是TF卡的质量很重要。CODESYS Runtime会频繁读写日志和配置文件劣质TF卡用不了多久就出坏块系统直接起不来。建议用工业级的TF卡或者干脆用SSD通过USB启动。第三个教训是调试的时候要有耐心。多轴同步的调试不是一蹴而就的需要反复调整参数、观察波形、分析数据。我一开始想半天调好结果花了两天。后来放平心态一天调一点反而效率更高。实操心得调试的时候准备一个笔记本把每次修改的参数和对应的效果都记下来。这样能快速定位到哪次修改是有效的避免重复劳动。我用了这个方法之后调试效率至少提高了一倍。5.4 这个方案的适用边界与替代选择说了这么多优点也得说说这个方案的局限性。树莓派加CODESYS SoftMotion的方案适合的是中小型自动化项目轴数不多、精度要求不是特别苛刻的场景。如果你的项目需要控制十几根轴、同步精度要求微秒级、或者需要功能安全认证那这个方案就不合适了还是得上专用的运动控制器。替代方案方面如果预算稍微充裕一点可以考虑用工业级的ARM工控机跑CODESYS实时性比树莓派好很多价格也就一两千块。如果预算更充裕直接用专用的运动控制器省心省力但成本就上去了。还有一个选择是用树莓派Pico做底层运动控制树莓派4B做上层逻辑两者通过串口或者SPI通信。Pico的RP2040芯片有PIO功能做脉冲方向控制很合适成本也低。但这个方案需要自己写底层固件开发工作量大一些。总的来说树莓派跑CODESYS SoftMotion是一个性价比很高的方案特别适合教学、实验、小型设备。它让你用几百块的硬件就能学到工业级的运动控制技术这个价值是很大的。我在这个过程中学到的凸轮同步、EtherCAT、实时系统调优的知识在后来做其他项目的时候都用上了。