硬件设备
本实验中使用到的设备如下:
1、S7-200 Smart SR20 PLC
作为受控设备,执行机构。
S7-200 Smart是西门子的一款小型PLC产品(以下简称Smart系列)。
Smart系列PLC是西门子公司经过大量调研,为中国小型自动化市场量身打造的一款PLC产品。与西门子S7-1200系列相比,Smart系列不支持博途开发环境(使用STEP 7-MicroWIN SMART编程)、不支持Profinet通信(但支持Profibus);最多能扩展6个信号模块(EM)和1个信号板(SB)。
S7-200 SMART PLC 主要性能参数 V2.3,如下图
2、串口服务器 :USR-TCP232-410s
将PLC的485 串口信号转成网络信号接入局域网
产品参数如下:
3、单板机Orange Pi 3 LTS
运行EPICS IOC,运行上位控制程序。
4、串口线
软件部分
1、PLC上编程
初始化PLC为从设备,设置其工作模式为modbus rtu, 地址为3,波特率为115200,使用PLC自带串口,无延时,最大IO个数为256,最大模拟量为56个字,V存储器是从VB2000开始的100个字
一直使能这个从设备
2、串口服务器部分
通过浏览器设置串口服务器的IP地址为自己所需的地址:
设置RS485端口的串口参数,需要和PLC设置的参数保持一致,以及访问此RS485所需的端口号:
3、单板机部分:
安装操作系统和所需的EPICS模块
1) 操作系统
Distributor ID: Ubuntu
Description: Ubuntu 22.04.2 LTS
Release: 22.04
Codename: jammy
2)所需安装的EPICS 模板
由于EPICS模块之间的依赖关系,需要以下4个模块:
base, seq , ipac ,asyn, modbus
4、IOC建立过程
先创建一个项目目录,在其下用makeBaseApp工具创建一个IOC应用程序的框架,编辑configure/RELEASE文件,添加本IOC依赖的模块,在程序src下Makefile中添加所依赖的库文件和源文件; 在Db文件下添加模板文件:
configure/RELEASE:
...
SUPPORT=/usr/local/EPICS/synApps/support# If using the sequencer, point SNCSEQ at its top directory:
#SNCSEQ = $(MODULES)/seq-ver
ASYN=$(SUPPORT)/asyn
MODBUS=$(SUPPORT)/modbus
AUTOSAVE=$(SUPPORT)/autosave...
xxxApp/src:
....sr20smart_DBD += asyn.dbd
sr20smart_DBD += drvAsynIPPort.dbdsr20smart_DBD += modbus.dbd
sr20smart_DBD += asSupport.dbd# Include dbd files from all support applications:
# #sr20smart_DBD += xxx.dbd
#
# # Add all the support libraries needed by this IOC
#sr20smart_LIBS += xxx
sr20smart_LIBS += asyn
sr20smart_LIBS += modbus
sr20smart_LIBS += autosave...
xxxApp/Db:
bi_bit.template:用于按位读取PLC的输入输出点。
record(bi,"$(P)$(R)$(D)$(M)_$(N)") {field(DTYP,"asynUInt32Digital")field(INP,"@asynMask($(PORT) $(OFFSET) 0x1)")field(SCAN,"$(SCAN)")field(ZNAM,"$(ZNAM)")field(ONAM,"$(ONAM)")field(ZSV,"$(ZSV)")field(OSV,"$(OSV)")
}
bo_bit.template:用于按位写PLC的输出点。
record(bo,"$(P)$(R)Q$(M)_$(N)") {field(DTYP,"asynUInt32Digital")field(OUT,"@asynMask($(PORT) $(OFFSET) 0x1)")field(ZNAM,"$(ZNAM)")field(ONAM,"$(ONAM)")
}
longin_int16.template:用于按字读取PLC的V存储器以及模拟输入映像区,并且转成16位整数。
record(longin,"$(P)$(R)$(T)_$(M)") {field(DTYP,"asynInt32")field(INP,"@asyn($(PORT) $(OFFSET))$(DATA_TYPE)")field(SCAN, "$(SCAN)")
}
longoutInt16.template: 用于把16位整数按字写入PLC的V存储器。
record(longout,"$(P)$(R)$(T)_$(M)") {field(DTYP,"asynInt32")field(OUT,"@asyn($(PORT) $(OFFSET))$(DATA_TYPE)")
}
float32_in.template:用于按双字读取PLC的V存储区,并且转成32位浮点数。
record(ai, "$(P)$(R)$(T)_$(M)") {field(DTYP,"asynFloat64")field(INP,"@asyn($(PORT) $(OFFSET))$(DATA_TYPE)")field(HOPR,"$(HOPR)")field(LOPR,"$(LOPR)")field(PREC,"$(PREC)")field(SCAN,"$(SCAN)")
}
float32_out.template:用于将32位浮点数按双字写入到PLC的V存储器。
record(ao, "$(P)$(R)$(T)_$(M)O") {field(DTYP,"asynFloat64")field(OUT,"@asyn($(PORT) $(OFFSET))$(DATA_TYPE)")field(HOPR,"$(HOPR)")field(LOPR,"$(LOPR)")field(PREC,"$(PREC)")
}
回到此IOC的顶层目录,编译以上代码,生产IOC程序。
5、编辑启动目录,添加模板替换文件,编辑启动脚本st.cmd:
1)添加的实例化文件如下:
1)qb.substitutions:实例化8个bo记录,用于写,分别写一个位到PLC的输出点Q0.0~Q0.7
file "../../db/bo_bit.template" { pattern
{P, R, M, N, PORT, OFFSET, ZNAM, ONAM}
{SR20SMART:, BIT:, 0 0 QB0, 0, Low, High}
{SR20SMART:, BIT:, 0 1 QB0, 1, Low, High}
{SR20SMART:, BIT:, 0 2 QB0, 2, Low, High}
{SR20SMART:, BIT:, 0 3 QB0, 3, Low, High}
{SR20SMART:, BIT:, 0 4 QB0, 4, Low, High}
{SR20SMART:, BIT:, 0 5 QB0, 5, Low, High}
{SR20SMART:, BIT:, 0 6 QB0, 6, Low, High}
{SR20SMART:, BIT:, 0 7 QB0, 7, Low, High}
}
2) qb_rbv.substitutions:实例化8个bi记录,用于读取,分别读取一个位到PLC的输出点Q0.0~Q0.7
file "../../db/bi_bit.template" { pattern
{P, R, D, M, N, PORT, OFFSET, ZNAM, ONAM, ZSV, OSV, SCAN}
{SR20SMART:, BIT:, Q, 0, 0_RBV, QB0_RBV, 0, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 1_RBV, QB0_RBV, 1, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 2_RBV, QB0_RBV, 2, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 3_RBV, QB0_RBV, 3, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 4_RBV, QB0_RBV, 4, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 5_RBV, QB0_RBV, 5, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 6_RBV, QB0_RBV, 6, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, Q, 0, 7_RBV, QB0_RBV, 7, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
}
3)ib.substitutions:实例化8个bi记录,用于读取,分别读取一个位到PLC的输出点I0.0~I0.7
file "../../db/bi_bit.template" { pattern
{P, R, D, M, N, PORT, OFFSET, ZNAM, ONAM, ZSV, OSV, SCAN}
{SR20SMART:, BIT:, I 0 0 IB0_1, 0, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 1 IB0_1, 1, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 2 IB0_1, 2, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 3 IB0_1, 3, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 4 IB0_1, 4, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 5 IB0_1, 5, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 6 IB0_1, 6, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
{SR20SMART:, BIT:, I 0 7 IB0_1, 7, Low, High, NO_ALARM, MAJOR, "I/O Intr"}
}
4) int.substitutions:实例化2个longin记录,第一个实例将从PLC模拟输入区或V存储区读取的一个字转换成16位有符号数,第二个实例将从PLC模拟输入区或V存储区读取的一个字转换成16位无符号数。
file "../../db/longin_int16.template" { pattern
{P, R, T, M PORT, OFFSET, DATA_TYPE , SCAN}
{SR20SMART:, INT, 16, I0, VW, 0 , INT16 , "I/O Intr"}
{SR20SMART:, UINT, 16, UI0, VW, 1 , UINT16 , "I/O Intr"}
}
5)into.substitutions:实例化2个longout记录,第一个实例将16位有符号数按字写入到PLC的V存储区,第一个实例将16位无符号数按字写入到PLC的V存储区。
file "../../db/longoutInt16.template" { pattern
{P, R, T, M, PORT, OFFSET, DATA_TYPE}
{SR20SMART:, INT 16, IO, VWO, 0, INT16}
{SR20SMART:, UINT 16, UIO, VWO, 1, UINT16}
}
6) float.substitutions:实例化2个ai记录,这两个实例将分别从PLC模拟输入区或V存储区读取的二个字转换成32位浮点数。
file "../../db/float32_in.template" { pattern
{P, R, T, M, PORT, OFFSET, DATA_TYPE , HOPR, LOPR, , PREC ,SCAN}
{SR20SMART:, FLOAT, 32: F00 VW, 2 ,FLOAT32_BE , 1000, -1000, ,3 , "I/O Intr"}
{SR20SMART:, FLOAT, 32: F01 VW, 4 ,FLOAT32_BE , 1000, -1000, ,3 , "I/O Intr"}
}
7)实例化2个ao记录,这两个实例将分别将32位浮点数按双字写入到PLC的V存储区
file "../../db/float32_out.template" { pattern
{P, R, T, M, PORT, OFFSET, DATA_TYPE , HOPR, LOPR, , PREC}
{SR20SMART:, FLOAT, 32: F00 VWO, 2 ,FLOAT32_BE , 1000, -1000, ,3 }
{SR20SMART:, FLOAT, 32: F01 VWO, 4 ,FLOAT32_BE , 1000, -1000, ,3 }
}
2) 编辑st.cmd文件:
#!../../bin/linux-x86_64/sr20smart#- You may have to change sr20smart to something else
#- everywhere it appears in this file< envPathscd "${TOP}"## Register all support components
dbLoadDatabase "dbd/sr20smart.dbd"
sr20smart_registerRecordDeviceDriver pdbbasedrvAsynIPPortConfigure("sr20smart","192.168.3.209:6666",0,0,1)
modbusInterposeConfig("sr20smart",1 ,2000,0)# func code = 5 按位写线圈
drvModbusAsynConfigure("QB0", "sr20smart", 3, 5, 0, 8 , 0, 100, "QB0")
# func code = 1 按位读线圈
drvModbusAsynConfigure("QB0_RBV", "sr20smart", 3, 1, 0, 8 , 0, 200, "QB0_RBV")# func code = 2 按位读取离散输入
drvModbusAsynConfigure("IB0_1", "sr20smart", 3, 2, 0, 8 , 0, 200, "IB0_1")# func code = 3 按字读取保持寄存器
drvModbusAsynConfigure("VW", "sr20smart", 3, 3, 0, 20 , 0, 200, "VW")# func code = 4 按字读取输入寄存器
drvModbusAsynConfigure("AWI", "sr20smart", 3, 4, 0, 10 , 0, 200, "AWI")# func code = 6 按字写入保持寄存器
drvModbusAsynConfigure("VWO", "sr20smart", 3, 6, 0, 20 , 0, 200, "VWO")cd "${TOP}/iocBoot/${IOC}"
dbLoadTemplate("qb.substitutions")
dbLoadTemplate("qb_rbv.substitutions")
dbLoadTemplate("ib.substitutions")dbLoadTemplate("int.substitutions")
dbLoadTemplate("float.substitutions")
dbLoadTemplate("floato.substitutions")
dbLoadTemplate("into.substitutions")iocInit
IOC程序启动以及测试
在IOC启动目录下,程序启动命令:../../bin/linux-aarch64/sr20smart st.cmd
dbl查看所有加载的记录。
root@orangepi3-lts:/usr/local/EPICS/program/sr20smart/iocBoot/iocsr20smart# ../../bin/linux-aarch64/sr20smart st.cmd
#!../../bin/linux-x86_64/sr20smart
...
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.7
## Rev. 2023-06-25T15:50+0000
## Rev. Date build date/time:
############################################################################
iocRun: All initialization complete
## Start any sequence programs
#seq sncxxx,"user=blctrl"
epics> dbl
SR20SMART:FLOAT32:_F00
SR20SMART:FLOAT32:_F01
SR20SMART:FLOAT32:_F00O
SR20SMART:FLOAT32:_F01O
SR20SMART:BIT:Q0_0_RBV
SR20SMART:BIT:Q0_1_RBV
SR20SMART:BIT:Q0_2_RBV
SR20SMART:BIT:Q0_3_RBV
SR20SMART:BIT:Q0_4_RBV
SR20SMART:BIT:Q0_5_RBV
SR20SMART:BIT:Q0_6_RBV
SR20SMART:BIT:Q0_7_RBV
SR20SMART:BIT:I0_0
SR20SMART:BIT:I0_1
SR20SMART:BIT:I0_2
SR20SMART:BIT:I0_3
SR20SMART:BIT:I0_4
SR20SMART:BIT:I0_5
SR20SMART:BIT:I0_6
SR20SMART:BIT:I0_7
SR20SMART:BIT:Q0_0
SR20SMART:BIT:Q0_1
SR20SMART:BIT:Q0_2
SR20SMART:BIT:Q0_3
SR20SMART:BIT:Q0_4
SR20SMART:BIT:Q0_5
SR20SMART:BIT:Q0_6
SR20SMART:BIT:Q0_7
SR20SMART:INT16_I0
SR20SMART:UINT16_UI0
SR20SMART:AINT16_I0
SR20SMART:AUINT16_UI0
SR20SMART:INT16_IO
SR20SMART:UINT16_UIO
1)bo记录SR20SMART:BIT:Q0_0 ~ SR20SMART:BIT:Q0_7:用于设置PLC Q0.0~Q0.7。
2)bi记录SR20SMART:BIT:Q0_0_RBV ~ SR20SMART:BIT:Q0_7_RBV:用于读取PLC Q0.0~Q0.7的状态。
3)bi记录SR20SMART:BIT:I0_1~SR20SMART:BIT:I0_7:用于读取PLC I0.0~I0.7的状态。
4) longin记录SR20SMART:INT16_I0和SR20SMART:UINT16_UI0:用于读取V存储区VW2000,VW2002。
5)longin记录SR20SMART:AINT16_I0和SR20SMART:AUINT16_UI0:用于读取模拟量输入寄存器AIW0和AIW2。
6)bo记录SR20SMART:INT16_IO和SR20SMART:UINT16_UIO:用于写入V存储区VW2000,VW2002。
7)ai记录SR20SMART:FLOAT32:_F00和SR20SMART:FLOAT32:_F01用于读取V存储区VD2004和VD2008。
8) ao记录SR20SMART:FLOAT32:_F00O和SR20SMART:FLOAT32:_F01O:写入V存储区VD2004和VD2008。
测试
用STEP7 Micro/Win SMART状态表设置V存储区如下:
用通道访问进行读取:
# VW2000
orangepi@orangepi5:~$ caget SR20SMART:INT16_I0
SR20SMART:INT16_I0 -12345
# VW2002
orangepi@orangepi5:~$ caget SR20SMART:UINT16_UI0
# VD2004
SR20SMART:UINT16_UI0 22222
orangepi@orangepi5:~$ caget SR20SMART:FLOAT32:_F00
SR20SMART:FLOAT32:_F00 3.1415
# VD2008
orangepi@orangepi5:~$ caget SR20SMART:FLOAT32:_F01
SR20SMART:FLOAT32:_F01 0.1111
# AIW0
orangepi@orangepi5:~$ caget SR20SMART:AINT16_I0
SR20SMART:AINT16_I0 -2000
# AIW2
orangepi@orangepi5:~$ caget SR20SMART:AUINT16_UI0
SR20SMART:AUINT16_UI0 2000
用通道访问写更改Q和V存储区:
# Q0.0
orangepi@orangepi5:~$ caput SR20SMART:BIT:Q0_1 0
Old : SR20SMART:BIT:Q0_1 High
New : SR20SMART:BIT:Q0_1 Low
# Q0.1
orangepi@orangepi5:~$ caput SR20SMART:BIT:Q0_0 0
Old : SR20SMART:BIT:Q0_0 High
New : SR20SMART:BIT:Q0_0 Low
# VW2000
orangepi@orangepi5:~$ caput SR20SMART:INT16_IO -6666
Old : SR20SMART:INT16_IO 0
New : SR20SMART:INT16_IO -6666
# VW2002
orangepi@orangepi5:~$ caput SR20SMART:UINT16_UIO 8888
Old : SR20SMART:UINT16_UIO 0
New : SR20SMART:UINT16_UIO 8888
# VD2004
orangepi@orangepi5:~$ caput SR20SMART:FLOAT32:_F00O 1.2345
Old : SR20SMART:FLOAT32:_F00O 0
New : SR20SMART:FLOAT32:_F00O 1.2345
# VW2008
orangepi@orangepi5:~$ caput SR20SMART:FLOAT32:_F01O 5.4321
Old : SR20SMART:FLOAT32:_F01O 0
New : SR20SMART:FLOAT32:_F01O 5.4321
从STEP7 Micro/Win SMART状态表查看相应的存储区: