Pwm Sine Wave Synthesis Essay - Homework for you

Homework for you

Pwm Sine Wave Synthesis Essay

Rating: 4.0/5.0 (17 Votes)

Category: Essay

Description

Pwm sine wave generation

pwm sine wave generation

1. Overview Pulse Width Modulation (PWM) refers to a form of signal modulation where data is represented by the ratio of the on time to the total time (known as the duty cycle). PWM has the property where the instantaneous DC component is directly proportional to the duty cycle. It is primarily used for controlling digital encoded analog signal of varying amplitude. The relationship between the time-average voltage (Vavg) the high and low voltages of the square wave (Vhi and Vlo) and the duty cycle (D) in percent is as follows: Vavg = (Vhi - Vlo) * D + Voffset……………….……………………….……………….….[1] where D = tON / tW or D = PWDR value/1023 (for 10-bit PWM) …………………………[2] If Vhi is 5V, Vlo is 0V (i.e. Voffset = 0) and D is 80%, Vavg would be 4 V. Another important parameter of PWM is the frequency. It is defined by number of pulse per second. f = 1 / tW……………………………………………………………….….….….….….……[3] where tW = tON + tOFF…………………………………………………………….….…….[4] From equations [2] and [3], it can be proven that F = D / tON………………………………[4] 2.2 Basic Operation To use the 10-bit PWM, set the registers in the following 3 steps: 1. Select PWM channel: Set PWM1 or PWM2 in PMR9 to 1 for PWM channel to be used, so that pin P90/PWM1 or P91/PWM2 is designated as the PWM output pin. 2. Select Conversion Period: Set bits PWCRm1 and PWCRm0 in the PWM control register (PWCRm) to select a conversion period. 3. Set Pulse Width: Set output waveform data in PWDRUm and PWDRLm. Data should be first written to PWDRLm and then to PWDRUm for the same channel. One conversion period consists of 4 pulses, as shown in Fig. 2.2. The total of the high-level pulse widths during this period (TH) corresponds to the data in PWDRUm and PWDRLm. The waveform will be changed at the next conversion period. TH = (data value in PWDRUm and PWDRLm + 4) * tØ/2 Where tØ is the PWM input clock period: 1/Ø, 2/Ø, 4/Ø or 8/Ø 3. Theory Of Sine Wave Generation The basic working principle is based on the generation of DC voltage level. (Details can be found in AN entitle PWM as a DAC). Ifthe generated DC voltage level is in a sinusoidal manner, a sine wave is generated. Based on a fixed Conversion Period (step 2), and when the Duty Cycle (step 3) is changed, the DC level voltage will be changed in the next conversion period. For a sine wave of 128 points, between AVcc (at amplitude A) and AVss (at zero ground), The period of the sine wave, T = 256 * tcp, where tcp is the conversion period From AVss to AVcc, it will take 256/2 = 128 conversion periods. If the step change is uniform and equals to AVcc/128, then a triangular wave is generated. There are two considerations in sine wave generation: • Frequency of waveform: This depends on the choices of main clock, system clock divider, PWM divider and number of sampling points for the sine wave. • Shape of sine wave: This depends only on the number of sampling points.

related

Other articles

Pwm sine wave generation

pwm sine wave generation

1. Overview Pulse Width Modulation (PWM) refers to a form of signal modulation where data is represented by the ratio of the on time to the total time (known as the duty cycle). PWM has the property where the instantaneous DC component is directly proportional to the duty cycle. It is primarily used for controlling digital encoded analog signal of varying amplitude. The relationship between the time-average voltage (Vavg) the high and low voltages of the square wave (Vhi and Vlo) and the duty cycle (D) in percent is as follows: Vavg = (Vhi - Vlo) * D + Voffset……………….……………………….……………….….[1] where D = tON / tW or D = PWDR value/1023 (for 10-bit PWM) …………………………[2] If Vhi is 5V, Vlo is 0V (i.e. Voffset = 0) and D is 80%, Vavg would be 4 V. Another important parameter of PWM is the frequency. It is defined by number of pulse per second. f = 1 / tW……………………………………………………………….….….….….….……[3] where tW = tON + tOFF…………………………………………………………….….…….[4] From equations [2] and [3], it can be proven that F = D / tON………………………………[4] 2.2 Basic Operation To use the 10-bit PWM, set the registers in the following 3 steps: 1. Select PWM channel: Set PWM1 or PWM2 in PMR9 to 1 for PWM channel to be used, so that pin P90/PWM1 or P91/PWM2 is designated as the PWM output pin. 2. Select Conversion Period: Set bits PWCRm1 and PWCRm0 in the PWM control register (PWCRm) to select a conversion period. 3. Set Pulse Width: Set output waveform data in PWDRUm and PWDRLm. Data should be first written to PWDRLm and then to PWDRUm for the same channel. One conversion period consists of 4 pulses, as shown in Fig. 2.2. The total of the high-level pulse widths during this period (TH) corresponds to the data in PWDRUm and PWDRLm. The waveform will be changed at the next conversion period. TH = (data value in PWDRUm and PWDRLm + 4) * tØ/2 Where tØ is the PWM input clock period: 1/Ø, 2/Ø, 4/Ø or 8/Ø 3. Theory Of Sine Wave Generation The basic working principle is based on the generation of DC voltage level. (Details can be found in AN entitle PWM as a DAC). Ifthe generated DC voltage level is in a sinusoidal manner, a sine wave is generated. Based on a fixed Conversion Period (step 2), and when the Duty Cycle (step 3) is changed, the DC level voltage will be changed in the next conversion period. For a sine wave of 128 points, between AVcc (at amplitude A) and AVss (at zero ground), The period of the sine wave, T = 256 * tcp, where tcp is the conversion period From AVss to AVcc, it will take 256/2 = 128 conversion periods. If the step change is uniform and equals to AVcc/128, then a triangular wave is generated. There are two considerations in sine wave generation: • Frequency of waveform: This depends on the choices of main clock, system clock divider, PWM divider and number of sampling points for the sine wave. • Shape of sine wave: This depends only on the number of sampling points.

related

Please title this page

http://www.dattalo.com/technical/theory/sqwave.html Theoretical stuff on how harmonics may be suppressed in a stream of pulses. Referring to the section: 011 Harmonic Content of a Periodic Pulse Train from that page, Scott Dattalo says, If you don't feel like wading through the gory details, here's the conclusion reached:

If you have a periodic pulse stream of period T, then M is the number of possible positions at which a pulse may appear. Each pulse is the same width, T/M. 'm1' and 'm2' are two integers between 0 and M-1 describing the positions of two pulses. Finally, n is the harmonic number that is suppressed.

There are are two conditions that need to be satisfied before this equation can be used:

The first says that M must be even. The second says that the n'th harmonic must evenly divide half of M.

The example on the web page is for M = 12. For M=12, it's only possible to simultaneously suppress the 2nd and 3rd harmonic. If you want to suppress the 4th harmonic, then M has to be increased to 24. I haven't analyzed the requirements beyond n=5. However, the other day I claimed that M had to be on the order of n! to suppress the 2nd through n'th harmonic. That doesn't appear to be true. A casual examination for the 6th harmonic shows that it's possible to satisfy the equation for M=120. However, I don't if it's possible to cancel the 2nd through 6th harmonics with M=120. In other words, the equation is known to be necessary, but I don't know if it's sufficient.

[ed: and previously]

It finally dawned on me yesterday how magic sine waves can be sythesized. What's frustrating, is that the answer is so simple that it's obvious; so obvious that it's been overlooked in the discussions we had off and on for the last couple of years (at least by me). Lancaster is probably a chuckling lurker :). [Don Lancaster's Magic Sin Waves ]

There are probably a few ways to go about it, but this is the one I tried. Imagine how you'd go about synthesizing a sine wave if you had an A/D converter. The most common way is to produce `N' samples for one sine wave cycle and repeatedly write these to an A/D converter. The sine wave frequency is determined by the rate at which the samples are written to the A/D converter.

Now imagine replacing the A/D converter with a PWM generator that has the same resolution. So for example, if you had a 12-bit A/D converter the PWM generator would be capable of producing 4095 (2^12 - 1) different duty cycles. Theoretically, the low-pass filtered output of the A/D converter and the PWM are the same. Practically however, it's difficult to design a filter that would have the proper cut-off characteristics. So to ease the filter requirements, the PWM synthesized sine wave is usually made to be a much higher frequency than the frequency at which samples are written to the A/D converter.

Now when we, or at least I, begin to think about `magic sine waves' the idea that the pwm frequency can be reduced is forgotten. Furthermore, we constrain ourselves to the low-resolution 8 or 10 bit pwm generators that are available in the various pic's. What the magic sine wave algorithm does, AFAICT, is find a suitable time discretization for a high resolution PWM synthesized sine wave.

So, there are two parts to the synthesis. Part 1 invovles finding the high resolution PWM representation of the sine wave. Part 2 involves finding an optimum way to make time discrete. The first part is easy and the attached octave (or matlab) program will do this. The second part can be determined using brute force search techniques. I don't have an elegant solution though, but hopefully some others have some insight.

PS, this octave program is meant to be tool and otherwise not too useful (in other words, I don't bother to explain hardly anything. )

If you had a square wave with a 50% duty cycle, there are no even harmonics. Furthermore, the relative magnitude of the harmonics are inversely proportional to their harmonic numbers. If you vary the duty cycle to say 33%, you'll have no 3rd,6th, 9th harmonic, but some of the evens will pop up. I don't think there's a way to arbitrarily kill the odd harmonics. But you can do (at least) two things: vary the pulse width of individual pulses and vary the number of pulses. The plot:

cancels the 2nd and 3rd harmonics. You could say that it consists of three pulses; one twice as wide as the other. (But the program generating it had 4 bits for those 3 pulses. ).

I don't have time right now to explain, but as I mentioned earlier, it's possible to exactly cancel the first N harmonics. However, the number of 'time slots' or quantized positions at which the pulse edges may occur is of the order of N! (factorial). There is technique that involves examining the phases of the harmonics of the individual pulses. I found that pulses can be collected into groups that totally cancel one another at a given harmonic number. The smallest group I experimented with is just a pair. For example, for the second harmonic, the pulses are grouped in pairs. One pulse is 180 degrees out of phase with the other. The pairs for the second harmonic are two pulses separated by one pulse. For the third harmonic, the pulses are separated by two pulses.

So the objective is to discover the pairs that cancel at a given harmonic and then to find a set of pulses that will have complete coverage for each harmonic. I've done this for 24 pulses, but beyond that it gets pretty hairy.

Comments:
  • This is extremely similar to work in power electronics that started 40+ years ago called "harmonic elimination." There are general algorithms to eliminate any number of harmonics from the baseband and they don't require n! pulses. Search IEEE literature for any of about 100 references on the subject. +

file: /Techref/io/pwm/harmonic.htm, 8KB. updated: 2014/9/29 18:23, local time: 2016/7/26 06:32,

©2016 These pages are served without commercial sponsorship. (No popup ads, etc. ).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc. Please respect this requirement and DO NOT RIP THIS SITE. Questions?

Did you find what you needed? From: "/ "
  • "No. Take me to the search page."
  • "No. Take me to the top so I can drill down by catagory"
  • "No. I'm willing to pay for help, please refer me to a qualified consultant"

Lab3 - Laboratory for Experimental Computer Science

Arduino DDS Sinewave Generator Arduino Sine wave Generator using the direct digital synthesis Method

Here we describe how to generate sine waves with an Arduino board in a very accurate way. Almost no additional hardware is required. The frequency range reaches form zero to 16 KHz with a resolution of a millionth part of one Hertz! Distortions can be kept less than one percent on frequencies up to 3 KHz. This technique is not only useful for music and sound generation another range of application is test equipment or measurement instrumentation. Also in telecommunication the DDS Method is useful for instance in frequency of phase modulation (FSK PSK).

The DDS Method (digital direct synthesis)

To implement the DDS Method in software we need four components. An accumulator and a tuning word which are in our case just two long integer variables, a sinewave table as a list of numerical values of one sine period stored as constants, a digital analog converter which is provided by the PWM (analogWrite) unit, and a reference clock derived by a internal hardware timer in the atmega. To the accumulator. the tuning word is added, the most significant byte of the accu is taken as address of the sinetable where the value is fetched and outputted as analog value bye the PWM unit. The whole process is cycle timed by an interrupt process which acts as the reference clock. Further details of the DDS Method are described in web of course. This article published by Analog Devices is one of many good references.

Software implementation

To run this software on an Arduino Diecimila or Duemilenove connect a potentiometer to +5Volt and Ground and the wiper to analog 0. The frequency appears on pin 11 where you can connect active speakers or an output filter described later.

Results

In the upper part of the picture you see PWM signal on pin 11 and in the lower part what the filter makes out of it. The sinewave looks not so clean but thats mainly the limited resolution of the digital oscilloscope.

The spectrogram shows a surprisingly good result. The big peak is the output frequency of about 1000 Hz. All unwanted distortions are below 50 dB which is roughly what we expect from a signal what is generated by an 8-bit DAC. ( 1/256 = 48dB).

DDS Spreadsheet

dds_calc A little worksheet around the DDS formula to calculate the tuning word.

PWM Output lowpass Filter

For a start you can just connect the output pin 11 to active speakers. But usually you need lowpass filter is to get rid of the 32KHz sampling frequency in the output signal. A Chebyshef lowpass with a cutoff at 12 KHz build with standard component values is shown here.

PWM DDS dedicated Hardware

This software implementation of DDS has of course several drawbacks in case of signal purity and frequency range due to the limited speed of the software algorithm and analog capabilities of the atmega chip. DDS modules which are using dedicated DDS chips are the state of the art in signal generation and offer a frequency coverage from zero up into the 100MHz range.

WSPR Application

WSPR “W eak S ignal P ropagation R eporter” pronounced Whisper is a system which reports the propagation of very weak radio signals over the world. The DDS Method was used here to generate a tone sequence where four frequencies (1497,8 1499,3 1500,7 1502,2 Hz) are used code a message in a very robust manner. This message is transmitted with a low power radio beacon and can be observed worldwide via wspr.net .

Forum

Further questions to this topic can be discussed here:

Arduino Forum. Using Arduino. Audio. Arduino DDS Sinewave Generator

Arduino music using Direct Digital Synthesis

Arduino music using Direct Digital Synthesis

This page is a brief introduction to the use of an Arduino micro-controller board to make beautiful musical music, starting with a basic square wave generator, all the way to a wavetable synthesizer which can play chords of up to 8 notes.

All this without any external hardware (except for whatever speaker / amplifier / headphones you choose to hook up), and only using a single output pin on the arduino.

Simple square wave sound generation

Arduinos are a digital device. So, in output mode, each pin can output a zero (0v) or a 1 (5v).

If we connect the pin to a speaker, when the pin is 0, the speaker will move one way, and when the pin is 1, it will move all the way the other way. Note: if you’re just starting, I’d recommend using a simple piezo sounder, they are cheap, and can be connected directly to an Arduino digital pin. Later on, you’re likely to want more volume and a nicer tone, which will need some kind of amplifier, or going to headphones or an external amplifier. See my arduino amplifier instructions for more details of that

Anyway, assuming we have a pin connected to a speaker or piezo sounder, if we repeatedly change from zero to one and back very quickly, the speaker will output what is known as a square wave. Changing how fast the value changes from zero to one alters the frequency or pitch of the note that is played – for example if you change from zero to one and back 440 times a second, the frequency will be 440Hz, or the A above middle C, used for tuning orchestral instruments.

The following code simply uses the arduino’s ‘delaymicroseconds’ function in order to play a square wave with the pitch of A 440hz, on digital pin 11.

LOW); // set output to 0 volts
delaymicroseconds(1136); // wait for an 880th of a second
>

Play A440 Square Wave using delaymicroseconds

It’s pretty trivial to alter this code to make it play tunes, or alter pitch based on an analog input, or whatever. The good news however, is that you don’t need to. The lovely Arduino libraries happen to have a built in function, tone. which does this for you. It is dead simple to use, and handily, it runs on an interrupt, meaning that you can get on with doing other stuff while your note is playing. Basically, you use tone(pin,frequency) to start a note playing, and notone(pin). to stop a note playing. Alternatively, you can use tone(pin,frequency,duration) to play a note.

Play square waves using tone() library method

Direct Digital Synthesis Using Pulse Width Modulation

Square waves are all nice and lovely, but really sound quite nasty. With a basic square wave, we have no control over volume either. Yuck.

So, to fix this, we use something called pulse width modulation. In particular, using a technique known as ‘direct digital synthesis’.

What we do is change the amount of time the square wave is 1, as opposed to 0. This allows us to change the volume of the square wave (it is loudest when it is 1 half the time and 0 the other half, and silent if it is always 0). The amount of time the square wave is 1 vs 0 is known as the duty cycle of the square wave. Changing the volume like this is known as pulse width modulation .

Now, lets say we want to output something that sounds nicer than a square wave, like a sine wave, or chords made out of multiple sine waves, triangle waves, or whatever sound you want to make. If we had a real analog output, or a digital to analog converter, we would just send the values out of that, and they’d be output to the speaker as continuous values in between 0 and 1.

However, we don’t have analog outputs, in reality we can output only 0 and 1. However,using the pulse width modulation technique described above, we can make approximations to volumes that are in between 0 and 1. So, we output a very very high frequency square wave (32,000hz in my code), and we use pulse width modulation to alter each individual cycle of the square wave. This gives us a sound which has a single pitch at 32000hz, which changes in volume 32,000 times a second. Now, we use what is known as a low pass filter. which removes high frequencies from a signal to remove the 32,000hz tone, and what we are left with is the changes in volume. As if by magic, we’re changing in volume 32,000 times a second, which in effect is roughly the same as outputting a continuous value between 0 and 1 to our output 32,000 times a second, providing roughly the same effect as using a digital to analog convertor on our wave signal.

As an example, here is a pulse width modulation of a sine wave, showing how the duty cycle is modified based on the input signal value:

Pulse width modulation of a sine wave

In that example, the square wave is quite slow compared to the wave, in reality, we quite likely use a very high frequency square wave compared to the audible frequencies we want to output, so it would look more like this:

High frequency pulse width modulation of a sine wave

One final thing that simplifies this, is that if the square wave frequency is much higher than the human ear can hear (about 22khz maximum), then it doesn’t matter if we output it, so we can omit the low pass filtering of our output signal and just bung it straight out the speaker. Most speakers and amplifiers do not respond to such high frequencies anyway, so there is yet another reason not to bother about low pass filtering. You might need to low pass filters if you intend to bung your signal into high end recording equipment that supports 96 or 192khz digital recording, otherwise you will be able to see the square wave, but you should not be able to hear it even then (and 192khz studio setups will almost certainly have better filters built in than anything analog that you stick on the output of your arduino).

So, how to do direct digital synthesis using the Arduino? Essentially, we want to generate a very high frequency square wave, with a variable duty cycle. Handily, the ATMEGA processor used in the Arduino has two very useful functions which will let us do exactly this, Timer Interrupts. and Pulse Width Modulation .

Timer Interrupts let you set some code to be run repeatedly, many times a second. You can set the speed at which the interrupt is called, and it will just get called at that speed forever. For example, in the code below, I set an interrupt so that my interrupt code (the interrupt routine ) is run approximately 32000 times a second.

Pulse Width Modulation (PWM) essentially lets you generate square waves on a pin with a particular duty cycle. The frequency of these square waves can also be set, conveniently in the same units as we use for setting the speed of interrupts.

So, do to direct digital synthesis, we need to:

  1. Set up PWM so that it is doing a very high frequency square wave.
  2. Set an interrupt that alters the duty cycle of the square wave.

If we run the interrupt function on the same timer that is driving the PWM, then cunningly, for every cycle of the square wave, the interrupt is fired to set a new value to the square wave duty cycle, and voila, we have our direct digital synthesis.

To use this to generate tones, we use what is called a wave table – this is essentially an array, holding the volume values to generate a sound, such as a sine wave. Our interrupt routine simply loops around this wave table, taking a value out of it each cycle, and setting that to the square wave duty cycle, and as if by magic, we get a lovely sound coming out of our Arduino. To alter the pitch, we alter how fast we go round the wave table.

It is important that the wavetable is 256 bytes long, and aligned on a 256 byte boundary, because in the code below, we assume you can loop round the table by just taking the position&0xff.

So, what our interrupt routine looks like is:

  1. Move our pointer into the wave table (faster for higher pitch, or slower for lower pitch).
  2. Retrieve a value out of the wave table.
  3. Set the pulse width modulation duty cycle to the value from the wave table.

To set up an interrupt routine in code, we use the Arduino ISR macro, like this:

For multiple oscillators mixed on one pin it is as simple as adding the two values together:

Each interrupt can drive 2 pins, if you want to do stereo, or output one oscillator per pin or something.

A basic example of this is a 4 pin wave synth for arduino which I wrote – this runs 4 independent oscillators on 4 pins, using interrupts 1 and 2 on the Arduino, and demonstrates how to set up the interrupts, change the frequency and volume of the oscillators and all that jazz.

You can also heavily optimise this stuff, in the Arduino Octosynth there is example code for an 8 oscillator version of this, which has the interrupt routine written mostly in assembler. This makes it fast enough that you can also run a resonant filter on the output of the oscillators, or can mix 16 or more oscillators of unfiltered sound into a single pin.

Fun With Direct Digital Synthesis

You know that good feeling you get when a project comes together? Thats what I felt when I saw this sine wave on my oscilloscope. It’s a Pulse Width Modulation (PWM) signal generated by an Arduino using a Direct Digital Synthesis (DDS) technique and a lookup table of amplitude values. It was the result of searching for a way to improve the tone quality of a morse code keyer project and I had gotten half wave, then quarter sine wave symmetry working in a demonstration sketch.

Quarter Wave Symmetry
1000 Hz 256 Step Table

Digital to Analog Conversion is best done with optimized precision circuits. The relatively simple processor in an Arduino does not have a DAC device but it can do Pulse Width Modulation which can, in most cases, do the job adequately.

Pulse Width Modulation is widely documented. Basically it is a technique for generating an analog voltage from a digital signal. The device generates a high speed pulse train with varying pulse widths. This is fed through a filter circuit which averages the energy in the pulses. Fat pulses average to a higher voltage, skinny pulses average to a low voltage. By changing the pulse width over time, digital software can create a good analog representation of an arbitrary periodic signal. Other interesting applications are possible.

An Arduino generates PWM by setting up a timer. This is a counter with a circuit to trigger an interrupt at a specified count. The counter is incremented by the processor clock or, through a prescaler, a submultiple of the processor clock. PWM is achieved by the Interrupt Processing Routine (ISR) manipulating the specified count at which the timer fires. DDS applications synthesize an arbitrary waveform by using a lookup table of values that the ISR accesses sequentially to change the terminal count.

Common non-DDS applications might be dimming an LED. feeding an RC servo. or controlling the speed of a motor, and the Arduino environment has a convenient analogWrite() function that handles all the details for you. Hybrid cars use PWM to control the traction motors.

I found many articles on generating DDS sound using the Arduino platform. I picked one from Jeff Whitlatch KO7M as a base to learn more about the method. Read Jeff’s weblog entry with source code here. His sketch sets up timer 2 for PWM with a 32 KHz base frequency. Timer 2 is normally used by the Arduino for the tone() function and since my aim is to supersede the tone() function with something better, his example was a perfect starting point. In this article, I will only describe the changes I made in Jeff’s Interrupt Service Routine (ISR) and in the tables. Details of setting up the timers are covered in the source code and in many Internet sources. Here is a drawing of the Arduino connections:

Schematic for DDS Demo

Only five external parts needed including a button switch that stops and starts the sweep.

My test bed started out simple but it grew some (gruesome?).

Part 0: Analyzing and Parting Out the KO7M Sketch

After confirming that the sketch actually worked, I added code to sweep the frequency range from 50 to 2000 HZ so I could hear what it would sound like, and observe fidelity on my oscilloscope. Later I also added lines to generate a pulse at the start of the sine wave on a different pin. Using this pulse as an external sync source allowed the scope to display a steady waveform. I removed the sync code in the examples in this post for clarity.

This is the ISR from the original sketch (with small changes by me). TuningWord is the only parameter passed from the main part of the program. It is adjusted to set the particular PWM output frequency desired:

Note Jeff is storing his sine table in flash memory. If you’re not familiar with that technique, read this tutorial. It is a good method for reducing the RAM footprint of an Arduino sketch. You can find my version of Jeff’s sketch here. This is the 1000 Hz output from the original sketch with floating point math:

Original Floating Point
1000 Hz 256 Table

Part 1: Integer Conversion and Multiple Sine Tables

At this time, all floating point math in the example was converted to integer. To my surprise, it still works. There is more jitter on the waveforms due to integer truncation, but for keyer sidetone it is acceptable and the sketch sized dropped by about half.

I wanted to experiment with multiple lookup tables to get an idea of the minimum memory footprint possible while still producing acceptable sound. Libre Office Calc easily produced data with a 0-255 range for tables of length 256, 128, 64, 32 and 16 samples. See my spreadsheet here. Calc could also graph the tables to show how rough the waveform might be. It was a simple matter to paste a table column into VI and join the values into C style statements. These lines of data were inserted into the sketch and wrapped with #ifdef and #endif statements. At the top of the sketch is this code:

Which allows me to choose a table size to evaluate at compile time. The wrapped tables look like:

Bits is a constant definition that controls how far the ISR has to right shift the phase accumulator variable so the number that remains does not exceed the sine table size.

The interrupt handler changed little and looks like this:

Code for this full table sketch is here. These are waveforms from the Integer version:

Integer Version
Three Table Sizes

Part 2: Using Half Wave Symmetry of Sine Waves to Reduce Table Size

During my Google research I found articles pointing out that the size of the sine table could be reduced by a factor of two or four if you exploited the symmetry of a sine wave. Several pages described how to do this in FPGA hardware but I could not find a good example of symmetry use in C code and nothing at all for an Arduino. I tackled symmetry in two stages.

For half wave symmetry it is only necessary to duplicate the first half of the wave for the second half, inverting the second half as it is generated. First you need to know which half is being processed during the interrupt. The Most Signifigant Bit (MSB) of the phase accumulator variable has that information. It will be zero in the first half of the sine wave, one in the second half. I added a variable to record this bit and use a mask of 0x8000 to extract the bit. Then a new constant MSBMask was created inside the table definitions to turn off the high order MSB during table lookup. The tables now look like this example:

Note the table sizes are half the original. This 16 stepe per period table is now only 8 bytes long. The modified ISR with half wave symmetry now looks like:

The only additions to the ISR were the whichHalf variable, MSBMask which is defined with the sine table to remove the MSB, and the if statement at the end which does the actual inversion.

Code for the half wave symmetry version is here. These photos are from the half wave version:

Half Wave Symmetry Version
Three Table Sizes

Part 3: Using Quarter Wave Sine Symmetry to Reduce Table Size

Exploiting quarter wave symmetry is more complicated. It is a left/right symmetry while half wave symmetry is up/down. First you have to know which quarter of the wave is being generated. The second most significant bit in the phase accumulator variable has this information. It will be 0 if in the first or third quarter, 1 if second or fourth. A new state variable and a mask of 0x4000 records this bit. Since we are using less of the lookup tables, the MSBMask is smaller, it now needs to discard two MSB bits. The tables now look like:

Note that the sixteen sample table has been reduced to five (not four) bytes. The 256 level table is only 65 bytes long! The odd byte at the end was necessary to work around a glitch – the table read from flash would look up the same value twice at the beginning and end of the even quadrant. Adding one to the index and one extra table byte solves that issue. The ISR now looks like this:

This code does quarter wave symmetry first, then wraps half wave symmetry around that for the final output. The changes to add quarter wave are the whichQtr variable and it’s masking line, and the if(whichQtr) statement which inverts the table lookup left to right. MSBMask in in the byte read statement because it is the number of steps that exactly form a quarter of the wave form.

Code for the quarter wave symmetry sketch is here. Here are scope traces of the quarter wave symmetry version:

Quarter Wave Symmetry Version
Three Table Sizes

Conclusion:

These changes to the original Interrupt Service Routine allowed the table sizes to be reduced by a factor of four with hopefully, not too much additional overhead. Any ISR overhead added is executed 32000 every second so you have to be conservative. CPU time in the ISR is traded for a smaller program.

All three of these sketches can be useful for arbitrary waveform synthesis by constructing an appropriate table. The base sketch would work for any periodic waveform, including those that have no symmetry either up/down or left/right. A sawtooth wave for example. Half wave symmetry would be good for representing an underdamped or overdamped square wave. Quarter wave symmetry works for sine waves, as shown here, or a triangle wave.

The oscilloscope traces are interesting by themselves. These sketches and a scope could be used to demonstrate microcontroller techniques at your local science fair. My scope is an 80’s vintage Tektronix clone. On the screen you can see the generated sine waves and by zooming in, see the artifacts of PWM happening at a 32 KHz rate. Use the coarse 16 step table and the staircase model of DDS is clear. You can view the raw PWM by simply disconnecting the 0.1 Ufd integrating capacitor from the scope input. Interesting though, disconnecting the filter capacitor does not affect the audio much because your ears can’t respond to 32 Khz sound.

DDS quantization is most visible at low frequencies, using the smaller tables. Here you can clearly see the 16 steps and 32Khz fuzz on the trace.

50 Hz 16 Step Waveforms

Footnote:

The 64 step sine synthesizer with quarter wave symmetry was successfully added to my keyer project. I see no degradation of the morse timing at 50 WPM. A brief video is here. Also I recorded MP3s of the tone before and after. The tone produced by the stock Ardino tone() function is here. The tone from the 64 step (16 values) DDS function is here .

Sine wave

Sine wave

This example demonstrates a method of generating more complicated analog signal using simple DAC. To be more precise, sine wave but the same method can be used to generate any type of wave.

In the previous example it was shown how to generate voltage level using PWM and low pass RC filter.

If you change voltage level you get not horizontal line but wave. The shape of the wave depends on the way you change voltage level.
To set output voltage from RC filter, RMS value of PWM must be changed what means output voltage is proportional to OCR x .

The wave on the above picture has only 32 levels to show the idea. To get nice smooth wave, we need to increase the number of levels for one sine period. In connection with RC filter this give us sine wave that looks like true analog not discrete wave.

In the example timer0 is used in Fast PWM mode to achieve the maximum frequency of the sine wave.

Wave table generation

For this example we use 256 samples. sin() function gives values from -1 to 1. PWM duty cycle is controller by OCR0 register, so we need values from 0 to 255.
Equation for the n sample is:

256 is the number of samples.
For practical implementation see InitSinTable() function in the sample code.

Filter

We use the same type of filter as in previous example but with different parameters.

In the previous example frequency of the wave was 0Hz, that is we assumed output is constant in time. For sine wave this is not true and new values of C and R must be used.

This article is not about low pass filters, so filter theory is limited to minimum. In other words, just use R=10kΩ and C=0.1µF .

The most important parameter of the filter is cut-off frequency. For RC low pass filter it is:

which gives us fcutoff =159.2Hz. The filter passes frequency from 0 to 159Hz. Good filter should generate smooth waves in desired frequency of sine wave.

Sine wave frequency

We use timer0 in Fast PWM mode and prescaler 1 to generate PWM signal. For 8MHz clock:

Period is equal to 1/31250=0.000032s (32µs). As 256 samples is used to generate sine wave, period of the sine wave is 256×0.000032s=0.008192s. From that frequency is: 1/0.008192=122.07Hz.
In other words frequency of the resulting wave is always:

where Samples is the number of samples. Note, that this equation is true for any wave not only sine wave.

The same modified equation gives the answer what PWM frequency use to achieve specific analog wave frequency:

To change the frequency of the sine wave you can:
  1. Change PWM frequency (set prescaler or system clock or use different PWM mode with smooth frequency control)
  2. Change the number of samples
Code snippets

OC0 pin as output.

Configure Fast PWM mode of timer0

Sample code

The example code (pwm_sinusoid.zip ) generates sine wave on OC0 pin. This signal is then filtered by low pass RC filter. To see the results an oscilloscope must be connected to the output of RC filter (see diagram at the beginning).

First timer0 is initialized (Fast PWM Mode). Then Timer/Counter0 Overflow Interrupt is enabled. The interrupt routine changes PWM frequency every time timer0 overflows. That automatically synchronize PWM frequency change and the end of PWM period. Fast PWM mode is not phase correct, so this simple solution prevents from changing PWM frequency in the middle of the period.

When macro COMPUTE_SINE_WAVE is defined program compute sine table at startup. Playing a bit with InitSinTable() function it is possible to generate any wave. By default program uses predefined sine table with 256 samples.
To increase or decrease the number of samples value of WAVE_PROBES must be changed. In addition COMPUTE_SINE_WAVE must be defined to force program to compute new samples.

Oscilloscope snapshots

Sine wave – output from the RC filter. Grid: 1ms/0.5V.

Two signals: PWM (yellow) and sine wave (blue). PWM duty cycle grows from left to right. Grid: 50µs/0.5V.

Additional links