EPICS电机支持(asynMotor)

news2025/1/11 11:15:54

EPICS电机支持

1) 顶层对象是EPICS motor记录

已经对这个对象编写了很多代码:spec,IDL和Python类等

2)下一层是EPICS设备支持

了解motor记录,与驱动会话

3)最底层是EPICS驱动

对motor记录一无所知,与硬件会话

当前推荐的设备和驱动开发框架是asynMotor(模型3)

asynPortDriver用于扩展这个框架用于不被motorRecord支持的硬件特性。

asynMotor(模型3)

1)从2011年,在synApps motor模块中出现。

2)C++模型。

3)两个基类,asynMotorController和asynMotorAxis。

4)基类提供了大部分功能,只需要编写设备相关的实现。

5)易于支持控制器相关的特性。

6)在驱动API中对协同轮廓移动的直接支持。

基于synApps的motor驱动开发

1) synApps motor模块(需要ASYN,BUSY,IPAC和SNCSEQ)

        a) motorRecord($(MOTOR)/motorApp/MotorSrc)

        b) asynMotor设备支持(devMotorAsyn.c)

        c) asynMotor驱动基类

                i) asynMotorController.h, .cpp
                ii) asynMotorAxis.h, .cpp

 

2) Motor驱动代码要实现asynMotor基类的控制器相关方法

        a) <Name>MotorDriver.cpp

        b) <Name>MotorDriver.h

        c) <Name>MotorSupport.dbd

’控制器‘构造器做什么?

1) 创建一个实现了一个'真实'电机控制器的控制器对象(asynPortDriver)。

        电机控制器硬件必须初始化

2)为在'CreateController'参数中,为每个请求的电机通道调用轴数次'Axis'构造器。

3)启动Poller任务,将更新所有电机通道的状态。

4)实现非-motorRecord特性。

  • 用于其它控制器参数的asynPortDriver方法
  • 内建"轮廓移动"(协同多轴)方法

ACRController构造器

在从st.cmd调用iocInit()前:asynMotor.cmd(BCDA标准IOC启动文件)

ACR示例:motor/iocWithAsyn/st.cmd.acr

# portName, asynPort, num of axes, active poll period(ms), idle poll period(ms)

ACRCreateController("ACR1", "ARIES", 1, 20, 1000)

extern "C" int ACRCreateController(const char * portName, const char * ACRPortName, 
        int numAxes,
        int movingPollPeriod,
        int idlePollPeriod)
{
    new ACRController(portName, ACRPortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.)
}

创建一个新的ACRController对象。

参数:

  • [in] portName:将为这个驱动创建的asyn端口的名称。
  • [in] ACRPortName:先前创建的为连接ACR控制器的drvAsynIPPort的名称。
  • [in] numAxes:这个控制器支持的轴数。
  • [in] movingPollPeriod:当任何轴在移动时,轮询之间的时间。
  • [in] idlePollPeriod:当没有轴在移动时,轮询之间的时间。
ACRController::ACRController(const char * portName, 
const char * ACRPortName, int numAxes, double movingPollPeriod, double idlePollPeriod)
: asynMotorController(portName, numAxes, NUM_ACR_PARAMS, asynUInt32DigitalMask,
asynUInt32DigitalMask, ASYN_CANBLOCK | ASYN_MULTIDEVICE, 1, 0, 0)
asynMotorController:asynMotorController(const char * portName,
                                        int         numAxes,
                                        int         numParams,
                                        int         interfaceMask,
                                        int         interruptMask,
                                        int         asynFlags,
                                        int         autoConnect,
                                        int         priority,
                                        int         stackSize
)

 创建一个新的asynMotorController对象。所有参数只是被传递给了asynPortDriver基类的构造器。在调用这个基类构造器后,这个方法创建了在asynMotorDriver.h中定义的电机参数。

ACRController::ACRController(const char * portName, 
const char * ACRPortName, int numAxes, double movingPollPeriod, double idlePollPeriod)
: asynMotorController(portName, 
                      numAxes, 
                      NUM_ACR_PARAMS, 
                      asynUInt32DigitalMask,
                      asynUInt32DigitalMask, 
                      ASYN_CANBLOCK | ASYN_MULTIDEVICE, 
                      1,  // 自动连接
                      0, 0) // 默认优先级和栈尺寸
{
    ...
    // 创建控制器相关的参数
    createParam(ACRJerkString,            asynParamFloat64,    &ACRJerk_);
    createParam(ACRReadBinaryIOString,    asynParamInt32,      &ACRReadBinaryIO_);

    // 连接到ACR控制器
    status = pasynOctetSyncIO->connect(ACRPortName, 0, &pasynUserContorller_, NULL);

     // 关闭命令回送
    sprintf(outString_, "ECHO 4");
    writeController();

    // 创建轴对象
    for (axis = 0; axis < numAxes; axis++){
        new ACRAxis(this, axis);
    }

    startPoller(movingPollPeriod, idlePollPeriod, 2);
}
ACRAxis::ACRAxis(class ACRController * pc, int axisNo)

创建一个ACRAxis对象。

参数:

[in] pC:指向这个轴所属的ACRController的指针

[in]axisNo:这个轴的索引,范围从0到pc->numAxes_-1。

初始化寄存器数目等。

asynStatus asynMotorController::startPoller(double movingPollPeriod,
                                            double indlePollPeriod,
                                            int    forcedFastPolls)

启动这个电机的poller线程。派生类将在它们构造器接近末尾处调用这个方法。派生类一般可以使用这个poller线程的基类实现,但如果需要,可以自动重新实现。

参数:

  • [in] movingPollPeriod:当电机正在运动时,轮询之间的时间。
  • [in] idlePollPeriod:当没有轴运动时,轮询之间的时间。
  • [in] forcedFastPolls:在唤醒这个poller后,执行movingPollPeriod的次数。对于在告诉一个轴已经启动后,不立即报告那个轴正在移动的控制器,这需要非0。

asynMotorController方法ACRController自定义参数

asynStatus ACRController::writeFloat64(asynUser * pasynUser, epicsFloat64 value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;

    ACRAxis * pAxis = getAxis(pasynUser);

    static const char * functionName = "writeFloat64";

    if (function == ACRJerk_){
        sprintf(outString_, "%s JOG JRK %f", pAxis->axisName_, value);
    }
    else{
        /* 调用基类方法 */
        status = asynMotorController::writeFloat64(pasynUser, value);
    }

    /* 进行回调, 因而更高层看到任何变化 */
    pAxis->callParamCallbacks();
}
asynStatus ACRController::writeFloat64(asynUser * pasynUser, epicsFloat64 value)

当客户端调用pasynFloat64->write()时,被调用。

从pasynUser中提取功能和轴编号。在参数库中设置这个值。如果功能时ACRJerk_,它设置控制器中的jerk值。对这个pasynUser->reason和地址,调用任何已注册的回调。对于所有其它功能,它调用asynMotorController::writeFloat64()。

参数:

[in] pasynUser:编码reasone和地址的asynUser结构体。

[in] value:要写的值。

对asynMotorController的重新实现。

asynMotorAxis构造器

创建一个Axis对象,它自定义为一个特定的电机控制器。

1)在控制器硬件中的电机轴必须初始化。

2)根据motorRecord表征motorRecord:GrainSupport, HasEncoder

3)实现提供所有可用motorRecord功能的方法:move,moveVelocity, home, setPosition,...

实现'report'方法

ACRAxis

ACRAxis::ACRAxis(ACRController * pc, int axisNo) : asynMotorAxis(pC, axisNo), pC_(pC)

ACRAxis::ACRAxis(ACRController * pc, int axisNo) 

创建一个新的asynMotorAxis对象。

参数:

[in] pC:指向这个轴所属的asynMotorController的指针。

[in] axisNo:这个轴的索引号,范围从0到pC->numAxies_ - 1。

检查那个pC不是NULL,并且axisNo在有效范围内。在pC->pAxes[axisNo_]中设置一个指向自身的指针。连接pasynUser_为这个asyn端口和axisNo。

asynMotorAxis方法

ACRAxis Move

asynStatus ACRAxis::move(double position,
                         int    relative,
                         double minVelocity,
                         double maxVelocity,
                         double acceleration)

移动电机到一个绝对位置或者通过相对量。

参数:

[in] position:(如果relative=0)移动到绝对位置,或者(如果relative=1)要移动的相对位置。(单位steps)。

[in] relative:表明相对移动(1)或者绝对移动(0)的标记。

[in] minVelocity:初始速度,经常称为基速度。单位=steps/sec。

[in] maxVelocity:最大速度,经常称为回转速度。单位=steps/sec。

[in] acceleration:加速度值。单位=steps/sec/sec。

asynStatus ACRAxis::move(double position, int relative, double minVelocity,
                         double maxVelocity, double acceleration)
{
    sprintf(pc_->outString_, "%s JOG ACC %f", axisName_, acceleration/pulsesPerUnit_);
    status = pC_->writeController();

    sprintf(pc_->outString_, "%s JOG VEL %f",  axisName_, maxVelocity/pulsePerUnit_);
    status = pc_->writeCOntroller();

    if (relative){
        sprintf(pC_->outString_, "%c:%s JOG INC %f", CtlY, axisName_, position/pulsePerUnit_);
        status = pC_->writeController();
    }
    else{
        sprintf(pC_->outString_, "%c:%s JOG ABS %f", CtlY, axisName_, position/pulsesPerUnit_);
        status = pC_->writeController();
    }
}

ACRAxis MoveVelocity

asynStatus ACRAxis::moveVelocity(double minVelocity, double maxVelocity, double acceration)

以固定速度移动电机,直到告诉电机停止。

参数:

[in] minVelocity:初始速度,经常被称为基速度。单位=steps/sec。

[in] maxVelocity:最大速度,经常称为回转速度。单位=steps/sec。

[in] acceration:加速度值。单位=steps/sec/sec。

对来自asynMotorAxis的重新实现。

ACRAxis Poll

asynStatus ACRAxis::poll(bool * moving)

查询这个轴。这个函数读取控制器位置,编码器位置,限位状态,移动状态和驱动上电状态。它为它轮询的每项调用setIntegerParam()和setDoubleParam(),并且接着在末尾调用callParamCallbacks()。

参数:

[out] moving:一个标记,设置它来表明这个轴是移动(1)或者结束(0)。

 

asynStatus ACRAxis::poll(bool * moving)
{
    // 读取当前编码器位置
    sprintf(pC_->outString, "?P%d", encoderPostionReg_);
    comStatus = pC_->writeReadController();
    if (comStatus) goto skip;
    encoderPosition_ = atof(pC_->inString);
    setDoubleParam(pC_->motorEncoderPosition_, encoderPostion);

    // 读取当前标记
    sprintf(pC_->outString_, "?P%d", flagReg_);
    comStatus = pC_->writeReadController();
    if (comStatus) goto skip;
    currentFlag_ = atoi(pC_->inString_);
    done = (currentFlags & 0x1000000) ? 0: 1;
    setIntegerParam(pC_->motorStatusDone_, done);
    * moving = done ? false : true;
        

    // 读取当前状态
    sprintf(pC_->outString, "?P%d", limitsReg_);
    comStatus = pC_->writeReadController();

    if (comStatus) goto skip;

    currentLimits_ = atoi(pC->inString_);
    limit = (currentLimts_ & 0x1) ? 1:0;
    setIntegerParam(pC_->motorStatusHighLimit_, limit);
    limit = (currentLimits_ & 0x2)?1:0;
    setIntegerParam(pC_->motorStatusAtHome_, limit);
    
skip:
    setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1: 0);
    callParamCallbacks();
    return comStatus ? asynError : asynSuccess;
}

ACRAxis Home

asynStatus ACRAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)

移动电机到home位置。

参数:

[in] minVelocity:初始速度,经常称为基速度。单位=steps/sec。

[in] maxVelocity:最大速度,经常称为回转速度。单位=steps/sec。

[in] acceraltion:加速度值。单位=steps/sec/sec。

[in] forwards:表明正(1)反(0)方向移动电机的标记。某些控制器需要被告知方向,另一些直到用哪种方式移动到home。

ACRAxis Report

void ACRAxis::report(FILE *fp, int level)

报告驱动的状态。

参数:

[in] fp:文件指针,报告信息将写入这个文件。

[in] level:详细程度。

如果detail>0,则输出每个轴的信息。在打印控制器相关信息后,调用asynMotorController::report()。

ACRAxis setPosition

asynStatus ACRAxis::setPosition(double position)

设置电机的当前值。

参数:

[in] position:新的绝对电机位置应该被设置到硬件中。Units=Steps。

ACRAxis Stop

asynStatus ACRAxis::stop(double acceleration)

停止电机。

参数:

[in] acceleration:绝对值。单位=steps/sec/sec。

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

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

相关文章

FastJson 漏洞复现

文章目录 FastJson 漏洞复现1. FastJson 1.2.24 反序列化导致任意命令执行漏洞1.1 漏洞描述1.2 漏洞原理1.3 漏洞复现1.3.1 环境启动1.3.2 漏洞检测1.3.3 漏洞验证 1.4 漏洞利用1.5 修复方案 2. Fastjson 1.2.47 远程命令执行漏洞2.1 漏洞描述2.2 漏洞复现2.2.1 环境启动2.2.2 …

SV-315C 15寸触模屏 I3工控机 网络广播主机

SV-315C 15寸触模屏 I3工控机 网络广播主机 智能公共广播系统IP网络广播主机 ※ 高档7U铝合金黑色拉丝面板&#xff0c;美观大方&#xff1b; ※ 嵌入触摸屏和数字矩阵键盘操作集成软件&#xff1b; ※ 工业级机柜式机箱设计&#xff0c;有较高的防磁、防尘、防冲击的能力…

FPGA原理与结构——时钟IP核的使用与测试

一、前言 本文介绍xilinx的时钟IP核 Clocking Wizard v6.0的具体使用与测试过程&#xff0c;在学习一个IP核的使用之前&#xff0c;首先需要对于IP核的具体参数和原理有一个基本的了解&#xff0c;具体可以参考&#xff1a; FPGA原理与结构——时钟IP核原理学习https://blog.c…

[网鼎杯 2020 青龙组]singal详细题解--VMP 直接逆向,angr模拟执行,ponce符号化

文章目录 直接逆向提取opcode获取指令执行流getflag注意 使用Angr使用Ponce插件安装并配置Ponce具体操作 参考资料 直接逆向 提取opcode 主函数并不复杂,关键内容在vm_opcode中,先提取出main函数中的opcode unsigned int OpCode[114] {0x0000000A, 0x00000004, 0x00000010,…

Spring上下文模块ApplicationContextAware

博主介绍:✌全网粉丝3W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

《数字图像处理-OpenCV/Python》连载(6)基于Matplotlib显示图像

《数字图像处理-OpenCV/Python》连载&#xff08;6&#xff09;基于Matplotlib显示图像 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第1章 图像的基本操作 …

软件系统验收测试需要注意的地方

验收测试 一、软件验收测试含义&#xff1a; 软件验收测试是指测试人员检验软件是否符合软件规格说明书和用户需求的测试活动。 验收测试是软件测试的最后一个环节&#xff0c;也是最为关键的一个要素。 它关系到软件开发公司的产品质量&#xff0c;也关系到需求方的产品能…

二分查找[整数二分]

引例 不知道你有没有玩过猜数字游戏,在0到100之间随机选取一个数,让你猜是几,比如这个数是67,如果你猜了50,就会提示你小了,那么你就会去51到100之间猜,你猜了75,就会提示你大了,你就会去51到74之间去猜,就这样一直猜,数字可取的区间越来越小,用不了多久就可以猜出.当你每次都…

SpringBoot如何实现热部署

热部署是软件开发中一个非常有用的功能&#xff0c;它允许我们在不重新启动整个应用的情况下&#xff0c;依旧能够使我们修改的代码生效。 现在Java Web 开发应该都是使用的 SpringBoot&#xff0c;那么本篇文章就来介绍SpringBoot 如何实现热部署&#xff1f; 1、热部署的优点…

如何提取视频中的音频?几个步骤轻松提取

在现今社交媒体的风靡下&#xff0c;许多人都会使用手机录制视频来记录生活中的美好瞬间。有时候&#xff0c;我们也会想要提取视频中的音频&#xff0c;例如将自己的演讲录音分发给听众。本文将会介绍如何在手机上提取视频中的音频以及需要注意的事项。 使用应用程序 首先&am…

Linux Debian12使用git将本地项目上传到码云(gitee)远程仓库

一、注册码云gitee账号 这个可以参考其他教程&#xff0c;本文不做介绍。 gitee官网&#xff1a;https://gitee.com/ 二、Linux Debian12安装git 如果Linux系统没有安装git&#xff0c;可以使用下面命令安装git sudo apt install git 三、gitee新建仓库 我这只做测试&…

实现分别在Linux、Docker、Kubernetes上安装部署Mysql、Redis、Nginx软件

目录 实现目的&#xff1a; Linux上一键安装Mysql、Nginx、Redis软件 一键安装Mysql脚本 一键安装Redis脚本 一键安装Nginx脚本 docker上安装部署Mysql、Nginx、Redis容器 Kubernetes上安装部署Mysql、Nginx、Redis的Pod和通过Service发布 创建Pod生成容器 使用Servic…

时间序列论文-聚类和异常检测(二)

同样摘自知乎的回答&#xff1a;https://www.zhihu.com/question/29507442/answer/1212624591?utm_id0 正巧之前做过时间序列 的异常检测项目&#xff0c;这里介绍几种尝试过的方法&#xff0c;也算是抛砖引玉 吧&#xff0c;欢迎大家讨论交流~ 背景与定义 时间序列异常 检测…

c++实现数据结构栈和队列

1、栈 头文件 #ifndef ZHAN_H #define ZHAN_H#define MAX 8 #include <iostream> using namespace std;class Shu {int datatype; //入栈的数据int *arr; //栈的数组int top; //记录栈顶元素的下标public://构造函数Shu();//析构函数~Shu();//判断空int stack_empty…

COSCon'23 Call for Speakers

一年一度的开源盛会&#xff0c;COSCon23 第八届中国开源年会&#xff0c;将于10月28~29日&#xff0c;在四川成都市高新区菁蓉汇召开&#xff01; The yearly open source event, COSCon23 8th Annual China Open Source Conference, will be taken place on 28th~29th Octobe…

【编码魔法师系列_构建型1.1】简单工厂模式(Static Factory)

学会设计模式&#xff0c;你就可以像拥有魔法一样&#xff0c;在开发过程中解决一些复杂的问题。设计模式是由经验丰富的开发者们&#xff08;GoF&#xff09;凝聚出来的最佳实践&#xff0c;可以提高代码的可读性、可维护性和可重用性&#xff0c;从而让我们的开发效率更高。通…

让照片动起来的软件,轻松制作照片动效

随着社交媒体的日益普及&#xff0c;我们对于照片的要求也越来越高。普通的照片已经不能满足我们的需求&#xff0c;我们希望照片更加生动有趣。照片动效便应运而生&#xff0c;它可以让照片动起来&#xff0c;吸引更多的注意力&#xff0c;让照片更加生动有趣。 照片动效制作起…

软件验收测试

1. 服务流程 验收测试 2. 服务内容 测试过程中&#xff0c;根据合同要求制定测试方案&#xff0c;验证工程项目是否满足用户需求&#xff0c;软件质量特性是否达到系统的要求。 3. 周期 10-15个工作日 4. 报告用途 可作为进行地方、省级、国家、部委项目的验收&#xff0…

Java-华为真题-预定酒店

需求&#xff1a; 放暑假了&#xff0c;小王决定到某旅游景点游玩&#xff0c;他在网上搜索到了各种价位的酒店&#xff08;长度为n的数组A&#xff09;&#xff0c;他的心理价位是x元&#xff0c;请帮他筛选出k个最接近x元的酒店&#xff08;n>k>0&#xff09;&#xff…

JavaScript中的Generator函数及其使用方式

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Generator函数⭐ 创建Generator函数⭐ 调用Generator函数⭐ Generator函数的应用1. 异步编程2. 生成器&#xff08;Generator&#xff09; ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧…