Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

Acquiring simultaneously with PCIe 6535

Solved!
Go to solution

Hi,

- I am using one PCIe 6535 to manage an home-made(working) electronic board. The electronic board has a FIFO used to store data.
I need to read these data during the acquisition, and the instant for reading is defined by a signal generated from a DDS which
I have to read too. I am programming with CVILabwindow version 10.0.0.

In the software "processes" I start the DDS, and I wait for a signal(or event) which I detect with the following part of the code(thread0):

DAQmxCreateTask("",&line_Clk_TaskHandle);
DAQmxCreateDIChan(line_Clk_TaskHandle,"Dev1/port2line3","",DAQmx_Val_ChanPerLine);
DAQmxCfgChangeDetectionTiming(line_Clk_TaskHandle,"Dev1/port2/line3","Dev1/port2/line3",DAQmx_Val_ContSamps, 1); // I detect both event LOW-HIGH and HIGH-LOW.            
DAQmxRegisterSignalEvent(line_Clk_TaskHandle,DAQmx_Val_ChangeDetectionEvent,0,ChangeDetectionDD3,NULL);            
DAQmxGetTaskAttribute(line_Clk_TaskHandle,DAQmx_Task_NumChans,&line_NumLines);

ChangeDetectionDD3 is a function which start the FIFO acquisition.
FIFO acquisition is driven by the following part of code (thread1):

DAQmxErrChk (DAQmxCreateTask("",&taskRead));
DAQmxErrChk (DAQmxCreateDIChan (taskRead, "Dev1/port0", "DigitalIn", DAQmx_Val_ChanForAllLines));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskRead, "OnboardClock", 5000000, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, NUM_SAMP));
DAQmxErrChk(DAQmxExportSignal (taskRead, DAQmx_Val_SampleClock, "/Dev1/PFI5"));
DAQmxSetTimingAttribute (taskRead, DAQmx_SampQuant_SampMode,DAQmx_Val_FiniteSamps);

SYSEn[0] = 0;          ////// ENABLING acquisition chain
res = DAQmxWriteDigitalLines (Task_SYSENn_Handle, 1, 1, 10.0, DAQmx_Val_GroupByChannel, SYSEn, NULL, NULL);            
            
R4T[0] = 0;          ////// ENABLING FIFO Reading
res = DAQmxWriteDigitalLines (Task_FIFO_R4T_Handle, 1, 1, 10.0, DAQmx_Val_GroupByChannel, R4T, NULL, NULL);   
             /////// READING FIFO    
res = DAQmxReadDigitalU8 (taskRead, NUM_SAMP, 10.0, DAQmx_Val_GroupByChannel, F_OUT, NUM_SAMP, &sampsPerChanRead, NULL);    
            
R4T[0] = 1;          ////// STOP Reading
res = DAQmxWriteDigitalLines (Task_FIFO_R4T_Handle, 1, 1, 10.0, DAQmx_Val_GroupByChannel, R4T, NULL, NULL);   

Since I have to read more than one single set of data, I get in this part of the code several times (each time DDS AD9910 send a change on the line RAMP_SWP_OVER signal RAM Continuous Bidirectional Ramp Mode, in case).

- The problem I get is due to a "resource which is already used" when I read the FIFO through DAQmxReadDigitalU8.
In particular:
NON-FATAL RUN-TIME ERROR:   "Read_FIFO_Thread.c", line 44, col 23, thread id 0x000014C8, function id 1:   Function DAQmxReadDigitalU8: (return value == -200022 [0xfffcf2aa]). Resource requested by this task has already been reserved by a different task. Device: Dev1  Task Name: _unnamedTask<134>  Status Code: -200022

I already simplified up to the limits the code, and i get this ERROR only when I read both input line. When I run the code acquiring one signal
only the code works and I read the FIFO correctly or I read each event send by the DDS on port2/line3. I have supposed the problem lies on
the onboard clock of the PCIe (which cannot be share as I wish: over the port0, and port2/line3)  which is implicitly used by the functions
devoted to the detection of the event generated by the DDS.
I guess the first question is: Can I use the Onboard clock in this configuration?
and if I can use how I can manage it? I mean, what should I configure?

Carlo

0 Kudos
Message 1 of 11
(5,526 Views)

Hi Carlo,

 

The reason you get the error you are seeing is because you are trying to create two separate acquisition tasks (DAQmxCreateDIChan) yet there is only one acqusition timing engine on the 6535.  What this means is you can have port0 and port2line3 read together by placing them both in the same acquisition task, but they must be read using the same clock at the same frequency.

 

I can't quite tell if your DDS is a substitute sample clock or if you wish to use it as a start trigger, but here is my recommendation for each case.  In the case DDS is your sample clock, route that signal to a PFI (Programmable Function Interface) line and in your DAQmxCfgSampClkTiming, replace 'OnboardClock' with the PFI terminal you wish to use as the source for sampling.  If you want to use DDS as a start trigger, you can set up the acquisition to begin on a start trigger from a PFI line, and you can add the additional DAQmx function for configuring a start trigger.

 

While I don't have enough information on the purpose on DDS, another route you may have to go is to oversample your data continuously, and split your DDS line onto a PFI line and a data line.  Then, start the acquisition off DDS, and sample continuously over time.  This will require you to post process information out of your acquired array since you will not have a retrigger ability native to the PCIe-6535.

 

Finally, if you are trying to acquire X number of samples off your FIFO on every DDS edge/pulse, this is defined as a finite retriggerable acquisition, and as I stated before this is not native to the 6535/36/37 product line.  However, there are ways to get you close to this functionality.  

  • My first thought is implementing a Pause Trigger that will allow you to not acquire samples after a period of time.  This may require a lot of work to get perfect, but it is an option.
  • Secondly, you could use an external counter to gate a clock for the specified time you need.  For instance, DDS causes your counter to generate a finite pulse train, the number of pulses equal the number of samples you wish to acquire, and the output from your counter goes into a PFI line on your 6535 to clock the acquisition.  This would be easy to implement, but it does require another PCI/PCIe counter card, since the 6535 does not have a counter onboard.
  • Finally, there may be a way to rig up Burst handshaking using your DDS signal as a Request line, keeping Acknowledge always ready, and using the onboard clock to sample X amount of samples.  This would take some preparation to fully work through and see if its an acceptable path to go down, but it's an idea.

Hopefully this helps you progress with using the card, and best wishes with your home-made creation!

Kyle A.
National Instruments
Senior Applications Engineer
Message 2 of 11
(5,510 Views)

Hi Kyle,

 

thank you for the exhaustive answer. I did exclude the use of another PCI/PCIe card to keep the cost of the system as low as possible 🙂 With another card almost all the problems I found would be solved.

As you understood I would use DDS signal to stard the FIFO acquisition, but I cannot you DDS signal as a clock for acquiring FIFO data. The number of data acquired from fifo for each DDS signal is finite, and I have to repeat this task for N_times.


You wrote "My first thought is implementing a Pause Trigger that will allow you to not acquire samples after a period of time."

Would you mean to interrupt the clock task for a "Tot" amount of time and re-start it. I  have signal coming from the electronic board which eventually can be use for this issue. I mean the DDS signal is an High-Low-High signal and the High or Low phase has a duration that define exactly the time required for wrinting in FIFO the number of sample I would read.

But I could create a new Logical line (on the logic of the electronic board) were a signal is generated only for the amount of time required to read the sample I wanto from FIFO.

But in this way I still have the same problem because I have to read 2 channel????

- Could I try to generate directly the clock I need from electronic board and send to PCIe to use as a clock for FIFO? I think I am able to generate such a clock with the electronic.

I have some I/O spare line. And in this case I could only use PCIe as a bridge.

 

You wrote "Finally, there may be a way to rig up Burst handshaking using your DDS signal as a Request line, keeping Acknowledge always ready, and using the onboard clock to sample X amount of samples.  This would take some preparation to fully work through and see if its an acceptable path to go down, but it's an idea."

I have not understood because I am not very familiar with the HandShaking function... But if you could manage/manipulate as you wish the signal how you develop this idea.

 

Thanks
Carlo

 

 

 

 


0 Kudos
Message 3 of 11
(5,500 Views)

Dear Kyle,

 

you worte "Secondly, you could use an external counter to gate a clock for the specified time you need.  For instance, DDS causes your counter to generate a finite pulse train, the number of pulses equal the number of samples you wish to acquire, and the output from your counter goes into a PFI line on your 6535 to clock the acquisition.  This would be easy to implement, but it does require another PCI/PCIe counter card, since the 6535 does not have a counter onboard."

 

By starting from this idea I did create in my electronic board a finite pulse train with the number of pulses equal to the number of samples you would acquire. This train of pulses goes to dev1/portY/lineX.

Should I now export this train on PFI5 and refer to PFI5 for bursthandshaking acquisition?

Or I can simply use (if it works) a code like the following?

        DAQmxErrChk (DAQmxCreateTask("",&Task_CLK_FromBoard));
        DAQmxErrChk (DAQmxCreateDIChan (Task_CLK_FromBoard, "/Dev1/port2/line3", "", DAQmx_Val_ChanPerLine ));
        DAQmxErrChk (DAQmxCreateTask("",&taskRead));
        DAQmxErrChk (DAQmxCreateDIChan (taskRead, "Dev1/port0", "", DAQmx_Val_ChanForAllLines));
        DAQmxErrChk    (DAQmxExportSignal (Task_CLK_FromBoard, DAQmx_Val_SampleClock , "/Dev1/PFI5"));
        DAQmxErrChk (DAQmxCfgSampClkTiming(taskRead, "/Dev1/PFI5", rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, sampsPerChanToAcquire));
        DAQmxReadDigitalU8 (taskRead, sampsPerBuffer, 10.0, DAQmx_Val_GroupByChannel, data, sampsPerBuffer, &sampsRead, NULL);            
      
//DAQmxErrChk (DAQmxCfgBurstHandshakingTimingExportClock(taskRead,    DAQmx_Val_ContSamps, sampsPerBuffer, rate, "/Dev1/PFI5", 10095, 10214,10095));
       

Thank you

Best Wishes

carlo

0 Kudos
Message 4 of 11
(5,477 Views)

Hi Carlo,

 

Yes, if you have a finite pulse train set up equal to the number of samples you need to acquire, then you won't need burst handshaking.  By routing this to PFI 5, it will be the clock for your acquisition in Sample Clock mode.  The 6535 has the capability to use a non-continuous clock as it's clock source (it samples on edge detection).  So this means if you want 100 samples read from your FIFO at once, you send the clock pulse along with your data to the 6535, and after the last sample the clock stops along with the data.  It can be paused indefinitely until you wish to read another amount of samples, and as long as your clock pulse train has the sample number of edges as samples read, it will work.  

 

Looking at your code:

        DAQmxErrChk (DAQmxCreateTask("",&Task_CLK_FromBoard));
        DAQmxErrChk (DAQmxCreateDIChan (Task_CLK_FromBoard, "/Dev1/port2/line3", "", DAQmx_Val_ChanPerLine ));
        DAQmxErrChk (DAQmxCreateTask("",&taskRead));
        DAQmxErrChk (DAQmxCreateDIChan (taskRead, "Dev1/port0", "", DAQmx_Val_ChanForAllLines));

 

You do not need to read the clock from your DUT on port 2 line 3, you can just route that to your PFI 5 and sample on rising or falling edge.  If you wish to read it along with your data you can, but I expect that line to be all 0's or 1's since you will sample at the same frequency as the signal (aliasing in a sense).

 

  DAQmxErrChk    (DAQmxExportSignal (Task_CLK_FromBoard, DAQmx_Val_SampleClock , "/Dev1/PFI5"));

 

Are you creating the clock on the 6535?  I thought you were going to create a clock from your DUT.  The way the code is set up, you are exporting the sample clock and using it as a source, which will be invalid.  The clock will never run, and it will probably cause a timeout to occur.  

 

If this was the way you wanted to do the finite pulse train method, you might want to switch over and try the Pause trigger method since your DDS sounds like it can also act as a Data Active event from your DUT.  When the signal is low you sample, when the signal is high you don't sample.  You will set up a pause trigger with a digital level trigger, and you can import that on a PFI line.

Kyle A.
National Instruments
Senior Applications Engineer
Message 5 of 11
(5,468 Views)

Hi Kyle,

 

I create the clock from my DUT. But I do not (for moment) how to route it from /Dev1/port2/line3 to Dev1/PFI5. Smiley Embarassed

I never done this operation and I will try to do it now. I DO NOT NEED TO read the clock line.
To route the clock from DUT I though I should have to create a a DIChannel and after export on the PFI5.

My last question that should fix my problem:

If I have create a clock as I whish on my DUT and how can I route it from /Dev1/port2/line3 to Dev1/PFI5 for making the acquisition?

Many thank

Carlo Alberto



0 Kudos
Message 6 of 11
(5,457 Views)

Hi Kyle,

 

I hope this is the last post on this topic!!!

I am still working on the logic of the board, to get a clock from my DUT as I wish to send to the NI PCIe.

Alway referring to previous posts.

I read a bit about immediate routing and from my understanding I should run a code as the following to properly route the signal coming from Dev1/port2/line3:

At the moment I cannot run the code because the clk is not available...

 

Is Channel and task definition required??? I guess not!

so I can delete thi the 2 following lines

//   DAQmxErrChk (DAQmxCreateTask("",&Task_CLK_FromBoard));
//   DAQmxErrChk (DAQmxCreateDIChan (Task_CLK_FromBoard, "/Dev1/port2/line3", "", DAQmx_Val_ChanPerLine ));

 

   DAQmxErrChk (DAQmxConnectTerms ("/Dev1/port2/line3",  "/Dev1/PFI5", DAQmx_DoNotInvertPolarity));  // should I define this line in the Main?
   DAQmxErrChk (DAQmxCreateTask("",&taskRead));
   DAQmxErrChk (DAQmxCreateDIChan (taskRead, "Dev1/port0", "", DAQmx_Val_ChanForAllLines));      
   DAQmxErrChk (DAQmxCfgSampClkTiming(taskRead, "/Dev1/PFI5", rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, sampsPerChanToAcquire));
   DAQmxErrChk (DAQmxReadDigitalLines (taskRead, sampsPerBuffer, 10.0, DAQmx_Val_GroupByChannel, data, sampsPerBuffer*numChannels, &sampsRead, NULL, NULL));

 

These fews lines should be enought to read data each time a clock is send on PFI5. Am I wrong?

thank you and best wishes

Carlo Alberto

         

0 Kudos
Message 7 of 11
(5,450 Views)

Hi,

 

I cannot delete the post I wrote this morning, but after some reading I guess I am still wrong.... Smiley Embarassed

I have an hardware clock coming from my electronic board, generating the number of sample I want which has to drive the acquisition of data on Dev1/port1.

 

The first question regards the routing.

Can I route a signal coming from Dev1/port2/line3 to PFI5?

 

By looking at the "Device Routes" in MAX, apparently I cannot do it, because I have not explicity found the route, but I found I can use RTSI7 as an input clock to route to PFI5, and then Dev1/port0.

Of course, I did not know what was a RTSI and I had to get more information.

 

The second question is: If I cannot directly route Dev1/port2/line3 to PFI5, and I have to use RTSI7 do I have to physically connect a wire between my electronic board and the pin 34 (see table below)? [It is not a problem because I can do it]

Third question: do I have to add and configure RTSI7 (which it appears as RTSICable0) in MAX?

And finally: when I am importing my hardware clock and using it on RTSI bus, does it interdict the onboard clock?

 

Clocking Block Diagram  

 

RTSI Bus Pinout for PCI boards: Pinout for AT boards:
RTSI_OSC (clock) 34 1
RTSI 6 32 3
RTSI 5 30 5
RTSI 4 28 7
RTSI 3 26 9
RTSI 2 24 11
RTSI 1 22 13
RTSI 0 20 15
Not Used 1-18 (all) 17-34 (all)
Ground 19-33 (odd) 2-16 (eve

 

Sorry for previous morning posts I have been shallow

Many Thanks

Carlo Alberto

0 Kudos
Message 8 of 11
(5,439 Views)

Hi Carlo,

 

Unfortunately, it is not possible to internally route a data line to the clock of the 6535.  Ideally, you would have a breakout board (such as a CB-2162) that would allow you to manually connect the line your clock is on to PFI 5 on the connection block.  I'm unsure how you interface with your DUT, but if it is straight to a VHDCI connector, that will mean a major modification would be necessary on the DUT side to get that signal over to PFI 5.  

 

RTSI, as you probably know, is the 34 pin connector on the hardware itself that is intended for synchronizing multiple PCIe boards together.  Those lines do have access to the clock circuitry, and if you can find a way to route your DUT clock signal to that line, then you can route it to the internal clock circuitry on the 6535.  This is not a supported method for importing a clock, and I would still recommend trying to go through an accessory, but it may be easier for your application somehow to route the signal there.  You would need a physical wire to go from the clock to the RTSI 7 line.

Kyle A.
National Instruments
Senior Applications Engineer
Message 9 of 11
(5,433 Views)

Hi Kyle,

 

thank you for the support.

I guess I have not other short, easy and cheap solution to apply to my case.

I do need to route my hardware clock (imported from DUT) to PFI5 to fully manage the acquisition. By changing the electronic board logic I can define the number of samples to acquire each cycle then the number of clock generated from DUT, and this flexibility make a real difference on the whole acquisition method (electronics + software).

 

By assuming that I have physically connected the clock from DUT to RTSI7 (pni 34 on RTSI bus),  the following lines of code should be enough

from making 1 acquisition, or I am still missing something?

 

   DAQmxErrChk (DAQmxConnectTerms ("/Dev1/RTSI7",  "/Dev1/PFI5", DAQmx_DoNotInvertPolarity)); 
   DAQmxErrChk (DAQmxCreateTask("",&taskRead));
   DAQmxErrChk (DAQmxCreateDIChan (taskRead, "Dev1/port0", "", DAQmx_Val_ChanForAllLines));      
   DAQmxErrChk (DAQmxCfgSampClkTiming(taskRead, "/Dev1/PFI5", rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, sampsPerChanToAcquire));
   DAQmxErrChk (DAQmxReadDigitalU8 (taskRead, sampsPerChanToAcquire, 10.0, DAQmx_Val_GroupByChannel, data, sampsPerChanToAcquire, &sampsPerChanToAcquire, NULL));   

 

I know that the method I am using is not supported, but do you think tha PCIe card could be damaged even if I respect signal constraints?

Many Thank
Carlo Alberto Cecchetti

 

 

 

 

0 Kudos
Message 10 of 11
(5,424 Views)