EPICS modbus 模块数字量读写练习

news2024/11/30 1:48:32

本文使用modbus slave软件模拟一个受控的modbus设备,此模拟设备提供如下功能:

1、线圈1,起始地址为0,数量为8,软件设置如下(功能码1):

2、线圈2,起始地址为8,数量为8,软件设置如下(功能码1):

3、离散输入,起始地址为0,数量为8,软件设置如下(功能码2):

使用EPICS Modbus模块对以上modbus设备进行读写,过程如下:

使用makeBaseApp.pl构建IOC程序框架,并且在configure/RELEASE中指定base所在路径以及所需要的支持模块modbus路径。在程序的src路径下Makefile中指定要添加的数据块定义文件和库文件。

在程序的Db目录下,编写如下模板文件:

1) bo_bit.template:用于写modbus设备的单线圈

record(bo,"$(P)$(R)") {
    field(DTYP,"asynUInt32Digital")
    field(OUT,"@asynMask($(PORT) $(OFFSET) 0x1)")
    field(ZNAM,"$(ZNAM)")
    field(ONAM,"$(ONAM)")
}

2)bi_bit.template:用于读modbus设备的线圈状态或者离散输入状态

record(bi,"$(P)$(R)") {
    field(DTYP,"asynUInt32Digital")
    field(INP,"@asynMask($(PORT) $(OFFSET) 0x1)")
    field(SCAN,"$(SCAN)")
    field(ZNAM,"$(ZNAM)")
    field(ONAM,"$(ONAM)")
    field(ZSV,"$(ZSV)")
    field(OSV,"$(OSV)")
}

3)wfo_bit.template:用于一次写modbus设备的多个线圈

record(waveform,"$(P)$(R)") {
    field(DTYP,"asynInt32ArrayOut")
    field(INP,"@asyn($(PORT) $(OFFSET=0))MODBUS_DATA")
    field(FTVL,"ULONG")
    field(NELM,"$(NELM)")
}

4) wfi_bit.template:用于读取modbus设备多个线圈状态或这多个离散输入状态。

record(waveform,"$(P)$(R)") {
    field(DTYP,"asynInt32ArrayIn")
    field(INP,"@asyn($(PORT) $(OFFSET=0))MODBUS_DATA")
    field(SCAN,"$(SCAN)")
    field(FTVL,"ULONG")
    field(NELM,"$(NELM)")
}

将以上模板文件添加到相同路径下Makefile文件中:

...
DB +=  bo_bit.template
DB +=  bi_bit.template
DB +=  wfo_bit.template
DB +=  wfi_bit.template
...

回到IOC顶层目录,执行make命令,编译这个IOC。

进入到启动目录iocBoot/iocmodbusbit中,编写记录实例化文件:

1)coil_bo_bits.substitutions:用于实例化8个bo记录,每个bo写modbus设备1个线圈。

file "../../db/bo_bit.template" { pattern
{P,        R,             PORT,       OFFSET,   ZNAM,   ONAM}
{COUT:,    CO0B,     C0_Out_Bits,     0,        Low,    High}
{COUT:,    CO1B,     C0_Out_Bits,     1,        Low,    High}
{COUT:,    CO2B,     C0_Out_Bits,     2,        Low,    High}
{COUT:,    CO3B,     C0_Out_Bits,     3,        Low,    High}
{COUT:,    CO4B,     C0_Out_Bits,     4,        Low,    High}
{COUT:,    CO5B,     C0_Out_Bits,     5,        Low,    High}
{COUT:,    CO6B,     C0_Out_Bits,     6,        Low,    High}
{COUT:,    CO7B,     C0_Out_Bits,     7,        Low,    High}
}

2)coil_bi_bits.substitutions:用于实例化16个bi记录,每个bi读取modbus设备1个线圈状态。

file "../../db/bi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   ZNAM,   ONAM,  ZSV,       OSV,    SCAN}
{CIN:,    CI00B,     C0_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI01B,     C0_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI02B,     C0_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI03B,     C0_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI04B,     C0_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI05B,     C0_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI06B,     C0_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI07B,     C0_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI08B,     C1_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI09B,     C1_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI10B,     C1_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI11B,     C1_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI12B,     C1_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI13B,     C1_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI14B,     C1_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{CIN:,    CI15B,     C1_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
}

3)dis_bi_bits.substitutions:用于实例化8个bi记录,每个bi取modbus设备离散输入状态。

file "../../db/bi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   ZNAM,   ONAM,  ZSV,       OSV,    SCAN}
{DIN:,    DI00B,     D0_In_Bits,     0,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI01B,     D0_In_Bits,     1,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI02B,     D0_In_Bits,     2,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI03B,     D0_In_Bits,     3,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI04B,     D0_In_Bits,     4,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI05B,     D0_In_Bits,     5,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI06B,     D0_In_Bits,     6,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
{DIN:,    DI07B,     D0_In_Bits,     7,        Low,    High,  NO_ALARM,  MAJOR,  "I/O Intr"}
}

4)coil_wfo_bits.substitutions:实例化一个waveform记录,用于一次最多设置modbus设备8个线圈。

file "../../db/wfo_bit.template" { pattern
{P,        R,             PORT,       OFFSET,   NELM}
{COUT:,    WFO,            C0_Out_WF,         0,        8}
}

5) dis_wfi_bits.substitutions:实例化一个waveform记录,用于读取modbus设备8个离散输入的状态。

file "../../db/wfi_bit.template" { pattern
{P,        R,          PORT,         OFFSET,   , NELM ,    SCAN}
{DIN:,    WFI,         D0_In_Bits,     8,       8,  "I/O Intr"}
}

编写启动脚本st.cmd:

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

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

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/modbuspoll.dbd"
modbuspoll_registerRecordDeviceDriver pdbbase

# 连接modbus设备
drvAsynIPPortConfigure("mpoll","192.168.3.15:502",0,0,1)
# 使用modbus tcp类型
modbusInterposeConfig("mpoll", 0 ,2000,0)

# 用于写线圈,起始地址0,每次写1个,一共写8次
drvModbusAsynConfigure("C0_Out_Bits", "mpoll", 0, 5,  0, 8, 0,  100, "mpoll")
# 用于写线圈,起始地址8,一次写8个线圈
drvModbusAsynConfigure("C0_Out_WF",   "mpoll", 0, 15, 8, 8, 0,  100, "mpoll")

# 用于读线圈,起始地址0,每次读取一个,一共读8次,轮询时间为500ms
drvModbusAsynConfigure("C0_In_Bits",  "mpoll", 0, 1,  0, 8, 0,  500, "mpoll")
# 用于读线圈,起始地址8,每次读取一个,一共读8次,轮询时间为500ms
drvModbusAsynConfigure("C1_In_Bits",  "mpoll", 0, 1,  8, 8, 0,  500, "mpoll")

# 用于读取离散输入,起始地址0,每次读取一个,读取8次,轮询时间100ms
drvModbusAsynConfigure("D0_In_Bits", "mpoll",  0,  2, 0, 8, 0,  100, "mpoll")

cd "${TOP}/iocBoot/${IOC}"
# 加载实例化记录
# 写线圈
dbLoadTemplate("coil_bo_bits.substitutions")
# 写线圈
dbLoadTemplate("coil_wfo_bits.substitutions")
# 读线圈
dbLoadTemplate("coil_bi_bits.substitutions")
# 读离散输入
dbLoadTemplate("dis_bi_bits.substitutions")
# 读离散输入
dbLoadTemplate("dis_wfi_bits.substitutions")

iocInit

启动这个IOC:

[root@localhost iocmodbusbit]# ../../bin/linux-x86_64/modbuspoll st.cmd
#!../../bin/linux-x86_64/modbuspoll
...
# bit write
drvModbusAsynConfigure("C0_Out_Bits", "mpoll", 0, 5,  0, 8, 0,  100, "mpoll")
# bit array write
drvModbusAsynConfigure("C0_Out_WF",   "mpoll", 0, 15, 8, 8, 0,  100, "mpoll")
# Coil bit Read
drvModbusAsynConfigure("C0_In_Bits",  "mpoll", 0, 1,  0, 8, 0,  500, "mpoll")
drvModbusAsynConfigure("C1_In_Bits",  "mpoll", 0, 1,  8, 8, 0,  500, "mpoll")
# Discrete bit Read
drvModbusAsynConfigure("D0_In_Bits", "mpoll",  0,  2, 0, 8, 0,  100, "mpoll")
cd "/usr/local/EPICS/program/modbuspoll/iocBoot/iocmodbusbit"
dbLoadTemplate("coil_bo_bits.substitutions")
dbLoadTemplate("coil_wfo_bits.substitutions")
dbLoadTemplate("coil_bi_bits.substitutions")
dbLoadTemplate("dis_bi_bits.substitutions")
dbLoadTemplate("dis_wfi_bits.substitutions")
iocInit
Starting iocInit
...
## Start any sequence programs
#seq sncxxx,"user=blctrl"
epics> dbl
COUT:CO0B
COUT:CO1B
COUT:CO2B
COUT:CO3B
COUT:CO4B
COUT:CO5B
COUT:CO6B
COUT:CO7B
COUT:WFO
DIN:WFI
CIN:CI00B
CIN:CI01B
CIN:CI02B
CIN:CI03B
CIN:CI04B
CIN:CI05B
CIN:CI06B
CIN:CI07B
CIN:CI08B
CIN:CI09B
CIN:CI10B
CIN:CI11B
CIN:CI12B
CIN:CI13B
CIN:CI14B
CIN:CI15B
DIN:DI00B
DIN:DI01B
DIN:DI02B
DIN:DI03B
DIN:DI04B
DIN:DI05B
DIN:DI06B
DIN:DI07B

1) COUT:CO0B~COUT:CO7B:bo记录,每个bo记录用于写一个线圈。

2)COUT:WF:waveform记录,用于一次写8个线圈。

3)DIN:WFI:waveform记录,用于读取8个离散输入。

4)CIN:CI00B~CIN:CI15B:bi记录,每个bi记录读取一个线圈状态。

5)DIN:DI00B~DIN:DI00B,bi记录,每个bi记录读取一个离散输入。

用css绘制控制界面,进行记录连接后,如下所示:

1)顶层窗口区域:Coil Out按钮写线圈,Coil In回读线圈状态

2)中间窗口区域:Coil Array Out可以一次最多写8个线圈,Coil In回读线圈状态。

3)底层窗口区域:用于读取离散输入,离散输入状态需要在modbus slave窗口中设置 ,Discrete Bit in 和Discrete Bit Array In都回读modbus slave窗口中设置的离散输入的状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1290783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

easyui实现省市县三级联动

一、技术: 前端采用的是easyui+jquery+jsp页面 后端采用springmvc+mybatis+mysql8 效果图 二、cascadeEasyui.jsp页面 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%String path = request.getContex…

Stable Diffusion 系列教程 - 2 WebUI 参数详解

Stable Diffusion 的整个算法组合为&#xff1a; UNet VAE 文本编码器 UNet&#xff1a;就是我们大模型里的核心。 文本编码器&#xff1a;将我们的prompt进行encoder为算法能理解的内容&#xff08;可以理解为SD外包出去的项目CLIP&#xff09;。 VAE&#xff1a;对UNet生…

现货白银简单介绍

在贵金属投资领域&#xff0c;现货白银是当前国际上最为流行、交投最为活跃的白银投资方式&#xff0c;其交易市场遍布全球&#xff0c;包括伦敦、苏黎世、纽约、芝加哥及香港等主要市场&#xff0c;是一种以杠杆交易和做市商的形式进行的现货交易。 现货白银可以说是当下交易模…

ELK的日志解决方案

ELK的日志解决方案 ELK是什么 ELK 是一个缩写&#xff0c;代表 Elastic Stack&#xff0c;而不是三个独立的产品名称。Elastic Stack 是一个开源的数据处理和分析平台&#xff0c;用于实时搜索、分析和可视化大规模数据。ELK 是由三个主要的组件构成&#xff1a; Elasticsea…

分享一个基础面试题---手写call

分享一个基础面试题---手写call 手写call笔记第一步第二步第三步 手写call笔记 call()&#xff1a;在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法。 let foo {value:1 }; function bar(){console.log(this.value); } bar.call(foo);//1注意两点&…

Vue2与Vue3的语法对比

Vue2与Vue3的语法对比 Vue.js是一款流行的JavaScript框架&#xff0c;通过它可以更加轻松地构建Web用户界面。随着Vue.js的不断发展&#xff0c;Vue2的语法已经在很多应用中得到了广泛应用。而Vue3于2020年正式发布&#xff0c;带来了许多新的特性和改进&#xff0c;同时也带来…

unity 2d 入门 飞翔小鸟 飞翔脚本(五)

新建c#脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Fly : MonoBehaviour {//获取小鸟&#xff08;刚体&#xff09;private Rigidbody2D bird;//速度public float speed;// Start is called before the first frame up…

浅谈web性能测试

什么是性能测试&#xff1f; web性能应该注意些什么&#xff1f; 性能测试&#xff0c;简而言之就是模仿用户对一个系统进行大批量的操作&#xff0c;得出系统各项性能指标和性能瓶颈&#xff0c;并从中发现存在的问题&#xff0c;通过多方协助调优的过程。而web端的性能测试…

【华为数据之道学习笔记】2-建立企业级数据综合治理体系

数据作为一种新的生产要素&#xff0c;在企业构筑竞争优势的过程中起着重要作用&#xff0c;企业应将数据作为一种战略资产进行管理。数据从业务中产生&#xff0c;在IT系统中承载&#xff0c;要对数据进行有效治理&#xff0c;需要业务充分参与&#xff0c;IT系统确保遵从&…

若依项目前后端部署记录

前言 本文较乱&#xff0c;用于笔者记录项目部署过程&#xff0c;对于想学习若依项目部署的同学看文章可能会导致误导&#xff0c;建议读者多查资料&#xff0c;保持疑问并谨慎验证。 项目官方指导&#xff1a; 环境部署 | RuoYi 1、环境部署相关 JDK > 1.8 (推荐1.8版本…

TIMO后台管理系统 Shiro 反序列化漏洞复现

0x01 产品简介 TIMO 后台管理系统,基于SpringBoot2.0 + Spring Data Jpa + Thymeleaf + Shiro 开发的后台管理系统,采用分模块的方式便于开发和维护,支持前后台模块分别部署,目前支持的功能有:权限管理、部门管理、字典管理、日志记录、文件上传、代码生成等,为快速开发后…

记录 | vscode pyhton c++调试launch.json配置

下面提供 vscode 中 python 和 c 调试配置的 launch.json (好用&#xff0c;已用好几年&#xff0c;建议收藏) {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: https://go.microsoft.com/fwlink/?linkid830387&qu…

多人聊天UDP

服务端 package 多人聊天;import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList;…

神经网络 模型表示(一)

神经网络 模型表示 模型表示一 为了构建神经网络模型&#xff0c;我们需要首先思考大脑中的神经网络是怎样的&#xff1f;每一个神经元都可以被认为是一个处理单元/神经核&#xff08;processing unit/Nucleus&#xff09;&#xff0c;它含有许多输入/树突&#xff08;input/…

分布式分布式事务分布式锁分布式ID

目录 分布式分布式系统设计理念目标设计思路中心化去中心化 基本概念分布式与集群NginxRPC消息中间件&#xff08;MQ&#xff09;NoSQL&#xff08;非关系型数据库&#xff09; 分布式事务1 事务2 本地事务3 分布式事务4 本地事务VS分布式事务5 分布式事务场景6 CAP原理7 CAP组…

PACS源码,医学影像传输系统源码,全院级应用,支持放射、超声、内窥镜、病理等影像科室,且具备多种图像处理及三维重建功能

​三维智能PACS系统源码&#xff0c;医学影像采集传输系统源码 PACS系统以大型关系型数据库作为数据和图像的存储管理工具&#xff0c;以医疗影像的采集、传输、存储和诊断为核心&#xff0c;集影像采集传输与存储管理、影像诊断查询与报告管理、综合信息管理等综合应用于一体的…

Arrarys类的相关细节与知识点

Arrarys类在Java中存储了一些对数组操作的一些方法&#xff0c;比如Sort()&#xff0c;toString&#xff0c;BinarySearch()&#xff0c;copyof()&#xff0c;fill()&#xff0c;equals()&#xff0c;aList这几种方法&#xff0c;这里面最重要的可能就是Sort()方法&#xff0c;…

AWS 日志分析工具

当您的网络资源托管在 AWS 中时&#xff0c;需要定期监控您的 AWS CloudTrail 日志、Amazon S3 服务器日志和 AWS ELB 日志等云日志&#xff0c;以降低任何潜在的安全风险、识别严重错误并确保满足所有合规性法规。 什么是 Amazon S3 Amazon Simple Storage Service&#xff…

汽车网络安全--ISO\SAE 21434解析(二)

1.风险评估方法 书接上文,我们正式开始对车灯系统的TARA分析,首先回顾下整车关于车灯系统描述: 可以比较肯定的是,我们定义的item为车灯系统,因此可以看到上图中画出了item boundary;同时定义出运行环境,个人理解,这块就是为TARA分析提供足够的环境支撑,不管是直接还…