Sine Wave Generation and Implementation using dsPIC33FJ

27
Syed Tahmid Mahbub Sine Wave Generation and Implementation using dsPIC33FJ

description

I have tried to explain thoroughly the functioning and programming of the PWM mode of the Output Compare Module of the dsPIC33FJ12GP202. I have tried to discuss in detail the generation of the sine table to be used for SPWM and have provided a brief look at my software “Smart Sine” which I’m sure will aid you in your sine table generation. I have provided the code/program I have used alongside detailed description of the code, as well as the circuit configuration, output (filter) stage configuration and finally, simulation results of the presented code. I hope that the tutorial/article that I have prepared and presented here will be of use to those who are interested in applying the (seemingly difficult) concept of SPWM to generate sine wave outputs in (not restricted to, but especially suitable for) power electronics applications, such as inverters.

Transcript of Sine Wave Generation and Implementation using dsPIC33FJ

Page 1: Sine Wave Generation and Implementation using dsPIC33FJ

Syed Tahmid Mahbub

Sine Wave Generation and Implementation using dsPIC33FJ

Page 2: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

2

2

Image Sources:

Fig. 1 - dsPIC33FJ12GP202 datasheet

Fig. 2 - dsPIC33F Reference Manual – Output Compare Module

Fig. 3 - Generated using MATLAB

Fig. 4 - Screenshot of my software “Smart Sine”

Fig. 5 - Drawn by me

Fig. 6 - Drawn by me

Fig. 7 - Drawn by me

Fig. 8 - Simulation result obtained by me

Fig. 9 - Simulation result obtained by me

Page 3: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

3

3

Introduction

Sine wave generation is extremely important in power electronics. It finds applications in many circuits,

the most common ones being sine wave DC-AC inverters and AC motor control circuits. I have previously

covered sine wave generation control using SPWM based on the PIC (with or without ECCP module) and

the AVR microcontrollers. Here I’ll talk about the implementation of SPWM using a dsPIC33FJ series

microcontroller. The specific microcontroller I’ll use is the dsPIC33FJ12GP202. This microcontroller is

available in a 28-pin prototype-friendly PDIP package, making it easy to prototype; the large pin count

also leaves a lot of pins free for other use. That is primarily why I chose this microcontroller. The

microcontroller is certainly more than powerful enough for the application.

While I have used the dsPIC33FJ12GP202 microcontroller, the same concepts can be ported to other

dsPIC microcontrollers, or even any other capable microcontroller, of course with some necessary

changes.

The principle of SPWM is quite simple and I’ll go through the entire process of implementing SPWM to

generate sine wave using the dsPIC33FJ12GP202. I have divided this tutorial into 6 parts:

1. Explanation of the use of the dsPIC33FJ12GP202 Output Compare Module in PWM mode

(without fault detection, as this isn’t necessary for this simple application here)

2. Generation of the Sine Table

3. The code

4. Detailed explanation of the code, especially the sine wave generation control part

5. Circuit Configuration

6. Simulation Results

Page 4: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

4

4

Explanation of the use of the dsPIC33FJ12GP202 Output Compare Module in PWM mode

The Output Compare Module uses one of two 16-bit timers, Timer 2 and Timer 3. The Output Compare

Module compares the value of the selected timer with the output compare registers OCxR and OCxRS.

The Output Compare Module changes the state of the output pin when there is a match between the

timer value and the output compare register value, and also at the end of the period.

The Output Compare Module has quite a lot of modes in which it can be used, but here I’m using only

the PWM mode (without fault protection).

The dsPIC33FJ12GP202 has 2 Output Compare Modules. It is extremely useful to have 2 compare

modules as you will see in the sine wave generation implementation below.

Page 5: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

5

5

Here’s the Output Compare X Control Register, along with the description of the bits, (where X = 1 for

Output Compare Module 1 or X = 2 for Output Compare Module 2):

Fig. 1 – OCxCON (Output Compare x Control Register)

The bits description above clearly explains the function of the bits of the OCxCON register. You should

notice that, with fault pin disabled, PWM mode is selected when OCM<2:0> is set to 6 (110 in binary

equals 6 in decimal, 0x06 in hexadecimal).

Page 6: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

6

6

Now let’s go on to how the PWM mode in the Output Compare Module works.

As you know by now, the Output Compare Module can use either Timer 2 or Timer 3 as the time base.

Which timer is used is configured by the OCTSEL bit (bit 3) of the OCxCON register. Setting OCTSEL to 1

uses the Timer 3, whereas clearing OCTSEL to 0 uses the Timer 2.

The timer starts from zero and increments on every clock until it reaches the value of the Period Register

(PRy, where y = 2 for Timer 2 and y = 3 for Timer 3). When the period value is reached (when value of

timer equals value of the Period Register), the timer is reset and starts incrementing once again. The

timer can be clocked using the internal clock source (Fosc/2) or a synchronized external clock source

applied at the TxCK pin. In our circuit, we need not use any external clock and we use the internal clock

source. Do remember that the internal clock frequency is not fixed at Fosc/2 and can be adjusted by

changing the timer prescale value.

If the timer overflow interrupt is enabled, a timer overflow interrupt will be generated when the value

of the timer equals the value of the Period Register PRy. Again, this timer will be either Timer 2 or Timer

3, as selected by the configuration of the OCTSEL bit in the output compare control Register OCxCON.

Page 7: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

7

7

Now, let’s look at the how we’ll set the value of PRy. PRy is related to the PWM period and PWM

frequency by the following equations:

𝑃𝑊𝑀 𝑝𝑒𝑟𝑖𝑜𝑑 = 𝑃𝑅𝑦 + 1 ⋅ 𝑇𝑐𝑦 ⋅ 𝑇𝑀𝑅𝑦 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒 𝑉𝑎𝑙𝑢𝑒

𝑃𝑊𝑀 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦 =1

𝑃𝑊𝑀 𝑝𝑒𝑟𝑖𝑜𝑑

So, rearranging:

𝑃𝑅𝑦 = (𝑃𝑊𝑀 𝑝𝑒𝑟𝑖𝑜𝑑)

𝑇𝑐𝑦 ⋅ (𝑇𝑀𝑅𝑦 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒 𝑉𝑎𝑙𝑢𝑒)− 1 =

𝑓𝑐𝑦

𝑓𝑝𝑤𝑚 ⋅ (𝑇𝑀𝑅𝑦 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒 𝑉𝑎𝑙𝑢𝑒)− 1

So, you can set the PWM frequency by setting PRy. That’s good. Now how do we set the duty cycle? The

PWM duty cycle is set by the value of the OCxR register. However, in PWM mode, the OCxR register is

read-only. It cannot be written to. So, how do we set the PWM duty cycle? By using the OCxRS register.

The OCxRS register acts as a shadow register for the OCxR register. This prevents glitches in the PWM

output. Whenever the timer is reset, ie the timer rolls over, the value of the OCxRS register is loaded

onto the OCxR register. So, by setting the value of the OCxRS register, we are setting the value of the

OCxR register and thus setting the PWM duty cycle. So, you might think that we don’t need to deal with

the OCxR register. Well, we do. We should set the value of the OCxR register before enabling PWM

mode because this initial value of OCxR will set the initial duty cycle of the PWM – the duty cycle of the

first pulse. Usually, we start with zero duty cycle and so it’s common to have OCxR cleared to zero

before the PWM mode is enabled. That’s also what I’ve done in the code.

So when the PWM mode is enabled, the OCx pin is:

Driven high if the value of OCxR is non-zero.

Driven low if the value of OCxR is zero.

When the timer is enabled, it starts incrementing until its value equals that of its Period Register. The

value of OCxR is constantly compared with the value of the timer. When a match occurs, the OCx pin is

driven low. On a timer roll-over, the value of the OCxRS register is loaded into the OCxR register. The

OCx pin is then:

Driven high if the value of OCxR is non-zero.

Driven low if the value of OCxR is zero.

Page 8: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

8

8

The PWM duty cycle is specified by writing to the OCxRS register. The duty cycle value can be written at

any time, but the duty cycle value is not latched onto the OCxR register until timer Reset on a period

match. This provides a double buffer for the PWM duty cycle and is essential for glitch-free PWM

operation.

Some important boundary parameters of the PWM duty cycle include:

• If the duty cycle register, OCxR, is loaded with 0000h, the OCx pin remains low (0% duty cycle)

• If the OCxR register is greater than PRy (Timer Period register), the pin remains high (100% duty cycle)

• If the OCxR register is equal to PRy, the OCx pin is low for one time base count value and high for all

other count values

The PWM resolution depends on PWM frequency and the timer clock frequency. The timer clock is

derived from the internal clock (FCY) divided by a programmable prescaler.

Page 9: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

9

9

The mode of operation is explained clearly by this diagram:

Fig. 2 – PWM Mode Operation

Page 10: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

10

10

Generation of the Sine Table

So now, let’s talk about sinusoidal pulse width modulation a bit. We want to generate a sine wave

digitally – using square waves. When digitally producing sine wave, we do so by using a fixed number of

square wave pulses. The larger the number, the cleaner the sine wave. The duty cycles of the continuous

pulses vary sinusoidally. If you don’t get this now, don’t worry; the following explanations will clear it up

for you. For example’s sake, let’s say that we are using 10 samples – 10 square wave pulses per sine

wave half-cycle. Do bear in mind that usually, for a clean output, we’ll use more pulses per half-cycle,

usually at least 32.

So we have y=sin(x); x varies between 0° to 360° or, in radians, 0 to 2π. Now, let’s concentrate on the

positive half-cycle. The negative half-cycle will have the same pulses in the opposite direction. Since we

want to use 10 pulses per half-cycle, and the half-cycle is from 0° to 180°, we have an interval equal to

18°. So, we’re using 18° steps. So the pulses will be sent at 0°, 18°, 36° and so on. The values we need

are:

1. sin(0°) = 0 2. sin(18°) = 0.31 3. sin(36°) = 0.59 4. sin(54°) = 0.81 5. sin(72°) = 0.95 6. sin(90°) = 1 7. sin(108°) = 0.95 8. sin(126°) = 0.81 9. sin(144°) = 0.59 10. sin(162°) = 0.31

Notice that we don’t take sin(180°) as this value will be called in the next half-cycle, at the beginning,

when sin(0°) = 0.

Page 11: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

11

11

Now that we know how to find the values, we have to scale them to something meaningful. We know

that:

1. sin(0°) = 0% 2. sin(18°) = 31% 3. sin(36°) = 59% 4. sin(54°) = 81% 5. sin(72°) = 95% 6. sin(90°) = 100% 7. sin(108°) = 95% 8. sin(126°) = 81% 9. sin(144°) = 59% 10. sin(162°) = 31%

100% is at the amplitude value – at 90°. This will equal the Period Register (or less if you want, but this

will be the maximum value). Let’s say that the carrier frequency of the SPWM is 25kHz and the

dsPIC33FJ12GP202 is run from a 20MHz crystal oscillator. The carrier frequency is the frequency of the

square wave pulses that will be sent, that, upon filtering, will represent a sine wave. I’ve explained

below about why I chose 25kHz as the carrier frequency.

From the equation given:

𝑃𝑅𝑦 = (𝑃𝑊𝑀 𝑝𝑒𝑟𝑖𝑜𝑑)

𝑇𝑐𝑦 ⋅ (𝑇𝑀𝑅𝑦 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒 𝑉𝑎𝑙𝑢𝑒)− 1 =

𝑓𝑐𝑦

𝑓𝑝𝑤𝑚 ⋅ (𝑇𝑀𝑅𝑦 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒 𝑉𝑎𝑙𝑢𝑒)− 1

𝑃𝑅𝑦 = 10 ∗ 106

25000 ⋅ 1− 1 = 399

We know that when OCxRS = PRy, the duty cycle is 100%. OCxRS is related to PRy linearly. So, if OCxRS is

half of PRy, the duty cycle is 50%, and so on.

Page 12: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

12

12

So, considering that the table values correspond to the duty cycles, the sine table:

1. sin(0°) = 0 2. sin(18°) = 0.31 3. sin(36°) = 0.59 4. sin(54°) = 0.81 5. sin(72°) = 0.95 6. sin(90°) = 1 7. sin(108°) = 0.95 8. sin(126°) = 0.81 9. sin(144°) = 0.59 10. sin(162°) = 0.31

can be written as below, where the values represent the value to be stored in OCxRS:

1. sin(0°) = 0 * (PRy + 1) 2. sin(18°) = 0.31 * (PRy + 1) 3. sin(36°) = 0.59 * (PRy + 1) 4. sin(54°) = 0.81 * (PRy + 1) 5. sin(72°) = 0.95 * (PRy + 1) 6. sin(90°) = 1 * (PRy + 1) 7. sin(108°) = 0.95 * (PRy + 1) 8. sin(126°) = 0.81 * (PRy + 1) 9. sin(144°) = 0.59 * (PRy + 1) 10. sin(162°) = 0.31 * (PRy + 1)

We have calculated PRy as being equal to 399. So, our table is:

1. sin(0°) = 0 * (PRy + 1) = 0 * 400 = 0 2. sin(18°) = 0.31 * (PRy + 1) = 0.31 * 400 = 124 3. sin(36°) = 0.59 * (PRy + 1) = 0.59 * 400 = 236 4. sin(54°) = 0.81 * (PRy + 1) = 0.81 * 400 = 324 5. sin(72°) = 0.95 * (PRy + 1) = 0.95 * 400 = 380 6. sin(90°) = 1 * (PRy + 1) = 1 * 400 = 400 7. sin(108°) = 0.95 * (PRy + 1) = 0.95 * 400 = 380 8. sin(126°) = 0.81 * (PRy + 1) = 0.81 * 400 = 324 9. sin(144°) = 0.59 * (PRy + 1) = 0.59 * 400 = 236 10. sin(162°) = 0.31 * (PRy + 1) = 0.31 * 400 = 124

That is our sine table: [0, 124, 236, 324, 380, 400, 380, 324, 236, 124]

Page 13: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

13

13

This is what I meant previously when I said that the duty cycles are changed sinusoidally. If you plot the

values of the sine table and draw a graph, you’ll see a sine wave shape. The more points you take, the

smoother the wave will be.

I’ll show that here. Here is a graph of the resultant graph of the sine table points plotted.

Fig. 3 –Table points forming a sine wave

How do continuous pulses with sinusoidally varying duty cycles generate a sine wave? You know that

the duty cycle controls the output voltage. When the output signal is filtered, the output voltages at

different points vary sinusoidally as the duty cycle values vary sinusoidally, and the output voltage is

proportional to the duty cycle. So, due to this, the output voltage observed will also be sinusoidal.

Notice the sinusoidal-ish shape obtained with just 10 values! The more values you’ll use the smoother

the wave will be.

Page 14: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

14

14

Let’s find the sine table for our program. The carrier frequency is 25kHz. I selected 25kHz for two

reasons:

1. It is above 20kHz. So, being beyond the audible range, audible noise will not be generated.

2. The switching frequency is large enough to require a reasonably small inductor and capacitor for

filtering. At the same time, the switching frequency is not too large that there will be huge

switching losses.

For the PWM mode, I have used Timer 2 as the time base. So the Period Register is PR2. As calculated

above, PR2 equals 399. For a really smooth sine wave, I chose 256 points per half-cycle.

It would be way too much hassle trying to calculate so many values by hand. So what I did was, I made

the software “Smart Sine” and I use that for calculating tables. I found the above sine table using the

“Smart Sine” software. Here’s a screenshot showing the generation of the sine wave table mentioned

above. For more information about “Smart Sine” and/or to download “Smart Sine” visit my blog or go to

this link:

http://tahmidmc.blogspot.com/2012/10/smart-sine-software-to-generate-sine.html

Fig. 4 – Generating sine table with “Smart Sine”

Page 15: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

15

15

The sine table for both half-cycles is:

{

0, 5, 10, 15, 20, 25, 29, 34, 39, 44, 49, 54, 59, 64, 68, 73, 78, 83, 88, 92, 97, 102,

107, 111, 116, 121, 125, 130, 135, 139, 144, 149, 153, 158, 162, 167, 171, 175, 180,

184, 189, 193, 197, 201, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250,

254, 258, 261, 265, 269, 272, 276, 279, 283, 286, 290, 293, 296, 300, 303, 306, 309,

312, 315, 318, 321, 324, 327, 330, 333, 335, 338, 341, 343, 346, 348, 350, 353, 355,

357, 359, 362, 364, 366, 368, 370, 371, 373, 375, 377, 378, 380, 381, 383, 384, 386,

387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 396, 397, 398, 398, 399, 399, 399,

400, 400, 400, 400, 400, 400, 400, 400, 400, 399, 399, 399, 398, 398, 397, 396, 396,

395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 384, 383, 381, 380, 378, 377, 375,

373, 371, 370, 368, 366, 364, 362, 359, 357, 355, 353, 350, 348, 346, 343, 341, 338,

335, 333, 330, 327, 324, 321, 318, 315, 312, 309, 306, 303, 300, 296, 293, 290, 286,

283, 279, 276, 272, 269, 265, 261, 258, 254, 250, 246, 242, 238, 234, 230, 226, 222,

218, 214, 210, 206, 201, 197, 193, 189, 184, 180, 175, 171, 167, 162, 158, 153, 149,

144, 139, 135, 130, 125, 121, 116, 111, 107, 102, 97, 92, 88, 83, 78, 73, 68, 64, 59,

54, 49, 44, 39, 34, 29, 25, 20, 15, 10, 5,

0, 5, 10, 15, 20, 25, 29, 34, 39, 44, 49, 54, 59, 64, 68, 73, 78, 83, 88, 92, 97, 102,

107, 111, 116, 121, 125, 130, 135, 139, 144, 149, 153, 158, 162, 167, 171, 175, 180,

184, 189, 193, 197, 201, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250,

254, 258, 261, 265, 269, 272, 276, 279, 283, 286, 290, 293, 296, 300, 303, 306, 309,

312, 315, 318, 321, 324, 327, 330, 333, 335, 338, 341, 343, 346, 348, 350, 353, 355,

357, 359, 362, 364, 366, 368, 370, 371, 373, 375, 377, 378, 380, 381, 383, 384, 386,

387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 396, 397, 398, 398, 399, 399, 399,

400, 400, 400, 400, 400, 400, 400, 400, 400, 399, 399, 399, 398, 398, 397, 396, 396,

395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 384, 383, 381, 380, 378, 377, 375,

373, 371, 370, 368, 366, 364, 362, 359, 357, 355, 353, 350, 348, 346, 343, 341, 338,

335, 333, 330, 327, 324, 321, 318, 315, 312, 309, 306, 303, 300, 296, 293, 290, 286,

283, 279, 276, 272, 269, 265, 261, 258, 254, 250, 246, 242, 238, 234, 230, 226, 222,

218, 214, 210, 206, 201, 197, 193, 189, 184, 180, 175, 171, 167, 162, 158, 153, 149,

144, 139, 135, 130, 125, 121, 116, 111, 107, 102, 97, 92, 88, 83, 78, 73, 68, 64, 59,

54, 49, 44, 39, 34, 29, 25, 20, 15, 10, 5

}

Why both half-cycles? That’ll be clear once we look at my code on the next page.

Page 16: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

16

16

The Code

//----------------------------------------------------------------

//Programmer: Syed Tahmid Mahbub

//Compiler: mikroC PRO for dsPIC v5.0.1

//Target dsPIC: dsPIC33FJ12GP202

//Program for sine wave generation using SPWM

//----------------------------------------------------------------

const int sin_table[512] =

{

0, 5, 10, 15, 20, 25, 29, 34, 39, 44, 49, 54, 59, 64, 68, 73,

78, 83, 88, 92, 97, 102, 107, 111, 116, 121, 125, 130, 135, 139,

144, 149, 153, 158, 162, 167, 171, 175, 180, 184, 189, 193, 197,

201, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250,

254, 258, 261, 265, 269, 272, 276, 279, 283, 286, 290, 293, 296,

300, 303, 306, 309, 312, 315, 318, 321, 324, 327, 330, 333, 335,

338, 341, 343, 346, 348, 350, 353, 355, 357, 359, 362, 364, 366,

368, 370, 371, 373, 375, 377, 378, 380, 381, 383, 384, 386, 387,

388, 389, 390, 391, 392, 393, 394, 395, 396, 396, 397, 398, 398,

399, 399, 399, 400, 400, 400, 400, 400, 400, 400, 400, 400, 399,

399, 399, 398, 398, 397, 396, 396, 395, 394, 393, 392, 391, 390,

389, 388, 387, 386, 384, 383, 381, 380, 378, 377, 375, 373, 371,

370, 368, 366, 364, 362, 359, 357, 355, 353, 350, 348, 346, 343,

341, 338, 335, 333, 330, 327, 324, 321, 318, 315, 312, 309, 306,

303, 300, 296, 293, 290, 286, 283, 279, 276, 272, 269, 265, 261,

258, 254, 250, 246, 242, 238, 234, 230, 226, 222, 218, 214, 210,

206, 201, 197, 193, 189, 184, 180, 175, 171, 167, 162, 158, 153,

149, 144, 139, 135, 130, 125, 121, 116, 111, 107, 102, 97, 92, 88,

83, 78, 73, 68, 64, 59, 54, 49, 44, 39, 34, 29, 25, 20, 15, 10, 5,

0, 5, 10, 15, 20, 25, 29, 34, 39, 44, 49, 54, 59, 64, 68, 73,

78, 83, 88, 92, 97, 102, 107, 111, 116, 121, 125, 130, 135, 139,

144, 149, 153, 158, 162, 167, 171, 175, 180, 184, 189, 193, 197,

201, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250,

254, 258, 261, 265, 269, 272, 276, 279, 283, 286, 290, 293, 296,

300, 303, 306, 309, 312, 315, 318, 321, 324, 327, 330, 333, 335,

338, 341, 343, 346, 348, 350, 353, 355, 357, 359, 362, 364, 366,

368, 370, 371, 373, 375, 377, 378, 380, 381, 383, 384, 386, 387,

388, 389, 390, 391, 392, 393, 394, 395, 396, 396, 397, 398, 398,

399, 399, 399, 400, 400, 400, 400, 400, 400, 400, 400, 400, 399,

399, 399, 398, 398, 397, 396, 396, 395, 394, 393, 392, 391, 390,

389, 388, 387, 386, 384, 383, 381, 380, 378, 377, 375, 373, 371,

370, 368, 366, 364, 362, 359, 357, 355, 353, 350, 348, 346, 343,

341, 338, 335, 333, 330, 327, 324, 321, 318, 315, 312, 309, 306,

303, 300, 296, 293, 290, 286, 283, 279, 276, 272, 269, 265, 261,

258, 254, 250, 246, 242, 238, 234, 230, 226, 222, 218, 214, 210,

206, 201, 197, 193, 189, 184, 180, 175, 171, 167, 162, 158, 153,

149, 144, 139, 135, 130, 125, 121, 116, 111, 107, 102, 97, 92, 88,

83, 78, 73, 68, 64, 59, 54, 49, 44, 39, 34, 29, 25, 20, 15, 10, 5

};

Page 17: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

17

17

sbit MOSA at LATB2_bit;

sbit MOSC at LATB3_bit;

//D at LATB0_bit;

//B at LATB1_bit;

unsigned int Result;

int PWM_Scaling = 399; //25kHz

int Frequency = 131; //50Hz

unsigned int Phase;

int TBL_ID;

void T2Int() org 0x0022{ //Timer 2 overflow interrupt

Phase = Phase + Frequency;

Result = Phase >> 7;

TBL_ID = sin_table[Result];

if (Result < 256){ //A and D on

OC2RS = 0;

MOSC = 0;

OC1RS = TBL_ID;

MOSA = 1;

}

else{ //B and C on

OC1RS = 0;

MOSA = 0;

OC2RS = TBL_ID;

MOSC = 1;

}

T2IF_bit = 0;

}

void main() {

LATB = 0;

TRISB = 0; //All PORTB output

AD1PCFGL = 0x3F; //All digital

PR2 = PWM_Scaling; //Set Frequency by setting Period Register

//PR2 since I'll be using Timer 2

OC1CON = 0; //Disable compare module

OC1R = 0; //Initial duty cycle = 0

OC1RS = 0;

OC1CON = 0x0006; //Keep running in idle mode, Time base is TMR2,

//PWM mode with fault pin disabled

OC2CON = 0;

OC2R = 0; //Initial duty cycle = 0

OC2RS = 0;

OC2CON = 0x0006;

RPOR0 = 0x1213; //RP0 - OC1, RP1 - OC2

Page 18: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

18

18

SR = 0; //CPU priority interrupt level 0

T2IF_bit = 0; //Clear TMR2 interrupt flag

T2IP_2_bit = 1;

T2IP_1_bit = 1;

T2IP_0_bit = 1; //TMR2 interrupt priority 7

T2IE_bit = 1; //Enable TMR2 interrupt

T2CON = 0x8000; //TMR2 on, prescaler 1

while (1){ //Infinite loop – Nothing to do now

}

} //End of code

Page 19: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

19

19

Explanation of the Code

I’ve added comments to every line in the main() function to make it self-explanatory. I’ll have to explain

the interrupt and I’ll do that here.

Here’s the interrupt code:

void T2Int() org 0x0022{ //Timer 2 overflow interrupt

Phase = Phase + Frequency;

Result = Phase >> 7;

TBL_ID = sin_table[Result];

if (Result < 256){ //A and D on

OC2RS = 0;

MOSC = 0;

OC1RS = TBL_ID;

MOSA = 1;

}

else{ //B and C on

OC1RS = 0;

MOSA = 0;

OC2RS = TBL_ID;

MOSC = 1;

}

T2IF_bit = 0;

}

The interrupt is generated at the end of every PWM cycle. That is when the value of Timer 2 equals the

value of the Period Register PR2. The PWM frequency is 25kHz. So the PWM period is equal to

(1/25000)s = 40µs. So, the interrupt service routine is carried out every 40µs. 1 50Hz half cycle is 10ms.

So in one half-cycle, the ISR is carried out (10000/40) times = 250 times. 0x0022 is the interrupt vector

for the TMR2 overflow interrupt.

The value of the register “Frequency” sets the frequency of the output sine wave. Okay, so let’s go on to

explain the interrupt. “Phase” is a 16-bit register. Every interrupt, the value of “Phase” is increased by

the value that equals “Frequency”.

Every 40µs, the value of “Phase” is increased by 131. Initially, “Phase” has a value of 0 and every 40µs,

“Phase” is increased by 131. So, initially “Phase” equals 0; after the first interrupt “Phase” equals 131;

Page 20: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

20

20

after the second interrupt “Phase” equals 262; and so on. After “Phase” is incremented by 131 every

interrupt, it is then divided by 128 (>>7 is the same as dividing by 27). So every time “Phase” is increased

by 131, “Result” is incremented by 1. “Result” is the table pointer. After 499 interrupts, “Phase” holds

65369. On the next interrupt, “Phase” overflows. So on the 500th interrupt “Phase” overflows, and

“Result” then holds 0. So, “Result” takes values from 0 to 499. It acts as the table pointer to the sine

table. The corresponding value is retrieved from the table and stored in “TBL_ID”.

This value is then assigned to the required duty cycle register. Now comes the tricky (and interesting)

part. The first 256 values (when the table pointer will have a value from 0 to 255) correspond to one

half-cycle. The next 256 values (when the table pointer will have a value from 256 to 511) correspond to

the opposite half-cycle. I’ve used both Output Compare Modules in PWM here. The two Output

Compare Modules drive opposite MOSFETs, thereby “reversing” the direction of current through the

load/transformer. Notice also that two MOSFETs are SPWM-ed at 25kHz, while the other two MOSFETs

are turned on and off at 50Hz.

When the first 256 values are retrieved from the sine table, Output Compare Module 1 is used to drive

the output, while the Output Compare Module 2 has a duty cycle of 0%, ie it is off. Similarly when the

next 256 values are retrieved from the sine table, Output Compare Module 2 is used to drive the output,

while the Output Compare Module 1 has a duty cycle of 0%, ie it is off. To understand this in the context

of the circuit, refer to the “Circuit Configuration” section below.

Now, if you want to make changes to the code, here’s how to calculate the different parameters.

“Phase” is a 16-bit register. When you change the number of sine table entries, you need to change the

number of times “Phase” is right-shifted before being stored in “Result”. The number of times “Phase” is

right-shifted before being stored in “Result” is equal to:

16 − log2(𝑁𝑜. 𝑜𝑓 𝑠𝑖𝑛𝑒 𝑡𝑎𝑏𝑙𝑒 𝑒𝑛𝑡𝑟𝑖𝑒𝑠)

In our program, this was equal to:

16 − log2 512 = 16 − 9 = 7

And that is what I used. Just giving you an example.

Page 21: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

21

21

If you want to change the carrier frequency, you have to adjust the Period Register (PRy). I’ve already

shown you how to calculate the value of the Period Register (PRy).

Now, if you want to change the frequency of the output sine wave, you need to change the value of the

register “Frequency”. “Frequency” is related to the output sine wave frequency and the carrier

frequency by the relationship:

"𝐹𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦" = 216 ∗ (𝑂𝑢𝑡𝑝𝑢𝑡 𝑠𝑖𝑛𝑒 𝑤𝑎𝑣𝑒 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦)

(𝐶𝑎𝑟𝑟𝑖𝑒𝑟 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦)

For our program, this was:

Frequency = 216 ∗ 𝑂𝑢𝑡𝑝𝑢𝑡 𝑠𝑖𝑛𝑒 𝑤𝑎𝑣𝑒 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦

𝐶𝑎𝑟𝑟𝑖𝑒𝑟 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦 =

65536 ∗ 50

25000= 131.072 ≈ 131

So now that I’ve explained the code, let’s look at the circuit configuration.

Page 22: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

22

22

Circuit Configuration

Fig. 5 – Circuit Configuration for the dsPIC33FJ12GP202

This is how the dsPIC33FJ12GP202 is configured. The configuration is a typical configuration for the

dsPIC33FJ12GP202 and follows the guidelines mentioned in the datasheet (check “RECOMMENDED

MINIMUM CONNECTION” in the dsPIC33FJ12GP202 datasheet).

C1 should be between 4.7µF and 10µF. C1 is the filter capacitor for the internal voltage regulator. 6.8µF

is a good value lying safely in the middle of the range. C2, C3 and C4 are decoupling capacitors and

should be placed as close to the microcontroller as possible.

Page 23: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

23

23

Fig. 6 – MOSFET Configuration section

I’ll just talk about the operation of the circuit a little bit. Go back to the code and look again at the

interrupt. You’ll notice that when QD is SPWM-ed, QA is kept on, whereas QB and QC are kept off.

Similarly when QB is SPWM-ed, QC is kept on, whereas QA and QD are kept off.

After the first 256 values from the sine table are called, the direction of the output is to be reversed

(remember I said this before too?). For the first 256 sine table calls (when table pointer = 0 to 255), QD

is SPWM-ed and QA is kept on while QB and QC are kept off. Then for the next 256 sine table calls (when

table pointer = 256 to 511), QB is SPWM-ed and QC is kept on while QA and QD are kept off. This

essentially reverses the direction of current through the “OUTPUT”. This is the direction reversion I was

talking about. Do keep in mind that this is a full-bridge converter circuit and that the MOSFETs will

require high-low side drive (QA and QC will require high-side MOSFET drive while QB and QD will require

low-side MOSFET drive).

Another point to note is the “OUTPUT” labeled in the circuit configuration shown above. This will either

be a step-up transformer or your output load. If you’re using a step-up transformer, you usually don’t

need an inductor for filtering and the filter capacitor is usually placed at the secondary of the

Page 24: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

24

24

transformer. If you’re not using a transformer and are feeding the output to your load, then you must

use an LC filter to smooth out the resulting SPWM-ed square wave output to a pure sine wave output.

Below I show three common output (filter) stages used between the bridge output and the load.

Fig. 7 – Common Output (Filtering) Stages

So now let’s see the simulation results on the next page.

Page 25: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

25

25

Simulation Results

Here are the drive signals:

Fig. 6 – SPWM drive signals

Here is the output sine wave:

Fig. 7 – Generated Output Sine Wave

Drive Signals

Yellow – Drive signal to QA

Green – Drive signal to QD

Pink – Drive signal to QC

Blue – Drive signal to QB

-----------------------------------------

SPWM Frequency: 25kHz

Output Sine Wave after

filtration: this same output

shape should be obtained using

an LC filter at the bridge output.

Simulation uses an RC filter at

the microcontroller switching

outputs for demonstration.

------------------------------------------

Sine Wave Frequency: 50Hz

Page 26: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

26

26

Conclusion

The method of sinusoidal pulse width modulation (SPWM) and generating a sine wave output from

these signals is not too difficult if you understand the concepts behind these. The extremely powerful

dsPIC33FJ series of microcontrollers can be used to gain complete control over the SPWM signals

generation and also further control of the overall circuit. I have tried to explain thoroughly the

functioning and programming of the PWM mode of the Output Compare Module of the

dsPIC33FJ12GP202. I have tried to discuss in detail the generation of the sine table to be used for SPWM

and have provided a brief look at my software “Smart Sine” which I’m sure will aid you in your sine table

generation. I have provided the code/program I have used alongside detailed description of the code, as

well as the circuit configuration, output (filter) stage configuration and finally, simulation results of the

presented code. I hope that the tutorial/article that I have prepared and presented here will be of use to

those who are interested in applying the (seemingly difficult) concept of SPWM to generate sine wave

outputs in (not restricted to, but especially suitable for) power electronics applications, such as

inverters.

Feel free to leave your comments and feedback and do make sure that you regularly visit my blog

(www.tahmidmc.blogspot.com) as I try to frequently update it with new (and hopefully useful)

information. If you have any suggestions or questions regarding “Sine Wave Generation and

Implementation using dsPIC33FJ” or even regarding my blog, feel free to post them in the “Comments”

section below.

___________________________________________

Syed Tahmid Mahbub

Page 27: Sine Wave Generation and Implementation using dsPIC33FJ

Sine Wave Generation and Implementation using dsPIC33FJ – Syed Tahmid Mahbub

27

27

Reference and Related Documents

1. dsPIC33FJ12GP202 datasheet:

http://ww1.microchip.com/downloads/en/DeviceDoc/70264E.pdf

2. dsPIC33F Reference Manual – Output Compare section:

http://ww1.microchip.com/downloads/en/DeviceDoc/70209A.pdf

3. “Generation and Implementation of Sine Wave Table”:

http://tahmidmc.blogspot.com/2011/01/generation-and-implementation-of-sine.html

4. “Smart Sine – Software to generate sine table”:

http://tahmidmc.blogspot.com/2012/10/smart-sine-software-to-generate-sine.html

5. “Demystifying the Use of Table Pointer in SPWM – Application in Sine Wave Inverter”:

http://tahmidmc.blogspot.com/2013/02/demystifying-use-of-table-pointer-in.html