完成人:中国科学院大学 孙翔宇

指导老师:庄建(英特尔边缘计算创新大使,中国科学院高能物理研究所, 研究员)

本案例适用于x86以上英特尔平台

1. 序言

1.1 爱克斯板介绍

AIxBoard™爱克斯板开发者套件是一款功能强大的小型计算机,专为支持入门级边缘人工智能应用程序和设备而设计。无论是在人工智能学习、开发还是实训等应用场景下,它都能完美胜任。

该开发板是类树莓派的x86主机,可支持Linux Ubuntu及 完整版Windows操作系统。板载一颗英特尔4核处理器,最高运行频率可达2.9 GHz,且内置核显(iGPU),板载 64GB eMMC存储及LPDDR4x 2933MHz(4GB/6GB/8GB),内置蓝牙和Wi-Fi模组,支持USB 3.0、HDMI视频输出、3.5mm音频接口,1000Mbps以太网口。完全可把它作为一台mini小电脑来看待,且其可集成一块Arduino Leonardo单片机,可外拓各种传感器模块。

此外, 其接口与Jetson Nano载板兼容,GPIO与树莓派兼容,能够最大限度地复用树莓派、Jetson Nano等生态资源,无论是摄像头物体识别,3D打印,还是CNC实时插补控制都能稳定运行。可作为边缘计算引擎用于人工智能产品验证、开发;也可以作为域控核心用于机器人产品开发。

然而,虽然爱克斯板具有如上的诸多优点。但由于其运行的Windows或者Linux系统都是非实时性的操作系统,难以用于对实时性要求较高的工业环境中。而实时性的PLC环境通常较为封闭,难以使用python,Openvino等外界程序。

1.2  CODESYS介绍

CODESYS是一款工业自动化领域的一款开发编程系统(CODESYS是Code System的简写),应用领域涉及工厂自动化、汽车自动化、嵌入式自动化、过程自动化和楼宇自动化等等。CODESYS软件可以分为两个部分,一部分是运行在各类硬件中的RTE(Runtime Environment),另一部分是运行在PC机上的IDE。因此CODESYS的用户既包括生产PLC、运动控制器的硬件厂商,也包括最终使用PLC、运动控制器的用户。

目前全球有近400家的控制系统生产制造商是CODESYS的用户:如ABB、施耐德电气SchneiderElectric、伊顿电气EATON、博世力士乐Rexroth、倍福BECKHOFF、科控KEBA、日立HITACHI、三菱自动化MITSUBISHI、欧姆龙OMRON、研华科技、凌华科技ADLINK、新汉电脑、和利时集团、SUPCON 中控集团、步科自动化KINCO、深圳雷赛、汇川技术、深圳合信、深圳英威腾、华中数控、固高科技等等。

简单来说,CODESYS可以说是PLC界的安卓,许多PLC厂商都以CODESYS作为其PLC的内核。

此外,CODESYS可以将任何一款arm架构或者x86架构的处理器变为实时的PLC系统。CODESYS结合AIxBoard,我们能够得到一个可以用于工业控制检测领域的一款功能强大的人工智能小型计算机。

1.3  实验仿真介绍

通常而言,如果想要进行CODESYS控制实验,需要购买支持CODESYS的PLC控制器、支持EtherCAT通讯协议的步进电机驱动器、步进电机、滚珠丝杠平台、以及对整套系统的供电电源。购置一整套实验设备不仅费时费力费钱,并且占用空间极大,不便于初学者进行学习。

通过使用CODESYS对AIxBoard的软PLC配置,并结合着Factory软件仿真,能够极大的减少学习成本。

2. 前期准备

CODESYS软件分三层架构,可用下图来表示:

图1  CODESYS软件架构示意图

其中开发层(IDE)可使用CODESYS Development System(具有完善的在线编程和离线编程功能)、编译器及其配件组件、可视化界面编程组件等对CODESYS程序进行开发与部署。本文使用的版本为CODESYS V3.5 SP17,下载与安装教程可见:CODESYS 3.5.17.0 软件安装_codesys安装教程_小 Co的博客-CSDN博客

2.1  开发层主机前期准备

在安装完CODESYS后,还需要根据需求下载安装部分CODESYS软件包,由于本文需要在运行有Ubuntu的AIxBoard上部署CODESYS Runtime,并通过共享内存实现与外界程序通信,故需安装的软件包有以下几种:

  1. CODESYS Control for Linux SL
  2. CODESYS Edge Gateway for Linux
  3. Shared Memory Communication

完成安装后,可在包管理器中查看到这三个软件包。

图2 在CODESYS中安装软件包

安装完成三个软件包后,重启CODESYS,随后能够在工具中最下面一行找到Update Linux,点击后会打开一个能够与安装了Linux系统的AIxBoard进行通信部署的界面。

图3 安装软件包完成后的效果

2.2  设备硬件层前期准备

为了提高AIxBoard的适用性,本文将使用Ubuntu系统作为AIxBoard的操作系统,系统版本为Ubuntu 20.04LTS,这里使用的是Canonical为Intel优化的版本。下载与安装教程如下:系统安装 - AIxBoard开发指南 (xzsteam.com)

除此之外,安装完成系统后,还需安装python以进行共享内存通信,本文使用的python版本为3.8.10。

为验证CODESYS能够与外界程序通信,同时也安装了Epics。Epics全称为Experimental Physics and Industrial Control System即“实验物理及工业控制系统”,是上世纪90年代初由美国洛斯阿拉莫斯国家实验室(LANL)和阿贡国家实验室(ANL)等联合开发的大型控制软件系统。安装完成Epics后,需使其在后台运行,后续将通过CODESYS与其进行通信。

图4 在AIxBoard中预先安装好Ubuntu系统与Epics

2.3  实验仿真前期准备

进入factory i/o的官网Features - Factory I/O,点击Try for free 能够免费使用factory i/o 30天。

图5 在factory i/o官网上下载

安装完成后,打开factory IO能够看到下面有着对于CODESYS的使用教程:

图6 打开factory IO 能够看到下面对于CODESYS的使用教程

3. 工程建立

3.1 CODESYS工程建立(位于PC端)

3.1.1 新建标准工程

在CODESYS中,选择文件-新建工程,命名工程为AIxBoard,选择新建标准工程。

图7 新建标准工程

在弹出的标准工程对话框中,选择设备为CODESYS Control for Linux SL,选择结构化文本(ST)作为编程语言。

图8 新建标准工程选项

3.1.2  加载所需函数库

将我们刚刚安装的软件包中的所需函数库加载到此工程中,需要添加的函数库有:

· SysShm,3.5.8.0 (System)

· SysTypes2 Interfaces,3.5.4.0 (System)

打开库管理器(Library Manager),选择“添加库(Add Library)”,点“高级(Advanced...)”;

图9 在工程中加载刚刚安装好的函数库

在搜索框(String for a fulltext search...)中分别输入SysShm和SysTypes搜索添加SysShm,3.5.8.0 和SysTypes2 Interfaces,3.5.4.0 ,

选中搜索到的库,点“OK”确认添加,

     图10  搜索并添加所需的两个函数库

3.1.3  建立设备通信

点击工具-Update Linux打开与Linux通信的界面,在左侧输入用户名和密码,搜索到AIxBoard的IP后,点击Install将CODESYS Runtime安装至AIxBoard中,安装文件可以在AIxBoard的/etc/中找到。

图11 与AIxBoard通信并将Runtime部署在AIxBoard上

经过图10的操作之后,AIxBoard便已经成为了一个能够运行CODESYS的实时性系统的PLC了。

图12 在AIxBoard上安装好的CODESYS Runtime程序文件

新建项目后,点击左下角设备进入设备树,双击Device后,点击扫描网络进行设备连接,选择AIxBoard为控制器的网络路径。

图13 进行设备扫描与连接

输入账号密码进行登录,如果是第一次登陆,还需要另外设置一次登录密码。

图14 在CODESYS Runtime上登录并自动下载代码

登陆完成后,将会自动下载程序代码至AIxBoard上,并且可以在device中看到设备信息。

图15 连接完成后的设备网络图

3.2  Openvino工具包部署(位于AIxBoard端)

3.2.1 Openvino介绍

Openvino是英特尔基于自身现有的硬件平台开发的一种可以加快高性能计算机视觉和深度学习视觉应用开发速度工具套件,支持各种英特尔平台的硬件加速器上进行深度学习,并且允许直接异构执行,是一款可轻松实现“一次写入,处处部署”的开源工具套件。

通过使用Openvino能够极大简化对于机器视觉和深度学习等算法模型框架的部署过程,并且最大程度上开发intel的硬件平台的潜力。

3.2.2  Openvino下载与安装

在AIxBoard上,仅需通过四行简单的代码即可完成openvino部署。

首先需要进入英特尔官网中,Openvino工具套件的下载界面:https://www.intel.cn/content/www/cn/zh/developer/tools/openvino-toolkit/download.html

进入后,配置好所需使用的版本、环境、操作系统、下载方式以及所需使用的框架即可在下方看到相应的下载方式

为了便于之后在python上同时完成codesys内存数据读取写入以及机器视觉识别,使用pytorch作为模型训练框架,使用pip作为下载方式。

下载代码如下:

第 1 步:创建虚拟环境。

python3 -m venv openvino_env

第 2 步:激活虚拟环境。

source openvino_env/bin/activate

第 3 步:将 pip 升级到最新版本。

python -m pip install --upgrade pip

第 4 步:下载并安装程序包。

pip install openvino-dev[pytorch]==2022.3.1

4. 代码编写

4.1 CODESYS代码编写

4.1.1 定义数据单元类型与全局变量

右击Application,选择添加DUT(Data Unit Type,数据单元类型),DUT为自定义的数据类型,本文中新建自定义的数据单元类型目的为通过不同类型的数据单元,将输出至外部程序的变量与从外部程序输入进来的变量分离开。

新建两个数据类型分别为:Str_ParaFromHMI与Str_ParaToHMI,目前结构体内部仅包含一个长整型格式的数据(LREAL),可根据实际需求修改或添加。

TYPE Str_ParaToHMI :

STRUCT

    fOut: LREAL;

END_STRUCT

END_TYPE



TYPE Str_ParaFromHMI :

STRUCT

    fIn: LREAL;

END_STRUCT

END_TYPE

右击Application添加全局变量列表GVL(Global Var List),并将刚刚新建的两种数据类型实例化,并添加至全局变量中。实例化的名称分别为GetPara与SetPara。其中GetPara用于从外部程序中获取数据进入CODESYS,SetPara用于将CODESYS中的数据输出至外部程序中。

VAR_GLOBAL

    GetPara:Str_ParaFromHMI;

    SetPara:Str_ParaToHMI;

END_VAR

4.1.2  编写共享内存POU

右击Application添加POU(Program organizational unit,程序组织单元),命名为Sharedmemory。

图16 新增程序组织单元的相关配置

POU上方为局部变量声明区域,下方为结构化文本程序区域。

局部变量声明如下:

PROGRAM SharedMemory

VAR

           

            bStart: BOOL:= FALSE;

            ReadHandle: RTS_IEC_HANDLE:= RTS_INVALID_HANDLE;

            WriteHandle: RTS_IEC_HANDLE:= RTS_INVALID_HANDLE;

            szNameRead: STRING:= 'CODESYS_MEMORY_READ';             //声明共享内存的读取内存名称

            szNameWrite: STRING:= 'CODESYS_MEMORY_WRITE';          //声明共享内存的写入内存名称

            ulPhysicalAddressRead: __UXINT:= 0;//读取数据的偏移地址,0为从头读取

            ulPhysicalAddressWrite: __UXINT:= 0;//写入数据的偏移地址,0为从头写入

            ulSizeRead: __UXINT:= 1024;//读取空间大小

            ulSizeWrite: __UXINT:= 1024;//写入空间大小

            ResultRead: ARRAY[0..2] OF RTS_IEC_RESULT;             //返回运行错误码,0中为运行错误码,1中为读取执行错误码,2中为写出执行错误码

            ResultWrite: ARRAY[0..2] OF RTS_IEC_RESULT;     //返回运行错误码,0中为运行错误码,1中为读取执行错误码,2中为写出执行错误码

           

            SMRead: __UXINT;

            SMWrite: __UXINT;

            ulOffsetRead: __UXINT:= 0;

            ulOffsetWrite: __UXINT:= 0;

           

END_VAR

其中,高亮部分语句所指定的名称是之后需要与python中读取共享内存中数据一致的文件名称。可任意修改但是应与python中程序一致,共享内存的文件将会保存在/dev/shm/中。

下方ST程序部分编写代码如下:

//Init Memory

IF NOT bStart THEN

            ReadHandle:= SysSharedMemoryCreate(pszName:= szNameRead, ulPhysicalAddress:= ulPhysicalAddressRead, pulSize:= ADR(ulSizeRead), pResult:= ADR(ResultRead[0]));

            WriteHandle:= SysSharedMemoryCreate(pszName:= szNameWrite, ulPhysicalAddress:= ulPhysicalAddressWrite, pulSize:= ADR(ulSizeWrite), pResult:= ADR(ResultWrite[0]));

            IF RTS_INVALID_HANDLE <> ReadHandle AND RTS_INVALID_HANDLE <> WriteHandle THEN

                        bStart:= TRUE;

            END_IF

END_IF



//读入数据

IF RTS_INVALID_HANDLE <> ReadHandle THEN

            SMRead:= SysSharedMemoryRead(

            hShm:= ReadHandle,                                                 //读取内存的设备句柄

            ulOffset:= ulOffsetRead,                                //读取数据的偏移地址

            pbyData:= ADR(GVL.GetPara),                    //指向读取数据的缓冲区

            ulSize:= SIZEOF(Str_ParaFromHMI),          //读取数据的字节大小         

            pResult:= ADR(ResultRead[1]));                   //返回执行的错误码

END_IF



//写出数据

IF RTS_INVALID_HANDLE <> WriteHandle THEN

            SMWrite:= SysSharedMemoryWrite(

            hShm:= WriteHandle,                                                 //写入内存的设备句柄

            ulOffset:= ulOffsetWrite,                                //写入数据的偏移地址

            pbyData:= ADR(GVL.SetPara),                     //指向写入数据的缓冲区

            ulSize:= SIZEOF(Str_ParaToHMI),   //写入数据的字节大小

            pResult:= ADR(ResultWrite[2]));                  //返回执行的错误码

END_IF

在Maintask中调用编辑好的POU,将此POU加入到执行程序中。

图17 在任务配置中调用编写好的程序

4.1.3  编写数据来源POU

在主程序PLC_RPG中添加正弦数据函数,不断向SetPara中发送正弦波数据。

图18 编写主程序相关函数,用于输入正弦波形以检测连接情况

完成后,点击上方编译,编译通过后即可将程序登录下载至AIxBoard中。

4.2  仿真模型连接

在factory上通过右侧菜单栏将所需使用的元器件直接拖入场景中,建立仿真模型。

图19 编写主程序相关函数,用于输入正弦波形以检测连接情况

为使得能够更好的展示AIxBoard的强大视频处理能力,选用不同的工件作为识别物体。当检测到目标工件时,控制搬运设备将目标工件从流水线上移动至指定位置。

在完成模型搭建后,需将搬运设备与流水线的控制接口与CODESYS上的变量相连接,具体连接配置过程可参考以下教程:http://bbs.inovance.com/t-16948.html

4.3  AIxBoard代码编写

4.3.1 数据传递代码

在AIxBoard上,编写相关python程序,通过读取共享内存中的文件内容,来接收来自CODESYS传递的信号,并将其传递至机器视觉算法中,代码如下:

import mmap

import struct

import time

read_Name="CODESYS_MEMORY_WRITE"

write_Name="CODESYS_MEMORY_READ"

file_Read= open('/dev/shm/'+read_Name,"r")

file_Write=open('/dev/shm/'+write_Name,"wr")

for i in range(5):

output=random.randint(1,50)

while 1:

    file_Read.flush()

    mmr=mmap.mmap(file_Read.fileno(),0,prot=mmap.PROT_READ)

    #print(mmr.read(8))

    [input,]=struct.unpack('d',mmr.read(8))

print(input)

file_Write.flush()

output_text=f.write(str(output)+"\n")

#print(output_text)

time.sleep(0.05)

input中放置的是来自codesys的输入信息,output中放置的是准备输出至codesys中的信息。通过调用此python代码,可以实现向CODESYS发送任何所需的指令或者获取任何来自CODESYS的信息。

4.3.2  视觉识别代码

视觉识别部分使用yolov5模型进行目标模型检测,YOLO的全称是you only look once,指只需要浏览一次就可以识别出图中的物体的类别和位置。通过使用YOLO模型,能够识别出目标物体的类别、位置、大小等信息。通过识别物体的类别能够判定出是否是我们所需要进行搬运的物件,通过获取位置、大小等信息能够进一步建模出物体的空间位置,并以此来控制搬运装置。

5. CODESYS与外界程序通信验证

以管理员身份运行python程序,可在AIxBoard上不断读取到CODESYS发送的数据。

图20 AIxBoard上最终运行结果,左侧为接收到的数据量

同时在CODESYS中可建立信号跟踪器,检测发送出的数据波形。

图21 信号跟踪器上显示的CODESYS中发出的数据波形

通过新建CS-Studio界面,可以从Epics中查看数据,验证CODESYS中发送出来的数据的正确性。

图22 在CS-Studio界面上监视到的Epics网络中PV量的变化波形

至此,我们已在AIxBoard上配置了软PLC,顺利将AIxBoard从一台非实时性的开发板变成了一个能够用于工业控制领域的实时PLC控制器,并且使其能够与外界进行通信。通过以上步骤,能够使基于AIxBoard与CODESYS配置而成的软PLC相比传统的PLC而言,具有了更高的灵活性,通过搭配OpenVINO等人工智能模型,能够实现更加智能化的控制效果。

文中所涉及到的所有工程文件与代码均已开源于github,网址为:GitHub - EHU0/Codesys_ShareMemory_On_AIxBoard: 使用爱克斯板与CODESYS实现软PLC配置并与外界程序通信。Use the AIxboard with CODESYS to implement soft PLC configuration and communicate with external programs.

Logo

为开发者提供丰富的英特尔开发套件资源、创新技术、解决方案与行业活动。欢迎关注!

更多推荐