PyDAQmx

Table of Contents

Previous topic

Installation

Next topic

How to use callback functions in PyDAQmx

Global Table of Contents

Documentation license

Creative Commons License

How to use PyDAQmx

The PyDAQmx module uses ctypes to interface with the NI-DAQmx dll. We thus advise users of PyDAQmx to read and understand the documentation of ctypes.

Three core modules are defined, and one higher-level object-oriented module:

  • PyDAQmx.DAQmxTypes maps the types defined by National Instruments to the corresponding ctypes types (TaskHandle, DAQmxEveryNSamplesEventCallbackPtr, etc.).
  • PyDAXmx.DAQmxConstants imports all the constants defined in NIDAQmx.h (DAQmx_Val_Cfg_Default, DAQmx_Val_Rising, etc.).
  • PyDAQmx.DAQmxFunctions imports all the functions defined in NIDAQmx.h (DAQmxCreateTask(), DAQmxCfgSampClkTiming(), etc.).
  • PyDAQmx.Task provides an object-oriented interface to NIDAQmx taskHandle objects. See the section Task object.

Argument types

All the types defined by NI in the NIDAQmx.h file are translated to ctypes, and can be found in the PyDAQmx.DAQmxTypes module:

from PyDAQmx.DAQmxTypes import *

The module automatically converts variables to the right type. If a library function requires a pointer, use the byref() function to pass parameters by reference.

For example the following C source:

TaskHandle taskHandle=0;
DAQmxCreateTask("",&taskHandle)

will translate into Python as:

taskHandle = TaskHandle(0)
DAQmxCreateTask("",byref(taskHandle))

When looking at the C API help file or the examples provided by NI, there is an almost one-to-one relationship between the C and Python code:

  • Constants can be imported from PyDAQmx.DAQmxConstants
  • Variables that are not pointers can be used directly, as they will be automatically converted by ctypes
  • For pointers, first declare them and then use byref() to pass by reference
  • NULL in C becomes None in Python

If numpy is installed, PyDAQmx uses numpy arrays as dataArrays instead of a ctypes array, as this is more efficient.

For example, to read a 1000 long array of float64:

C code:

int32       read;
float64     data[1000];
DAQmxReadAnalogF64(taskHandle,1000,10.0,
    DAQmx_Val_GroupByChannel,data,1000,&read,NULL);

PyDAQmx without numpy:

read =  int32()
data_type = float64*1000 # define a c_double_Array_1000 type
data = datatype()
DAQmxReadAnalogF64(taskHandle,1,10.0,
    DAQmx_Val_GroupByChannel,data,1,byref(read),None)

PyDAQmx with numpy (recommended):

read = int32()
data = numpy.zeros((1000,), dtype=numpy.float64)
DAQmxReadAnalogF64(taskHandle,1,10.0,
    DAQmx_Val_GroupByChannel,data,1,byref(read),None)

Example

To consider a complete example, let’s look at the Acq-IntClk.c example from the AI category (Analog In/Measure Voltage/Acq-Int Clk/Acq-IntClk.c):

#include <stdio.h>
#include <NIDAQmx.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void)
{
    int32       error=0;
    TaskHandle  taskHandle=0;
    int32       read;
    float64     data[1000];
    char        errBuff[2048]={'\0'};

    /*********************************************/
    // DAQmx Configure Code
    /*********************************************/
    DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
    DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
    DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000));

    /*********************************************/
    // DAQmx Start Code
    /*********************************************/
    DAQmxErrChk (DAQmxStartTask(taskHandle));

    /*********************************************/
    // DAQmx Read Code
    /*********************************************/
    DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,&read,NULL));

    printf("Acquired %d points\n",read);

Error:
    if( DAQmxFailed(error) )
        DAQmxGetExtendedErrorInfo(errBuff,2048);
    if( taskHandle!=0 )  {
        /*********************************************/
        // DAQmx Stop Code
        /*********************************************/
        DAQmxStopTask(taskHandle);
        DAQmxClearTask(taskHandle);
    }
    if( DAQmxFailed(error) )
        printf("DAQmx Error: %s\n",errBuff);
    printf("End of program, press Enter key to quit\n");
    getchar();
    return 0;
}

This translates into Python as:

from PyDAQmx import *
import numpy

# Declaration of variable passed by reference
taskHandle = TaskHandle()
read = int32()
data = numpy.zeros((1000,), dtype=numpy.float64)

try:
    # DAQmx Configure Code
    DAQmxCreateTask("",byref(taskHandle))
    DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,None)
    DAQmxCfgSampClkTiming(taskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000)

    # DAQmx Start Code
    DAQmxStartTask(taskHandle)

    # DAQmx Read Code
    DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,byref(read),None)

    print "Acquired %d points"%read.value
except DAQError as err:
    print "DAQmx Error: %s"%err
finally:
    if taskHandle:
        # DAQmx Stop Code
        DAQmxStopTask(taskHandle)
        DAQmxClearTask(taskHandle)

Note

This exemple is for Python 2. In order to use it with Python 3, you should replace strings with binary strings (for example b'Dev1/ai0')

Task object

The PyDAQmx package introduces an object-oriented interface to the NIDAQmx package. Basically, you replace the taskHandle mechanism with a Task object. Each function of NIDAQmx that works with a taskHandle is a method of the Task object. The method names are the same as the NIDAQmx function names without the DAQmx at the beginning, and the taskHandle argument of the function is omitted.

The above example now reads:

from PyDAQmx import *
import numpy

analog_input = Task()
read = int32()
data = numpy.zeros((1000,), dtype=numpy.float64)

# DAQmx Configure Code
analog_input.CreateAIVoltageChan("Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,None)
analog_input.CfgSampClkTiming("",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000)

# DAQmx Start Code
analog_input.StartTask()

# DAQmx Read Code
analog_input.ReadAnalogF64(1000,10.0,DAQmx_Val_GroupByChannel,data,1000,byref(read),None)

print "Acquired %d points"%read.value

Note

DAQmxClearTask() is automatically called when a Task instance is garbage collected, obviating the need to clean up manually.