Search code examples
pythonnidaqmxdaq-mx

Triggering an output task with NIDAQmx


I'm having trouble carrying out what I think should be a pretty straightforward task on a NIDAQ usb6002: I have a low frequency sine wave that I'm measuring at an analog input channel, and when it crosses zero I would like to light an LED for 1 second. I'm trying to use the nidaqmx Python API, but haven't been able to clear up some of my basic questions with the documentation. https://nidaqmx-python.readthedocs.io/en/latest/

If anyone can offer any thoughts about the code or the basic logic of my setup, that would be hugely helpful.

Here's what I have tried so far. I start with some imports and the definition of my channels:

import matplotlib.pyplot as plt
from math import *
import nidaqmx
from nidaqmx import *
from nidaqmx.constants import *
import time

V_PIN = "Dev1/ai6"
LED_PIN = "Dev1/ao0"

I understand how tasks and things work generally- I can read and plot a signal of a given sampling rate and number of samples using task.ai_channels methods without any trouble. But here's my best guess at how to carry out "detect zero and trigger output":

writeLED = nidaqmx.Task('LED')
writeLED.ao_channels.add_ao_voltage_chan(LED_PIN)
writeLED.timing.cfg_samp_clk_timing(1)
writeLED.triggers.start_trigger.cfg_anlg_edge_start_trig(V_PIN,trigger_level = 0)
writeLED.write([5], auto_start=True)

This gives me the error below at the cfg_anlg_edge line

DaqError: Requested value is not a supported value for this property. The property value may be invalid because it conflicts with another property.
Property: DAQmx_StartTrig_Type
Requested Value: DAQmx_Val_AnlgEdge
Possible Values: DAQmx_Val_DigEdge, DAQmx_Val_None

I don't know why an analog input channel wouldn't be supported here. Page 245 of this document makes it sound like it should be: https://media.readthedocs.org/pdf/nidaqmx-python/latest/nidaqmx-python.pdf

I'm sure there are other problems with the code, too. For example, it seems like the sample clock manipulations are quite a bit more complicated than what I've written above, but I haven't been able to find anything that explains how it would work in this situation.

Thanks in advance for any help!


Solution

  • With NI, it's "RTFMs"

    When programming NI devices, you usually need two manuals.

    1. NI-DAQmx Help (for the programming part)
    2. the device specification (for the device part)

    You need both because the NI-DAQmx API supports every DAQ device NI makes, but not every device has the same capabilities. "Capabilities" includes more than how many channels of each kind, but also the timing and triggering subsystems as well as internal signal routing. A DAQmx application that runs with one device is not guaranteed to run with another because the application might use the API in a way the second device cannot support.

    Finally, on the documentation front, any given NI DAQ device typically belongs to family of related devices and these families also have a manual called User Guide. These User Guides act as a bridge between the API and device spec, helping you understand how the device responds to commands. For the 6002, the family is "Low-Cost DAQ USB Device".

    Analog trigger for analog output on NI 6002

    Your determination is correct that

    writeLED.triggers.start_trigger.cfg_anlg_edge_start_trig(V_PIN,trigger_level = 0)
    

    is possible, just not for the USB 6002. This line is asking the analog output subsystem to use an analog edge trigger, but the analog output subsystem for the 6002 only has these trigger capabilities:

    • software
    • PFI 0
    • PFI 1

    For this device, you're only option is the software trigger because the PFI lines are digital triggers and their trigger level is specified to be between 0.8 V and 2.3 V.

    Change your Python program to detect a zero-crossing from the analog input stream and, when it does, make it call stop() and then start() on the AO task.

    The reason for the stop-start sequence is retriggering: you want to light the LED for each zero crossing, but a task cannot be restarted unless it has either been stopped (by the API or by completing its task) or configured for retriggering. Because the 6002 is in the low-cost family, this hardware feature isn't available, so you must use the API to stop the AO task or wait for the AO generation to complete before restarting the pulse for the LED

    6002 AO Specification

    clip from 6002 specifications showing the analog output subsystem capabilities