Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

DAQmx - Continuous Reconfigurable Waveform Generation - Frequency Shifting with C++

Dear all,
I would like to have your advice on how to achieve shifting the frequency of a continuous sinusoidal Analog voltage waveform. I am using a NI-6062E and I want to shift from 500Hz to 1500Hz in 20Hz per step? I am using Measurement Studio 7.1 & NIDAQ7.4 on VStudio.Net, and I am developing in C++.
 ,however the freq is adjusted manually, I think it can be programmed to shift in steps.
I wonder if there is a similar example for MStudio and C++?
Please advise, and thank you all.
 
Regards,
Rolly
0 Kudos
Message 1 of 10
(5,881 Views)
Rolly,

You should be able to alter the shipping example that comes with DAQmx 7.4

ContGen-IntClk.c

Take the section of the example code below
---------------------------
    while( !done && !_kbhit() ) {
        /*********************************************/
        /*/ DAQmx IsDone Code
        /*********************************************/
        DAQmxErrChk (DAQmxIsTaskDone(taskHandle,&done));

        if( !done )
            Sleep(100);
    }
-----------------------------
and add the following code after the DAQmxlsTaskDone function

DAQmxErrChk (DAQmxWriteAnalogF64(taskHandle,1000,0,10.0,DAQmx_Val_GroupByChannel,data,&written,NULL));

You will need a conditional statement which will run the DAQmxWriteAnalogF64 function at the proper times.  This will update the output buffer so that it contains new sinusoudal data which has the right frequency.

Use the code below (which is also in the example program) to create your sine wave
------
    for(;i<1000;i++)
        data[i] = 6.95*sin((double)i*2.0*PI/1000.0);
------

I hope this helps,
Lorne Hengst
Application Engineer
National Instruments


0 Kudos
Message 2 of 10
(5,871 Views)

Hello Lorne,

I have a very basic question, how do I adjust the output waveform frequency from the formula and DAQmxWriteAnalogF64:

(1)for(;i<1000;i++) data[i] = 9.95*sin((double)i*2.0*PI/1000.0);

(2)DAQmxWriteAnalogF64(taskHandle,1000,0,10.0,DAQmx_Val_GroupByChannel,data,&written,NULL)

I notice if I change the 1000 in data[i] = 9.95*sin((double)i*2.0*PI/1000.0) to 100, 10 respectively, the output freq change from 1Hz, 10Hz then 100Hz, but the waveform becomes no longer sinusoidal but with sharp square steps. I know this is no a proper way to change the output frequency so I need your advice on what to do?

Thank you!


 

0 Kudos
Message 3 of 10
(5,866 Views)
Rolly,

You are very close to the proper solution. 1000 is the period of the sine wave and 1/1000 is the frequency, so changing that value will change your signal to the proper frequency.  In actuality, the for loop does not create a sine wave of any given frequency, because we have not given the array any time information.  The time information comes into the picture once we use the DAQmxCfgSampClkTiming function.  The output frequency declared in your DAQmxCfgSampClkTiming function determines the frequency of the sine wave.

The problem you are running into is caused by the fact that the number of data points sent to the buffer remained the same, the output frequency stayed the same, but the frequency of your sine wave changed.

This creates a problem, the beginning and the end of the sine wave created in the for loop does not match up.  So basically, every 1000 data points you will see a large jump from one voltage to another.  In your case you will jump from (assuming you used 100 as your period) 8.85 volts to 0 volts.

The easiest way to change frequency is to not change the freqency used in the for loop, rather, just change the frequency in the DAQmxCfgSampClkTiming function.

The original example used the for loop to create a sign wave containing 1000 data points.  If we set the output frequency of your device (using DAQmxCfgSampClkTiming) to 1000 Hz, then your device will output a sine wave at 1 Hz.  If we set the output frequency of your device to 2000 Hz then your device will output a sine wave at 2 Hz.

The other way to change the frequency of your output is to change the for loop equation.  Instead of creating a 1000 data point sine wave, you can create a 100 data point sine wave (check the for loop example below).

----------
for(;i<100;i++) data[i] = 9.95*sin((double)i*2.0*PI/100.0);
----------

That for loop will create one period of a sine wave that is composed of 100 data points instead of 1000.  Now, when you use an output frequency of 1000, your device will output a sine wave with a 10 Hz frequency and an output frequency of 100 would cause your device to output a sine wave with a 1 Hz frequency.

In your case, the best solution is to change the sine wave created in the for loop instead of changing the output frequency of your device.  To do this succesfully, make sure your for loop only iterates enough times to create one period of a sine wave (like above).  Then, when you use the DAQmxWriteAnalogF64 function, only write 100 points to the buffer instead of 1000 points.  Below is an example of the for loop and the DAQmxWrite function which will allow you to output a sine wave at 100 Hz (assuming the DAQmxCfgSampClkTiming function has the output frequency set to 1000 Hz).

----------
for(;i<10;i++) data[i] = 9.95*sin((double)i*2.0*PI/10.0);
----------
DAQmxWriteAnalogF64(taskHandle,10,0,10.0,DAQmx_Val_GroupByChannel,data,&written,NULL)
----------

This will create a horrible sine wave because each period only consists of 10 data points.  To increase the number of data points, you would have to also increase the output frequency.

Glad to help,
Lorne Hengst
Application Engineer
National Instruments
0 Kudos
Message 4 of 10
(5,856 Views)

Hello Lorne,

I can change the output freq if I change the "10" to "100" and get a smooth sinusoidal wfm,

----------
for(;i<10;i++) data[i] = 9.95*sin((double)i*2.0*PI/10.0);
----------
DAQmxWriteAnalogF64(taskHandle,10,0,10.0,DAQmx_Val_GroupByChannel,data,&written,NULL)
----------

But how can I change the wfm output freq on-the-fly by specifying

the beginning freq, ie. 500Hz;

the ending freq ie. 1500Hz;

the freq step ie. 20Hz;

Within a period of, say, 2 seconds?

I try to change something called Sample Clock Timebase Divisor, with can do the similar thing of varying output wfm freq, but I cannot adjust it with the program is running? Is this another approach?

thank you!

0 Kudos
Message 5 of 10
(5,841 Views)
Rolly,

I think you almost have it.  In order to change your waveform on the fly you will either need to create the waveform in while loop (with the for loop) or, if you know that you will only output 3 different frequencies, create 3 waveforms (3 data arrays).

If you want the waveform to be changed every 2 seconds, you will have to use some type of timer (you will have to see what type of timer functions are available in C) and have your program execute the write function every 2 seconds.

Let me reiterate.

either run the code below inside your while loop
for(;i<10;i++) data[i] = 9.95*sin((double)i*2.0*PI/10.0);
and create a new data array when you need one.

or

in the beginning of the program create multiple arrays
for(;i<1000;i++) sine1[i] = 9.95*sin((double)i*2.0*PI/1000.0);
for(;i<100;i++) sine10[i] = 9.95*sin((double)i*2.0*PI/100.0);
for(;i<10;i++) sine100[i] = 9.95*sin((double)i*2.0*PI/10.0);
and write the array you want to see on the output using the DAQmxWrite function every 2 seconds.

Lorne Hengst
Application Engineer
National Instruments
0 Kudos
Message 6 of 10
(5,832 Views)

hi Lorne,

I managed to fulfill my objective please have a look at the attached c file. And I discovered something strange as I limit the freq shifting process within 2000 msec:

If I set the min freq 500Hz, max freq 1500Hz, freq step 20Hz, it finish shifting within 2 sec;

if I changed max freq to 5000Hz with the rest 2 parameters unchanged, it takes longer than 2 sec to complete shifting; and if i set Sleep(1) inside the FOR loop, it is the same, taking more than 2 sec to complete the shift!? If I set Sleep(0) then there is no delay, I wonder what had happened to the Sleep()??

Can you help? Thank you.

Regards

Rolly

 

Message Edited by Rolly on 07-09-2005 07:51 PM

0 Kudos
Message 7 of 10
(5,824 Views)
Rolly,

I think I know what is going wrong.

I believe windows XP/2000/NT use a timer with a minimum time step of 10 ms.  Thus, if you tell the computer to sleep for 5 ms it will actually sleep for 10 ms.
So, if you tell it to sleep for 1 ms, it will sleep for 10ms.  When you tell the computer to sleep for 0 ms, it actually does that.

You will probably need to use a different function to pause your program, or create your own delay using a for loop.

Lorne Hengst
Application Engineer
National Instruments
0 Kudos
Message 8 of 10
(5,807 Views)

Dear Lorne,

I have a question related to your conversation with Rollie.  Maybe you, or someone, can help me.  I also want to change my output waveforms on the fly.  I want to continuously cycle through one waveform, and then do a DAQmxWrite to switch to another waveform, also continuously cycled.  But I need to carefully control the signal continuity and slope at the transition point.  I can make sure that the digital signal at the tail of one output buffer lines up with the digital signal at the head of the next.  But when I do the DAQmxWrite in the middle of a continuously cycling analog output, will the output complete a pass through the one buffer before switching to the next, or will it switch over in the middle of the buffer, as soon as the DAQmxWrite executes, causing a discontinuity in the analog signal?  Is my question clear?

Josh Moses

 

0 Kudos
Message 9 of 10
(5,740 Views)

Hello Josh,

The DAQmx Write function will finish writing the old buffer before writing the new one.  If the endpoints of your buffers match up, you shouldn't see any discontinuity.

Regards,
Sean C.

0 Kudos
Message 10 of 10
(5,726 Views)