07-09-2018 09:05 PM - last edited on 07-10-2018 08:44 AM by Kristi_Martinez
I am trying to synchronize my digital output and input tasks. To get started I use this barebones code of basic functionality. the synchronization is by using the same sample clock (default clock) for both digital input and output.
freq_master = 600000.0; #dataDO is for lines 4:7, and increments by 1 dataDO = [ 0x00000000, 0x00000010, 0x00000020, 0x00000030, 0x00000040, 0x00000050, 0x00000060, 0x00000070, 0x00000080, 0x00000090, 0x000000a0, 0x000000b0, 0x000000c0, 0x000000d0, 0x000000e0, 0x000000f0]; nsmpls = dataDO.size; #dataDI is used by digital read dataDI = zeros(nsmpls, dtype=uint32); ##### Begin Digital Output ##### # DAQmx Configure Code DAQmxCreateTask("taskDO", &taskHandleDO) DAQmxCreateDOChan(taskHandleDO, "Dev1/port0/line4:7", "", DAQmx_Val_ChanForAllLines) # DAQmx Timing Setup freq_master = 600000.0 DAQmxCfgSampClkTiming(taskHandleDO, "", freq_master, DAQmx_Val_Rising, DAQmx_Val_ContSamps, dataDO.size) wrtDig = c_int(0) # DAQmx Write Code DAQmxWriteDigitalU32(taskHandleDO, dataDO.size*2, 0, 10.0, DAQmx_Val_GroupByChannel, dataDO, byref(wrtDig), None) DAQmxStartTask(taskHandleDO) ##### End Digital Output ##### ##### Begin Digital Input ##### DAQmxCreateTask("taskDI", &taskHandleDI) DAQmxCreateDIChan(taskHandleDI, "Dev1/port0/line0:3", "", DAQmx_Val_ChanForAllLines) # DAQmx Timing Setup, freq_master = 600000.0 DAQmxCfgSampClkTiming(taskHandleDI, "", freq_master, #DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, DAQmx_Val_Rising, DAQmx_Val_ContSamps, dataDI.size) DAQmxStartTask(taskHandleDI); DAQmxReadDigitalU32(taskHandleDI, nsmpls, 30e-0, DAQmx_Val_GroupByChannel, dataDI, nsmpls, byref(written), None) ##### End Digital Input ##### print("dataDI", dataDI)
The read data is saved in an array, and the array is printed out. I was expecting the read array contents to be [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf] (or a circular shift of this array). But the read array is a random combination of numbers between 0x0 to 0xf. e.g.
A) [0xe, 0x0, 0x2, 0x4, 0x3, 0x6, 0x8, 0x4, 0x6, 0x7, 0x6, 0x0, 0x1, 0x2, 0x3, 0x4]
B) [0xe, 0xf, 0xe, 0x0, 0x0, 0xb, 0x2, 0x4, 0x6, 0x8, 0xa, 0xf, 0xc, 0x0, 0xc, 0xc]
C) [0xc, 0xd, 0xe, 0xf, 0xc, 0x0, 0x6, 0x9, 0xe, 0x4, 0x6, 0x6, 0x4, 0x0, 0xe, 0x5]
Why is the read data randomized? is the written data itself mixed up while writing?
Thanks,
07-10-2018 08:28 AM
Well, you're writing to lines 4:7 while you're reading from lines 0:3.
Are you doing direct loop-back wiring? If so, double-check it. If not, where are the signals on lines 0:3 coming from? Why *should* they match the output pattern?
-Kevin P
07-10-2018 11:25 AM - edited 07-10-2018 11:25 AM
Hi Kevin,
"Are you doing direct loop-back wiring? If so, double-check it. If not, where are the signals on lines 0:3 coming from? "
Yes, I am testing my code with the breakout board SCB-68A, and connecting the output lines to input lines.
"Why *should* they match the output pattern?"
If the read operation can not match what is being written, that's highly problematic. This is just the basic functionality of read. If I am reading 4 words from read operation, and if the 4 words are scrambled, the application would simply not work.
07-10-2018 12:26 PM
I looked at the digital output on oscilloscope, and the patterns of the output bits don't make sense with the write array. I suspect that the write operation itself is struggling to put the write array in correct sequence.
07-10-2018 12:32 PM
A couple thoughts, no clear conclusions.
The tasks appear to be configured to sample at the same rate (freq_master = 600000). That alone doesn't fully sync them, but I agree that the data you read should at least be a circular shift of the data you write, not a more-or-less random sequence of values.
What DAQ device are you using? Are you sure it can generate its own sample clock at 600kHz for both DO and DI? (Many devices don't support an internally-generated clock for DIO. I suspect yours does or you'd get errors instead of data.) Have you observed the DO signals on a scope?
I only program in LabVIEW and don't know the text syntax. I notice that your write and read lines contain a parameter "DAQmx_Val_GroupByChannel". I don't exactly know what the term "group by channel" means here, but my initial thought is that I'd expect to want to group by *sample* -- i.e., each u32 value would represent one sample of the digital bits. Do you know what other values are allowed for that argument in the write/read function calls?
-Kevin P
07-10-2018 12:38 PM
Just saw your followup that you posted while I was still typing.
If the DO itself doesn't look right, I'm more suspicious of that "group by channel" term. Makes me wonder if it treats your 12-entry u32 array as a 12x32 array of bits and then handles it as 32 samples of a 12-bit value rather than 12 samples of a 32-bit value?
-Kevin P
07-10-2018 02:04 PM
Hi Kevin,
I still have to try all of your suggestions on the constants used in my code.
But, it seems the write call has a problem in using the subset of port lines: ("Dev1/port0/line4:7")
DAQmxCreateDOChan(taskHandleDO, "Dev1/port0/line4:7", "", DAQmx_Val_ChanForAllLines)
The write code seems to work better if I use the whole port: ("Dev1/port0")
DAQmxCreateDOChan(taskHandleDO, "Dev1/port0", "", DAQmx_Val_ChanForAllLines)
I still need to figure the proper write code with a subset of port lines.
Thanks,
07-13-2018 12:13 PM
An update on write problem. The code that is able to write the digital pattern correctly, and synchronously is:
data = [ 0x00000000, 0x00000010, 0x00000020, 0x00000030, 0x00000040, 0x00000050, 0x00000060, 0x00000070, 0x00000080, 0x00000090, 0x000000a0, 0x000000b0, 0x000000c0, 0x000000d0, 0x000000e0, 0x000000f0]*2; # DAQmx Configure Code DAQmxCreateTask("", byref(taskHandle); DAQmxCreateDOChan(taskHandle, "Dev1/port0/line0:7", "", DAQmx_Val_ChanForAllLines); DAQmxCfgSampClkTiming(taskHandle, "", 600000.0, DAQmx_Val_Rising, DAQmx_Val_ContSamps, data.size*1); # DAQmx Write Code DAQmxWriteDigitalU32(taskHandle, data.size*1, 0, 10.0, DAQmx_Val_GroupByChannel, data, None, None); # DAQmx Start Code DAQmxStartTask(taskHandle);
This seems to be some undocumented behaviour of the write buffer. The digital pattern to write is:
data = [ 0x00000000, 0x00000010, 0x00000020, 0x00000030, 0x00000040, 0x00000050, 0x00000060, 0x00000070, 0x00000080, 0x00000090, 0x000000a0, 0x000000b0, 0x000000c0, 0x000000d0, 0x000000e0, 0x000000f0];
But, I had to repeat this pattern twice in the array to make the continuous write work:
data = [ 0x00000000, 0x00000010, 0x00000020, 0x00000030, 0x00000040, 0x00000050, 0x00000060, 0x00000070, 0x00000080, 0x00000090, 0x000000a0, 0x000000b0, 0x000000c0, 0x000000d0, 0x000000e0, 0x000000f0] * 2;
The "*2" after an array repeats the pattern before it.
07-13-2018 11:19 PM
I'd be surprised if what you consider an undocumented behavior turns out to be what you're thinking it is. Not ruling it out either though. I just know I've successfully used DAQmx with 1 cycle patterns plenty of times, I never encountered a need to define the cycle twice.
Hang on to your observation a whie, and come back to it after all the other various kinks with sync and finite vs. continuous sampling are worked out. Once you get everything working well, re-investigate whether 2 cycles vs 1 cycle is still a make-or-break criterion. You may have found a subtle bug, or they may turn out to be some other explanation. I kinda think it's still too early to tell.
-Kevin P
07-15-2018 04:46 PM
OK, thanks for the feedback.