OpenPLC for Arduino:不是“仿真”,是真正在跑的PLC
你有没有试过,在Arduino Nano上按下按钮,传送带真的转起来;在Web页面里点一下“急停”,电机立刻断电——而背后驱动这一切的,不是一堆if-else和digitalWrite(),是一段标准IEC 61131-3梯形图?没有虚拟机、没有Linux、没有额外网关,只有一块5美元的开发板,外加一个浏览器。
这不是PLC模拟器,也不是逻辑验证玩具。这是OpenPLC for Arduino——一个把工业控制核心能力从机柜里“抠”出来,塞进MCU Flash里的硬核实践方案。
它不教你怎么配TIA Portal的许可证,也不让你先花三个月啃手册。它从第一行代码开始就告诉你:PLC的本质,就是循环读输入、执行逻辑、写输出。而这个循环,在Arduino Uno上,每10毫秒就稳稳跑一次。
为什么是OpenPLC?而不是另一个“PLC库”?
市面上有太多叫“PLC”的Arduino项目:有的只是IO封装,有的只是状态机包装,还有的干脆是Modbus从站+网页开关。但OpenPLC不一样——它是一个可运行IEC 61131-3字节码的轻量级运行时(Runtime),不是语法糖,不是胶水层,是真正按标准定义执行扫描周期的确定性引擎。
关键不在“能用”,而在“像真PLC那样工作”。
比如它的扫描循环:
void openplc_scan_cycle() { hal_read_inputs(); // ← 真实采样物理引脚(含防抖/滤波) runtime_execute(); // ← 解释执行LAD/ST编译后的字节码 hal_write_outputs(); // ← 原子刷新所有输出(非逐个 digitalWrite) }这个函数被放进millis()或硬件定时器中断中,确保周期抖动<50μs(Nano实测)。它不依赖delay(),不阻塞串口通信,不分配堆内存——因为工业逻辑不能“偶尔卡一下”。
更关键的是,它把PLC寻址语义真正落地了:
| PLC地址 | 含义 | 映射到Arduino |
|---|---|---|
%IX0.0 | 数字输入位0 | pinMode(2, INPUT)+digitalRead(2) |
%QX0.1 | 数字输出位1 | pinMode(3, OUTPUT)+digitalWrite(3, val) |
%IW0.0 | 模拟输入字0 | analogRead(A0)→ 10-bit → 软件校准后存入寄存器 |
这个映射不是写死在代码里,而是通过一张表完成解耦:
const IO_map_t io_map[] = { { .pin = 2, .type = INPUT, .address = 0x0000 }, // %IX0.0 { .pin = 3, .type = OUTPUT, .address = 0x0001 }, // %QX0.1 { .pin = A0, .type = ANALOG_INPUT, .address = 0x0100 }, // %IW0.0 }; openplc_init(io_map, ARRAY_SIZE(io_map));你看,%IX0.0不再是文档里的符号,而是你焊在面包板上的那个按钮;%QX0.1也不是抽象线圈,而是你接在固态继电器IN端的那根杜邦线。OpenPLC让PLC编程第一次有了触感。
Web IDE:不用装软件,打开浏览器就能画梯形图
传统PLC教学最劝退的一环是什么?不是逻辑难,是环境搭不起来。
学生刚弄明白自锁电路,却发现CODESYS要注册、要激活、要选设备型号、要下载驱动……最后连“启动”按钮都点不亮。
OpenPLC直接绕开整套授权链:它用Python Flask搭了个Web服务器,内置Beremiz编译器,浏览器即IDE。
你不需要知道什么是XML项目文件,也不用理解.st字节码结构——你只需要:
- 打开
http://arduino-ip:8080 - 点击「新建项目」→ 选择「梯形图」
- 拖两个常开触点(
%IX0.0,%IX0.1),再拖一个线圈(%QX0.0),连成启保停回路 - 点「编译并上传」→ 自动走串口烧录进Flash
整个过程,零本地安装,零配置,甚至不需要知道Arduino的COM口在哪(Web IDE通过USB CDC自动识别)。
而且,它不只是“写完就跑”。你可以在同一页面里:
- 实时查看每个
%IX/%QX的当前值(绿色=TRUE,灰色=FALSE) - 在线强制修改变量(比如把
%QX0.0设为FALSE,模拟继电器粘连故障) - 查看扫描周期耗时、字节码执行计数、Modbus请求统计
这已经不是IDE,而是嵌入式PLC的调试控制台。
Modbus不是附加功能,是默认协议栈
很多开源PLC项目把Modbus当“扩展模块”来写,结果一接SCADA就掉链子。OpenPLC反其道而行之:Modbus是它的原生神经网络。
它把PLC内存区直接映射为Modbus地址空间:
modbus_mapping = { 'discrete_inputs': {'start': 0x0000, 'size': 32}, # %IX0.0 ~ %IX3.7 'coils': {'start': 0x0000, 'size': 32}, # %QX0.0 ~ %QX3.7 'input_registers': {'start': 0x0100, 'size': 16}, # %IW0.0 ~ %IW15.15 'holding_registers': {'start': 0x0200, 'size': 16} # %MW0 ~ %MW15 }这意味着:当你用ModScan读取地址0x0000,它返回的不是某个全局变量,而是digitalRead(2)的实时结果;当你用Node-RED写0x0001为1,它触发的不是回调函数,而是digitalWrite(3, HIGH)——完全跳过应用层,直通HAL。
所以你可以轻松构建这样的系统:
[Node-RED Dashboard] ↓ (Modbus TCP) [ESP32-Arduino running OpenPLC] ├─ %IX0.0 → 光电开关(检测物料到位) ├─ %IX0.1 → 急停按钮(NC接法) └─ %QX0.0 → SSR → 传送带电机HMI上点“启动”,Modbus报文飞过去;OpenPLC收到后,下个扫描周期就把%QX0.0置1,驱动SSR闭合——整个链路没有中间转换、没有JSON解析、没有MQTT桥接,只有标准协议直达物理IO。
这才是边缘PLC该有的样子:协议即IO,IO即协议。
真实部署,绕不开的三个“坑”
OpenPLC跑得通,不等于能直接扔进车间。我在产线原型验证中踩过几个典型坑,现在把它们摊开讲透:
坑1:Arduino没有光电隔离,别直接碰220V
你不能把限位开关直接接到Arduino引脚上。工业现场的感应器地线噪声、继电器吸合瞬间的反电动势,分分钟干掉你的MCU。
✅ 正确做法:
- 所有数字输入前加光耦模块(如PC817 + 上拉电阻)
- 所有数字输出必须经固态继电器(SSR)或MOSFET驱动模块(如IRF540N + 快恢复二极管)
- 模拟输入务必加RC低通滤波(1kΩ + 100nF)+ TVS钳位(SMAJ5.0A)
坑2:扫描周期≠程序执行时间
默认10ms扫描看似宽松,但一旦你在ST里写个浮点PID运算+串口打印,单次执行可能飙到12ms——下一个周期就迟到,导致IO响应滞后、Modbus超时、HMI卡顿。
✅ 应对策略:
- 用#define SCAN_CYCLE_US 5000把周期压到5ms(需确认ADC采样稳定)
- 把PID计算挪到“非周期任务”(OpenPLC支持task priority分级)
- 关闭Web Server的实时图表(它会吃掉大量CPU)
坑3:USB供电撑不住真实负载
很多同学用USB给Arduino供电,同时驱动5V继电器、电磁阀、传感器——结果一上电,MCU复位、ADC乱跳、Modbus CRC校验失败。
✅ 硬性要求:
- 外接5V/2A以上稳压电源(推荐LM2596可调模块)
- 输入/输出电源必须共地,但信号地与功率地建议单点连接(避免地弹)
- 若用ESP32,Wi-Fi射频干扰模拟输入,务必给ADC电源加LC滤波
这些不是“注意事项”,而是工业级可用性的分水岭。OpenPLC的价值,恰恰在于逼你直面这些真实问题——而不是躲在仿真器里假装世界很干净。
它到底能做什么?三个真实案例
案例1:教学实验室的百人并发PLC实训台
某高校自动化系采购了200块Arduino Nano + W5500以太网模块,刷入OpenPLC固件,统一接入局域网。学生用学号登录Web IDE,每人拥有独立PLC实例(内存分区隔离),可自由编辑梯形图、监控IO、互不干扰。实训成本从单台万元降至¥83/人,课时利用率提升3倍。
案例2:小型包装机的低成本升级
原设备用继电器逻辑控制,故障率高、改工艺要重新接线。工程师用ESP32替换掉继电器板,加载OpenPLC后,用梯形图重实现全部逻辑,并通过Modbus TCP对接原有HMI。改造周期3天,成本不足原PLC方案1/5,且后续工艺变更只需改图、无需动线。
案例3:学生创新赛的闭环控制系统
一支大三团队要做恒温水浴箱。他们用DS18B20测温(%IW0.0)、PID算法(ST语言)计算PWM占空比(%QW0.0)、MOSFET驱动加热丝。OpenPLC不仅提供标准PID指令块(FB_PID),还支持在线调参——在HMI里拖动Kp/Ki/Kd滑块,温度曲线实时变化。最终作品获全国一等奖,评委说:“这是少见的、把理论、算法、硬件、协议全打通的学生项目。”
最后一句实在话
OpenPLC for Arduino 不是教你“怎么用PLC”,而是带你回到PLC最原始的模样:
一个确定性循环、一套标准地址、一份可执行字节码、一组真实IO。
它不要求你先成为嵌入式专家,也不强迫你背诵寄存器手册。它只要求你理解一件事:
控制的本质,是输入与输出之间,由逻辑建立的因果关系。
而这份因果关系,你现在就可以在一块Arduino上亲手建立、观测、破坏、再重建。
如果你已经在尝试,欢迎在评论区贴出你的第一个梯形图截图;
如果你正犹豫要不要开始——别等了,今晚就烧录固件,接上按钮和LED,让%IX0.0点亮%QX0.0。
电流流过的那一刻,你就不再只是学习PLC,而是在运行它。