EPICS modbus模块驱动程序示例1(数字量)

本文以Moxa ioLogik E2210(Moxa官网对这种设备的详细介绍ioLogik E2210 - 通用控制器和远程 I/O ioLogik E2200 系列 | MOXA)通用控制器和远程I/O为例,讲解如何使用EPICS modbus模块实现对这种设备控制。

以下简要介绍ioLogik E2210设备的特性:

  • 具备12点24 VDC数字输入,可设置为DI和计数器模式。过滤时间可由软件选择
  • 具备8点24 VDC数字输出,可设置为脉冲输出模式。脉冲宽度可由软件选择
  • 可连接多达10台主机的100Mbps以太网,支持Modbus/TCP协议
  • 基于UDP/TCP传输方式的Active I/O Messaging功能,多连接10台主机
  • 支持SNMP到I/O的映射,可与网络管理系统整合
  • 方便使用的快速编程库,支持VB,VC++,BCB
  • 提供RS-485级联口,便于长距离I/O扩展

准备工作,使用Moxa ioAdmin软件将ioLogik E2210设备的IP地址更改为与控制计算机在相同子网内,这种设备的默认TCP端口为502,Modbus TCP的默认端口。

在已经安装了EPICS base,asyn和Modbus模块的计算机构建这个控制程序:

1) 在一个指定目录下,新建一个目录,在此目录中构建这个IOC应用程序:

[blctrl@main-machine exer]$ mkdir moxa-e2210
[blctrl@main-machine exer]$ cd moxa-e2210/
[blctrl@main-machine moxa-e2210]$ makeBaseApp.pl -t ioc e2210
[blctrl@main-machine moxa-e2210]$ makeBaseApp.pl -i -t ioc e2210
Using target architecture linux-x86_64 (only one available)
The following applications are available:
    e2210
What application should the IOC(s) boot?
The default uses the IOC's name, even if not listed above.
Application name?
[blctrl@main-machine moxa-e2210]$ ls
configure  e2210App  iocBoot  Makefile

2 ) 进入configure目录,编辑RELEASE文件,添加这个程序所需要的模块,此程序需要asyn和modbus模块:

# RELEASE - Location of external support modules
#
# IF YOU CHANGE ANY PATHS in this file or make API changes to
# any modules it refers to, you should do a "make rebuild" in
# this application's top level directory.
#
# The EPICS build process does not check dependencies against
# any files from outside the application, so it is safest to
# rebuild it completely if any modules it depends on change.
#
# Host- or target-specific settings can be given in files named
#  RELEASE.$(EPICS_HOST_ARCH).Common
#  RELEASE.Common.$(T_A)
#  RELEASE.$(EPICS_HOST_ARCH).$(T_A)
#
# This file is parsed by both GNUmake and an EPICS Perl script,
# so it may ONLY contain definititions of paths to other support
# modules, variable definitions that are used in module paths,
# and include statements that pull in other RELEASE files.
# Variables may be used before their values have been set.
# Build variables that are NOT used in paths should be set in
# the CONFIG_SITE file.
SUPPORT=/usr/local/EPICS/synApps/support     #添加行1
# Variables and paths to dependent modules:
#MODULES = /path/to/modules
#MYMODULE = $(MODULES)/my-module
ASYN=$(SUPPORT)/asyn                         #添加行2
MODBUS=$(SUPPORT)/modbus                     #添加行3

# If using the sequencer, point SNCSEQ at its top directory:
#SNCSEQ = $(MODULES)/seq-ver

# EPICS_BASE should appear last so earlier modules can override stuff:
EPICS_BASE = /usr/local/EPICS/base

# Set RULES here if you want to use build rules from somewhere
# other than EPICS_BASE:
#RULES = $(MODULES)/build-rules

# These lines allow developers to override these RELEASE settings
# without having to modify this file directly.
-include $(TOP)/../RELEASE.local
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
-include $(TOP)/configure/RELEASE.local

3) 进入e2210App/src目录下,编辑Makefile文件,添加所需模块的dbd文件和库文件:

TOP=../..

include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================

#=============================
# Build the IOC application

PROD_IOC = e2210
# e2210.dbd will be created and installed
DBD += e2210.dbd

# e2210.dbd will be made up from these files:
e2210_DBD += base.dbd

# Include dbd files from all support applications:
e2210_DBD += asyn.dbd
e2210_DBD += drvAsynIPPort.dbd
e2210_DBD += modbus.dbd

# Add all the support libraries needed by this IOC
e2210_LIBS += asyn
e2210_LIBS += modbus

# e2210_registerRecordDeviceDriver.cpp derives from e2210.dbd
e2210_SRCS += e2210_registerRecordDeviceDriver.cpp

# Build the main IOC entry point on workstation OSs.
e2210_SRCS_DEFAULT += e2210Main.cpp
e2210_SRCS_vxWorks += -nil-

# Add support from base/src/vxWorks if needed
#e2210_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary

# Finally link to the EPICS Base libraries
e2210_LIBS += $(EPICS_BASE_IOC_LIBS)

#===========================

include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

4) 从modbus模块modbusApp的Db目录下,复制模板文件bi_bit.template和bo_bit.template文件到当前IOC程序e2210App/Db路径下,并且编辑相同路径下的Makefile文件:

[blctrl@main-machine Db]$ cp /usr/local/EPICS/synApps/support/modbus/modbusApp/Db/bi_bit.template ./
[blctrl@main-machine Db]$ cp /usr/local/EPICS/synApps/support/modbus/modbusApp/Db/bo_bit.template ./
[blctrl@main-machine Db]$ ls
bi_bit.template  bo_bit.template  Makefile

把bi_bit.template和bo_bit.template文件添加到Makefile中:

TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE

#----------------------------------------------------
# Create and install (or just install) into <top>/db
# databases, templates, substitutions like this
DB += bi_bit.template
DB += bo_bit.template

#----------------------------------------------------
# If <anyname>.db template is not named <anyname>*.template add
# <anyname>_template = <templatename>

include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

5) 切换这个这个IOC程序的顶层目录,执行make程序进行编译。

6) 切换到启动目录:

[blctrl@main-machine moxa-e2210]$ cd iocBoot/ioce2210/
[blctrl@main-machine ioce2210]$ ls
envPaths  Makefile  st.cmd

7) 编辑启动文件st.cmd,根据moxa iologik e2210设备具有8个数字输出和12个数字输入分别创建驱Modbus端口驱动程序读写这些数字输出和输入:

#!../../bin/linux-x86_64/e2210

#- You may have to change e2210 to something else
#- everywhere it appears in this file

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/e2210.dbd"
e2210_registerRecordDeviceDriver pdbbase

# IOC程序使用IP地址和端口号去访问Modbus IO设备iologik e2210
# drvAsynIPPortConfigure(const char *portName,   这个asyn端口的端口名,供后面使用
#                       const char *hostInfo,   这个端口的主机信息,IP地址:tcp端口号
#                       unsigned int priority,  优先级,0为默认优先级
#                       int noAutoConnect,      是否自动连接,0表示进行自动连接
#                       int noProcessEos);      是否进行字符末尾字符处理,1表示不处理
drvAsynIPPortConfigure("moxa-iologik-e2210", "192.168.3.81:502", 0, 0, 1)

# modbusInterposeConfig(const char *portName,    先前创建的asynIPPort或asynSerialPort的名称
#                      modbusLinkType linkType,  链路类型,0表示TCP/IP
#                      int timeoutMsec,          对底层asynOcet驱动程序写和读操作的超时时间
#                      int writeDelayMsec)       每次从EPICS写到设备前延时(毫秒为单位)。
modbusInterposeConfig("moxa-iologik-e2210", 0, 2000, 0)

# 对Modbus地址0进行位访问
# 访问8比特位作为输出
# 功能码为5,表示写单线圈
# 用以下命令创建一个modbus端口驱动程序
# 以下创建一个modbus端口驱动程序
# 要被创建的modbus端口的名称"C0_Out_Bits"
# 先前创建的asyn IP名称
# slave地址为1,以写单线圈的方式,写地址从0开始到7的8个位地址,这个端口使用MODBUS_DATA数据类型
# 用于读取功能的查询线程的查询延时为100毫秒,PLC类型为"moxa-iologik-e2210"
drvModbusAsynConfigure("C0_Out_Bits", "moxa-iologik-e2210", 1, 5, 0, 8, 0, 100, "moxa-iologik-e2210")


# 对Modbus地址0进行位访问
# 访问8比特位作为输入
# 功能码为1,表示读单线圈
# 用以下命令创建一个modbus端口驱动程序
# 以下创建一个modbus端口驱动程序
# 要被创建的modbus端口的名称"C0_In_Bits"
# 先前创建的asyn IP名称
# slave地址为1,以读单线圈的方式,读地址从0开始到7的8个位地址,这个端口使用MODBUS_DATA数据类型
# 用于读取功能的查询线程的查询延时为100毫秒,PLC类型为"moxa-iologik-e2210"
drvModbusAsynConfigure("C0_In_Bits",  "moxa-iologik-e2210", 1, 1, 0, 8, 0, 100, "moxa-iologik-e2210")


# 对Modbus地址10000进行位访问
# 访问12比特位作为输入
# 功能码为2,表示读离散输入
# 用以下命令创建一个modbus端口驱动程序
# 以下创建一个modbus端口驱动程序
# 要被创建的modbus端口的名称"D0_In_Bits"
# 先前创建的asyn IP名称
# slave地址为1,以写单线圈的方式,写地址从10000开始到10011的12个位地址,这个端口使用MODBUS_DATA数据类型
# 用于读取功能的查询线程的查询延时为100毫秒,PLC类型为"moxa-iologik-e2210"
drvModbusAsynConfigure("D0_In_Bits",  "moxa-iologik-e2210", 1, 2, 0, 12, 0, 100, "moxa-iologik-e2210")


## Load record instances

cd "${TOP}/iocBoot/${IOC}"
# 加载数据库记录实例
dbLoadTemplate("moxa-iologik-e2210.substitutions")

iocInit

8) 创建一个数据库实例文件moxa-iologik-e2210.substitutions:

# These are the C0 outputs done with bit access.
file "../../db/bo_bit.template" { pattern
{P,        R,             PORT,       OFFSET,   ZNAM,   ONAM}
{MOXA-E2210:,    BO00B,     C0_Out_Bits,     0,        Low,    High}
{MOXA-E2210:,    BO01B,     C0_Out_Bits,     1,        Low,    High}
{MOXA-E2210:,    BO02B,     C0_Out_Bits,     2,        Low,    High}
{MOXA-E2210:,    BO03B,     C0_Out_Bits,     3,        Low,    High}
{MOXA-E2210:,    BO04B,     C0_Out_Bits,     4,        Low,    High}
{MOXA-E2210:,    BO05B,     C0_Out_Bits,     5,        Low,    High}
{MOXA-E2210:,    BO06B,     C0_Out_Bits,     6,        Low,    High}
{MOXA-E2210:,    BO07B,     C0_Out_Bits,     7,        Low,    High}
}



# These are the C0 inputs done with bit access
file "../../db/bi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   ZNAM,   ONAM,  ZSV,       OSV,    SCAN}
{MOXA-E2210:,    BI00B,     C0_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI01B,     C0_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI02B,     C0_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI03B,     C0_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI04B,     C0_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI05B,     C0_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI06B,     C0_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    BI07B,     C0_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
}


# These are the D0 discrete  inputs done with bit access
file "../../db/bi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   ZNAM,   ONAM,  ZSV,       OSV,    SCAN}
{MOXA-E2210:,    DBI00B,     D0_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI01B,     D0_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI02B,     D0_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI03B,     D0_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI04B,     D0_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI05B,     D0_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI06B,     D0_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI07B,     D0_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI08B,     D0_In_Bits,     8,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI09B,     D0_In_Bits,     9,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI10B,     D0_In_Bits,     10,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{MOXA-E2210:,    DBI11B,     D0_In_Bits,     11,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
}

9) 用以下命令启动这个IOC程序,并且查看这个IOC中所有的记录:

 ../../bin/linux-x86_64/e2210 st.cmd
epics> dbl
MOXA-E2210:BO00B
MOXA-E2210:BO01B
MOXA-E2210:BO02B
MOXA-E2210:BO03B
MOXA-E2210:BO04B
MOXA-E2210:BO05B
MOXA-E2210:BO06B
MOXA-E2210:BO07B
MOXA-E2210:BI00B
MOXA-E2210:BI01B
MOXA-E2210:BI02B
MOXA-E2210:BI03B
MOXA-E2210:BI04B
MOXA-E2210:BI05B
MOXA-E2210:BI06B
MOXA-E2210:BI07B
MOXA-E2210:DBI00B
MOXA-E2210:DBI01B
MOXA-E2210:DBI02B
MOXA-E2210:DBI03B
MOXA-E2210:DBI04B
MOXA-E2210:DBI05B
MOXA-E2210:DBI06B
MOXA-E2210:DBI07B
MOXA-E2210:DBI08B
MOXA-E2210:DBI09B
MOXA-E2210:DBI10B
MOXA-E2210:DBI11B

MOXA-E2210:BO00B~MOXA-E2210:BO07B分别对应写单个输出线圈,MOXA-E2210:BI00B~MOXA-E2210:BI07B分别对应读单个输出线圈,这些输出线圈从地址0开始到地址7的地址位。

MOXA-E2210:DBI00B~MOXA-E2210:DBI11B分别对应读单个离散输入,这些离散输入地址从10000开始到10011的地址位。

用moxa ioAdmin软件查看moxa iologik e2210的数字输出和数字输入的状态,如下:

 用通道访问可以操作和读取输出线圈状态和读取离散输入状态,进行验证:

1) 读入地址为10000,10001,10002和10006的离散输入:

[blctrl@main-machine ioce2210]$ caget MOXA-E2210:DBI00B MOXA-E2210:DBI01B MOXA-E2210:DBI02B MOXA-E2210:DBI06B
MOXA-E2210:DBI00B              Low
MOXA-E2210:DBI01B              Low
MOXA-E2210:DBI02B              High
MOXA-E2210:DBI06B              High

2) 写地址为0,1的线圈,使其闭合,写地址为3,5的线圈,使其断开:

[blctrl@main-machine ioce2210]$ caput  MOXA-E2210:BO00B 0
Old : MOXA-E2210:BO00B               High
New : MOXA-E2210:BO00B               Low
[blctrl@main-machine ioce2210]$ caput  MOXA-E2210:BO01B 0
Old : MOXA-E2210:BO01B               High
New : MOXA-E2210:BO01B               Low
[blctrl@main-machine ioce2210]$ caput  MOXA-E2210:BO03B 1
Old : MOXA-E2210:BO03B               Low
New : MOXA-E2210:BO03B               High
[blctrl@main-machine ioce2210]$ caput  MOXA-E2210:BO05B 1
Old : MOXA-E2210:BO05B               Low
New : MOXA-E2210:BO05B               High

用ioAdmin观察数字输出的状态为:

可以用Control System Stdio把以上操作集成到一个图形界面中,操作将更加直观:

1) 控制八个数字输出的操作界面,点击不同线圈对应的Low和High按钮,就可以闭合和断开各自的线圈:

2) 读取12个数字输入的操作界面,当相应数字输入的状态发生变化,就能显示在这个窗口中:

猜你喜欢

转载自blog.csdn.net/yuyuyuliang00/article/details/127351436