8000 GitHub - CentralLaserFacility/asynPythonDriver: An asynPortDriver in Python
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

CentralLaserFacility/asynPythonDriver

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

asynPythonDriver

This driver derives from asynPortDriver. By its essence, the parameter value access is delegated to the Python module, provided by user.

Configure

IOC shell command to configure a python port:

/*
 * portName: The name of the asyn port driver to be created.
 * moduleName: The python module to import.
 * numParams: The number of parameters in this driver.
 */
asynPythonDriverConfigure(const char *portName, const char *pythonModule, int numParams)

Note

The last argument numParams can be omitted for asyn 4.32+.

PythonDriver

PythonDriver is a base class that implements the connection between EPICS database and asynPortDriver parameter table. There are two steps for the derived class to define this connection.

Suppose we have an EPICS template file test.template,:

record(ai, "RAND")
{
    field (DTYP, "asynFloat64")
    field (INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))RAND")
    field (PREC, "4")
    field (SCAN, "I/O Intr")
    info  (pyname, "rand")
}

The key is the info (pyname, "rand") field, that defines the variable name which we will refer to in our Python class.

In the Python module test.py, class TestPythonDriver,

import time
import random
import threading
from PythonDriver import PythonDriver

class TestPythonDriver(PythonDriver):
    __db__ = "test.template"
    def __init__(self):
        self.tid = threading.Thread(target=self.simTask)
        self.tid.start()

    def simTask(self):
        while True:
            self.rand = random.random()
            self.update()
            time.sleep(1)

# create an instance
driver = TestPythonDriver()

The __db__ class attribute links Python class to EPICS database. The base class in turn creates class attributes for each records having info (pyname, "") specified. In this example, rand will be accessible just like a normal numeric value. Call base class method update to update the value.

In the startup script,

## add python module paths
epicsEnvSet PYTHONPATH,${TOP}/python:${ASYNPYTHON}/python

...

asynPythonDriverConfigure("PY2", "test", 1)

## Load record instances
dbLoadRecords("${TOP}/db/test.template", "PORT=PY2,ADDR=0,TIMEOUT=1")

Examples

Simulated Oscilloscope

The driver from testAsynPortDriver has been ported. The original EPICS database is copied, with addition of info(pyname,"") fields. Only that the C++ file testAsynPortDriver.cpp has been written in Python scope.py.

cd iocs
make
cd scopeIOC/iocBoot/iocscope
./start_epics

Launch MEDM:

medm -x -macro P=MTEST:,R=SCOPE: testAsynPortDriver.adl

Known Problems

  • For input records, ai, longin, stringin, the SCAN field can only be I/O Intr. That means these records have to be updated by the driver and then call self.update.
  • Each asynPythonDriverConfigure creates a Python sub-interpreter, in order to isolate the modules. And watch out the bug and caveats about sub-interpreter.

About

An asynPortDriver in Python

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 64.2%
  • Python 22.3%
  • Makefile 13.4%
  • Batchfile 0.1%
0