OpenPLC本质上是另一个开源项目MatIEC的扩展,其将PLC的设计以XML的格式表达,生成运行代码的时候先把利用XML设计文件生成 PLC的指令文件(generated_plc.st),再用 matiec把PLC的指令文件翻译成一组 C语言的源代码文件,最后再由具体平台的编译工具编译出运行程序。matiec生成的C语言源代码基本上没有什么平台依赖的特征,所以是跨平台,在AVR AtMega2560或者STM32之类的单片机也可以用得起来,但是STM32或者AVR之类的平台要扩展IOT工作量太大,硬件资源也不合适,软件的支持库太少。
在OpenPLC开发平台 OpenPLC_Editor的安装目录下,有一个\editor\targets目录:
可以找到 OpenPLC在Linux、Win32和Xenomai内核上的参考实现,总体是需要实现IO的映射,系统定时和固化存储的接口。PLC程序作为应用程序或者后台服务的形式在Linux、Win32内核上运行,借助Linux、Win32丰富的软件资源,这类软PLC的功能上优势十分显著,但有两个缺点无法克服:成本高,实时性低。ESP32的硬件资源(尤其是200MHz双核)和ESP-IDF丰富的软件资源(尤其是物联网所需的通信协议栈),对PLC的IOT功能扩展提供有力支撑,成本也是IOT应用能接受的。
OpenPLC的官方信息表明,ESP32是被支持的硬件平台,可以基于arduino实现集成。我们用一个测速的PLC程序做一下验证。
自动生成对应的C语言代码
void P2_body__(P2 *data__) {
// Initialise TEMP variables __SET_VAR(data__->,Y2,,(__GET_VAR(data__->X2,) || __GET_VAR(data__->X3,)));
__SET_VAR(data__->,C,,!(__GET_VAR(data__->C,)));
__SET_VAR(data__->R_TRIG1.,CLK,,__GET_VAR(data__->X2,));
R_TRIG_body__(&data__->R_TRIG1);
__SET_VAR(data__->R_TRIG2.,CLK,,__GET_VAR(data__->C,));
R_TRIG_body__(&data__->R_TRIG2);
__SET_VAR(data__->CTU_LINT0.,CU,,__GET_VAR(data__->R_TRIG2.Q,));
__SET_VAR(data__->CTU_LINT0.,R,,__GET_VAR(data__->CLR,));
__SET_VAR(data__->CTU_LINT0.,PV,,5000);
CTU_LINT_body__(&data__->CTU_LINT0);
__SET_VAR(data__->,DIV10_OUT,,__P2_DIV__LINT__LINT__LINT1(
(BOOL)(!(__GET_VAR(data__->STOP,)) && __GET_VAR(data__->R_TRIG1.Q,)),
(LINT)__GET_VAR(data__->TM,),
(LINT)__GET_VAR(data__->CTU_LINT0.CV,),
data__));
__SET_VAR(data__->,CLR,,__GET_VAR(data__->DIV10_ENO,));
__SET_VAR(data__->,STOP,,__GET_VAR(data__->CTU_LINT0.Q,));
__SET_VAR(data__->,SEL25_OUT,,SEL__LINT__BOOL__LINT__LINT(
(BOOL)__BOOL_LITERAL(TRUE),
NULL,
(BOOL)__GET_VAR(data__->CTU_LINT0.Q,),
(LINT)__GET_VAR(data__->DIV10_OUT,),
(LINT)0));
__SET_EXTERNAL(data__->,RPM,,__GET_VAR(data__->SEL25_OUT,)); goto __end;
__end:
return;
} // P2_body__()
尽管代码风格有点高深,意思还是表达得比较清楚的。
运行的结果表明,0.1us的扫描周期可以稳定工作,性能是符合预期的。
但是看到生成的二进制文件,我们知道距离作为 “工业互联网、数字化工程便利的基础工具”的目标还挺远。生成的二进制文件有 4M 字节,用下载工具下载要下载好一会,线上或者远程升级更加难言“便利”了。
这种情况我们可以很深刻体会到操作系统的重大差异,FreeRTOS这种微型嵌入式实时操作系统内核在实时性方面令人满意,但是缺少 ELF文件的动态加载运行、动态库支持,系统软件和应用软件做成铁饼一块,改一点程序就要整个系统一起编译、刷新。我们很期待FreeRTOS能向其他成熟操作系统靠拢,实现ELF加载运行和动态库支持,目前只能自己做一个非标的实现。