简介:面向PLC初学者与初次接触CODESYS的工程师,这份学习资料以《PLC 综合开发利器——CoDeSys 基础编程及应用指南》为核心,围绕IEC 61131-3标准与结构化文本编程,系统讲解CODESYS软件的基本使用、常用指令和典型案例,并延伸至EtherCAT等工业总线下的软PLC应用场景。压缩包内共1个PDF文档,整体大小约12.38MB;内容从IEC 61131-3标准、PLCopen组织介绍入手,逐步展开软PLC控制方案、CODESYS实时核与开发系统框架,再到软件安装步骤、帮助获取及编程界面使用,章节划分清晰,便于按序学习。目前已有1954人学习下载,适合希望从零开始掌握CODESYS编程环境、夯实结构化文本编程能力的读者。通过学习,读者能够快速搭建开发环境,理解IEC 61131-3各语言特点,并结合案例积累常见指令与典型工程应用的经验,为后续工业自动化项目开发打下扎实基础。 很多人第一次装好CODESYS,第一反应不是兴奋,而是懵。打开那个灰扑扑的IDE,发现没有传统PLC那种固定的梯形图入口,设备树、POU、任务配置、库管理器铺了一屏幕,想下手都不知道从哪点起。我自己从日系PLC转过来时,就卡在“这玩意儿到底算软件还是算平台”这个问题上好几天。项目越做越多才想明白:CODESYS不是一个PLC品牌,它是基于IEC 61131-3标准的整套自动化开发平台。IDE负责编程调试,Runtime负责在控制器或PC上跑程序,两者分开,所以你写好的程序可以部署到不同厂商的硬件里,也能直接跑到Windows或Linux系统的普通电脑上。
这篇东西不是官方文档的翻译,是我把学习CODESYS过程中查过的资料、踩过的坑、验证过的代码模板整理成一份参考。适合刚入门的同行按顺序看,也适合已经写过几个项目的人当速查手册用。里面涉及的内容比较杂,从环境搭建、语法细节,到飞剪凸轮、HMI标签通讯都有,属于典型的“遇到哪块点哪块”型资料。
1. 学习路线与资料体系:别急着敲代码
1.1 先搞懂CODESYS的体系结构
CODESYS的全称是Controller Development System,翻译过来就是“控制器开发系统”。它的核心思路是把编程环境和运行环境拆开:开发环境叫CODESYS Development System,也就是你电脑上装的那个IDE;运行环境叫CODESYS Control Runtime,需要单独部署在目标设备上,比如工控机、树莓派、第三方PLC,或者直接装在电脑系统里跑仿真。
这个架构带来的好处是硬件无关性。今天你在仿真器里写的程序,换一台支持CODESYS Runtime的国产PLC,大概率可以直接运行;反过来,厂商定制版基于CODESYS的设备,也可以用原版IDE打开工程。这个特性在工作里很实用,我见过不少公司用同一套CODESYS工程移植到不同项目的控制器上,只改IO映射和轴参数。
学习阶段最省钱的方案是这样的:去官网或者CODESYS Store下载Development System,再装一个CODESYS Control Win V3(负责在Windows上模拟软PLC)。这样没有硬件也能跑完整个开发调试流程,包括可视化、运动控制、OPC UA通讯,都能在电脑上验证。我强烈建议新手先这么玩,别一上来就买PLC。
1.2 官方资料从哪里找、怎么用
CODESYS的官方资料其实非常全,问题在于分散。第一手资料永远是IDE自带的Help文档,你装好软件后在菜单栏里就能打开,里面不光有函数功能块说明,还有各类库的编程规范。第二是CODESYS Store,很多官方库和第三方组件都可以在这里下载,比如运动控制用的SoftMotion、HMI用的TargetVisu,都是从这个渠道安装的。
中文资料方面,CODESYS有官方中文社区和公众号,里面有不少技术文章和培训视频,质量在免费资源里算不错的。如果遇到英文错误提示,直接复制到官方论坛搜,基本都能找到官方工程师的回复。我的建议是:遇到问题先看Help,再看Store里的库描述,最后去论坛搜,这一套顺序下来,90%的问题都能自己解决。
2. 语法细节:命名空间、数据类型转换与冷门类型
2.1 为什么floor函数必须带命名空间
很多从西门子或其他平台转过来的人,第一次在CODESYS里写FLOOR(1.8)会直接报错:找不到函数。原因在于,CODESYS标准库里很多数学函数并不在全局命名空间里,而是放在Standard命名空间下,直接调用时解析器无法识别。正确写法是:
// 错误写法 x := FLOOR(1.8); // 正确写法 x := Standard.FLOOR(1.8);除了命名空间问题,还要注意FLOOR和TRUNC对负数的处理逻辑不一样。FLOOR是向下取整,FLOOR(-1.2)结果会是 -2;而TRUNC是直接截断小数部分,结果 -1。这个坑在配方计算、产量统计这些场景里很容易出现误差。如果项目里有“取整”逻辑,一定要先想清楚业务上需要的是向下取整还是截断取整。
2.2 byte转real的两种不同思路
热词里经常有人搜“CODESYS byte转real”,但搜到答案还是搞不定,因为大家问的其实是两件不同的事。
第一种是“数值转换”,就是想把BYTE里的数值10变成REAL类型的10.0。CODESYS不支持BYTE直接隐式转REAL,需要先转成整数类型再转浮点:
VAR bData : BYTE; rValue : REAL; END_VAR rValue := INT_TO_REAL(bData);第二种是“位模式转换”,就是从通讯报文里取出4个字节,希望把这4个字节重新解释成一个REAL浮点数。这种情况下做数值转换就完全错了。比如收到3F 80 00 00四个字节,按IEEE 754解释是1.0,但按数值转换会得到63.0之类的数。正确做法是用UNION或指针:
TYPE U_ByteToReal : UNION b : ARRAY[0..3] OF BYTE; r : REAL; END_UNION END_TYPE这是我在串口仪表通讯、MODBUS浮点读取里最常用的处理方式。很多人卡了半天,其实就是没分清这两种转换场景。
2.3 _UXINT这类系统类型是什么
__UXINT是CODESYS里的系统保留类型,全称是Unsigned eXtended INTeger,表示“无符号扩展整型”。它和__XINT(有符号扩展整型)一样,位宽会跟随目标平台自动变化:32位系统下就是32位,64位系统下就是64位。
正常业务逻辑里几乎不会主动声明这种类型,它主要出现在指针运算、地址偏移、SIZEOF这些底层操作中。举个例子,用ADR()取数组地址后做指针偏移,如果平台是64位,地址宽度是64位,而DINT只有32位,你拿DINT去做偏移计算就可能溢出。这种情况用__XINT或__UXINT就安全得多:
VAR pAddr : POINTER TO BYTE; offset : __UXINT; END_VAR pAddr := ADR(arrData); offset := SIZEOF(arrData); // 返回值本质上是UXINT类型说白了,遇到这种类型不用慌,它就是为了适配不同CPU位宽而存在的。在ARM、x86这类不同架构的软PLC上调试程序,这类类型能避免不少移植问题。
3. 数据封装与文件操作实战
3.1 把“全局变量满天飞”改成结构化封装
我刚写CODESYS时,习惯把所有状态量都丢到全局变量表里,设备一复杂,几百个变量堆在一起,调试时眼睛都能看花。后来学乖了,用STRUCT把一类数据包起来,再用FUNCTION_BLOCK把这些数据封装成带行为的对象。
比如一个简单的电机轴配置:
TYPE ST_AxisData : STRUCT bEnable : BOOL; bRun : BOOL; rSpeed : REAL; rAcceleration : REAL; nFaultCode : WORD; tLastRunTime : TIME; END_STRUCT END_TYPE这样在IO映射时只映射一个结构体实例,程序里传参也只传一个结构体指针,代码立刻清爽很多。再进一步,把对轴的操作也封装进功能块里,外部调用者只需要调用Start()、Stop()、ResetFault()这几个方法,内部怎么做根本不用管。别人接手你的工程时,不用从底层一行行看逻辑,效率能高出不少。
3.2 文件操作:读写配置和日志
CODESYS的文件操作经常被问到,很多人以为要用底层C库的fopen、fread,其实标准库和扩展库已经封装好了常用函数。常规操作包括:
| 函数名 | 用途 | 返回值 | 注意事项 |
|---|---|---|---|
FileOpen | 打开或创建文件 | 文件句柄/错误码 | 路径必须存在,否则创建失败 |
FileRead | 从文件读数据 | 实际读取字节数 | 需要分配足够缓冲区 |
FileWrite | 写数据到文件 | 实际写入字节数 | 注意缓冲区长度 |
FileClose | 关闭文件句柄 | 错误码 | 忘记关闭会占用句柄 |
FileDelete | 删除指定文件 | 错误码 | 文件必须关闭后才能删 |
不同库版本里函数所在的位置不一样,SysFile、CAA.File都见过,具体看库管理器里装的是什么。这里要特别提醒:路径写法和Windows习惯不一样,软PLC跑在Linux下时路径区分大小写,Windows下作为服务运行时相对路径经常定位不到,所有路径建议写绝对路径。
3.3 实操:配方文件读取
给一个最常用的配置读取流程:开机时通过文件读取配方参数,失败则使用默认参数。步骤是:先FileOpen以“读”方式打开文件,然后FileRead()把内容读入字节数组,再用MEMCPY把字节拷贝到结构体,最后FileClose()。
如果文件不存在,CODESYS没有直接“文件是否存在”的通用函数,可以用FileOpen尝试打开,返回错误码就说明文件不存在,此时创建默认文件或者直接跳到默认参数逻辑。这个“先试错再判断”的思路在嵌入式环境里比查询API更通用。
4. 运动控制:电子凸轮、飞剪与偏心轮机构
4.1 飞剪工艺与电子凸轮的核心逻辑
飞剪是典型的电子凸轮应用场景。生产线上材料连续前进,切刀要在材料行进到指定长度时追上材料、完成剪切、再返回原位。这里的关键是切刀轴的位置不能和主轴保持固定比例,而是要在剪切区有一段“同步段”,让刀子速度匹配材料速度;剪切完成后再快速返回。
用简单的MC_GearIn齿轮耦合做不到这种非线性关系,必须用电子凸轮MC_CamIn。它的本质是建立一张表:把主轴(通常是传送轴编码器)角度或位置映射到从轴(切刀轴)的位置。主轴转过多少,从轴该走到哪,全部预先定义好。
4.2 偏心轮滑块的数学模型与凸轮表生成
曲柄滑块机构是最常见的机械执行机构之一,凸轮行业里常叫“偏心轮滑块”。主动轴旋转角度θ,滑块输出位移x,公式是:
x = r·cosθ + sqrt(L² - r²·sin²θ)其中r是偏心距(曲柄半径),L是连杆长度。实际设计时可以根据这个公式在Excel或Python里生成一组主轴角度和从轴位移的点数组,再导入CODESYS的凸轮表编辑器,或者用MC_CamTableSelect关联到凸轮表变量。
生成凸轮表时有三个要求需要特别注意。第一,凸轮表首尾必须闭合:从轴在主轴起点和终点的位置要一致,速度加速度更要一致,否则机构会有明显冲击。第二,剪切区的曲线要保证平滑过渡,建议至少让速度和加速度连续。第三,主轴经过回零后再进入凸轮耦合,凸轮起点永远以主轴当前位置为基准,否则相位错位。
4.3 MC_CamTableSelect调用细节
凸轮表准备好后,在CODESYS SoftMotion里调用MC_CamTableSelect选表,再通过MC_CamIn执行耦合。选表的代码逻辑如下:
// 选择凸轮表并建立主轴从轴耦合 MC_CamTableSelect_Execute := TRUE; MC_CamTableSelect_Master := ADR(gAxisMaster); MC_CamTableSelect_Slave := ADR(gAxisSlave); MC_CamTableSelect_CamTable := ADR(gCamTable);这里有个容易踩的坑:执行MC_CamTableSelect时,从轴最好处于停止状态;如果从轴还在运动,凸轮起点会直接和当前位置做差,导致上电瞬间就跳一段距离。另外,主轴一定要配置成位置轴,不能是速度轴。很多初学者图省事把主轴设成速度控制,结果凸轮跟随时相位一直对不齐,查了半天才发现主轴模式不对。
5. HMI交互与标签通讯
5.1 自定义图片导入:不要只拖一个PNG进去
在CODESYS可视化里做界面的新手,常犯一个错误:直接从文件管理器把PNG拖进画面,发现图片要么不显示,要么显示成空白。正确做法是先把图片添加到工程的“图片集合”里,给它一个明确的名称,然后在可视化元素的“图标”属性里引用这个名称。
图片集合管理里支持PNG透明通道,所以创建图标、状态指示灯图片时可以直接用透明背景图片。注意两点:第一,图片名称不要用中文和空格,运行时按名称索引容易出问题;第二,如果你做的是WebVisu网页可视化,图片是单独上传并按需加载的,第一次打开页面时会有一个缓存过程,这很正常。
5.2 威纶通与CODESYS通讯:Modbus TCP与OPC UA
威纶通触摸屏连CODESYS,常见有两条路:Modbus TCP和OPC UA。
Modbus TCP方式:在CODESYS设备树里添加一个Modbus TCP Slave设备,把要通讯的变量映射到保持寄存器地址;威纶通侧新建一个Modbus TCP Master设备,指向CODESYS的IP地址和端口502,按寄存器地址读写。这个方案胜在稳定,只要寄存器映射表设计清楚,不易出问题,缺点是每次加变量都要改映射表。
OPC UA方式:CODESYS工程启用OPC UA Server后,威纶通新组态软件支持直接走OPC UA,能浏览到PLC的变量树,拖拽绑定标签。开发效率高,不用维护寄存器映射,但上位机多的时候要注意服务器连接数限制。
我的经验是:点数少、开发周期紧选OPC UA;点数多、有实时性要求或者现场上位机种类复杂,选Modbus TCP。可靠性的优先级永远高于开发效率。
5.3 汇川AM系列与触摸屏的标签通讯
汇川AM系列PLC(比如AM400、AM600)本身就是基于CODESYS内核开发的,只是IDE换成了InoProShop。所以它在原理上和通用CODESYS是一致的,只是通讯功能被汇川二次封装过,和自家触摸屏的标签通讯做得很顺。
实际项目中,在触摸屏组态软件里新建工程时选择对应PLC型号,通讯建立后可以直接“导入PLC变量”,然后从变量列表里勾选需要监视的变量,连线就完成了。不需要手动定义寄存器地址。这个流程是“标签通讯”最直白的体现——上位机直接按变量名读写,而不是按地址读写。
如果发现变量列表里很多变量导入不进去,先检查这些变量是不是被声明成了局部变量或者被编译器优化掉了。CODESYS的LADDER/FBD里如果某个变量从未被引用,编译器很可能直接忽略它,导致HMI侧根本看不到。解决办法是把这些变量放到全局变量表中,或者确保在某个POU里被实际读写过。
6. 虚拟机环境、授权与常见问题排查
6.1 虚拟机里跑软PLC的几个坑
先用虚拟机搭CODESYS学习环境是很省钱的做法,但会有几个实际困难。第一个坑是网卡识别:CODESYS For Linux在虚拟机里装好后网卡名可能和物理机不一样,导致EtherCAT主站扫描不到从站,建议直接改用虚拟网卡或者把目标IP绑定成固定地址。第二个坑是实时性:Windows虚拟机不适合做硬实时运动控制,任务周期设到1ms以下就容易抖,所以只适合功能验证,别指望拿它调伺服参数。
第三个坑是密码问题。很多人会给工程或虚拟机系统设置密码,时间久了就忘。工程密码是没法找回的,我的建议是:在工程属性里设置保护密码时,务必同步备份一份未加密工程,或者把密码记录在团队共享的密码表里。虚拟机系统的默认账号密码拿到手第一件事就是改掉,并做快照,这样折腾坏了能快速恢复。
6.2 授权机制与合规使用
CODESYS的IDE本身是免费下载的,但Runtime运行环境通常需要授权。学习阶段可以用CODESYS Control Win SL的免费试用授权,或者从CODESYS Store里下载带体验授权的组件,这些足够跑通一个完整项目。商用落地时需要购买对应Runtime的授权文件,具体费用跟设备类型和功能点数有关。
网上有一些“2小时破解runtime”的帖子,我的建议是别碰。这类破解文件经常捆绑木马,改系统时间还会导致软PLC授权检测异常,甚至把工程文件损坏。我做项目的原则是工具链必须清白,否则现场出问题你根本分不清是程序bug还是环境被改坏了。
6.3 常见问题速查
| 问题 | 常见原因 | 解决办法 |
|---|---|---|
| FLOOR找不到 | 没有引用Standard命名空间 | 写Standard.FLOOR() |
| BYTE转REAL报类型错误 | 缺少显式转换 | 用INT中间类型转换 |
| 浮点数读数异常大 | 把位模式当数值转了 | 用UNION或指针方式读取 |
| 文件写入失败 | 目录不存在/权限不足/大小写 | 提前创建目录,写绝对路径 |
| 凸轮耦合启动冲击 | 凸轮表首尾不闭合 | 检查首尾位置、速度、加速度 |
| HMI导入标签为空 | 变量被优化或未在全局表 | 放到全局变量表并实际引用 |
| 威纶通通讯假死 | 从站地址冲突/轮询太快 | 检查从站地址,延长轮询周期 |
写在最后的个人体会
同一种功能,CODESYS里有好几种实现路径,差别往往不在功能本身,而在后期的可维护性和调试成本。比如数据封装做得好,现场改工艺参数时不用翻代码;凸轮表定义得规范,换一种机构只需重新生成表,不需要改逻辑;HMI通讯方式选对了,现场调试效率能差出整整半天。
我在实际项目里最深刻的体会是:CODESYS不是靠背指令学会的,它是靠“结构化思维”驱动的。变量怎么组织、库怎么划分、轴怎么建模、通讯怎么规划,这些东西想清楚了,写起程序来水到渠成。刚开始学的人容易陷在单个功能块的用法里,我建议跳出来,先拿一个带HMI和运动控制的小项目当练习目标,做完一套,整个体系的脉络就出来了。
本文还有配套的精品资源,点击获取