EPICS modbus 模块数字量读写练习

本文使用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< envPathscd "${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.mzph.cn/news/203271.shtml

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

相关文章

使用GPT-4V解决Pycharm设置问题

pycharm如何实现关联&#xff0c;用中文回答 在PyCharm中关联PDF文件类型&#xff0c;您可以按照以下步骤操作&#xff1a; 1. 打开PyCharm设置&#xff1a;点击菜单栏中的“File”&#xff08;文件&#xff09;&#xff0c;然后选择“Settings”&#xff08;设置&#xff09;。…

论文笔记--A Fine-grained Interpretability Evaluation Benchmark for Neural NLP

论文笔记--A Fine-grained Interpretability Evaluation Benchmark for Neural NLP 1. 文章简介2. 文章概括3 文章重点技术3.1 数据收集3.2 数据扰动3.3 迭代标注和检查根因3.4 度量3.4.1 Token F1-score3.4.2 MAP(Mean Average Precision) 4. 文章亮点5. 原文传送门 1. 文章简…

日志框架梳理(Log4j,Reload4j,JUL,JCL,SLF4J,Logback,Log4j2)

原文链接 日志框架发展历程 在了解日志框架时总会列出一系列框架&#xff1a;Log4j&#xff0c;Reload4j&#xff0c;JUL&#xff0c;JCL&#xff0c;SLF4J&#xff0c;Logback&#xff0c;Log4j2&#xff0c;这么多框架让人感到混乱&#xff0c;该怎么选取、该怎么用。接下来…

分享“技艺与传承”的魅力!春城晚报(开屏新闻)生活节第七期媒体开放日活动举行

近日&#xff0c;由云南报业传媒&#xff08;集团&#xff09;有限责任公司、云南春晚传媒有限公司指导&#xff1b;金格金俊广场、云南精品文化传媒有限公司联合主办的第七期媒体开放日活动在金格金俊广场B1共享空间举办。本次活动以「技艺与传承」为主题&#xff0c;特邀青年…

2023年山东省职业院校技能大赛信息安全管理与评估第一阶段样题

2023年山东省职业院校技能大赛信息安全管理与评估样题 竞赛需要完成三个阶段的任务&#xff0c;分别完成三个模块&#xff0c;总分共计 1000 分。三个模块内容和分值分别是&#xff1a; \1. 第一阶段&#xff1a;模块一 网络平台搭建与设备安全防护&#xff08;240 分钟&…

MAMBA介绍:一种新的可能超过Transformer的AI架构

有人说&#xff0c;“理解了人类的语言&#xff0c;就理解了世界”。一直以来&#xff0c;人工智能领域的学者和工程师们都试图让机器学习人类的语言和说话方式&#xff0c;但进展始终不大。因为人类的语言太复杂&#xff0c;太多样&#xff0c;而组成它背后的机制&#xff0c;…

华为数通---配置ARP安全综合功能案例

简介 ARP&#xff08;Address Resolution Protocol&#xff09;安全是针对ARP攻击的一种安全特性&#xff0c;它通过一系列对ARP表项学习和ARP报文处理的限制、检查等措施来保证网络设备的安全性。ARP安全特性不仅能够防范针对ARP协议的攻击&#xff0c;还可以防范网段扫描攻击…

搭建个人网盘应用Nextcloud

使用DNF管理软件包 1 使用winscp工具将openeuler-20.03-LTS-x86_64-dvd.iso上传至openeuler虚拟机的/root目录下&#xff0c;然后执行如下命令挂载ISO [rootopenEuler ~]# mount -o loop /root/openEuler-20.03-LTS-everything-x86_64-dvd.iso /mnt/2 添加软件源 [rootope…

数据挖掘 分类模型选择

选择的模型有&#xff1a; 决策树、朴素贝叶斯、K近邻、感知机 调用的头文件有&#xff1a; import numpy as np import pandas as pd from matplotlib import pyplot as plt from sklearn.linear_model import Perceptron from sklearn.naive_bayes import GaussianNB from s…

echerts 循环图 显示获取不到id

报错&#xff1a;Uncaught TypeError: Cannot read properties of null (reading getAttribute)&#xff0c; 我所出现的问题是 1&#xff0c;我在循环方法的时候 id没有从0开始&#xff0c;把id变成从0开始循环 2&#xff0c;设置myChart 全局属性 呈现效果 代码 html 动态绑…

0X05

打开题目 点击完登录和注册都没有什么反应&#xff0c;所以先扫一下看看 在出现admin.php后就截止了&#xff0c;访问看看,进入后台。。 尝试一下弱口令 admin/12345 或者是demo/demo 设计中-自定义->右上角导出主题 找到一个导出的点&#xff0c;下载了一个1.zip压缩包…

C#图像处理OpenCV开发指南(CVStar,07)——通用滤波(Filter2D)的实例代码

1 函数定义 void Filter2D (Mat src, Mat dst, int ddepth, InputArray kernel, Point anchor Point(-1,-1), double delta 0, int borderType BORDER_DEFAULT ) 1.1 原型 #include <opencv2/imgproc.hpp> Convolves an image wit…

Cocos Creator加入图片没有被识别

原因&#xff0c;需要更换类型&#xff0c;选择下图中的类型

VR远程带看,助力线下门店线上化转型“自救”

VR远程带看&#xff0c;因自身高效的沉浸式在线沟通功能&#xff0c;逐渐走进了大众的视野。身临其境的线上漫游体验以及实时同屏互联的新型交互模式&#xff0c;提升了商家同用户之间的沟通效率&#xff0c;进一步实现了远程线上一对一、一对多的同屏带看&#xff0c;用户足不…

卡码网 46携带研究材料 LeetCode 416分割等和数组 1049最后一块石头的重量-ii | 代码随想录25期训练营day42、43

动态规划算法4 卡码网 46 携带研究材料 2023.12.6 题目链接常规二维dp数组方法代码随想录讲解[链接]一维滚动数组方法代码随想录讲解[链接] //二维dp数组做法 #include<bits/stdc.h> using namespace std;int main() {//m为材料种类数&#xff0c;n为行李箱最大空间数…

如何使用 Zotero 导出所选条目的 PDF 文件

如何使用 Zotero 导出所选条目的 PDF 文件 Zotero 是一款强大的参考文献管理工具&#xff0c;但它并不直接提供将整个文件夹导出为 PDF 的选项。不过&#xff0c;您可以使用以下步骤来导出您所选的 Zotero 条目中的 PDF 文件&#xff0c;无需额外的插件。 选择所需的 Zotero 条…

智能优化算法应用:基于鹰栖息算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于鹰栖息算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于鹰栖息算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鹰栖息算法4.实验参数设定5.算法结果6.参考文献7.…

【华为数据之道学习笔记】3-1 基于数据特性的分类管理框架

华为根据数据特性及治理方法的不同对数据进行了分类定义&#xff1a;内部数据和外部数据、结构化数据和非结构化数据、元数据。其中&#xff0c;结构化数据又进一步划分为基础数据、主数据、事务数据、报告数据、观测数据和规则数据。 对上述数据分类的定义及特征描述。 分类维…

Spring Boot 项目的创建、配置文件、日志

文章目录 Spring Boot 优点创建 Spring Boot 项目创建项目认识目录网页创建&#xff08;了解&#xff09; 约定大于配置Spring Boot 配置文件配置文件格式读取配置项properties 配置文件yml 配置文件基本语法进阶语法配置对象配置集合yml 设置不同环境的配置文件 Spring Boot 日…

C语言之联合和枚举

C语言之联合和枚举 文章目录 C语言之联合和枚举1. 联合体1.1 联合体的声明1.2 联合体的特点1.3 结构体和联合体对比1.4 联合体大小的计算1.5 联合体小练习 2. 枚举2.1 枚举类型的声明2.2 枚举类型的优点2.3 枚举类型的使用 1. 联合体 1.1 联合体的声明 像结构体⼀样&#xff…