I am trying to develop a system that can output a square wave signal, with a variable frequency. I want to be able to input the minimum and maximum frequency and the number of steps, so that the frequency of the square wave can be changed:
a) from minimum up to the maximum frequency and then back down to the minimum and
b) from the minimum up the maximum frequency and then starting again at the minimum and working back up to the max frequency in defined steps.
any help or advice would be appreciated
What DAQ device(s) do you have available? How accurate / precise must the timing of the step changes be?
It's pretty easy to generate a pulse train with a counter and change the frequency on the fly via software calls. Some newer devices (X-series, others based on DAQ-STC3 timing chip) would let you predefine the entire pattern and have extremely precise timing for the step changes.
I have a C series NI 9381 running through a cRIO 9035 controller. in terms of accuracy and precision I am not too sure
Sorry, I'm not familiar enough with the cRIO platform to give any further confident advice.
I think it'll be possible, but it may take more learning and work to implement well on either the real-time controller or FPGA. Hopefully someone else will chime in with more specifics.
There are two ways to do it. One is easy (2-state state machine), but not accurate. The other is harder but much more accurate (Direct Digital Synthesis).
The easy way is to use a single counter and a state machine - but it's HARD to . A square wave generator can be thought of as a two-state state machine, where each state is held for some period of time and the output is toggled. State 1 increments a counter from 0 to LOW_COUNT-1. While in state 1, your sqwave output is false (logic 0). When LOW_COUNT-1 is met, the state changes to State 2 and the counter clears to 0. While in state 2, your sqwave output is true (logic 1). Again, while in State 2, you're incrementing a counter from 0 to HIGH_COUNT-1. If HIGH_COUNT-1 is reached, transition back to state 1, reset counter. If high_count = low_count, then you have a 50% duty cycle square wave. Change high and low count relative to each other to modify the duty cycle.
Example: 100 MHz clock rate, implemented in SCTL on the FPGA. Desired a 300 KHz sq wave. 100 MHz = 10ns. 300 KHz = 3.33333 us. Since a pulse is both a rising and a falling edge, we need the output to go high and go low. Therefore we need the toggling to occur at 600 KHz = 1.66667 us. Your counter in the state machine increments by 1 each clock cycle, so each 10 ns. 1.6667us = 1666.7ns. 10ns fits into 1666.7 with a remainder (that fraction of a clock cycle is your frequency error) 1666.7/10 = 166.67 times. So HIGH_COUNT = LOW_COUNT = 167. You end up with a square wave with period 1670*2 = 3.540 us = 282.5MHz. If this is close enough - then cool! Otherwise, move to DDS.
The LabVIEW FPGA express VI "Sine Wave Generator" uses a DDS to generate very precise frequencies - and you can do the same thing with a square wave. Rather than priming a lookup table with a sine wave, instead fill it with a square wave. All the rest of DDS implementation is the exact same. Read the NI whitepaper here: