Pages: [1]   Go Down

Author Topic: Generating a Sine Wave  (Read 1491 times)

W9AC

  • Member
  • Posts: 373
Generating a Sine Wave
« on: September 14, 2019, 09:50:02 AM »

I need to generate a low distortion (< 0.5%) sinewave on a fixed frequency near 2 kHz.  I would like to ramp the waveform up/down in 3-5  ms or so. What's the best and/or easiest way to accomplish this using a microcontroller?

I am already using a homebrew Wein bridge oscillator and VCA for ramping but want a digital solution. References to material that actually assist with programming code would be most helpful. 

Paul, W9AC
Logged

N8AUC

  • Member
  • Posts: 1007
RE: Generating a Sine Wave
« Reply #1 on: September 14, 2019, 10:32:51 AM »

I get what you're trying to do, but your request actually lacks some important details. For instance, what kind of microcontroller do you intend to use? It's rather difficult to point you at some code, if we don't know what kind of CPU you're using. You also don't specify what you want the amplitude of your sine wave to be, or how much current you need to source, and that matters quite a bit as well. Temperature stability is also a concern, and you didn't mention that either.

The general idea, assuming you have some dedicated pins on a data bus you can use, is to set a bit to 1, wait half the period, then set that same bit to zero. For 2KHz, the period is 0.5 mS. So set the bit to 1, wait 0.25 mS, then set the bit to zero, wait 0.25 mS, and repeat the process. You could use an on-chip counter timer to trigger an interrupt to tell you it's time to change the bit value, assuming your CPU has one. That will allow you to avoid writing a delay loop for the timing. The benefit of not using a delay loop, is your timing becomes independent of the processor clock speed. Doing that gets you a square wave with a frequency of pretty close to 2 KHz. You could also use a D-type flip flop, and strobe the clock line on the flip flop once every half period.

If your processor has an on-chip D/A converter, you can simply cycle values to the D/A to generate any waveform you want. How many updates you do to the D/A value within the desired period of the output waveform will govern how close an approximation to an actual sine wave you get.

Now you want it analog, and low distortion. Well, since the square wave is the fundamental frequency plus all the odd order harmonics, all you have to do with the square wave you've generated off a data pin, is filter out all the harmonics. Since we're working with an audio frequency, there are lots of ways you can do that. Basic choices are an active analog low pass (or band pass) filter (op-amps), or a passive analog low pass (or band pass) filter. Use care in the component parameters you choose to ensure temperature stability, because as the temperature changes, so will the component values for the parts you use, which will cause the cutoff frequency of your filter to shift as the temperature changes. Pick your filter cutoff frequency to be slightly above 2 KHz if you're using a low pass filter, so you can avoid the 3dB point on the filter roll off. You might need more than one stage in cascade to improve the Q of your filter and make the roll off steeper. The benefit of using op-amps, is you can give your filter a little voltage gain to keep the amplitude where you want it, and overcome any insertion losses for the filter. If you use a passive filter, you're going to lose a little amplitude due to insertion losses of the filter. Overcoming the insertion loss will require an amplifier with a little gain anyways, so you might as well cut to the chase and go with the active filter method using op-amps in the first place.

If you chose the D/A converter method, you're still going to have to filter out the harmonic content.

You mention ramping up the waveform. Not sure what you mean by that. The rise time of a 2 KHz sine wave from zero to maximum is going to be T/4, or 0.125 mS. That is well within your 3-5 mS limit. Or, do you mean modulating that 2 KHz sine wave with a triangle wave, to cause the peak values of your sine wave to rise and fall in step with the triangle wave.

Hope this helps, at least a little bit.

73 de N8AUC
Eric

« Last Edit: September 14, 2019, 10:41:49 AM by N8AUC »
Logged

W9AC

  • Member
  • Posts: 373
RE: Generating a Sine Wave
« Reply #2 on: September 14, 2019, 11:14:27 AM »

I am open concerning the type of CPU.  As to amplitude, I can amplify and filter the output from the microcontroller with high-performance op-amps so that's of little concern.  I'm well-versed in analog signal and switching techniques; I am trying bridge the gap to digital signal generation.  Visit my QRZ page and you'll see some past and present projects using an Arduino Nano controller.

By ramping, I mean an output that transitions from zero to full level between 3-5 mS.  Presently, I use a voltage controlled amplifier to ramp the waveform.  Ramping reduces bandwidth during the switching activation and deactivation of the tone.  Think of a raised-cosine CW generator used in today's SDR transceivers. 

Any sources to on-line examples?  Thanks.

Paul, W9AC



 
Logged

W6BP

  • Member
  • Posts: 629
RE: Generating a Sine Wave
« Reply #3 on: September 14, 2019, 11:28:25 AM »

Visit my QRZ page and you'll see some past and present projects using an Arduino Nano controller.

That's one very impressive QRZ page.
Logged

N8AUC

  • Member
  • Posts: 1007
RE: Generating a Sine Wave
« Reply #4 on: September 14, 2019, 09:02:08 PM »

Visit my QRZ page and you'll see some past and present projects using an Arduino Nano controller.

That's one very impressive QRZ page.

Indeed. Very impressive.

I'd go with an Analog Devices ADuC832.
Everything you could possibly want is on one IC. And it uses an 8051 core.
I've always liked the 8051 architecture. And it's not that expensive either.

Here's a link to the data sheet and app notes...
https://www.analog.com/en/products/aduc832.html#product-overview


Logged

W9AC

  • Member
  • Posts: 373
RE: Generating a Sine Wave
« Reply #5 on: September 15, 2019, 11:33:21 AM »

Visit my QRZ page and you'll see some past and present projects using an Arduino Nano controller.

That's one very impressive QRZ page.

Indeed. Very impressive.

I'd go with an Analog Devices ADuC832.
Everything you could possibly want is on one IC. And it uses an 8051 core.
I've always liked the 8051 architecture. And it's not that expensive either.

Here's a link to the data sheet and app notes...
https://www.analog.com/en/products/aduc832.html#product-overview

Eric, many thanks.  I'll start looking into this.

Paul, W9AC
Logged

PE1HZG

  • Posts: 86
    • HomeURL
RE: Generating a Sine Wave
« Reply #6 on: September 17, 2019, 11:20:22 AM »

I need to generate a low distortion (< 0.5%) sinewave on a fixed frequency near 2 kHz.  I would like to ramp the waveform up/down in 3-5  ms or so. What's the best and/or easiest way to accomplish this using a microcontroller?

The way I normally do this is using a pulse width modulator (PIC and ATMEL both have them) on a high frequency, as high as your hardware will do. By changing the pulse with, you change the average output voltage. You keep the frequency of the pulse width generator the same.

The code generating the sine wave is a tight loop that has *exactly* the same execution time each loop iteration, each loop adds something to a 16-bit or 24-bit value The highest bits of this value, via a sine lookup table, generate the values for the pulse width generator. I typically use assembly for this - code isn't difficult.

What is left is the increment, the "something" in previous section. This decides the frequency you generate.

At the output of the pulse width generator, use a simple low-pass (R-C) filter. When you look at the pulse width output directly it looks horrible, after the RC network the sine is perfect. Note that what you are essentially doing is noise shaping - by bringing the unwanted signals octaves above the desired signal, the R-C attenuation really helps.

The faster the pulse widths and the faster the iteration loop adjusting the value, the better the result.

As to the sine table (the table converting the 24-bit phase value to pulse widths), note that you can improve the result by changing the DC offset and the amplitude. I found a spread sheet, measuring the residual error after a full sine wave, really instructive.

Note that this isn't unlike how a DDS works.

73, Geert Jan
Logged

W9AC

  • Member
  • Posts: 373
RE: Generating a Sine Wave
« Reply #7 on: September 18, 2019, 04:35:38 AM »

Excellent info.  Many thanks.

Paul, W9AC
Logged

SM0AOM

  • Member
  • Posts: 325
RE: Generating a Sine Wave
« Reply #8 on: September 20, 2019, 12:06:57 PM »

All previous realisations are workable, but a simple one that gives very good performance has been overlooked, the binary counter and EXOR gate D/A converter.

It is shown on page 385 of Don Lancaster's CMOS Cookbook.

When clocked at 8 times the required output frequency with a
2-section Chebyshev lowpass filter after, it can generate sine waves with a distorsion so low that it was difficult to measure.

When a variable output amplitude is needed, one simple expedient is to vary the supply voltage to the EXOR-gates.

Otherwise, a multiplying D/A converter using a sine look-up table in firmware does also fulfill the requirements.
One problem may be to keep the update rate exactly uniform, especially if the microprocessor has to perform other tasks.

An 8-bit D/A converter must be updated at exactly 500/256 µs intervals to generate 2 kHz, which may tax the capabilities of interrupt-driven systems.
 
Logged

AE5GT

  • Member
  • Posts: 412
RE: Generating a Sine Wave
« Reply #9 on: September 23, 2019, 09:59:06 AM »

I am thinking that I would try two single bit DAC s , driving one pin 0,1  at 2 Khz generating a square wave , drive the second pin at 4khz and combine the two with a op amp subtract/add circuit , leaving just the 2 khz sine fundamental . Any micro should work PIC / Atmel .

At least I would try that because it doesn't require an A to D .
Logged
Pages: [1]   Go Up