Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] SPWM using dsPIC30F010

Status
Not open for further replies.

Teebos

Newbie level 4
Joined
Mar 12, 2015
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
40
Hi.

I'm trying to program the chip to perform spwm in a low voltage inverter. I need to update the duty cycle register at 50Hz from a sine look up table. It says in the manual that an interrupt is generated every time the timer (PTMR) is zero and the count goes upwards again. Can I use this to update the duty cycle somehow? I'm using 25kHz for my PWM period so would have to scale the interrupt to achieve 50Hz but I don't know if I'm on the right lines or how to call this interrupt.

Any help hugely appreciated.
 

Hi,

I need to update the duty cycle register at 50Hz from a sine look up table.

I think you want to generate a 50Hz sine. Sou you need to update the PWM register multiple times per fullwave (20ms)
Lets say you want 32 "samples" per fullwave then you need 50Hz x 32 = 1600 Hz update rate.
Or the same in time: you need 32 interrupts within 20ms = 20ms / 32 = 625us. One interrupt per 625us.

This is no problem for a pic.

Within the ISR just fetch the new PWM value from a table (with 32 items) and store it to the PWM register. This needs just some microseconds. Then leave the ISR.

Klaus
 
  • Like
Reactions: Teebos

    Teebos

    Points: 2
    Helpful Answer Positive Rating
Hi and thanks for the reply.

Should I use one of the timer modules to call the ISR rather than the interrupt generated by the PWM? Apologies if it's a daft question, I'm pretty new to this!

Jon
 

Hi,

usually the new PWM values is double buffered and at TOP or BOTTOM of PWM counter activated. Therefore there is no need to use the same timer.
But to be deterministic i´d use the same interrrupt.

But now you need to calculate: 25kHz to 50Hz means you get 500 "samples" per fullwave. this is not an integer multiple of 32.
So you may generate your sine with 50 samples. So you need a table with 50 PWM values.

Within the PWM ISR you need a counter and every tenth (500 samples per fullwave / 50 table values = 10) interrupt you need to fetch a new PWM value from the table and store it into the PWM register.
For sure there are countless other solutions possible.

Just to be sure: You want a fixed frequency, never changing?

Klaus
 
  • Like
Reactions: Teebos

    Teebos

    Points: 2
    Helpful Answer Positive Rating
Thanks again.

I was just working out how to use timer1 to generate the interrupt as I don't understand how to call the automatically generated one from the PWM.

I can have as many samples as I want so I could use 500 in which case I can fetch a new PWM value every interrupt yes?

Could you help me with the code I would need in the interrupt to fetch the value from the table? I've a nasty feeling it involves pointers and I don't understand them!

And yes I need a fixed frequency

Thanks again
Jon
 

It is usual consider creating a sine table that exactly matches a crystal frequency divided by a power-of-two value, so that the Timer overflow, with or without a prescaler, itself is able to generate the interruption with a minimum of extra processing or loss of accuracy. Although being considered somewhat as a slow option, the 3.276.800 Hz crystal meet such criterium.
 

Hi,

I'm using the internal 7.37MHz Oscillator with x8 PLL, so 58.96MHz.

Jon
 

Hi,

with this clock frequency you don´t get exactely 25.0000 kHz, isn´t it?
But it´s no problem.

***

Here a just one optimized calculaton to get a PWM frequency near to 25kHz and an exact sine frequency of 50.000Hz.

Maybe you find this interesting. Maybe not.

7372800Hz (i suppose) x 8 = 58982400 Hz.
Divide it by 50 (Hz) then you see how much clock cycles there are per full wave. ==> 1179648
Do the prime factorisation: ==> 2^17 x 3^2 (that´s good, a lot of "2")
the (little) problematic are the 3^2 = 9. This means your timer value should be multiple of 9.
If you want a PWM frequency of about 25000 kHz, this means about 58982400Hz/25000 = 2359 clock ticks.
What is the next multiple of 9 x 2^n to 2359 ==> 2304
So i´d set the prescaler to 1 and the TOP value to 2304-1 = 2303 (counter runs from 0 to 2303). Here you may adjust to your PWM hardware.
58982400 / 2304 = 25600 Hz PWM frequency
divide it by 50Hz and you get 512. this is the number of "samples"
So you need a table with 512 entires and PWM values with peak to peak amplitude of 2304 --> use +/- 1150 = sine amplitude of 1150. Add an offset of 1152.


Klaus
 
Hi

Thanks for all the help! It is really appreciated. That calculation is very neat.

Regarding the ISR: It should be simpler with this calculation as the table will be stepped through each time the ISR is called, Is that right? D I need to use a table pointer in the ISR? And does the look table belong within the ISR or in the main?

Thanks
Jon
 

Hi,

don´t be afraid of pointers.
It´s not difficult to understand, but once you understand you don´t want to miss then.

a pointer is just a variable that contains an address to a variable (or an array item).

Assume beginning at address 0x8000 there is an array of strings that contain music titles:
0x8000 "Dark side of the moon", 21 bytes plus one string delimiter
0x8016 "Sad old red", 11 bytes plus one delimiter
0x8022 "Slave to the rythm"
as tring that contains "This is just an example text". it is 28 bytes long plus the string delimiter

With the use of a pointer you only say "the string starts at addr. 0x8016"
if now a function modifies the string at addr. 0x8016, then it is really modified at this position. Any further read of data referenced with the pointer will see the modified string.

Without a pointer you have to copy the text to another variable (string) and give the whole string to the function. If the function modifes the string, it modifies only his local string, but the source (at 0x8016) is not changed.

****
I´m not that familiar with "C", so maybe here is anyone who could explain how to use the pointer (with table and index and so on)

***

Klaus
 
  • Like
Reactions: Teebos

    Teebos

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top