简介:以国外开源PLC编译器源码为主体,面向工业自动化和嵌入式控制开发者,围绕 IEC 61131-3 标准实现了指令表、结构化文本、功能块图、梯形图、顺序功能图五种编程语言,可用于学习 PLC 程序编译原理、语言解析流程及工业控制工具的设计方法。压缩包共216个文件,大小840KB,以 cc 和 hh 源文件为主,配合 C/C++ 头文件、构建脚本、Makefile 工程配置、测试及说明文档,构成完整开源项目结构,包含具体示例与构建细节。目前已有4558人学习下载,资源展示出清晰的模块划分,便于读者追踪词法分析、语法树构建、代码生成等关键环节,也可作为二次开发、毕业设计或课程设计的参考基底。整体轻量紧凑,源码组织清晰,适合从源码层面深入理解 IEC 61131-3 编译器的实现思路,以及跨平台构建脚本的组织方式。
1. 为什么我一个做项目的人,非要啃开源PLC源码
做工业自动化的朋友应该都有同感:从入门到做项目,大家接触的控制器基本绕不过几个大厂,开发环境是专用的,通信协议是半封闭的,扩展一个总线或者改一个底层时序,难度堪比重新写一遍上位机。工作时间长了,你慢慢会发现很多设备其实用不到那么多高端闭源功能,我们缺的是对控制器底层的掌控力。这也是我第一次注意到国外开源PLC源码的原因:它给我提供了一条从“只能猜”到“能看懂”的路径,让我能直接看控制器里面到底怎么调度任务、怎么收发包、怎么管理IO。
这篇内容不开任何平台,就是我个人对国外开源PLC源码的研究和实操记录。我会先梳理开源PLC生态里几个值得看的项目,再上手把一个应用最广的运行时从源码编译起来,部署到树莓派上,最后把执行逻辑通过Modbus读出来。全程不写虚的,只说自己的实测体验和踩坑过程。如果你对PLC底层感兴趣,或者在项目里受够了封闭生态的束缚,打算自己攒一套控制器逻辑,这篇文章应该能帮你少走一段弯路。
2. 国外开源PLC源码的几个主要流派
开源PLC源码不是一个单一项目,而是一整片生态。我刚开始接触的时候也被各种项目名搞晕了,后来按“用途”分类梳理,发现其实就三大类:一类是能直接当PLC运行时使用的框架,一类是把IEC 61131-3程序编译成可执行代码的IDE工具,还有一类是围绕PLC的通讯库和可视化界面。把这三条线理清楚,你就知道选谁更合适了。
2.1 OpenPLC:一条龙式的开源运行时
OpenPLC是我目前用得最多、也最推荐普通工程师上手的一个项目。它在GitHub上维护了完整源码,早期版本用C语言写运行时,后来衍生了OpenPLC v3,作为一套完整的软PLC系统。它的核心设计思路很直接:在Linux或者Windows上跑一个本地服务,接收你写好的梯形图或者结构文本程序,编译成原生C代码以后加载运行。整个过程非常透明,你甚至可以看到它生成的中间代码。
这套源码厉害的地方在于硬件适配层做得比较完善,树莓派、Arduino、ESP32、传统x86工控机都能跑。也就是说你可以先用一套逻辑在PC上仿真,然后原封不动部署到嵌入式设备里,硬件层面的差异被它尽量屏蔽掉了。对于需要快速做原型验证的团队,这是个非常讨巧的设计。
2.2 Beremiz:把PLC程序转成C语言的IDE
Beremiz是另一个我研究过的项目,它的定位和OpenPLC不太一样。OpenPLC自带Web管理界面,逻辑编译是内嵌的;而Beremiz更偏传统IDE,支持完整的IEC 61131-3五种编程语言,包括梯形图、功能块图、结构文本、指令表和顺序功能图。它的实现思路是先解析你的PLC程序,生成C代码,再通过GCC编译成目标平台可执行文件。
这套流程适合谁呢?适合那种需要深度定制,甚至想把PLC运行时嵌进自己硬件固件里的玩家。因为Beremiz生成的是标准C代码,拿到代码之后你想修改底层调度策略、增加特殊通信协议,都有充分空间。不过代价就是环境搭建比较繁琐,依赖的Python包不少,建议务必用虚拟环境隔离。
2.3 周边生态:PLC通讯库和HMI工具
除了完整的开源PLC,还有一类项目值得关注,就是通信库。比如Apache PLC4X,主打用统一API对接不同品牌的PLC;还有libplctag,专门用来读写AB系列PLC的标签数据。这些不是控制器本身,但在做上位机接入的时候,它们能让你节省大量时间。
HMI可视化这边,有FUXA、IoTOpenSCADA等开源方案,它们的通用思路是Web组态,界面直接跑在浏览器里。搭配OpenPLC这类运行时,整套控制系统的软件成本几乎可以压到零。我自己搭过一版测试环境:树莓派跑OpenPLC做逻辑,FUXA做SCADA页面,Modbus TCP一接就通,效果比预想中稳定很多。
3. 实操:把OpenPLC源码从GitHub拉到树莓派上跑起来
看源码不如跑源码。这一节记录我在树莓派上部署OpenPLC的全过程,包括环境准备、编译安装、上传PLC程序、用Modbus从站读出线圈状态。整个过程大概一两个小时,大部分时间耗在依赖包下载上。
3.1 环境准备:硬件选型和系统
我用的硬件是树莓派4B,8GB内存版本。说句实话,如果只是跑一个逻辑量不多的小控制器,1GB内存的版本也够用,因为OpenPLC运行时本身的资源占用不高,系统空闲时内存占用一般不到100MB。但既然要编译源码,建议内存大一点,否则GCC编译的时候容易卡死。
操作系统我装了64位Raspberry Pi OS Lite,不带桌面环境,减少系统开销。存储卡建议用32GB以上的工业级卡,因为编译过程会写入不少临时文件。安装系统时把SSH打开,后续操作全靠终端完成,不用接显示器。
3.2 拉源码与一键编译
OpenPLC v3源码拉下来之后,安装流程写得比较自动化。在终端依次执行:
git clone https://github.com/thiagoralves/OpenPLC_v3.git cd OpenPLC_v3 sudo ./install.sh rpiinstall.sh脚本会判断你传参的平台类型,树莓派对应的是rpi。它会自动调用apt-get安装一堆依赖,包括编译器、libmodbus开发库、Web服务器相关组件等。整个安装过程比较长,我这边大概跑了十几分钟,瓶颈主要在下载依赖包的速度上。
编译完成后,启动服务的方式同样简单:
sudo ./start_openplc.sh服务起来以后,浏览器访问树莓派的IP地址加8080端口,就能看到OpenPLC的Web管理界面。默认用户名是openplc,密码也是openplc,登录后可以上传PLC程序、监控变量状态、重启运行时。
3.3 上传一段最简单的逻辑,用Modbus读出来
光启动服务还不够,得让控制器真正执行逻辑。我用OpenPLC Editor写了一个简单的自锁启动程序,导出结构文本文件,然后在Web管理页面里上传。核心逻辑如下:
PROGRAM main VAR start_button AT %IX0.0 : BOOL; stop_button AT %IX0.1 : BOOL; run_contact AT %MX0.0 : BOOL; output_coil AT %QX0.0 : BOOL; END_VAR run_contact := (run_contact OR start_button) AND NOT stop_button; output_coil := run_contact; END_PROGRAM这一段逻辑实现了典型的启保停控制:按下启动按钮,线圈吸合;按下停止按钮,线圈断开。上传成功后,OpenPLC会触发重新编译,并在日志里显示编译是否通过。这个过程中你能直观看到开源PLC源码执行IEC 61131-3程序时的中间流程,跟我们用传统PLC时黑盒式的体验完全不同。
接着我用Modbus Poll工具连接树莓派的Modbus TCP端口,端口号默认502。OpenPLC把%QX0.0映射成Modbus线圈地址0,把%IX0.0映射成输入离散量地址0。点击Modbus Poll里的线圈写入,把线圈0置成True,再把输入离散量模拟成启动按钮信号,就能看到输出线圈跟着变化。实测下来,从信号变化到逻辑刷新,周期时间基本在10毫秒以内,这个速度满足相当一部分非严格实时控制场景了。
4. 从源码到落地:常用排查技巧和避坑心得
真拿开源PLC源码做项目,光会照抄安装步骤是不够的。我在几个月的使用过程中踩了各式各样的坑,挑几个有代表性的记在这里,希望对你有实际帮助。
4.1 编译安装类的坑
最典型的问题是依赖缺失。OpenPLC的install.sh脚本虽然会装依赖,但如果你的系统之前装了其他版本的工具链,容易出现libmodbus版本冲突。我踩过一次很无语的问题:编译都通过了,启动Web服务以后死活连不上Modbus端口,后来在终端里执行ldd /usr/bin/openplc才发现链接到了一个旧版的libmodbus库。解决办法是卸载旧库,重新安装开发版本,然后重新编译一次。
另外一点是要注意树莓派的/boot/config.txt里如果开了串口控制台,串口可能会被系统占用,导致你接了RS485模块却没反应。当时我在调试Modbus RTU从站时,所有设置都核对了一遍仍然超时,最后想起来树莓派的UART默认被控制台占用了。在/boot/config.txt里把enable_uart=1加上,并关闭蓝牙串口映射之后,问题才解决。
4.2 通讯和地址映射类的坑
地址映射这个问题,官方文档有写,但实际运行时会因为版本不同产生细微差异。OpenPLC默认把%QX0.0映射到Modbus Coil地址0,把%IW0.0映射到Input Register地址30001,%QW0.0映射到Holding Register地址40001。听起来很清晰,但如果你用的是非官方编译版本,映射关系可能被改过,排查起来会让人抓狂。
我的经验是:不要直接信文档,先在逻辑里给某个输出线圈赋值常量,然后用Modbus扫描工具全地址段扫一遍,看看哪个地址真的在变化。这种方法笨了点,但能最快确定实际映射关系,尤其在对方是非标定制系统时非常管用。
4.3 跑开源PLC前,先把许可证看清楚
这里要说一个很多初学者容易忽略的问题:开源不等于随意商用。OpenPLC用的是GPLv3协议,这意味着如果你分发的是基于它的修改版本,就要把源代码一起公开。如果你的项目只是内部自用,那没问题;但如果你打算做产品卖给客户,最好先在法律层面做好评估,或者考虑购买商业授权。
我见过一个团队,花半年时间基于某个开源PLC框架改了控制器程序,结果产品发布前才注意到GPL传染问题,被迫重构底层,非常痛苦。我的建议是:项目立项的第一天,就把许可证风险写到风险清单里,别等代码量上来再处理。
5. 最后分享一点我的个人体会
在整个研究过程中,我最大的收获不是“拿到了一套免费PLC”,而是搞懂了商业PLC很多设计背后的逻辑。当你亲手把源码读下来、编译出来、把一段梯形图跑到嵌入式板子上时,你会对循环扫描周期、输入输出刷新、通讯栈占用这些概念有完全不同的理解。现在我再回头用商业PLC做项目,心里踏实多了,出了问题也敢去排查底层原因。
如果你刚接触这个方向,我的建议是先从OpenPLC入手,用树莓派或者虚拟机搭一套测试环境,把简单的启保停逻辑跑通,然后逐步加模拟量、通信、PID控制。不要一上来就追最新的源码分支,稳定版更适合作业。等你对整体架构熟悉了,再去看Beremiz或者其他偏底层的项目,思路会清晰很多。
开源PLC源码这条路,并不会取代传统的商用PLC,但它给了我们这些人一把打开“控制器黑盒”的钥匙。能够看清底层的人,在任何平台上都不会被锁死。
本文还有配套的精品资源,点击获取