基于EPICS stream模块的直流电源的IOC控制程序实例

本实例程序实现了对优利德UDP6720系列直流电源的网络控制和访问,先在此介绍这个项目中使用的硬件:

1、UDP6721直流电源:受控设备

2、moxa串口服务器5150:将UDP6721直流电源设备串口连接转成网络连接

3、香橙派Zero3:运行IOC程序。

以下是实际连接图: 

 需要EPICS软件模块如下:

  1. base
  2. asyn
  3. stream
  4. autosave

以下步骤描述如何建立这个IOC程序的过程:

1、使用工具命令makeBaseApp.pl构建IOC程序架构,程序架构如下:

root@orangepizero3:/usr/local/EPICS/program/udp6721# ls
bin  configure  db  dbd  document  iocBoot  lib  Makefile  udp6721App

2、修改confiure/RELEASE文件,增加依赖模块所在的路径:

...
SUPPORT=/usr/local/EPICS/synApps/support
ASYN=$(SUPPORT)/asyn
STREAM=$(SUPPORT)/stream/streamDevice
AUTOSAVE=$(SUPPORT)/autosave
...

3、进入udp6721App/src/目录下,编写sub记录中所需要调用函数的源代码以及相应的dbd文件:

// ubRecordSleep.c
#include <stdio.h>
#include <dbDefs.h>
#include <epicsThread.h>
#include <registryFunction.h>
#include <subRecord.h>
#include <epicsExport.h>

int mySubDebug = 0;

static long mySubInit(struct subRecord *precord)
{
        if (mySubDebug)
        {
                printf("Record %s called mySubInit(%p)\n", precord->name, (void *)precord);
        }
        printf("subInit was called\n");
        return 0;
}

static long mySubProcess(struct subRecord * precord)
{
        if(mySubDebug)
        {
                printf("Record %s called mySubProcess(%p)\n", precord->name,(void *)precord);
        }
        epicsThreadSleep(precord->val);
        return 0;
}
# subRecordSleepSupport.dbd
variable(mySubDebug)
function(mySubInit)
function(mySubProcess)

修改这个目录中的Makefile文件,指明所需要的数据库定义文件以及链接的库文件以及需要编译的源文件:

TOP=../..

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

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

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

# udp6721.dbd will be made up from these files:
udp6721_DBD += base.dbd
udp6721_DBD += asyn.dbd
udp6721_DBD += stream.dbd
udp6721_DBD += subRecordSleepSupport.dbd
udp6721_DBD += drvAsynIPPort.dbd
udp6721_DBD += asSupport.dbd

# Include dbd files from all support applications:
#udp6721_DBD += xxx.dbd

# Add all the support libraries needed by this IOC
udp6721_LIBS += asyn
udp6721_LIBS += stream
udp6721_LIBS += autosave

udp6721_SRCS += subRecordSleep.c
# udp6721_registerRecordDeviceDriver.cpp derives from udp6721.dbd
udp6721_SRCS += udp6721_registerRecordDeviceDriver.cpp

# Build the main IOC entry point on workstation OSs.
udp6721_SRCS_DEFAULT += udp6721Main.cpp
udp6721_SRCS_vxWorks += -nil-

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

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

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

include $(TOP)/configure/RULES

4、进入udp6721App/Db/下编写协议文件,数据库实例文件和用于数据保存的req文件:

1)数据库实例文件:

record(stringin, "$(P)DeviceInfo")
{
    field (DESC, "Read Device Info of PS1")
    field (DTYP, "stream")
    field (INP,  "@udp6721.proto getIDNInfo PS1")
    field (PINI, "YES")
    field (SCAN, "10 second")
}

record(bo, "$(P)OnOff")
{
    field (DESC, "Turn On/Off the Device")
    field (DTYP, "stream")
    field (OUT,  "@udp6721.proto setSwitch PS1")
    field (ZNAM, "OFF")
    field (ONAM, "ON")
    field (PINI, "YES")
    field (FLNK, "$(P)OnOff_RBV")
}


record(bi, "$(P)OnOff_RBV")
{
    field (DESC, "The Status of  the Device")
    field (DTYP, "stream")
    field (INP,  "@udp6721.proto getSwitch PS1")
    field (ZNAM, "OFF")
    field (ONAM, "ON")
    field (PINI, "YES")
    field (SCAN, "Passive")
}

record(ai, "$(P)Voltage_M")
{
   field (DESC, "Output Voltage")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto measureVoltage PS1")
   field (PREC, "2")
   field (PINI, "YES")
}


record(ai, "$(P)Current_M")
{
   field (DESC, "Output Current")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto measureCurrent PS1")
   field (PREC, "3")
   field (SCAN, "I/O Intr")
}


record(ai, "$(P)Power_M")
{
   field (DESC, "Output Power")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto measurePower PS1")
   field (PREC, "4")
   field (SCAN, "I/O Intr")
}

record(bi, "$(P)CVCC_RBV")
{
   field (DESC, "Device Output Mode CV/CC")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto getCVCC PS1")
   field (ZNAM, "CV")
   field (ONAM, "CC")
   field (SCAN, "1 second")
   field (PINI, "YES")
}

record(ai, "$(P)Voltage_RBV")
{
   field (DESC, "Output Voltage")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto getVoltage PS1")
   field (PREC, "2")
   field (PINI, "YES")
}


record(ai, "$(P)Current_RBV")
{
   field (DESC, "Output Current")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto getCurrent PS1")
   field (PREC, "3")
   field (PINI, "YES")
}


record(ao, "$(P)SetVoltage")
{
   field (DESC, "Output Voltage")
   field (DTYP, "stream")
   field (OUT,  "@udp6721.proto setVoltage PS1")
   field (PREC, "2")
   field (FLNK, "$(P)SubSleep")
}


record(ao, "$(P)SetCurrent")
{
   field (DESC, "Output Current")
   field (DTYP, "stream")
   field (OUT,  "@udp6721.proto setCurrent PS1")
   field (PREC, "3")
   field (FLNK, "$(P)SubSleep")
}


record(fanout, "$(P)Fanout")
{
        field(SELM,"All")
        field(SCAN, "Passive")
        field(LNK0, "$(P)Voltage_M")
        field(LNK1, "$(P)Voltage_RBV")
        field(LNK2, "$(P)Current_RBV")
}

record(sub,"$(P)SubSleep")
{
    field(INAM,"mySubInit")
    field(SNAM,"mySubProcess")
    field(VAL, "0.8")
    field(FLNK, "$(P)Fanout.PROC")
}



record(ao, "$(P)SetVProtectValue")
{
   field (DESC, "Set Protect Voltage")
   field (DTYP, "stream")
   field (OUT,  "@udp6721.proto setVProtectValue PS1")
   field (PREC, "2")
   field (FLNK, "$(P)VProtectValue_RBV")
}

record(ai, "$(P)VProtectValue_RBV")
{
   field (DESC, "Protect Voltage")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto getVProtectValue PS1")
   field (PREC, "2")
   field (PINI, "YES")
}


record(ao, "$(P)SetCProtectValue")
{
   field (DESC, "Set Protect Currrent")
   field (DTYP, "stream")
   field (OUT,  "@udp6721.proto setCProtectValue PS1")
   field (PREC, "3")
   field (FLNK, "$(P)CProtectValue_RBV")
}

record(ai, "$(P)CProtectValue_RBV")
{
   field (DESC, "Protect Current")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto getCProtectValue PS1")
   field (PREC, "3")
   field (PINI, "YES")
}

record(bo, "$(P)OnOffVProtectState")
{
   field (DESC, "Set Volt Protect State")
   field (DTYP, "stream")
   field (ZNAM, "ON")
   field (ONAM, "OFF")
   field (OUT,  "@udp6721.proto switchVProtectState PS1")
   field (FLNK, "$(P)OnOffVProtectState_RBV")
}

record(bi, "$(P)OnOffVProtectState_RBV")
{
   field (DESC, "Volt Protect State")
   field (DTYP, "stream")
   field (ZNAM, "ON")
   field (ONAM, "OFF")
   field (INP,  "@udp6721.proto getVProtectState PS1")
   field (PINI, "YES")
}

record(bo, "$(P)OnOffCProtectState")
{
   field (DESC, "Set Current Protect State")
   field (DTYP, "stream")
   field (ZNAM, "ON")
   field (ONAM, "OFF")
   field (OUT,  "@udp6721.proto switchCProtectState PS1")
   field (FLNK, "$(P)OnOffCProtectState_RBV")
}

record(bi, "$(P)OnOffCProtectState_RBV")
{
   field (DESC, "Current Protect State")
   field (DTYP, "stream")
   field (ZNAM, "ON")
   field (ONAM, "OFF")
   field (INP,  "@udp6721.proto getCProtectState PS1")
   field (PINI, "YES")
}

record(stringout, "$(P)SetRemote")
{
   field (DESC, "Current Protect State")
   field (DTYP, "stream")
   field (OUT,  "@udp6721.proto setRemote PS1")
   field (FLNK, "$(P)Remote_RBV")
}

record(bi, "$(P)Remote_RBV")
{
   field (DESC, "Remote State")
   field (DTYP, "stream")
   field (INP,  "@udp6721.proto getRemote PS1")
   field (ZNAM, "YES")
   field (ONAM, "NO")
   field (PINI, "YES")
}

协议文件:

Terminator = LF;

getIDNInfo {
        out "*IDN?";
        in "Uni-Trend,%s";
}

# Switch is an enum, either OFF or ON
# use bi and bo records

getSwitch {
    out "OUTPUT?"; in "%{OFF|ON}";
}

setSwitch {
    out "OUTPUT %{OFF|ON}";
    @init { getSwitch; }
}


measureVoltage {
    out "MEASure:ALL?";
    in  "%f,%*f,%*f";
}

measureCurrent {
    in  "%*f,%f,%*f";
}

measurePower {
   in "%*f,%*f,%f";
}


getCVCC {
    out "OUTPUT:CVCC?"; in "%{CV|CC}";
}

setVoltage {
   out "VOLTage %.2f";
}

getVoltage {
   out "VOLTage?";
   in "%f";
}

setCurrent {
   out "CURRent %.3f";
}

getCurrent {
   out "CURRent?";
   in "%f";
}

setVProtectValue {
   out "VOLTage:PROTection %.2f";
}

getVProtectValue {
   out "VOLTage:PROTection?";
   in "%f";
}

setCProtectValue {
   out "CURRent:PROTection %.3f";
}

getCProtectValue {
    out "CURRent:PROTection?";
    in "%f";
}

switchVProtectState {
    out "VOLTage:PROTection:STATe %{ON|OFF}";
}

getVProtectState {
    out "VOLTage:PROTection:STATe?";
    in "%{ON|OFF}";
}

switchCProtectState {
    out "CURRent:PROTection:STATe {ON|OFF}";
}

getCProtectState {
    out "CURRent:PROTection:STATe?";
    in "%{ON|OFF}";
}

setRemote {
    out "SYSTem:REMote";
}

getRemote {
    out "SYSTem:REMote?";
    in "%{YES|NO}";
}

存储配置文件:

$(P)SetVoltage
$(P)SetCurrent
$(P)SetVProtectValue
$(P)SetCProtectValue
$(P)SetRemote

编辑相同路径下的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 += udp6721.proto
DB += udp6721.db
DB += udp6721.req

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

include $(TOP)/configure/RULES

5 切换到顶层目录,执行make命令,进行编译。

6 进入启动目录 iocBoot/iocudp6721/:

创建两个目录autosave和req,并且在req下添加一个auto_settings.req文件,内容如下:

file udp6721.req  P=$(P)

7 编辑启动文件st.cmd,内容如下:

#!../../bin/linux-aarch64/udp6721

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

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/udp6721.dbd"
udp6721_registerRecordDeviceDriver pdbbase

# UDP6721设备的IP地址和连接端口
drvAsynIPPortConfigure("PS1", "192.168.3.101:4001", 0, 0 ,1)

## Load record instances
epicsEnvSet ("STREAM_PROTOCOL_PATH", "$(TOP)/db/")
dbLoadRecords("db/udp6721.db","P=UDP6721:")

set_requestfile_path("$(TOP)/db")
set_requestfile_path("$(TOP)/iocBoot/$(IOC)/req/")

# 通过调用set_savefile_path函数指定你想要.sav文件被写到哪个目录中。
set_savefile_path("$(TOP)/iocBoot/$(IOC)/autosave/")

# 使用set_pass<N>_restoreFile()函数
# 指定哪些save文件要在记录初始化前(pass 0)前被恢复,以及哪些save文件在记录初始化后(pass 1)被恢复
set_pass1_restoreFile("auto_settings.sav")

save_restoreSet_numSeqFiles(3)
save_restoreSet_SeqPeriodInSeconds(600)
save_restoreSet_RetrySeconds(60)
save_restoreSet_CAReconnect(1)
save_restoreSet_CallbackTimeout(-1)

cd "${TOP}/iocBoot/${IOC}"
iocInit

create_monitor_set("auto_settings.req",5,"P=UDP6721:")

8 启动这个IOC,用dbl查看加载的记录实例:

 ../../bin/linux-aarch64/udp6721 st.cmd
epics> dbl
UDP6721:Voltage_M
UDP6721:Current_M
UDP6721:Power_M
UDP6721:Voltage_RBV
UDP6721:Current_RBV
UDP6721:VProtectValue_RBV
UDP6721:CProtectValue_RBV
UDP6721:SetVoltage
UDP6721:SetCurrent
UDP6721:SetVProtectValue
UDP6721:SetCProtectValue
UDP6721:OnOff_RBV
UDP6721:CVCC_RBV
UDP6721:OnOffVProtectState_RBV
UDP6721:OnOffCProtectState_RBV
UDP6721:Remote_RBV
UDP6721:OnOff
UDP6721:OnOffVProtectState
UDP6721:OnOffCProtectState
UDP6721:Fanout
UDP6721:DeviceInfo
UDP6721:SetRemote
UDP6721:SubSleep

9 用CSS查看连接以上记录实例:

可以通过以上图形界面设置直流电源的电压和电流输出。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【iOS】知乎日报前三周总结

这几天一直在进行知乎日报的仿写&#xff0c;仿写过程中积累了许多实用的开发经验&#xff0c;并对MVC有了更深的了解&#xff0c;特撰此篇作以总结 目录 第一周将网络请求封装在一个单例类Manager中SDWebImage库的简单使用运用时间戳处理当前时间自定义NavigationBar 第二周在…

HarmonyOS(二)—— 初识ArkTS开发语言(中)之ArkTS的由来和演进

前言 在上一篇文章HarmonyOS&#xff08;二&#xff09;—— 初识ArkTS开发语言&#xff08;上&#xff09;之TypeScript入门&#xff0c;我初识了TypeScript相关知识点&#xff0c;也知道ArkTS是华为基于TypeScript发展演化而来。 从最初的基础的逻辑交互能力&#xff0c;到…

VScode配置 github 上传代码

初始化&#xff0c;设置用户名和密码 # 设置你的 Git 用户名 git config --global user.name author# 设置你的 Git 邮箱 git config --global user.email authorgmail.com# 确保 Git 输出带有颜色 git config --global color.ui auto​# 查看 Git 配置 git list1. 初始化本地…

Java8实战-总结46

Java8实战-总结46 CompletableFuture&#xff1a;组合式异步编程让代码免受阻塞之苦使用 CompletableFuture 发起异步请求寻找更好的方案 CompletableFuture&#xff1a;组合式异步编程 让代码免受阻塞之苦 使用 CompletableFuture 发起异步请求 可以使用工厂方法supplyAsyn…

数据包端到端的流程

流程 A给F发送一个数据包的流程&#xff1a; 首先 A&#xff08;192.168.0.1&#xff09;通过子网掩码&#xff08;255.255.255.0&#xff09;计算出自己与 F&#xff08;192.168.2.2&#xff09;并不在同一个子网内&#xff0c;于是决定发送给默认网关&#xff08;192.168.0.…

vue3项目实践

创建 vue3 项目 node本版&#xff1a;node 16.x.x&#xff0c; 脚手架&#xff1a;create-vue 脚手架工具&#xff0c;底层vite 创建vue3项目&#xff1a;npm init vuelatest setup函数 vue3 单文件组件 1、vite.config.js配置文件基于vite的配置 2、template模板不再要求唯…

4 函数的升级-下

重载&#xff08;overload&#xff09; 同一个标识符在不同的上下文有不同的意义 如汉语中“洗”和不同的字搭配后&#xff0c;有不同的含义&#xff0c;play 和不同的单词搭配后有不同的含义。 函数重载&#xff1a;用同一个函数名定义不同的函数&#xff0c;通过不同的参数搭…

c++11中的线程库和包装器

c11 1. 线程库1.1 线程库1.2 锁mutex 2. 包装器2.1 funciton2.2 bind 1. 线程库 1.1 线程库 C11中的线程库提供了一种方便的方式来创建和管理线程。其中&#xff0c;std::thread是一个重要的类&#xff0c;它允许我们创建新线程并控制它们的执行。以下是std::thread的一些重要…

048基于web+springboot的校园资料分享平台

欢迎大家关注&#xff0c;一起好好学习&#xff0c;天天向上 文章目录 一项目简介技术介绍 二、功能组成三、效果图四、 文章目录 一项目简介 本校园资料分享平台有管理员和用户两个角色。管理员功能有个人中心&#xff0c;学生管理&#xff0c;资料分享管理&#xff0c;资源分…

03、SpringBoot + 微信支付 ---- 创建订单、保存二维码url、显示订单列表

目录 Native 下单1、创建课程订单保存到数据库1-1&#xff1a;需求&#xff1a;1-2&#xff1a;代码&#xff1a;1-3&#xff1a;测试结果&#xff1a; 2、保存支付二维码的url2-1&#xff1a;需求&#xff1a;2-2&#xff1a;代码&#xff1a;2-3&#xff1a;测试&#xff1a;…

[python 刷题] 1248 Count Number of Nice Subarrays

[python 刷题] 1248 Count Number of Nice Subarrays 题目如下&#xff1a; Given an array of integers nums and an integer k. A continuous subarray is called nice if there are k odd numbers on it. Return the number of nice sub-arrays. 这道题和 1343 Number of S…

Python实验五 异常处理

实验 1&#xff1a;为下列代码添加异常处理。 xint(input(请输入一个整数)) print(100/x) # 实验 1&#xff1a;为下列代码添加异常处理。 try:xint(input(请输入一个整数&#xff1a;))print(100/x) except ValueError:print(请输入一个整数) except ZeroDivisionError:print…

Spring Boot中解决跨域问题(CORS)

1. 跨域介绍 首先解释什么是跨域&#xff0c;跨域就是前端和后端的端口号不同&#xff1b;会产生跨域问题&#xff0c;这里浏览器的保护机制&#xff08;同源策略&#xff09;。 同源策略&#xff1a;前端和后端的协议、域名、端口号三者都相同叫做同源。 我们看一下不同源&am…

项目部署文档

申请SSL证书 先申请,用免费的 下载证书 先将下载下来的保存起来 服务器安装JDK: 创建develop目录 mkdir /usr/local/develop/ 把JDK压缩包上传到/usr/local/develop/目录 解压安装包 并且将安装到指定目录 tar -zxvf /usr/local/develop/jdk-8u191-linux-x64.tar.gz -C /us…

嵌入式中如何将BootLoader与APP合并成一个固件

1、前言 嵌入式固件一般分为BootLoader和App&#xff0c;BootLoader用于启动校验、App升级、App版本回滚等功能&#xff0c;BootLoader在cpu上电第一阶段中运行&#xff0c;之后跳转至App地址执行应用程序。 因此&#xff0c;在发布固件的时候&#xff0c;会存在BootLoader固件…

IOS手机耗电量测试

1. 耗电量原始测试方法 1.1 方法原理&#xff1a; 根据iPhone手机右上角的电池百分比变化来计算耗电量。 1.2实际操作&#xff1a; 在iOS通用设置中打开电池百分比数值显示&#xff0c;然后操作30分钟&#xff0c;60分钟&#xff0c;90分钟&#xff0c;看开始时和结束时电池…

【WSL/WSL 2-Redis】解决Windows无法安装WSL Ubuntu子系统与Redis安装

前言 在现代计算环境中&#xff0c;开发人员和技术爱好者通常需要在不同的操作系统之间切换&#xff0c;以便利用各种工具和应用程序。在这方面&#xff0c;Windows用户可能发现WSL&#xff08;Windows Subsystem for Linux&#xff09;是一个强大的工具&#xff0c;它允许他们…

第六章 块为结构建模 P1|系统建模语言SysML实用指南学习

仅供个人学习记录 概述 块是SysML结构中的模块单元&#xff0c;用于定义一类系统、部件、部件互连&#xff0c;或者是流经系统的项&#xff0c;也用于定义外部实体、概念实体或其他逻辑抽象 块定义图用于定义块以及块之间的相互关系&#xff0c;如层级关系&#xff0c;也用于…

vue+elementUI 设置el-descriptions固定长度并对齐

问题描述 对于elementUI组件&#xff0c;el-descriptions 在以类似列表的形式排列的时候&#xff0c;上下无法对齐的问题。 问题解决 在el-descriptions 标签中&#xff0c;添加属性&#xff1a; :contentStyle"content_style" 控制其内容栏长度 <el-descripti…

【快速解决】Android Studio ERROR: Read timed out

目录 前言 回顾我查到过的解决方案&#xff08;这里是我自己解决时候的经历&#xff0c;赶时间的可以直接跳过看文章最后&#xff0c;快速进行解决&#xff09; 快速解决方案如下 总结 前言 当我们新建一个安卓项目出现Read timed out时候不要慌&#xff0c;这篇文章会打开…