Device Controller Level

Overview

device level block diagram

The device level code consists of three major modules(green shaded blocks)

  • data acquisition device level module (terminal based)

  • Channel Access server modules

  • Graphical user interface (PyEpics based)

and two auxiliary modules(blue shaded blocks). The red shaded block is the must dependency without which the device level will simply not run. The driver module can be either real module that connected to a real device or a mock driver that simulates the performance of a real device, see driver section for details. The System Level red shaded block is only one client allowed to connect under normal operating conditions.

Data acquisition device level

Data acquisition device level module interacts with the DATAQ-4108 via Python based driver. The module is responsible to retrieve data from the DI-4108 buffer and put it in its’ own buffer. The data acquisition module passes digital inputs to the DI-4108. The data acquisition module uses two structures (TODO) and (TODO) to interact with the Channel Access server. The data acquisition server publishes new values (PVs or Process Variables) to a special dictionary that is available to Channel Access module. The acquisition server checks special process variable input dictionary to see if there are any commands that need to be processed.

Data Acquisition Loop

data acquisition loop

Channel Access server

The CA server is based on CAProto library which allows to create channel access servers. The server interacts with device level via two specialized inputoutput queues (dictionary like). The server checks on a timer if there is anything to do in the input queue and publishes any updates to the output queue if data need to be send to the device level data acquisition module.

Graphical User interface

PyEpics based graphical user interface.

Device Level

Start by importing analysis submodule for Icarus Pressure Jump for NMR .

from icarus_nmr.device_daq import Device
device = Device()

To import the mock driver instead of actual driver for the DI-4108

from icarus_nmr.driver_mock import Driver
driver = Driver()

Next step is to bind the device instance with appropriate driver.

device.bind_driver(driver)
device.init()

After the driver is bound, the device instance will use it for all communication with the device (or with the emulator).

device.bind_driver(driver)
device.init()

You can peek into the device queue with functions inside of the Queue object.

data = device.queue.peek_all()

from matplotlib import pyplot as plt
plt.figure()
plt.plot(data[:,5]) #will show sample pressure readings.

Device Level Client

There is a client associated with the Device level code but it interferes with the normal operation of the system and has to be used only for debugging.

cd /icarus_nmr
ipython3
run device_client.py
client.get_all()

Note, the server has to be running before client can access any process variables(PVs).

Device Level Server

The process variables(PVs) associated with the device level server are:

two main PVs:

  • data - next packet of data in the queue (read Only)

  • dio - digital input (Write Only)

  • queue_length

  • packet_shape

auxiliary PVs:

  • response - packet size

  • serial_number - driver/device serial number

  • frequency - data collection frequency

  • firmware - firmware

  • pressure_sensor_offset - eight integer long array of numbers that offset the sensors

Device Level Script

class icarus_nmr.device_daq.Device[source]
property DIO

get digital state from data queue

bind_driver(driver=None)[source]

bind driver to device instance

config_DIO(value='00000000')[source]

configure direction of digital IOs. It takes a string with 8 characters, ‘0’ or ‘1’ where ‘0’ - ‘1’ -

Parameters
value :: string

Examples

>>> device.config_DIO('00000000')
config_DL(baserate=None, dec=None, DOI_config=None, DOI_set=None)[source]

configure analog and digital channels, and rate via baserate and dec.

Parameters
value :: string

Examples

>>> device.config_DL(baserate = 20000, dec = 5, DOI_config = '1111111',DOI_set = '1111111')
first_time_setup()[source]

set control variables to factory settings

get_DIO()[source]

get digital state from data queue

init()[source]

initialize the DL program

io_pull(io_dict)[source]

a wrapper that takes care of ‘read’ command in the io module

Parameters
io_dict :: dictionary

a key-value pairs

Returns
——-

Examples

>>> self.io_pull(io_dict = {'key':'value'})
io_push(io_dict=None)[source]

a wrapper that takes care of write command to the io module

Parameters
io_dict :: dictionary

a string name of the variable

Examples

>>> self.io_push()
kill()[source]

Orderly self-destruction. kills all threads and deletes the instance.

Examples

>>> device.kill()
parse_binary(value=0)[source]

takes an integer and converts it to 8 bit representation as an array. If float number is passed, it will be converted to int.

property pg_delay_width

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pg_depre_pulse_width

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pg_period

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pg_pre_pulse_width

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_AI_channels

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_DI_channels

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_DOI_config

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_DOI_set

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_baserate

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_dec

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_os_buffer

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_packet_buffer_size

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_packet_size

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_rate

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
property pr_serial_number

serial number, five character long string

property pressure_sensor_offset

getter for SavedProperty. returns saved value if it exists in the database, otherwise returns default_value

Parameters
name :: (string)

name of the entry in the database.

Returns
value :: (object)

returns a value stored with the selected key in the database

Examples

>>>
run()[source]

This is a main fuction that will execute run_once function on the while running loop. Usually it gets submitted to a separate thread.

This function collects data and puts it in the Ring Buffer. It is run in a separate thread(See main priogram)

Examples

>>> device.run()
run_once()[source]

the repeated block executed in while running loop in the main run() thread

Examples

>>> device.run_once()
set_DIO(value='00000000')[source]

set digital input/output state

Parameters
value :: string

Examples

>>> device.DIO = 127
set_outside_DIO(value='00000000')[source]

sets digital input/output state

Parameters
value :: string

Examples

>>> device.DIO = 127
set_pressure_sensor_offset(dt=3)[source]

set pressure sensor offset

start()[source]

Create a new thread and submits self.run for execution

Examples

>>> device.start()
stop()[source]

Orderly stop of the device code. - stops data acquisiion - erases all data from USB buffers - set digital IO to all high - closes usb port connection

Examples

>>> device.stop()
unparse_binary(arr=array([1, 1, 1, 1, 1, 1, 1]))[source]

takes an integer and converts it to 8 bit representation as an array. If float number is passed, it will be converted to int.