当前位置: 首页 > news >正文

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

对应客户端图形界面:

http://www.lryc.cn/news/319664.html

相关文章:

  • 数据结构的概念大合集02(线性表)
  • CSS3DRenderer, CSS3DSprite API 使用案例demo
  • 河马优化算法(HO)-2024年Nature子刊新算法 公式原理详解与性能测评 Matlab代码免费获取
  • SLAM 算法综述
  • 搭建Hadoop3.x完全分布式集群
  • linux常用命令(二)
  • 【Vue】Request模块 - axios 封装Vuex的持久化存储
  • 【2024第一期CANN训练营】4、AscendCL推理应用开发
  • Rust 构建开源 Pingora 框架可以与nginx媲美
  • MediaCodec源码分析 ACodec状态详解
  • 【Elasticsearch】windows安装elasticsearch教程及遇到的坑
  • 如何快速搭建物联网工业云平台
  • Spring Data访问Elasticsearch----Elasticsearch对象映射
  • Linux之shell循环
  • Python入门教程(一)|基本语法概述
  • Android Studio入门——页面跳转
  • 肝了三天,完成了AIGC工具网站大全,建议收藏再看
  • 算法练习:前缀和
  • Kafka MQ 生产者
  • ​​SQLiteC/C++接口详细介绍之sqlite3类(十)
  • Vue中nextTick一文详解
  • 爱奇艺 CTR 场景下的 GPU 推理性能优化
  • 详解MySql索引
  • struct 和 union 的区别?
  • Linux - 安装 Jenkins(详细教程)
  • 【JAVA】JAVA方法的学习和创造
  • Rust写一个wasm入门并在rspack和vite项目中使用(一)
  • HTTP和HTTPS的区别,HTTPS加密原理是?
  • 基于Spring Boot+Vue的校园二手交易平台
  • 什么是软件开发?软件开发阶段划分是什么?并以LabVIEW为例进行说明