Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Syncing analog and digital output task using software trigger

Solved!
Go to solution

I'm trying to start two tasks simultaneously using software trigger (one for analog output, one for digital output).

I have something that looks like this:

 

 

    with nidaqmx.Task() as a_task, nidaqmx.Task() as d_task:
        # Set analog output.
        for a_ch in ni_config['analog']:
            a_task.ao_channels.add_ao_voltage_chan(a_ch)

        d_task.do_channels.add_do_chan(ni_config["digital"], line_grouping=LineGrouping.CHAN_PER_LINE)

        a_task.timing.cfg_samp_clk_timing(rate=ni_config["sample_rate_hz"],
                                          sample_mode=ni.constants.AcquisitionType.FINITE,samps_per_chan=a_data.shape[1])
        a_writer = AnalogMultiChannelWriter(a_task.out_stream, auto_start=False)
        a_writer.write_many_sample(a_data) 
        # Set digital output.
        d_task.timing.cfg_samp_clk_timing(rate=ni_config["sample_rate_hz"],
                                          sample_mode=ni.constants.AcquisitionType.FINITE,samps_per_chan=len(d_data))

        d_task.triggers.start_trigger.cfg_dig_edge_start_trig(a_task.triggers.start_trigger.term)

        d_writer = DigitalSingleChannelWriter(d_task.out_stream, auto_start=False)    
        d_writer.write_many_sample_port_byte(d_data)       

        a_task.start()

 

 

However, the digital task doesn't start.

When I try to add explicitly

 

 

d_task.start()

 

 

I get consistent delay between the analog and digital (probably the time it takes for NI to actually start the task)>

 

How can I have a single software trigger such that both start at the same time?

 

[Side note: The analog outputs use (multiple) PXIe-4468, and the digital output use PXIe-6535]

 

Thanks!

0 Kudos
Message 1 of 10
(1,327 Views)

A software trigger will always have an unknown delay. If you want to synchronize multiple devices, you should use a hardware trigger.

You can refer to nidaqmx-python/examples/ai_multi_task_pxie_ref_clk.py at master · ni/nidaqmx-python · GitHub

 

-------------------------------------------------------
Control Lead | Intelline Inc
0 Kudos
Message 2 of 10
(1,312 Views)

I'm getting multiple errors:

 

DaqError: Specified property is not supported by the device or is not applicable to the task.
Property: DAQmx_RefClk_Src

 

Specified property is not supported by the device or is not applicable to the task.
Property: DAQmx_Trigger_SyncType

 

 

0 Kudos
Message 3 of 10
(1,291 Views)

I've got a lot of general DAQmx knowledge, but don't know your devices specifically and also don't know Python syntax.

 

Here's some thoughts to try to give you a little boost, not likely to solve everything.

 

1. Maybe your 4468's for AO don't support multi-device tasks?  (See also "channel expansion" when searching)

 

2. When possible, I like to advocate sync via shared sample clock alone.  No dealing with triggers, sync pulses, reference clock config, etc.   Sample clock sharing is typically better for syncing tasks across devices than triggers alone.

 

3. I don't see where you set a sample rate for acquisition, unless the construct ni_config["sample_rate_hz"] resolves to a numeric value that's been set up elsewhere. 

 

4. However, PXI can be an exception.  Most devices sync up their internal timebases to the PXI chassis clock.  So in the specific case of PXI, sync via trigger alone often *can* be sufficient.  This appears to be what you're trying to do.

 

5. However, with the DI task wanting to trigger off the AO task's (internal) start trigger, you should be starting DI *before* you start AO.

 

6. This may not be the *only* way to make things work, but if your AO device doesn't support "channel expansion" I would consider the following:

  • think of DI as the master task, so it will need to start last.
  • Create several AO tasks, 1 for each physical device.  Configure them to trigger off the DI task's internal start trigger
  • Start all the AO tasks before you start the DI task.

 

In general, you could make any one of the tasks be the "master", but it seems sensible to me to have the one and only DI task play a special role while all the AO tasks are the same as one another.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
0 Kudos
Message 4 of 10
(1,276 Views)

Alternatively, if a software solution to trigger both at the same time is not possible, is there a way to trigger both tasks using an external hardware trigger? How do I set this up? 

0 Kudos
Message 5 of 10
(1,273 Views)

The below works on simulated devices. You can complete the multi writer/reader on your own.

Reference: Reference Clock Synchronization with the PXIe-6535

 

 

"""Example of AI multitask operation."""
import pprint

import nidaqmx
from nidaqmx.constants import AcquisitionType, TaskMode, LineGrouping, Signal

pp = pprint.PrettyPrinter(indent=4)


with nidaqmx.Task() as master_task, nidaqmx.Task() as slave_task:
    master_task.do_channels.add_do_chan("/6535/port0/line0:3", line_grouping=LineGrouping.CHAN_FOR_ALL_LINES)
    slave_task.ao_channels.add_ao_voltage_chan("/4468_1/ao0:1")
    slave_task.ao_channels.add_ao_voltage_chan("/4468_2/ao0:1")

    master_task.timing.cfg_samp_clk_timing(1000, sample_mode=AcquisitionType.FINITE, samps_per_chan=4)
    master_task.export_signals.export_signal(signal_id=Signal.SAMPLE_CLOCK, output_terminal="/6535/PXI_Trig7")
    slave_task.timing.cfg_samp_clk_timing(1000, source="/4468_1/PXI_Trig7", sample_mode=AcquisitionType.FINITE, samps_per_chan=4)

    master_task.control(TaskMode.TASK_COMMIT)

    slave_task.triggers.start_trigger.cfg_dig_edge_start_trig("/6535/do/StartTrigger")

    print("1 Channel N Lines N Samples Unsigned Integer Write: ")
    print(master_task.write([1, 2, 4, 8]))

    print("N Channel N Samples Write: ")
    print(
        slave_task.write(
            [[1.0, 2.0, 3.0, 4.0], [1.1, 2.1, 3.1, 4.1], [1.2, 2.2, 3.2, 4.2], [1.3, 2.3, 3.3, 4.3]],
        )
    )

    slave_task.start()
    master_task.start()

    slave_task.wait_until_done()
    slave_task.stop()

    master_task.wait_until_done()
    master_task.stop()

 

 

 

-------------------------------------------------------
Control Lead | Intelline Inc
Message 6 of 10
(1,254 Views)

Big kudos to ZYOng for the example!

 

Brief comment: he gave you a little bonus by showing 2 different ways to share timing signals.

- Explicitly - by exporting the master DO sample clock to a specific PXI trigger line and configuring AO to use it

- Implicitly - by telling the AO task to use a signal from the DO device "/6535/do/StartTrigger".  With this method, DAQmx figures out routing automatically.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
Message 7 of 10
(1,220 Views)

I see consistent latency between the two signals with both solutions.

The analog lags the digital by ~32.8 ms.

This happens regardless of how I configure things. Even when I set both to trigger to be an external PFI.

 

 

shohayon_1-1695835299213.png

 

0 Kudos
Message 8 of 10
(1,201 Views)
Solution
Accepted by topic author shohayon

Now that I've looked at the spec sheet for the 4468, I can probably explain the timing offset.   Do you have a sample rate of ~2kHz?

 

Your AO devices use a Delta Sigma converter which incorporates a bandwidth-limiting digital filter which brings with it an inherent delay along the signal path.  According to the spec sheet, the delay is ~65 samples for sample rates from 100 Hz to 10 kHz.  So a 2 kHz sample rate could be expected to have a 32.5 msec delay.

 

With acquisition signals, such delays can be compensated in post-processing.  That's not really an option for *output* signals that need to be synced though.  Instead you'd have to pre-compensate.

 

There may be other methods (possibly a "trigger delay" property in DAQmx?) but here's one that could work.  Configure a chassis counter to generate a 32.8 msec pulse.   Trigger AO off the leading edge and trigger DO off the falling edge.   The 32.8 msec head start you gave to AO will be used up by the filter delay, then the output signals should be in sync.

 

On a separate note, 'm a bit surprised though if you can use the DO as master and AO as slave for your sample clock config.  Delta Sigma devices typically don't allow for an external signal to be used directly as a sample clock.   Or did you drop the shared sample clock and try to sync solely via common trigger?

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
Message 9 of 10
(1,187 Views)

Yes! I was using 2kHz output sample rate. Thank you for that additional information 

0 Kudos
Message 10 of 10
(1,127 Views)