EPICS NI driver

*** This is the original documentation, so install instructions will be out of date; however usage instructions are still valid ***

*** The driver now uses DAQ-mx rather than DAQ-mxBase library ***

Installing

The driver works with DAQmxBase (version 2.1) It supports RedHat, Suse and Mandrake.

You need to install 2 rpms and then DAQmxBase from the CD.
Download 2 rpms and cd here

Use rpm -i command to install rpms.
Then mount the cd with “mount -o loop”
cd to nivisa folder first.
Run the INSTALL script and answer YES to everything
Then goto the root cd folder.
Run the INSTALL script there and answer YES to everything.

Now restart your PC. (YES you need to RESTART linux - stupid drivers)
now goto /usr/local/natinst/nidaqmxbase/bin
run lsdaq
you’re suppose to see a list of the NI cards detected.
If the cards not there it will not work.

If the card is listed the EPICS stuff might work.
Remember to rerun lsdaq everytime you change the cards in the PC.

Notes - SUSE

To get DAQmx to install:
in: /lib/modules/2.6.16.13-4-smp/source/include/asm
do: ln -s asm-offsets.h asm_offsets.h
else the kernel configure doesn’t work

To compile medm ect on SUSE:
copy /usr/include/Xm/* from ubuntu into SUSE
ln -s libXm.so.3 libXm.so (/usr/X11R6/lib/)

EPICS ASYN driver

Overview

This driver can work with most of the NI cards.

Current features:

  • DAQ modes: Analog Input, Analog Output, Binary Input, Binary Output , Counter Output , Counter Input
  • Configuration only limited by NI drivers
  • I/O Interrupts or interval-SCAN modes available
  • Supports NI Analog and Digital Triggering
  • Many usefull IOC commands
  • Most options can be changed/set with IOC commands and/or records
  • Can be used with standard record
  • Signal Generator functions
  • Software trigger mode
  • ASYN trace - for debugging

It works with the DAQmxBase drivers. This is a major problem. But it is currently the best solution.

Any further questions can be sent to Heinrich du Toit

SVN

This driver is being together with DIAMOND light source.

Main person there responsible is Ulrik Pederson (ulrik.pederson@diamon.as.uk)

Browse SVN repository http://epics.svn.sourceforge.net/viewvc/epics/applications/trunk/DAQmxBase/

checkout svn: svn co https://epics.svn.sourceforge.net/svnroot/epics/applications/trunk/DAQmxBase

You will need special previliges on sourceforge if you want to commit to this repository.
email heinrichdt@tlabs.ac.za for more details.

ASYN module

module name: drvDaqMxBase
sourcefile: drvDaqMxBase.c
header file required: NIDAQmxBase.h
dbd file: DAQmxBaseSupport.dbd

See Makefile if you want to add this to some other IOC.

See startup scripts under iocBoot/iocDAQmxBase for how to load the driver ect.
Commands explained below

DAQmx IOC commands

DAQmxBaseConfig (portName, deviceName, Channelnr, acqType, options)
portName - ASYN port name to create or to add to
devicename - NI device name (e.g. dev1/ai0)
Channelnr - Channelnr inside ASYN port (start with 0)
acqType - “AI” ,”AO”, “BI”, “BO” or “COUNTER”
options - see DAQmx Port Options

DAQmxReset (DeviceName)
Currently this doesn’t work - think NI library is bugged

DAQmxChangeDeviceName (portname, channelnr, newdevicename)
Use this at run-time to change the devicename of a port

DAQmxPortOptions (portname, channelnr, options)
Use to add or override options given to a specific port/channel

DAQmxGen and DAQmxGenP
See Signal Generation

DAQmxTrigger (portName, triggerSource, TriggerOptions)
Use this to enable trigger on a port
portname - ASYN port name
triggerSource - NI trigger Source
TriggerOptions - see DAQmx Port Options

DAQmxStart (portname)
Starts sampling on a ASYN port

DAQmx Port Options

These are all options given to the IOC commands DAQmxBaseConfig,DAQmxPortOptions or DAQmxTrigger

Terminal

To set the temination of the input type specify 1 of:
TerminalDef - Default
TerminalRSE
TerminalNRSE
TerminalDiff - Differential

Read Mode

The default mode is a non-monster continuous mode. In the default mode the driver will read the card as fast as it can. But it will stil stop and start the NI task every time. And it will use limited sampling mode when setting up the task. The problem is that if we put the card in continuous sampling and the driver can’t read the samples fast enough then a buffer overflow happens in side the driver.

The second mode is single-shot mode. In this mode the driver only reads the NI card when asked to. This will be done if the interface is read. A record setup with SCAN = “x second(s)” is usually used for this mode.

The last mode is Monster mode. In this mode continuous sampling is used and the driver will need to read the data from the NI card faster than sampling is done. 2 ways to assure this is to choose a slower sampling rate or to get a faster pc.

The options:
Continuous - default
OneShot
MONSTER

Trigger Options

Edge options:
TriggerRising
TriggerFalling

The Rising/Falling options will enable triggering - one of them must be specified.

Type options:
TriggerDig - Digital triggering
TriggerAnlg - Analog triggering

Other:
T=level - Trigger level (only for Analog triggering)
p=presamples - Number of Pre-samples

Soft Trigger Options

S=mode - Soft trigger mode
0 - no soft triggering - default
1 - Soft trigger on first sample higher than triggerlevel
2 - Soft trigger on first sample lower than triggerlevel
3 - Soft trigger on rising edge going past triggerlevel
4 - Soft trigger on falling edge going past triggerlevel

s=soft trigger channel number

In soft triggering you can use the pre-samples option also. If presamples=x then soft trigger will only trigger within the first x samples and not look further.

Soft trigger is still pretty much experimental. Only supported for Analog Input.

Counter options

For COUNTER (In) you must specify one of:
CIPeriod
CICountEdges
CIPulseWidth

IdleLow, IdleHigh - set Idle state - default = low
CountRising, CountFalling - edge option
CountUp, CountDown, CountExt - counting direction
CReadF64, CReadScalarF64, CReadScalarU32, CReadU32 - counter read modes overrrides

D=DutyCycle
d=delay (initial delay with counter)

Also uses F and N (see below)

Task options

m=min volts
M=max volts
F=Frequency of sampling
N=number of samples

C=clocksource (e.g. C=/Dev1/PFIO) default=OnBoardClock

Notes

Some cards (like the NI-622x cards) have internal ctrx channels.
You can in theory setup an internal counter on these to generate clock output and use that to driver a binary output signal
As in these cards OnBoardBlock doesn’t work.
(COUNTER not yet implemented - sorry)

Signal Generation

The signal generation functions is for Analog Output only. Everything is done with the DAQmxGen IOC command.

The signal generation works in an add-only principle. This means that every call to DAQmxGen will only add to/modify the signal and will not clear it unless specifically asked todo that. This way multiple calls to DAQmxGen can be made to build up fairly complex signals.

DAQmxGen

DAQmxGen(portName, Channelnr, params)
portName - Asyn port name - already created
Channelnr - Channelnr on which to run Generations
params - see below

DAQmxGenP(params)
This function wil call DAQmxGen with the previously used PortName and Channelnr
This is simply to make interactive commands easier in the IOC as you don’t need to specify the portName and Channelnr everytime.

Params

First you need to specify a Generate options. (The are listed below) This will tel DAQmxGen what type of function to add to the signal. Then you need to specify the parameters for that options. (Only 1 option per DAQmxGen call!)

The parameters are A through Z.
Simple specify A=value or C=value ect.
all value’s are floating point number - but some will be converted to integers depening on the generation option.

If a parameter is not specified a default value is used. Parameters must be specified after the generation options is given in the params string given to DAQmxGen.

clear

This is a special option as it can be specified together with the other options as to tell DAQmxGen to clear the signal before generation. It will make all samples inside the signal 0. You will need to specify this option probably the first time - as signals aren’t zero’d at startup.

block

Adds a block function.
A = number of samples at top
B = number of samples at bottom
C = Top Volts
D = Bottom Volts

Random

Adds random noise
A = max (default = 1) B = min (default = -1) C = number of levels between min and max (default=255) D = Seed if non-zero

Triangle

Adds a triangle/saw function
A = Height (peek-to-peek) of triangle (def: 5)
B = Centre of triangle (def:0)
C = delta Volts per sample for upwards slope
D = delta Volts per sample for downwards slope
(C and D > 0) - if C or D = 0 then the upwards edge is immediate (ie. no slope)
(C and D default = 0.1) E = Number of samples stationary at top
F = Number of samples stationary at bottom
(E and F default = 0)

Offset

Adds an Offset
A = volts

Sin

Adds a sinusoidal wave
A = Radiants per samples (def: 0.1)
B = Amplitude (def: 2)
C = Offset (def: 0)
D = Starting radiants (def:0)

RemoveOffset

Removes Offset from waveform

block2

Adds a single block into the waveform
A = starting sample number of block
B = number of samples the block will be
C = height of block (def:2) - can be negative also

Pulse

Adds a pulse to the waveform - used for scanner simulation
A = centre samples number of pulse
B = Amplitude (negative number allowed for inverse pulse)
C = Gravity factor (default: 0.7) - A smaller number will result in faster down fall on left and right of pulse

SmoothRandom

Adds “Smooth” random noise
A = max volts
B = min volts
C = max delta between 2 samples (noise factor - not resulting signal)
D = seed if non-zero

StartEndMatch

This will modify the start and end of the signal so they will meet each other.
Will try todo this smoothly
A = maximum rate of change. - A higher number will allow more drasting changes but a lower number will result in more samples being changed.

smooth

Will smooth the function as in not permitting fast changes between samples
A = maximum delta volts allowed between 2 samples

filter

Filters the function - very simple/stupid filter
A = filter (higher = more filtering) default = 4

buldge

Adds a “Buldge” to the waveform - also used for scanner simulation
A = Centre of buldge
B = Width of buldge
C = Amplitude of buldge (can be negative)

clearregion

Smoothly clears a region by removing everything between start and end and replacing it with a smooth “line”.
A = start sample number
B = end sample number
If B < A it will roll-around the end of the signal.

Scale

Will scale the samples
A = Scale factor
B = starting samples number (def:0)
C = ending samples number (def:0)
By default it will scale everything

House keeping

After generation the function will print out the difference in voltage between the first and last sample.

No effort is made to keep voltages within allowed limitations.

Digital Generation

If DAQmxGen is called on a BO signal then the params is ignored and a simple counter pattern is inserted. Starting with value 0 in samples 0 and counting onwards.

DAQ modes and Setting Up Tasks

Overview

There are 6 DAQ mode options available: AI, AO, BI, BO, COUNTER, CO

The driver creates a port per task. And then uses addresses for the channels inside the task. A task can have only 1 DAQ mode. So all channels in a given task must be the same type.

A task can also have clock options and trigger options.

Normally a task setup is done with DAQmxBaseConfig IOC commands. Then afterwards records are connected to the signals/channls inside this task/port.

task/port confusion?
In NI terms they are called tasks. But in EPICS there is an ASYN port for every task. So for the purpose of this driver the terms are almost interchangable.

signal/channel confusion?
Same as above. In IN terms a task has 1 or more channels. In ASYN a port has 1 or more signal differentiated by integer numbers called addresses.

examples

In the folder iocBoot/iocDAQmxBase there is many different startup scripts for the IOC that will do different setups. Please look at them for examples of how todo things.

Analog Input

This is when you want to read in analog signals.

You can have a maximum of 1 AI task. But this 1 task can have more than 1 Analog input channel.

All channels will have the same sampleRate. And the number of Samples per channel is fixed for the task.

e.g.
DAQmxBaseConfig(”portname”, “Dev1/ai0”, 0, “AI” , “TerminalNRSE F=1000 N=300”)

Analog Output

For analog output. Most cards that have analog output will support single value output.

Some cards will support waveform output. The Signal Generator functionality is a good way to generate a waveform for output.

e.g.
This will setup an output channel that can be controlled by an analog output record
DAQmxBaseConfig(”portname”, “Dev1/ao0”, 0 ,”AO”, “N=1 F=0”)

Binary/Digital Input

Most cards support binary input. Like analog input you can sample 1 value or multiple values at a given samplerate.

You can setup the read to use an external port (if this is a slave-device for example)

Binary/Digital Output

Binary output.

Multiple output value or single status output is possible.

Counter input

There are 3 Counter in modes.
Period measurement - return value in seconds (floating point)
Count Edges - return number that is continuously growing (integer)
Pulse Width measurement - return value in seconds (floating point)

In theory you can setup these Period and Pulse Width measurement to read single or multiple values. (Most of this is untested)

1 counter channel per task. More than 1 counter task allowed.

Counter output

Generate a single output pulse. Or a continuous output clock signal.

Initial delay, frequency and dutycycle are configurable. For single pulse you can also se the idle state high or low.

Some cards doesn’t have counter output connectors. But they may have internal counter signals that can be use as clock sources in other tasks.

1 counter channel per task. More than 1 counter task allowed.

ASYN record options

Please first read the section “Generic Device Support for EPICS records” in the asynDriver manual.

the DTYP field of the records can be one of:
asynInt32, asynInt32Array, asynFloat64, asynFloat64Array, asynUInt32Digital

Usually the INP or OUT field of the record is initialized.
→ @asyn(portname, channelnr, timeout) Options

portname is the same as given in DAQmxBaseConfig IOC command.
channelnr will also correlate with that given in DAQmxBaseConfig.
timeout is a value in seconds, usually something like 2.0 or 5.0 is good

Options are given to the driver.

The driver provides some different interfaces. And the Option parameter determine which one is used.
Here is the list:

  • DATA - This is the data interface. Data read or written to this interface is what is read from or output to the NI card. This is the only interface available for arrays (waveforms)
  • ACQUIRE - This is like the ON/OFF switch for the task. Writing a 1 here will start sampling/generation. A 0 will stop it.
  • TRIGGERMODE - This controls the trigger mode of the task.
  • SAMPLERATE - The frequency
  • NSAMPLES - number of samples per channel
  • MAX_NELM - This is no longer used
  • MIN_VOLTS - minimum volts of channel
  • MAX_VOLTS - maximum volts of channel
  • D_TIME - The time of last NI read command. (only works for Input channels - Interrupts is problematic)
  • STATE - The state of the state-machine is returned
  • TRIGGERENABLE - enable or disable the trigger
  • TRIGGERSLOPE - select rising/falling edge trigger mode.
  • TRIGGERLEVEL - the voltage level of the trigger
  • TRIGGERPRESAMPLES - number of samples to acquire before trigger
  • TERMINAL - Controls the Termination of the Analog Input Channel. (0=default 1=RSE 2=NRSE 3=Diff)

Custom record

None exist at this moment

Driver Internals

This part is for people that would like to read the source-code and maybe add features or do further development of any kind. Or if you would like a better understanding of how the driver works

Quick Overview

The first part of the source code is defines and structures used. Then there is also defines for asyn interfaces.

Second part is all the asyn functions. Read/write ect.

Then there generator section/function

Now you get the setup functions and also the implementations of IOC functions.

Then you have the thread section.

And lastly there is the registrar setup of IOC commands.

ASYN interfaces

Provided interfaces:

  • Common
  • DrvUser
  • int32
  • float64
  • int32array
  • float64Array
  • uint32Digital

The asynOption interface is not provided as there is custom IOC commands to work with that. Most options can be accessed using PVs.

State Machine

Every port starts a seperate thread. This threads runs a state-machine that controls the NI card.

In source:
See enum daqMxBaseState for states.
The thread function = daqThread

A pv can read the current state. Int32/Float64 interface and drvParam = STATE

Dual buffering

For input ports (Binary/Analog) there is a rawData and a prevData buffer. These gets swapped everytime after reading. Current reading is done in rawData. The interfaces read data from prevData. This is for thread safety.

The data pointers inside the channel structures are set to point to prevData everytime. Data is not copied again to some other data. But read directly from here when interface read commands are called.

thread safety

Every port has it’s own mutex (pPvt→Lock)

We are still unsure about the extend of thread-safety inside the DAQmxBase library.

ASYN Trace

The driver is making extensive use of the TRACE interface to output debug/error information.

For general debug and error information on a port specify with IOC:
asynSetTraceMask(”portname”, 0×11)

If you would want error information logged to a file:
asynSetTraceMask(”portname”, 0×01)
asynSetTraceFile(”portname”, “filename”)

Examples

Scanner Simulation

Simulates a scanner and reads it back in. Connect Ao0 → Ai0 and Ao1 → Ai1

run scannersim.cmd to start this simulation.

By altering the DAQmxGen commands’ parameters inside the scannersim.cmd scriptfile the waveform generated can easily be changed.

scannersim_ex.jpg

Trouble Shooting

Analog signals floating

Did you connect GND to the AI SENSE port on the card? - AI SENSE is the Analog Input measured GND signal
Did you setup Terminal mode correctly? - try TerminalNRSE

Some or other error

Does the card support what you’re trying todo?
Not all cards can do everything.

If you get a SEGFAULT or some other critical IOC error

Please put the output into a file.
Also include the .db file and the startup script your using and any other information.
Also specifiy which NI card you are using.
Send this information to heinrichdt@tlabs.ac.za or ulrik.pederson@diamond.ac.uk

If you want to do something else

Cool. Show us how!