EPICS和Arduino Uno之间基于串行文本协议的控制开发
Arduino Uno的串口服务程序设置如文本的串口通信协议设计以及在Arduino上的应用-CSDN博客中所示。通过在串口上发送约定的文本协议,它实现的功能如下:
实现功能:
- 读取三路0.0V~5.0V模拟量输入,读取端口A0~A2
- 设置三路0.0V~5.0V的模拟量输出,输出管脚3,5,6
- 读取三路数字量输入,读取管脚2,4,7
- 设置三路数字量输出,输出管脚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
对应客户端图形界面:
相关文章:

EPICS和Arduino Uno之间基于串行文本协议的控制开发
Arduino Uno的串口服务程序设置如文本的串口通信协议设计以及在Arduino上的应用-CSDN博客中所示。通过在串口上发送约定的文本协议,它实现的功能如下: 实现功能: 读取三路0.0V~5.0V模拟量输入,读取端口A0~A2设置三路0.0V~5.0V的模…...

数据结构的概念大合集02(线性表)
概念大合集02 1、线性表及其逻辑结构1.1 线性表的定义1.2 线性表的基本操作 2、线性表的顺序存储结构2.1 顺序表 3、线性表的链式存储3.1 链表3.1.1 头结点(头指针),首指针,尾指针,尾结点3.1.2 单链表3.1.3 双链表3.1.…...
CSS3DRenderer, CSS3DSprite API 使用案例demo
CSS3DRenderer, CSS3DSprite API 使用案例demo <!DOCTYPE html> <html><head><title>three.js css3d - sprites</title><meta charset"utf-8"><meta name"viewport" content"widthdevice-width, user-scalabl…...

河马优化算法(HO)-2024年Nature子刊新算法 公式原理详解与性能测评 Matlab代码免费获取
声明:文章是从本人公众号中复制而来,因此,想最新最快了解各类智能优化算法及其改进的朋友,可关注我的公众号:强盛机器学习,不定期会有很多免费代码分享~ 目录 原理简介 一、种群初始化 二、河马在河流或…...

SLAM 算法综述
LiDAR SLAM 其主要思想是通过两个算法:一个高频激光里程计进行低精度的运动估计,即使用激光雷达做里程计计算两次扫描之间的位姿变换;另一个是执行低频但是高精度的建图与校正里程计,利用多次扫描的结果构建地图,细化位…...

搭建Hadoop3.x完全分布式集群
零、资源准备 虚拟机相关: VMware workstation 16:虚拟机 > vmware_177981.zipCentOS Stream 9:虚拟机 > CentOS-Stream-9-latest-x86_64-dvd1.iso Hadoop相关 jdk1.8:JDK > jdk-8u261-linux-x64.tar.gzHadoop 3.3.6&am…...
linux常用命令(二)
目录 前言 常用命令 1.ls命令 2. cd命令 3.pwd命令 4.mkdir 命令 5. rmdir 命令 6.rm 命令 7.cp命令 8.mv命令 9.touch命令 10.cat命令 11.more命令 12.less命令 13.head命令 14.tail命令 15.tail命令 16.find命令 17.tar命令 18.gzip命令 19.gunzip命令 …...

【Vue】Request模块 - axios 封装Vuex的持久化存储
📝个人主页:五敷有你 🔥系列专栏:Vue ⛺️稳中求进,晒太阳 Request模块 - axios 封装 使用axios来请求后端接口,一般会对axios进行一些配置(比如配置基础地址,请求响应拦截器…...

【2024第一期CANN训练营】4、AscendCL推理应用开发
文章目录 【2024第一期CANN训练营】4、AscendCL推理应用开发1. 创建代码目录2. 构建模型2.1 下载原始模型文件2.2 使用ATC工具转换模型2.3 注意事项 3. 模型加载3.1 示例代码 4. 模型执行4.1 获取模型描述信息4.2 准备输入/输出数据结构4.3 执行模型推理4.4 释放内存和数据类型…...

Rust 构建开源 Pingora 框架可以与nginx媲美
一、概述 Cloudflare 为何弃用 Nginx,选择使用 Rust 重新构建新的代理 Pingora 框架。Cloudflare 成立于2010年,是一家领先的云服务提供商,专注于内容分发网络(CDN)和分布式域名解析。它提供一系列安全和性能优化服务…...

MediaCodec源码分析 ACodec状态详解
前言 本文分析ACodec状态机,ACodec是MediaCodec的底层实现,在MediaCodec命令下切换不同状态进行编解码,基于7.0代码。 ACodec状态介绍 UninitializedState:未初始化状态。 在业务层调用MediaCodec. createByCodecName 完成后切换到LoadedState。 LoadedState:表示解码器…...

【Elasticsearch】windows安装elasticsearch教程及遇到的坑
一、安装参考 1、安装参考:ES的安装使用(windows版) elasticsearch的下载地址:https://www.elastic.co/cn/downloads/elasticsearch ik分词器的下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases kibana可视化工具下载…...

如何快速搭建物联网工业云平台
随着物联网技术的快速发展,物联网工业云平台已经成为推动工业领域数字化转型的重要引擎。合沃作为专业的物联网云服务提供商,致力于为企业提供高效、可靠的物联网工业云平台解决方案。本文将深入探讨物联网工业云平台的功能、解决行业痛点的能力以及如何…...
Spring Data访问Elasticsearch----Elasticsearch对象映射
Spring Data访问Elasticsearch----Elasticsearch对象映射 一、元模型(Meta Model)对象映射1.1 映射注解概述1.1.1 控制向Elasticsearch写入和从其读取哪些属性1.1.2 日期格式映射1.1.3 Range类型1.1.4 映射的字段名1.1.5 Non-field-backed属性1.1.6 其他属性注解 1.2 映射规则1…...

Linux之shell循环
华子目录 for循环带列表的for循环格式分析示例shell允许用户指定for语句的步长,格式如下示例 不带列表的for循环示例 基于C语言风格的for循环格式示例注意 while循环格式示例 until循环作用格式示例 循环控制breakcontinue详细语法示例 循环嵌套示例 for循环 for循…...
Python入门教程(一)|基本语法概述
目录 1. 注释 2. 变量和数据类型 3. 控制流 4. 函数 5. 类与对象 6. 异常处理 7. 模块和包 8. 文件操作 1. 注释 在Python中,单行注释以#开始,多行注释使用三个引号 """ 或 。 # 这是单行注释""" 这是 多行 注释…...

Android Studio入门——页面跳转
1.工程目录 2.MainActivity package com.example.demo01;import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCo…...

肝了三天,完成了AIGC工具网站大全,建议收藏再看
说是肝了三天,其实远远不止,前前后后,从资料搜集到最后整理成文,有近一个月了,大家看在整理不易的份上,给点个赞吧,不要光顾着收藏呀! 国内网站 AIGC 导航 https://www.aigc.cn 网…...

算法练习:前缀和
目录 1. 一维前缀和2. 二维前缀和3. 寻找数组中心下标4. 除自身以外数组的乘积5. !和为k的子数字6. !和可被k整除的子数组7. !连续数组8. 矩阵区域和 1. 一维前缀和 题目信息: 题目链接: 一维前缀和思路:求前缀和数组,sum dp[r] …...

Kafka MQ 生产者
Kafka MQ 生产者 生产者概览 尽管生产者 API 使用起来很简单,但消息的发送过程还是有点复杂的。图 3-1 展示了向 Kafka 发送消息的主要步骤。 我们从创建一个 ProducerRecord 对象开始,ProducerRecord 对象需要包含目标主题和要发送的内容。我们还可以…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...

Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...

macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...