EPICS和Arduino Uno之间基于串行文本协议的控制开发

Arduino Uno的串口服务程序设置如文本的串口通信协议设计以及在Arduino上的应用-CSDN博客中所示。通过在串口上发送约定的文本协议,它实现的功能如下:


实现功能:

  1. 读取三路0.0V~5.0V模拟量输入,读取端口A0~A2
  2. 设置三路0.0V~5.0V的模拟量输出,输出管脚3,5,6
  3. 读取三路数字量输入,读取管脚2,4,7
  4. 设置三路数字量输出,输出管脚8,12,13

协议格式

1)读取三路0.0V~5.0V模拟量输入:

  • 发送:VOLTS:GET?\r\n
  • 接受:VOLTS:GET:2.5:1.5:3.2\r\n

2)设置三路0.0V~5.0V的模拟量输出:

  • 发送:VOLTS:SET:2.1:2.2:3.2\r\n
  • 接受:VOLTS:SET:2.1:2.2:3.2\r\n

3)读取三路数字量输入:

  • 发送:DIGITS:GET?\r\n
  • 接受:DIGITS:GET:1:1:0\r\n

4) 设置三路数字量输出:

  • 发送:DIGITS:SET:1:0:1\r\n
  • 接受:DIGITS:SET:1:0:1\r\n

开发EPICS IOC所需要模块

  • Base
  • asyn
  • stream

1)使用makeBaseApp构建IOC应用程序框架

2)编辑configure/RELEASE添加base,asyn和stream模块所在的路径。

3)编辑arduino/arduinoApp/src下Makefile文件:

# 添加所需数据库定义文件
arduino_DBD += asyn.dbd
arduino_DBD += stream.dbd
arduino_DBD += drvAsynSerialPort.dbd

# 添加所需库文件
arduino_LIBS += asyn
arduino_LIBS += stream

4)在arduino/arduinoApp/Db路径下添加如下文件,

用于字符串收发的解析文件: arduino.proto

# arduino.proto
Terminator = CR LF;

write_dos
{
        out "DIGITS:SET: %(A)d:%(B)d:%(C)d";
}

write_volts
{
        out "VOLTS:SET:%(A).2f:%(B).6f:%(C).2f";
}

read_dis
{
        out "DIGITS:GET?";
        in "DIGITS:GET:%d:%(\$1)d:%(\$2)d";
}

read_volts
{
        out "VOLTS:GET?";
        in "VOLTS:GET:%f:%(\$1)f:%(\$2)f";
}

添加数据库记录文件:

1)bis.db:位输入记录

# bis.db
record (bi, "$(P)$(R)DI0")
{
  field (DTYP, "stream")
  field (ZNAM, "LOW")
  field (ONAM, "HIGH")
  field (INP, "@$(ARDUINO).proto read_dis($(P)$(R)DI1, $(P)$(R)DI2) $(PORT)")
  field (SCAN, ".2 second")
}


record (bi, "$(P)$(R)DI1")
{
  field (ZNAM, "LOW")
  field (ONAM, "HIGH")
}


record (bi, "$(P)$(R)DI2")
{
  field (ZNAM, "LOW")
  field (ONAM, "HIGH")
}

2)bos.db:位输出记录

# bos.db
record(bo, "$(P)$(R)DO0")
{
    field (DESC, "Digital Bit 0")
    field (ZNAM, "LOW")
    field (ONAM, "HIGH")
    field(FLNK, "$(P)$(R)CALCOUTDOS")
}

record(bo, "$(P)$(R)DO1")
{
    field (DESC, "Digital Bit 1")
    field (ZNAM, "LOW")
    field (ONAM, "HIGH")
    field(FLNK, "$(P)$(R)CALCOUTDOS")
}


record(bo, "$(P)$(R)DO2")
{
    field (DESC, "Digital Bit 0")
    field (ZNAM, "LOW")
    field (ONAM, "HIGH")
    field(FLNK, "$(P)$(R)CALCOUTDOS")
}


record (calcout, "$(P)$(R)CALCOUTDOS") {
  field (INPA, "$(P)$(R)DO0")
  field (INPB, "$(P)$(R)DO1")
  field (INPC, "$(P)$(R)DO2")
  field (CALC, "0")
  field (DTYP, "stream")
  field (OUT, "@$(ARDUINO).proto write_dos $(PORT)")
}

3)volts_in.db:模拟量输入记录

# volts_in.db
record (ai, "$(P)$(R)VI0")
{
  field (DTYP, "stream")
  field (INP, "@$(ARDUINO).proto read_volts($(P)$(R)VI1, $(P)$(R)VI2) $(PORT)")
  field (EGU,  "V")
  field (PREC, "2")
  field (SCAN, ".2 second")
}


record (ai, "$(P)$(R)VI1")
{
  field (EGU,  "V")
  field (PREC, "2")
}


record (ai, "$(P)$(R)VI2")
{
  field (EGU,  "V")
  field (PREC, "2")

}

4)volts_out.db:模拟量输出记录

# volts_out.db
record (ao, "$(P)$(R)VO0")
{
    field (DESC, "Set Volt 0")
    field (EGU,  "V")
    field (PREC, "2")
    field (DRVL, "0.00")
    field (DRVH, "5.00")
    field (LOPR, "0.0")
    field (HOPR, "5.00")
    field (FLNK, "$(P)$(R)CALCOUTVOLTS")
}

record (ao, "$(P)$(R)VO1")
{
    field (DESC, "Set Volt 1")
    field (EGU,  "V")
    field (PREC, "2")
    field (DRVL, "0.00")
    field (DRVH, "5.00")
    field (LOPR, "0.0")
    field (HOPR, "5.00")
    field (FLNK, "$(P)$(R)CALCOUTVOLTS")
}


record (ao, "$(P)$(R)VO2")
{
    field (DESC, "Set Volt 2")
    field (EGU,  "V")
    field (PREC, "2")
    field (DRVL, "0.00")
    field (DRVH, "5.00")
    field (LOPR, "0.0")
    field (HOPR, "5.00")
    field (FLNK, "$(P)$(R)CALCOUTVOLTS")
}

record (calcout, "$(P)$(R)CALCOUTVOLTS") {
  field (INPA, "$(P)$(R)VO0")
  field (INPB, "$(P)$(R)VO1")
  field (INPC, "$(P)$(R)VO2")
  field (CALC, "0")
  field (DTYP, "stream")
  field (OUT, "@$(ARDUINO).proto write_volts $(PORT)")
}

将以上文件写入到同一路径下的Makefile中:

...
DB += bos.db
DB += bis.db
DB += volts_out.db
DB += volts_in.db
DB += arduino.proto
...

5) 编辑启动脚本:arduino/iocBoot/iocarduino/st.cmd

...
epicsEnvSet ("STREAM_PROTOCOL_PATH", "$(TOP)/db/")
drvAsynSerialPortConfigure("ARDUINO", "/dev/ttyACM0", 0, 0, 0)
asynSetOption("ARDUINO",0,"baud","9600")
asynSetOption("ARDUINO",0,"parity","none")
asynSetOption("ARDUINO",0,"bits","8")
asynSetOption("ARDUINO",0,"stop","1")

## Load record instances
dbLoadRecords("db/bos.db","P=ARDUINO:,R=CH:,PORT=ARDUINO,ARDUINO=arduino")
dbLoadRecords("db/bis.db","P=ARDUINO:,R=CH:,PORT=ARDUINO,ARDUINO=arduino")
dbLoadRecords("db/volts_out.db","P=ARDUINO:,R=CH:,PORT=ARDUINO,ARDUINO=arduino")
dbLoadRecords("db/volts_in.db","P=ARDUINO:,R=CH:,PORT=ARDUINO,ARDUINO=arduino")
...

6) 回到这个IOC的顶层目录,即arduino,执行make进行编译。

7)进入arduino/iocBoot/iocarduino,启动这个IOC:

../../bin/linux-x86_64/arduino st.cmd

8) 查看加载的记录:

epics> dbl
ARDUINO:CH:CALCOUTDOS
ARDUINO:CH:CALCOUTVOLTS
ARDUINO:CH:DO0
ARDUINO:CH:DO1
ARDUINO:CH:DO2
ARDUINO:CH:VO0
ARDUINO:CH:VO1
ARDUINO:CH:VO2
ARDUINO:CH:DI0
ARDUINO:CH:DI1
ARDUINO:CH:DI2
ARDUINO:CH:VI0
ARDUINO:CH:VI1
ARDUINO:CH:VI2

1、3个数字量输出:ARDUINO:CH:DO0 ARDUINO:CH:DO1 ARDUINO:CH:DO2

2、3个数字量输入:ARDUINO:CH:DI0 ARDUINO:CH:DI1 ARDUINO:CH:DI2

3、3个模拟量输出:ARDUINO:CH:VO0 ARDUINO:CH:VO1 ARDUINO:CH:VO2

4、3个模拟量输入::ARDUINO:CH:VI0 ARDUINO:CH:VI1 ARDUINO:CH:VI2

对应客户端图形界面:

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

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

相关文章

光伏电站信息化管理系统如何优化能源管理

随着可再生能源的快速发展,光伏电站作为其中的重要组成部分,其运营管理面临着越来越多的挑战。为了提升光伏电站的能源管理效率,信息化管理系统成为了不可或缺的工具,那么如何优化能源管理呢? 1.数据实时监控 信息化管…

一站式解决方案:uni-app条件编译及多环境配置,appid动态修改攻略!

前言 这篇文章主要介绍uniapp在Hbuilderx 中,通过工程化,区分不同环境、动态修改小程序appid以及自定义条件编译,解决代码发布和运行时手动切换到问题。 背景 在企业级的应用中,通常会分为,开发、联调、生产等多个环…

GPT-1, GPT-2, GPT-3, InstructGPT / ChatGPT and GPT-4 总结

1. GPT-1 What the problem GPT-1 solve? 在 GPT-1 之前,NLP 通常是一种监督模型。 对于每个任务,都有一些标记数据,然后根据这些标记数据开发监督模型。 这种方法存在几个问题:首先,需要标记数据。 但 NLP 不像 CV&…

从嵌套事务的日志看MyBatis的sqlSession生命周期

service层业务代码 Override public void test(){QueryWrapper<StoreRebateCalculateLog> queryWrapper;queryWrapper new QueryWrapper<>();queryWrapper.eq("delete_flag", 0);//执行查询A,A事务开启List<StoreRebateCalculateLog> storeRebat…

区块链推广海外市场怎么做,CloudNEO服务商免费为您定制个性化营销方案

随着区块链技术的不断发展和应用场景的扩大&#xff0c;区块链项目希望能够进入海外市场并取得成功已成为越来越多公司的目标之一。然而&#xff0c;要在海外市场推广区块链项目&#xff0c;需要采取有效的营销策略和措施。作为您的区块链项目营销服务商&#xff0c;CloudNEO将…

深度学习——SAM(Segment-Anything)代码详解

目录 引言代码目录segment-anything 代码详解build_sam.pypredictor.pyautomatic_mask_generator.py 引言 从去年年初至今&#xff0c;SAM(Segment Anything )已经问世快一年了&#xff0c;SAM凭借其强大而突出的泛化性能在各项任务上取得了优异的表现&#xff0c;广大的研究者…

详解MySql索引

目录 一 、概念 二、使用场景 三、索引使用 四、索引存在问题 五、命中索引问题 六、索引执行原理 一 、概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。暂时可以理解成C语言的指针,文章后面详解 二、使用场景 数据量较大&#xff0c;且…

【图像分割】使用Otsu 算法及迭代计算最佳全局阈值估计并实现图像分割(代码实现与分析)

本实验要求理解全局阈值分割的概念&#xff0c;并实现文本图像分割。需要大家深入理解Ostu 算法的实现过程及其迭代原理&#xff0c;同时通过学习使用Otsu 算法及其迭代&#xff0c;实践图像分割技术在文本图像处理中的应用。 以下将从实验原理、实验实现、实验结果分析三部分对…

老阳视频号带货项目,究竟是一个怎样的选择呢?

近年来&#xff0c;随着网络技术的飞速发展&#xff0c;直播带货已经成为电商行业的新宠。其中&#xff0c;网红老阳以其独特的风格和专业度&#xff0c;成功吸引了大量粉丝的关注&#xff0c;并带动了一波视频号带货的热潮。那么&#xff0c;现在跟随老阳的步伐&#xff0c;投…

sqllab第二十七A关通关笔记

知识点&#xff1a; 双引号闭合union select 大小写绕过 Union Select这里不能进行错误注入&#xff0c;无回显 经过测试发现这是一个双引号闭合 构造payload:id1"%09and%091"1 页面成功回显 构造payload:id0"%09uNion%09SElect%091,2,3%09"1 页面成功…

AI论文速读 | TPLLM:基于预训练语言模型的交通预测框架

论文标题&#xff1a;TPLLM: A Traffic Prediction Framework Based on Pretrained Large Language Models 作者&#xff1a;Yilong Ren&#xff08;任毅龙&#xff09;, Yue Chen, Shuai Liu, Boyue Wang&#xff08;王博岳&#xff09;,Haiyang Yu&#xff08;于海洋&#x…

Mysql 索引、锁与MVCC等相关知识点

文章目录 Mysql锁的类型锁使用MVCC快照读和当前读读视图【Read View】串行化的解决 索引类型存储方式区分逻辑区分实际使用区分索引失效情况 索引建立规范SQL编写规范exlpain字段解析ACID的原理日志引擎慢SQL整合SpringBoot博客记录 Mysql锁的类型 MySQL中有哪些锁&#xff1a…

2024-3-13,14(CSS)

1.复合选择器 有两个或者多个基础选择器&#xff0c;通过不同的方式组合而成。 目的是更加准确高效的选择目标元素&#xff08;标签&#xff09; 分类&#xff1a; 后代选择器&#xff1a;选中某个元素的所有后代元素 写法&#xff1a;父选择器 子选择器 {CSS属性}&#x…

软考高级:软件工程单元测试(驱动模块、被测模块、桩模块)概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

爱奇艺 CTR 场景下的 GPU 推理性能优化

01 背景介绍 GPU 目前大量应用在了爱奇艺深度学习平台上。GPU 拥有成百上千个处理核心&#xff0c;能够并行的执行大量指令&#xff0c;非常适合用来做深度学习相关的计算。在 CV&#xff08;计算机视觉&#xff09;&#xff0c;NLP&#xff08;自然语言处理&#xff09;的模型…

Spring炼气之路(炼气一层)

目录 一、IOC 1.1 控制反转是什么&#xff1f; 1.2 什么是IOC容器&#xff1f; 1.3 IOC容器的作用 1.4 IOC容器存放的是什么&#xff1f; 二、DI 2.1 依赖注入是什么&#xff1f; 2.2 依赖注入的作用 三、IOC案例实现 3.1下载Maven 3.2 配置Maven中的settings.xml文…

考研C语言复习进阶(2)

目录 1. 字符指针 2. 指针数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 4. 函数指针 5. 函数指针数组 6. 指向函数指针数组的指针 7. 回调函数 8.三步辗转法 9. 指针和数组笔试题解析 10. 指针笔试题 指针的主题&#xff0c;我们在初级阶段的《指…

​​SQLiteC/C++接口详细介绍之sqlite3类(十一)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;​​SQLiteC/C接口详细介绍之sqlite3类&#xff08;十&#xff09; 下一篇&#xff1a;​​SQLiteC/C接口详细介绍之sqlite3类&#xff08;十二&#xff09;&#xff08;未发表&#xff09; 33.sq…

JavaWeb07-会话

目录 一、会话跟踪技术 1.概述 2.实现方式 3.Cookie &#xff08;1&#xff09;基本使用 &#xff08;2&#xff09;原理 &#xff08;3&#xff09;存活时间 &#xff08;4&#xff09;存储中文 4.Session &#xff08;1&#xff09;基本使用 &#xff08;2&#x…

C#,图论与图算法,寻找图(Graph)中的桥(Bridge)算法与源代码

1 图(Graph)中的桥(Bridge) 如果删除无向连通图中的边会断开该图的连接,则该边就是桥。对于断开连接的无向图,定义类似,桥接是一种边移除,它增加了断开连接的组件的数量。 与连接点一样,网桥代表连接网络中的漏洞,对于设计可靠的网络非常有用。例如,在有线计算机网…