Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

USB-6353 analog input / output synchronization

Hi everyone.
I have a USB-6353 multifunction device, and I need to write continuously on the 4 analog output channels 4 different signals and, at the same time, read continuously 4 analog input channels.

I made a script to achieve this and to test if everything works I have connected the 4 analog outputs to 4 analog inputs to visualize if the write and read operations work.
With my script everything works, except for a little but annoying detail: if on the 4 outputs I write (for example) 4 sinusoids, on the first input channel I read the sinusoid of the first output channel but delayed by one sample. The other three input channels produce instead the desired result, they are synchronous between them and between the signal written on the corresponding output. Only on the first input channel I read a sinusoid delayed by one sample with respect to the related output channel and the other channel pairs.
It seems like the device can't write the first sample on the first output channel in time, and so all samples of that channel are shifted.

This behaviour happens for all kind of signals I can think of. Also, my script is written in Matlab but I have also made a python version and I have the same exact problem.

Probably I am missing something.... Below you can find my matlab code.

Thank you for the help!

 

clc
clear all
close all

%%
d=daqlist;
devId = d{1,"DeviceID"};
dq = daq("ni");
dq.Rate = 12800;

% Setup input channels
ch_i0 = addinput(dq,devId, "ai0","Voltage");
ch_i0.Range = [-5 5];
ch_i0.TerminalConfig = "SingleEnded";
ch_i1 = addinput(dq,devId, "ai1","Voltage");
ch_i1.Range = [-5 5];
ch_i1.TerminalConfig = "SingleEnded";
ch_i2 = addinput(dq,devId, "ai2","Voltage");
ch_i2.Range = [-5 5];
ch_i2.TerminalConfig = "SingleEnded";
ch_i3 = addinput(dq,devId, "ai3","Voltage");
ch_i3.Range = [-5 5];
ch_i3.TerminalConfig = "SingleEnded";

% Setup output channels
ch_o0 = addoutput(dq, devId, "ao0", "Voltage");
ch_o0.Range = [-5 5];
ch_o0.TerminalConfig = "SingleEnded";
ch_o1 = addoutput(dq, devId, "ao1", "Voltage");
ch_o1.Range = [-5 5];
ch_o1.TerminalConfig = "SingleEnded";
ch_o2 = addoutput(dq, devId, "ao2", "Voltage");
ch_o2.Range = [-5 5];
ch_o2.TerminalConfig = "SingleEnded";
ch_o3 = addoutput(dq, devId, "ao3", "Voltage");
ch_o3.Range = [-5 5];
ch_o3.TerminalConfig = "SingleEnded";

%%
n = 256*50;
outputSignal1 = 1.55 + (0.125*sin(2*pi*400*linspace(0,n/dq.Rate,n)'));
outputSignal2 = 1.55 + (0.125*sin(2*pi*800*linspace(0,n/dq.Rate,n)'));
outputSignal3 = 1.55 + (0.125*sin(2*pi*1600*linspace(0,n/dq.Rate,n)'));
outputSignal4 = 1.55 + (0.125*sin(2*pi*3200*linspace(0,n/dq.Rate,n)'));
outputSignal = [outputSignal1 outputSignal2 outputSignal3 outputSignal4];

preload(dq,outputSignal);
dq.ScansRequiredFcn = @(src,evt) write(src, repmat([outputSignal], 5, 1));
start(dq, "continuous")

t = tic;
while toc(t) < 60
    data = read(dq,1000);
    plot(data.Time, data.Variables)
    xlabel("Time (s)")
    ylabel("Amplitude")
    legend(data.Properties.VariableNames)
    drawnow
end

stop(dq)
data = read(dq,"all");
flush(dq)

 

 

 

0 Kudos
Message 1 of 3
(490 Views)

I was just in a discussion earlier today where I talked through a reason for a 1-sample offset between AO and AI in a fairly similar situation.

 

I don't know any of the Matlab syntax for configuring clocks and active edges, etc.  But the general idea of what's going on is probably the same.  What's different for you is *likely* that:

1. Sampling for AO and AI probably start at the same time

2. Multiple AO channels get D/A converted simultaneously, while multiple AI channels get A/D converted one at a time in sequence b/c you have a mutliplexing device.

3. The tiny delay mentioned in the linked thread means that you A/D convert your first AI channel *before* the AO channels have fully accomplished their update.  But then subsequent AI channels get A/D converted *after*.

 

Again, sorry, I'm no help with any Matlab or Python syntax.  In LabVIEW, I would:

 

  • Create a counter pulse train output for AO and AI to use as their sample clock.
  • I would be very particular about choosing a duty cycle for that pulse train, because...
  • I would configure AO to use its leading edge as a sample clock and configure AI to use its trailing edge as a sample clock
  • I would then *also* be very particular about setting up the AI "convert clock" for the multiplexing rate.  The whole idea is to lay out timing such that AO updates first, then make sure all AI channels get converted before the next AO update.  The default behavior of DAQmx is to try to spread out the multiplexing as widely as possible across the sample interval.  This is why you probably need to take control of both the pulse train duty cycle *and* the convert clock rate.

 

 

-Kevin P

 

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
Message 2 of 3
(464 Views)

@Kevin_Price wrote:

I was just in a discussion earlier today where I talked through a reason for a 1-sample offset between AO and AI in a fairly similar situation.

 

I don't know any of the Matlab syntax for configuring clocks and active edges, etc.  But the general idea of what's going on is probably the same.  What's different for you is *likely* that:

1. Sampling for AO and AI probably start at the same time

2. Multiple AO channels get D/A converted simultaneously, while multiple AI channels get A/D converted one at a time in sequence b/c you have a mutliplexing device.

3. The tiny delay mentioned in the linked thread means that you A/D convert your first AI channel *before* the AO channels have fully accomplished their update.  But then subsequent AI channels get A/D converted *after*.

 

Again, sorry, I'm no help with any Matlab or Python syntax.  In LabVIEW, I would:

 

  • Create a counter pulse train output for AO and AI to use as their sample clock.
  • I would be very particular about choosing a duty cycle for that pulse train, because...
  • I would configure AO to use its leading edge as a sample clock and configure AI to use its trailing edge as a sample clock
  • I would then *also* be very particular about setting up the AI "convert clock" for the multiplexing rate.  The whole idea is to lay out timing such that AO updates first, then make sure all AI channels get converted before the next AO update.  The default behavior of DAQmx is to try to spread out the multiplexing as widely as possible across the sample interval.  This is why you probably need to take control of both the pulse train duty cycle *and* the convert clock rate.

 

 

-Kevin P

 


Full acknowledge !

 

Assuming you want to measure some sort of FRF(s)

We have seen that this update glitsch doesn't need to be repeatable. It's a small delay with jitter and for me it's obvious the only the first channel in the multiplexed ADC is affected.  So go for the update-sample  edge seperation, or don't use the first channel, but read it and dump it.

You found a one sample delay, but there will be even subsample delays due to the multiplexing scheme.

Since you use a multiplexed DAQ there are individual delays for each channel. If you always use the same configuration(s), I recommend to measure these and compensate in software. (EDIT: Do this for each configuration, and repeat it on different days to get confidense on your values)

If you measure the delay (one way: directly feed the inputs with your output, apply sines, measure the phase) beware of crosstalk due to settletime (fig 1 in the spec). So using different, nonharmonic frequencies can help here. (AND a really low source impedance)

If you 'just' want to plot them with correct timing, you can use the t0 values for correction (and tell the graph to NOT ignore the t0 timestamp!) . In the frequency domain a delay is just a linear phase shift 🙂

 

Greetings from Germany
Henrik

LV since v3.1

“ground” is a convenient fantasy

'˙˙˙˙uıɐƃɐ lɐıp puɐ °06 ǝuoɥd ɹnoʎ uɹnʇ ǝsɐǝld 'ʎɹɐuıƃɐɯı sı pǝlɐıp ǝʌɐɥ noʎ ɹǝqɯnu ǝɥʇ'


0 Kudos
Message 3 of 3
(412 Views)