Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Sqaure Waveform Generation with DAQmx

0 Kudos
Message 11 of 17
(1,910 Views)

Hi Daniel,

Please also take a look at this link, someone else also has problem with no-regeneration mode Analog Output.

http://forums.ni.com/ni/board/message?board.id=250&message.id=13661&query.id=65563#M13661

Is it possible to output the waveform I attached?

Thx,

Rolly 

0 Kudos
Message 12 of 17
(1,900 Views)

Hi Rolly-

I agree with Alan's comment in the other thread- it doesn't seem that the error you are seeing is related to the non-regeneration setting but rather to something else in programming.  However, based on the diagram you posted it seems that the durations at each voltage level are basically set. 

If this is the case then the best method to avoid glitching and to avoid the necessity of continually writing buffer information "on the fly" is to write the entire buffer at the beginning and then simply clock it out.  Is it safe to assume that the timing of your output changes is set and will not change?  If so then this method is generally recommended for better results.

Thanks-

Tom W
National Instruments
0 Kudos
Message 13 of 17
(1,884 Views)
All right, I apologize for my being away. Rolly, the waveform generation you want to achieve is definitely possible. However, the example code you sent me is still using start and stop more than once, so let me give you a bit of code so I can better get my suggestion across.

These are the steps you have to follow to achieve the generation:
1. create two arrays of points, and fill them with your two waveforms (let's call the first one square_low_amp_data and the second one square_high_amp_data). Make sure they both have the exact number of points.
2. create the AO task, create an AO channel and configure the timing.
3. write square_low_amp_data to the channel
4. start the task
5. when you want to change the amplitude, write square_high_amp_data to the channel
6. any time you want to change the amplitude write the corresponding array.
7. stop the task.
8. clear the task

Note that the task is only created and cleared once, and also started and stopped once, throughout the entire application.
Also note that I changed my mind about the non-regeneration, due to the fact that you're using interrupts and PCMCIA, I don't think you would be able to consistently keep up if we go for the shortest latency.

And here's some psudocode (make sure you do error checking). This program will start by generating the low amplitude signal over and over, and do a sleep(10) every time there's no keypress. The waveform amplitude will change back and forth each time 'n' is pressed. If you press 'q' the program will end:

float64 square_low_amp_data[100];
float64 square_high_amp_data[100];
int quit = 0;
int currentWaveform = 1;
char character_received = NULL;

//ADD code here to fill your arrays

DAQmxCreateTask("",&taskHandle);
DAQmxCreateAOVoltageChan(taskHandle,"Dev1/ao0","",-10.0,10.0,DAQmx_Val_Volts,NULL);
DAQmxCfgSampClkTiming(taskHandle,"",200000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,100);
DAQmxWriteAnalogF64(taskHandle,100,0,10.0,DAQmx_Val_GroupByChannel,square_low_amp_data,&written,NULL);
DAQmxStartTask(taskHandle);
while(quit == 0)
{
    while(!_kbhit())
    {
         Sleep(10);
    }
    received_character = _getch();
    if(character_received == 'n' && current_waveform == 1)
    {
       DAQmxWriteAnalogF64(taskHandle,100,0,10.0,DAQmx_Val_GroupByChannel,square_high_amp_data,&written,NULL);
       current_waveform =2;
    }
    if(character_received == 'n' && current_waveform == 2)
    {
       DAQmxWriteAnalogF64(taskHandle,100,0,10.0,DAQmx_Val_GroupByChannel,square_low_amp_data,&written,NULL);
       current_waveform = 1;
    }
    if(character_received == 'q')
       quit = 1;
}
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);

I hope this solves the issue.

Daniel D

Message Edited by Quantumbyte on 08-18-2005 04:17 PM

0 Kudos
Message 14 of 17
(1,878 Views)

Hi Daniel,

Thank you for the advice, I did a little modification of your code to produce the 15Hz/2KHz sqwfm generation, please have a look at my code:

#include <NIDAQmx.h>
#include <windows.h>
#include <stdio.h>
#include <conio.h>

int main()
{
TaskHandle taskHandle;
int32 written;
float64 square_low_amp_data[100];
float64 square_high_amp_data[100];
int i,j;

//ADD code here to fill your arrays
for (i=0;i<50;i++)
 square_low_amp_data[i]=-1;
for (i=50;i<100;i++)
 square_low_amp_data[i]=1;

for (j=0;j<50;j++)
 square_high_amp_data[j]=-5;
for (j=50;j<100;j++)
 square_high_amp_data[j]=5;


DAQmxCreateTask("",&taskHandle);
DAQmxCreateAOVoltageChan(taskHandle,"Dev1/ao0","",-10.0,10.0,DAQmx_Val_Volts,NULL);
DAQmxCfgSampClkTiming(taskHandle,"",200000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000);
DAQmxWriteAnalogF64(taskHandle,100,0,10.0,DAQmx_Val_GroupByChannel,square_low_amp_data,&written,NULL);
DAQmxStartTask(taskHandle);

while(!_kbhit())
    {
    Sleep(33);
       DAQmxWriteAnalogF64(taskHandle,100,0,10.0,DAQmx_Val_GroupByChannel,square_high_amp_data,&written,NULL);

    Sleep(33);
       DAQmxWriteAnalogF64(taskHandle,100,0,10.0,DAQmx_Val_GroupByChannel,square_low_amp_data,&written,NULL);
    }

DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
return 0;
}

However I notice from scope display, the 15Hz component of this sqwfm is not stable, it jumps randomly form 64ms to 78ms, as attached BMP. Could you please have a look? I think the Sleep() function is the reason behind, is there way to lock-up this component at 66ms(15Hz)?

Thank you very much,

Rolly

0 Kudos
Message 15 of 17
(1,869 Views)

Hi Rolly-

I think you are definitely correct that the sleep function is causing the problem.  Because you are not using non-regeneration the output waveform will begin to loop automatically if the end of a segment is reached before new data is written.  In order to prevent this situation you need to make absolutely sure that you write to the buffer more frequently that it is emptied.

For instance, if your waveforms are composed of 100 points and your sample clock is running at 50Hz then you will be writing 2 seconds worth of data each time you write the information out to the buffer.  You just need to make sure that you add data to the buffer more frequently than the time it takes to reach the end of the current data to avoid re-writing the same samples again.  Decreasing or perhaps even removing the sleep command should aid in achieving this.

Hopefully this helps-

Tom W
National Instruments
0 Kudos
Message 16 of 17
(1,861 Views)
OK, if you already know exactly how long you want to generate each waveform, I suggest you write the exact number of points for that time (6600 points). Let's start by making your arrays 6600 points long, and filling them completely with square waves.
So before you write the 6600 points down set Regeneration Mode to non-regeneration, then write the points, start the task, and then simply remove all the sleep(33) from within your code, so that you're always writing to the buffer. That will give you the right behavior.
Of course, make sure to be writing 6600 every time you call the write function

Daniel D

Message Edited by Quantumbyte on 08-19-2005 10:46 AM

Message 17 of 17
(1,858 Views)