How to write a counter/timer controller¶
The basics¶
An example of a hypothetical Springfield counter/timer controller will be build incrementally from scratch to aid in the explanation.
By now you should have read the general controller basics chapter. You should be able to create a CounterTimerController with:
- a proper constructor,
- add and delete axis methods
- get axis state
import springfieldlib
from sardana.pool.controller import CounterTimerController
class SpringfieldCounterTimerController(CounterTimerController):
def __init__(self, inst, props, *args, **kwargs):
super(SpringfieldCounterTimerController, self).__init__(inst, props, *args, **kwargs)
# initialize hardware communication
self.springfield = springfieldlib.SpringfieldCounterHW()
# do some initialization
self._counters = {}
def AddDevice(self, axis):
self._counters[axis] = True
def DeleteDevice(self, axis):
del self._counters[axis]
StateMap = {
1 : State.On,
2 : State.Moving,
3 : State.Fault,
}
def StateOne(self, axis):
springfield = self.springfield
state = self.StateMap[ springfield.getState(axis) ]
status = springfield.getStatus(axis)
return state, status
The examples use a springfieldlib
module which emulates a counter/timer
hardware access library.
The springfieldlib
can be downloaded from
here
.
The Springfield counter/timer controller can be downloaded from
here
.
The following code describes a minimal Springfield base counter/timer controller which is able to return both the state and value of an individual counter as well as to start an acquisition:
class SpringfieldBaseCounterTimerController(CounterTimerController):
"""The most basic controller intended from demonstration purposes only.
This is the absolute minimum you have to implement to set a proper counter
controller able to get a counter value, get a counter state and do an
acquisition.
This example is so basic that it is not even directly described in the
documentation"""
def __init__(self, inst, props, *args, **kwargs):
"""Constructor"""
super(SpringfieldBaseCounterTimerController, self).__init__(inst, props, *args, **kwargs)
self.springfield = springfieldlib.SpringfieldCounterHW()
def ReadOne(self, axis):
"""Get the specified counter value"""
return self.springfield.getValue(axis)
def StateOne(self, axis):
"""Get the specified counter state"""
springfield = self.springfield
state = springfield.getState(axis)
if state == 1:
return State.On, "Counter is stopped"
elif state == 2:
return State.Moving, "Counter is acquiring"
elif state == 3:
return State.Fault, "Counter has an error"
def StartAll(self):
self.springfield.start_count()
def StartOne(self, axis, value=None):
"""acquire the specified counter"""
self.springfield.activate_channel(axis)
def LoadOne(self, axis, value):
self.springfield.set_master(axis, value)
def StopOne(self, axis):
"""Stop the specified counter"""
self.springfield.stop(axis)
This code is shown only to demonstrate the minimal controller API. The advanced counter/timer controller chapters describe how to account for more complex behaviour like reducing the number of hardware accesses.
Todo
finish counter/timer controller howto