EPICS使用有限状态机创建一个计时器

本实例演示了如何使用有限状态机创建一个计时器的完成过程:

状态机源文件为:

#define PVSYS    "pvsys=ca"
program seqCmdBtns(PVSYS)

option -c;  /*  不等待pv连接.   */
option +r;  /*  允许多个实例   */

/* 定义变量,连接通道 */
short   startBtn;
assign  startBtn to "{P}:Start";
monitor startBtn;

short   stopBtn;
assign  stopBtn to "{P}:Stop";
monitor stopBtn;

int     countsEntry;
assign  countsEntry     to "{P}:CountSet";

string  seqMsg;
assign  seqMsg to "{P}:SeqMsg";

float   period;
assign  period to "{P}:Period";

int counter;

ss seqCmdBtns{
        state init{
                when (pvConnectCount() == pvChannelCount()){
                        printf("seqCmdBtns: All channels connected\n");
                        sprintf(seqMsg, "Ready for counting!");
                        pvPut(seqMsg);
                } state idle
        }

        state idle{
                when (pvConnectCount() < pvChannelCount()){
                        printf("seqCmdBtns: Lost pv connection\n");
                        sprintf(seqMsg, "Lost connection");
                        pvPut(seqMsg);
                } state init

                when (startBtn){
                        sprintf(seqMsg, "0 counts");
                        pvPut(seqMsg);
                        pvGet(countsEntry);
                        if (countsEntry <= 0 || countsEntry > 1000){
                                countsEntry = 10;
                                pvPut(countsEntry);
                        }

                        pvGet(period);
                        printf("Sleep Period: %3.1f\n", period);
                } state start

                when (stopBtn){
                        stopBtn = 0;
                        pvPut(stopBtn);
                } state idle
        }

        state start{
                when (startBtn){
                        for (counter = 1; counter <= countsEntry; counter++){
                                if (stopBtn){
                                        stopBtn = 0;
                                        pvPut(stopBtn);
                                        break;
                                }
                                else{
                                        epicsThreadSleep(period);
                                        sprintf(seqMsg, "%d counts", counter);
                                        pvPut(seqMsg);
                                }
                        }

                        startBtn = 0;
                        pvPut(startBtn);
                } state idle
        }
}

记录数据库源文件为:

record(bo, "$(P)Start") {
    field(DESC, "Start counter")
    field(ZNAM, "Ready")
    field(ONAM, "Start")
}

record(bo, "$(P)Stop") {
    field(DESC, "Stop counter")
    field(ZNAM, "Ready")
    field(ONAM, "Abort")
}

record(longout, "$(P)CountSet"){
    field(DESC, "Set the Count Range")
    field(DOL,  "10")
}

record(mbbo, "$(P)PeriodOption")
{
    field(DESC, "Set the Count Period")
    field(DTYP, "Raw Soft Channel")
    field(NOBT, "2")
    field(ZRVL,"1")
    field(ONVL,"3")
    field(TWVL,"5")
    field(THVL,"10")
    field(ZRST,"0.1 Second")
    field(ONST,"0.3 Second")
    field(TWST,"0.5 Second")
    field(THST,"1.0 Second")
    field(FLNK, "$(P)Period")
}

record(calc, "$(P)Period")
{
   field(INPA, "$(P)PeriodOption.RVAL")
   field(CALC, "0.1 * A")
}


record(stringout, "$(P)SeqMsg") {
    field(DESC, "Message box from seq")
}

启动脚本文件为:

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

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

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/seqcmd.dbd"
seqcmd_registerRecordDeviceDriver pdbbase

## Load record instances
dbLoadRecords("db/seqcmd.db","P=CmdSeq:")

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

## Start any sequence programs
seq &seqCmdBtns,"P=CmdSeq"

启动这个IOC程序,并且查看加载的记录:

root@orangepi5:/usr/local/EPICS/program/seqcmd/iocBoot/iocseqcmd# ../../bin/linux-aarch64/seqcmd st.cmd
#!../../bin/linux-aarch64/seqcmd
< envPaths
...
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.7
## Rev. 2023-05-26T09:07+0000
## Rev. Date build date/time:
############################################################################
iocRun: All initialization complete
## Start any sequence programs
seq &seqCmdBtns,"P=CmdSeq"
sevr=info Sequencer release 2.2.8, compiled Mon May 29 11:45:00 2023
sevr=info Spawning sequencer program "seqCmdBtns", thread 0x558bc49fb0: "seqCmdBtns"
seqCmdBtns: All channels connected
epics> dbl
CmdSeq:Start
CmdSeq:Stop
CmdSeq:Period
CmdSeq:CountSet
CmdSeq:PeriodOption
CmdSeq:SeqMsg

CSS客户端文件:

EPICS使用有限状态机创建一个计时器_第1张图片

这个IOC程序具有以下功能:

1)count set设置计数量。

2)count period可以有4个选项,可以设置计数之间的时间间隔;可以设置的间隔为0.1s, 0.3s, 0.5s和1.0s。

3)按下start按钮,开始Counter开始计数,计数直到达到count set中设置的值或者按下Stop按钮时停止。 

你可能感兴趣的:(EPICS教程,EPICS)