Discussion:
Generation Buffer Control
(too old to reply)
FrustratedwithDAQmxHelp
2007-09-25 14:40:15 UTC
Permalink
Hi Guys, I need to generate a large buffer for pattern generation and do not want to duplicate the memory requires. It seems to me if I use:DAQmxWriteDigitalU16(OutTaskHandle,OutBufPnt,0,0,DAQmx_Val_GroupByChannel,OutBuf,NULL,NULL)I have to allocate space for the buffer OutBuf (in this case), write my vectors to this buffer and then DAQmx will duplicate this buffer and copy it to another memory space, thus require two large buffers (which I do not have enough memory for). 1. Can I not just create the DAQmx buffer and write to it directly?2. If so how do I do this?My second part of this question is that I also need to alter some of the vectors in my buffer, recopy this vector buffer to DAQmx buffer and the rerun the entire set. I do this in the loop shown below:   for (count1=0;count1<TotalSequencesInAquisition;count1++)   {/* Load vector buffer with correct DAC codes */
      InsertDACCodeToConvVectors(DACBuf,OutBuf,DACPointer,DACCodesPerSequence,count1); 
/* DAQmx Start Pattern Generation */       DAQmxErrChk (DAQmxWriteDigitalU16(OutTaskHandle,OutBufPnt,0,0,DAQmx_Val_GroupByChannel,OutBuf,NULL,NULL));       DAQmxErrChk (DAQmxStartTask(InTaskHandle));       DAQmxErrChk (DAQmxStartTask(OutTaskHandle));       DAQmxErrChk (DAQmxWaitUntilTaskDone(InTaskHandle,10));       DAQmxErrChk
(DAQmxReadDigitalU16(InTaskHandle,DataPerSequence,0,DAQmx_Val_GroupByChannel,&DataBuf[DataPerSequence*count1],DataPerSequence,NULL,NULL));       DAQmxErrChk (DAQmxWaitUntilTaskDone(OutTaskHandle,10));       DAQmxErrChk (DAQmxStopTask(InTaskHandle));       DAQmxErrChk (DAQmxStopTask(OutTaskHandle));   }The issue is that this runs correctly the first time through but the second time it does not seem that the updated OutBuf buffer is being copied to the DAQmx buffer and the first set of vectors are simply rerun. 1. What am I doing wrong?I suppose if my first question is answered then the second is probably not relevant. However, I still am a little baffled as to why this does not work.Thanks
FrustratedwithDAQmxHelp
2007-09-27 11:40:10 UTC
Permalink
Paul,
 
Thanks for the response. The buffer size needs to be as large as I can make it. I am already breaking it up into smaller chunks (1024 to be more specific). What I am finding is DAQmxWriteDigitalU16 seems to fail if I attempt to make the buffer larger than 512Mbytes. My machine has 4Gbytes. I can live with 512Mbytes as long as I can get DAQmxWriteDigitalU16 to reload the buffer and run the new vectors each time through the loop. What it is currently doing after stopping the task and then recalling DAQmxWriteDigitalU16 is simply rerunning the vectors in the first call of DAQmxWriteDigitalU16.
 
As I understand what is currently happening is I create my own 512Mbyte buffer in which I generate the vectors, then DAQmx generates another 512Mbyt buffer and copies my buffer to its buffer and then run the vectors from its buffer. What I would prefer to do is create the DAQmx buffer with the buffer create command and then write my vectors directly to that buffer and then run them straight from this single buffer.
 
If this is not possible, then I can go ahead and do what I am currently doing but release my buffer after it is copied to the DAQmx buffer with DAQmxWriteDigitalU16 call and then I would like to directly manipulate the DAQmx buffer with my vector updates (I need to change only about 1% of the vectors each time through the loop). By releasing this redudant buffer, I have more space for the input data storage buffer, which needs to be even larger (at least 2Gbytes).
 
I am not sure I made sense here but I will read the links you have pointed me to and hopefully they will give me some clues on how to proceed.
 
Thanks
FrustratedwithDAQmxHelp
2007-09-30 17:10:09 UTC
Permalink
Thanks Paul,
 
I am using BorlandC 5.02 and DAQmx 8.3. Attached is the main program (test.c) and the function of interest (runconversion.c) and the custom header (AC80TrimHeaders.h). There are 3 other subroutines needed but the system will only allow me to attach 3 files. If you send and email address I will forward the other functions.
 
Note that in the final application EndDAC=2^22, StartDAC=0, StepSize=1, ConvPerDACCode=32, thus MemoryInConvVectors=17408*2^22 and TotalSequencesInAquisition=72. More simply, I am running a 22-bit DAC over all codes sampling it 32 times per code (with some settling time)
Look at lines 142 to 173 in runconversion.c for the DAQmx setup and calling. Most likely I am just doing something stupid as the DAQmx C function reference manual is both woefully incomplete and obscure (thus the user name FrustratedWithDAQmxHelp). Please let me know if you see something wrong here. What this does is time I run DAQmxStartTask(OutTaskHandle), I seem to get the set of vectors copied by the first call to DAQmxWriteDigitalU16. Thus subsequent passes through the loop produces the same set of output vectors.
 
One thing you mentioned that I was hoping you would elaborate on (although I may just be misunderstanding you) is the idea of what use to be called double buffering in the older versions of DAQ. I could not see how to do this with DAQmx, however, I would like to do this with this application. With the present way I have written this, there is a delay between segments while the function InsertDACCodesToConvVectors copies new DAC codes to the buffer and then DAQmxWriteDigitalU16 recopies that buffer before the next segment runs. It would be nice if that delay did not exist.
 
Is there a way to use two buffers and while the first is being outputted, we generate a second and as soon as the first is completed, we start the second. Note that my clock speed is 40MHz.
 
Thanks again.
 


AC80TrimHeaders.h:
http://forums.ni.com/attachments/ni/70/7509/1/AC80TrimHeaders.h


test.c:
http://forums.ni.com/attachments/ni/70/7509/2/test.c


RunConversion.c:
http://forums.ni.com/attachments/ni/70/7509/3/RunConversion.c
jcarbonell
2007-10-01 14:40:10 UTC
Permalink
FrustratedwithDAQmxHelp wrote:Is there a way to use two buffers and while the first is being outputted, we generate a second and as soon as the first is completed, we start the second. Note that my clock speed is 40MHz.
 
Thanks again.
 Yes, there is.  Configure the DAQmx Buffer size to be smaller than your total generation size, before starting the task, write enough to fill the buffer, start the task, and then start writing.  DAQmx internally will double buffer for you.  Assuming that your application can compute the data fast enough for the buffer, you won't need a large working set for the generation side.Changing the subject a little, but why does RunConversion.c configure the 6537 to allow regeneration and pause until data is available?Jeff
FrustratedwithDAQmxHelp
2007-10-01 15:10:10 UTC
Permalink
Jeff,
 
How is synchronization maintained? I do not see how what you are proposing will work. Can you give me an example code?
 
To answer your question, I have no idea what 95% of the DAQmx functions do because the documentation is so poor. Please do something to get better documentation because what I have (which I have been told by several NI employees is all that there is) is insufficient to actually compentently use this hardware. Thus I am left to a frustrating trial and error approach to writing the interface code to this board. I have attempted several combinations of allowing and dissallowing regeneration as well as states of pause data and have not been able to correllate the response of the card to either. Quit frankly I have no idea what these functions are suppose to do outside the vague implecations of their names.
 
The hardware I am attempting to test does not require pause control for pattern generation. It can run as fast as the card can feed it data. What is important to me is that there is no jitter. If I have to run a bit slower to not get jitter, that is fine.  I am providing and external clock (really a data valid input) to the InTaskHandle task to aquire states of port2 at certain times during the pattern generation.
 
I would like to use double buffering so I can generate 2^27 conversions in a continuous manner. Since I compute and write all of the vectors to memory prior to starting the pattern generation, I beleive the PC should be able to keep up as it only has to copy from one buffer to another. However, I would not know how to implement what you are suggesting. Any assistance you can provide (examples are most helpful) would be much appreciated.
 
Thanks again
 
Larry
FrustratedwithDAQmxHelp
2007-10-02 02:40:13 UTC
Permalink
Paul,
I appreciate your reply. I have looked at all of the examples that you refer to. Without those I would certainly have gotten nowhere. However, they are limited. I can honestly tell you with what you have given me on the double buffering, I will not succeed. There are far too many options and subtile nuances involved and resolving each takes far longer than I have time. It would be much better for either better documentation on the each function to be provided or for you to give me more details (like an actual example). In the mean time do you have any idea why my exiting code keeps output the state of the first buffer call.
 
Thanks Larry
FrustratedwithDAQmxHelp
2007-10-19 13:10:14 UTC
Permalink
Thanks Jeff,
 
Sorry for being so slow on this. I guess I am so use to thinking on a low level, that when you say DAQmxWriteDigitalU16 will handle the additional calls, I find that hard to believe. If I am understanding you correctly, you are saying DAQmxWriteDigitalU16 will queu all of my additonal calls until the buffers become available.
 
How will it avoid lossing data as I am only clocking out so fast and I am sure I will generated it faster than it clock out? There is not enough memory in the machine for everything I am going to stream at it. Is it going to try to write it to disk? Would it not be better for me to wait until some of the buffers free up?
 
Thanks Larry
Paul C.
2007-10-19 21:10:15 UTC
Permalink
Hi Larry,

Your first statement is correct in that DAQmxWriteDigitalU16 will queue the additional calls until the buffer becomes available.

In regards to your second question, I understand your concerns with
memory usage with writing such a large array of data.  This is why you
will want to generate the data in chunks which may require setting up
some type of delay between calling the DAQmxWriteDigitalU16 function
calls.  I believe the DAQmxRegisterEveryNSamplesEvent might help you
accomplish this task.  This event counts the samples that are sent from
PC memory to the DAQ onboard memory.  This will allow you to time
exactly when you start loading your next array chunk from disk or start
generating it to memory.  This will help you avoid running out of
memory.  For example, lets say that you have 1GB of data you need to
output.  First, you can load 200MB with the first DAQmxWriteDigitalU16
to the output buffer.  Now you can wait for 50,000,000 samples to be
written (2 Bytes per sample so 100MB) and then you can start writing
your next 100MB chunk of data with another DAQmxWriteDigitalU16.  You
can continue to do this until you have written the entire 1GB of data. 
This also guarantees that there will be at least 100MB of data in the
buffer at all times.  This would essentially follow the same pseudocode mentioned by Jeff except adding a step between 3 and 4 to wait for this event.

This is demonstrated in a different type of application in the example found <a href="http://zone.ni.com/devzone/cda/epd/p/id/4800" target="_blank">here</a>.&nbsp; You might like to take a look at this example and see how they use the event for analog output.

I hope this helps,
Paul C.
jcarbonell
2007-10-22 14:10:14 UTC
Permalink
FrustratedwithDAQmxHelp wrote:Thanks Jeff,
&nbsp;
Sorry for being so slow on this. I guess I am so use to thinking on a low level, that when you say DAQmxWriteDigitalU16 will handle the additional calls, I find that hard to believe. If I am understanding you correctly, you are saying DAQmxWriteDigitalU16&nbsp;will queu all of my additonal calls until the buffers become available.
&nbsp;
How will it&nbsp;avoid lossing data as I am&nbsp;only clocking out so fast and I am sure I will generated it faster than it clock out? There is not enough memory in the machine for everything I am going to stream at it. Is it going to try to write it to disk? Would it not be better for me to wait until some of the buffers free up?
&nbsp;
Thanks LarryHi Larry,What DAQmx does is it allocates a buffer for you. The hardware accesses only this buffer.&nbsp; Usually, the buffer size is the size of the DAQmx Write that you perform before starting the task.&nbsp; With this first write, DAQmx will memcpy your buffer into its buffer.&nbsp; After you've started the task, DAQmx Write will wait for space in the buffer before performing the memcpy.&nbsp; The device generates an underflow error (1) if the device is generating data faster than what the bus can give, or (2) if regeneration is disallowed and the software hasn't notified the hardware that it can transfer more data and the internal FIFOs have drained.Also, if the amount of data in the DAQmx Write call is bigger than the buffer, the DAQmx write call will break up the writes into smaller writes.It's probably more efficient if you just do your writes in a loop.&nbsp; You may want to put the write loop in a separate thread if your application provides some kind of a GUI:void writeLoop(){ &nbsp;&nbsp; bool started = false;&nbsp;&nbsp; configureDAQmxTask();&nbsp;&nbsp; while (haveMoreData()) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write(Data);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!started) { started = true; startDAQmxTask() }&nbsp;&nbsp; }} Hope this helps,Jeff
Loading...