Continue to Site

# Sine PWM calculated with pic, instead of using table

Status
Not open for further replies.

#### ljille

##### Member level 1
I have seen several posts about PWM in order to make a one phase inverter,

and most use a long values table calculated to get the sine wave,

but what if it calculates the duty value each time?

I have a graph where can be seen some details, but I don't see the way to
attach it. There I see I will have to compensate about 1/7 of cicle time due to the
calculation time.

Code Basic4GL - [expand]1
2
3
4
5
6
7
8
9
-----------------     picbasic pro:
counter=0
loop:
duty=sin[(counter/100)]    '  to compesate decimal handle in above lines  PWM
pin,duty,1      ´  PWM pin,duty,cycle  at 11,718 Hz
counter=counter+ n    ' 127 cicles n=1,  n= 127/195= 0.65  -> 65
if counter= 19500 then counter=0
goto loop
-----------------

So, What do you think about it?
L.J.

Last edited by a moderator:

#### dick_freebird

Question is, do you have enough CPU / MCU cycles per PWM
period to perform this calculation?

Calculating it once and storing a table is more CPU-efficient,
less memory-efficient. Which do you have more of, resource-
wise?

V
Points: 2

##### Super Moderator
Staff member
The sine function produces negative values for a portion of each cycle. Does your switching scheme need positive numbers only? Or, does your loop calculate only the positive waveform?

V
Points: 2

#### ljille

##### Member level 1
>
Question is, do you have enough CPU / MCU cycles per PWM
>period to perform this calculation?

I don't have the machine cycles reference for each picbasic instruction, so I'm supossing that simple ones take 10 cycles and complex as if of goto takes 20 cycles. That plus 30 extra cycles gives me 100 cycles, which I estimate about 7 uS. Thats why I say I have to compensate it, otherwise it would be added to the 'switch off' of the IGBTs I plot to use, so I have to sustain 3 uS a high value of duty at each side of the sinus maximum. But I'd like to know first if this idea you think can work in order to go implementing with a little more confidence.

>Calculating it once and storing a table is more CPU-efficient,
>less memory-efficient. Which do you have more of, resource-wise?
16F628A has 128 EEPROM bytes, so I'd have to handle 1/4 of sine cycle and decrement pointer to handle about 100 data table. So it is possible but some tricky, and maybe I liked how short is this program without memory and table handles.

What do you think?

- - - Updated - - -

Good point. I plot to have two pins with PWM out (I have not complemented the program but I will), p1 (maybe port B0) for branch 1 of a IGBTs bridge (FWD direction) and p2 (maybe port B1) for branch 2 of the bridge (BAK direction), in a way that by program (with programmed histeresis) I set ON one branch showing a sinus half wave, and then it becomes OFF, takes histeresis time and then set ON the opposite branch on the other pin. Each branch will handle two IGBTs drivers simultaneously, so it becomes practically impossible to get a short circuit. I suppose that 100 pulses/half sinus cycle gives us a smooth curve after the final filter.
What do you think?

#### dick_freebird

I don't think you can "compensate" a cycle-by-cycle slip,
you're going to roll through the beat cycle.

You could look at the amount of sine wave distortion you
can stand; overkill on the pulse width resolution helps
none. Maybe there are hybrid approaches such as stored
"delta" and simple add, per cycle. Figure the per-clock
delta of an 8-bit sine wave is what, a couple of bits?
Store them 4 to a byte?

Of course there are now many, many microcontroller dev
options out there and many with more better resources
than you describe using. I would not be surprised if there
was something out there in app notes that is like what
you're doing, and maybe eval kits that are set up like you
want. Don't get too committed to whatever specific one
you have in hand (unless somebody else has gone and
committed you to it).

V
Points: 2

#### KlausST

##### Super Moderator
Staff member
Hi,

Don't:
* wait for the timout (PWM interrupt, timer interrupt...)
* calculate value (resulting in unpredictable delay)
* output the calculated value

But do:
* wait for the timout (PWM interrupt, timer interrupt...)
* output the previously calculated value
* pre-calculate the next value and store it (causing no jitter and no delay)

With this you get low jitter, low delay (from timeout to output) output signal.

Klaus

V
Points: 2

#### betwixt

##### Super Moderator
Staff member
16F628A has 128 EEPROM bytes, so I'd have to handle 1/4 of sine cycle and decrement pointer to handle about 100 data table.
Easier to store the sine table in program memory than EEPROM. I don't know PicBasic but the equivalent in 'C' of making it a 'const' table.
I doubt the 16F628A can manage 'on the fly' calculations with sufficient timing accuracy, trig functions can be very slow and more importantly take different times for each value. Even using Klaus's pre-calculate method I doubt it would keep up and if it had to do anything else, for example react to feedback it wouldn't cope.

Brian.

#### Easyrider83

The concept of using constant table in flash is to fully dedicate the processing to interrupts/perepherials. So, the main cycle will be free for other purpose.
In your case you don't need mcu at all. Just store the table in EPROM and switch the values by counter.

ljille

### ljille

Points: 2

#### ljille

##### Member level 1
The advantage I saw of using PWM function would be not to deal with measuring time and its interruptions.
* Is there a picbasic document who gives us the time of execution of each instruction in the loop as the program showed?.
* Would it be better to make the subrutine of clock, to make the loop and avoid PWM function?
What do you think?

#### KlausST

##### Super Moderator
Staff member
Hi,

I recommend to use PWM ... and PWM hardware. It generates the perfect timing without processing power.

Is there a picbasic document who gives us the time of execution of each instruction in the loop as the program showed?.
I'm not experienced with PIC, but each instruction set (in the datasheet or in an extra document) should show the count of clock cycles per instruction.

Klaus

#### ljille

##### Member level 1
Hi,

I recommend to use PWM ... and PWM hardware. ...

Klaus

I was in a confusion: PWM is different than HPWM. PWM is a very slow software based picbasic instruction. HPWM is a pcbasic instruction that handles the hardware based PWM for PICs with this capability. So, table 9-3 of the PIC I have, works for HPWM instruction on CCP1 (RB3 port) and the times there stated are true under this instruction. Thank you for your comments. I will reconfigure the program and reply it.

#### KlausST

##### Super Moderator
Staff member
Hi,

PWM = pulse width modulation
HPWM .... never heared about it.....you mentioned it for the first time now.

PWM can be made with software, but very most nowadays microcontrollers have built in PWM periferal.
I'd always prefer to use built in hardware.

What is "table 9-3 of the pic"?

Klaus

ljille

### ljille

Points: 2

##### Super Moderator
Staff member
HPWM .... never heared about it.....you mentioned it for the first time now.
I'd assume it is short for Hardware PWM

google also seems to indicate that PICs use that acronym for the Hardware PWM.

ljille

### ljille

Points: 2

#### ZASto

In PICBasic and Proton Basic, HPWM is related to hardware PWM module in PIC micro, which directly sets registers of PWM module, leaving micro to do other work.

ljille

### ljille

Points: 2

#### ljille

##### Member level 1
Well, considering comments, What do you think of this version of program for inverter?:

'This is a version for Sinus wave inverter without PWM or HPWM instructions
'It alternates pins, each one responsible of a branch oa an H bridge of IGBTs
'half positive half cycle on 96 program cycles
'Table of 1/4 cycle, 48 pulses then it decrement pointer to get 1/2 cycle
'Then it repeats but for the other H branch
'Pendant: to shorten to compensate program time, taking some time to the off time of cycle Luis Jiménez

'It can be done a timers and interrupt version (not pulsout)

Code dot - [expand]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
ARRAYWRITE SineWave {0,2,5,8,10,13,16,19,21,24,27,29,32,34,37,39,42,44,46,49,51,53,55,57,59,61,63,65,67,68,70,71,73,74,75,77,78,79,80,81,82,82,83,84,84,84,85,85,85}   ' uS  (excel calculated originally for HPWM but anyway it most work

'INITIAL SETTINGS OF 16F628A, WILL BE HERE   CLOCK 12 MHz

b0 VAR BYTE   ' array's pointer
Dir VAR BIT       ' pointer direction
MAXIT = [MAX SineWave Count]   '
dir =0
b0=0
´set off PINs

MAIN:
'BRANCH 1
PIN = RB0       '   DEFINE PORT (ver circuito)
DO HALF_CYCLE
pauseus 40      'histeresys to set off IGBTs

'BRANCH 2
PIN = RB1        ' DEFINE PORT
Do HALF_CYCLE
pauseus 40       'histéresis

GOTO MAIN

HALF_CYCLE:         ' each cycle = 1/195 pulses
FIN=0
DO WHILE FIN=0
ON= SineWave[b0]
OFF = 85 - ON         'this makes a fixed pulse width   (uS)

PULSOUT PIN, ON    ' send pulse by PIN, width as table elem.
'pulse width 1/11,700 + calc
Pauseus OFF

IF Dir = 0 THEN      ' increment or decrement pointer
b0 = b0 + 1
ELSE
b0 = b0 - 1
ENDIF

IF (b0 = MAXIT)  THEN   'changes pointer direction or ends half second of one branch
Dir = 1
ENDIF
IF (b0 = 0) AND (Dir = 1) THEN
Dir = 0
FIN = 1
ENDIF

END WHILE
RETURN

END SUB

'----------------

Luis J

Last edited by a moderator:

#### betwixt

##### Super Moderator
Staff member
I think it will work but the waveform will be quite distorted. I do not use BASIC at all but I would guess the PULSOUT command uses a software loop to create the delay. It is unlikely the delay will be exact because your calculations and the software loop time uses 16-bit values and it is an 8-bit processor which means the path taken to get a result will depend on the internal algorithms used by the language.

Seriously, the 16F628A has a built in PWM module which does most of the work for you and is extremely accurate, why not use it?

All you have to do is set the timers so you get the frequency you need then for each point in the sine wave you load the value from the array into the PWM registers, there may already be a command for doing that in PicBasic.

Brian.

ljille

### ljille

Points: 2

#### ljille

##### Member level 1
I think it will work but the waveform will be quite distorted....
there may already be a command for doing that in PicBasic.
Brian.

Yes, the HPWM instruction of PicBasic uses the PWM hardware. I ommited this because I wanted to use two branches (so two pins), one for each branch, but this uController has only one PWM port RB3, so I have to use an external AND gate in order to get the two branches control.

OK. Considering what you tell, I'll make the HPWM version although I have to use the AND gate, so I get a high quality sinus function out, then I'll post it.

Thank you very much
Best regards
Luis Jiménez

#### betwixt

##### Super Moderator
Staff member
Remember that you can't produce two different PWM signals simultaneously with only one PWM generator but if one of the signals is the inverse of the other you can use a logic inverter to produce it.

Brian.

#### ljille

##### Member level 1
This squema I think can clarify what I am trying to do. I was trying to avoid the logical gates after the PIC, but as I have only one PWM port... The other factor is that I have already a printed circuit board good for this PIC, so I only will put components on it, solder and will see it easier than doing it from scratch.

Last edited:

#### ljille

##### Member level 1

Code Basic4GL - [expand]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
'This is a version for Sinus wave inverter with hardware PWM module
' in uController
'It alternates pins, each one responsible of a branch on a H bridge
'half positive cycle on 96 program cycles
'Table of 1/4 cycle, 48 pulses then it decrement pointer to get 1/2 cycle
'Then it repeats but for the other H branch
'Pendant to shorten to compensate program time, taking some time 'to the off time of cycle       Luis Jiménez

'It can be done a timers and interrupt version  (not pulsout)

ARRAYWRITE SineWave {0,8,16,24,32,40,48,56,64,72,80,88,96,103,111,118,125,132,139,146,152,159,165,171,177,183,189,194,199,204,209,214,218,222,226,230,233,236,239,242,244,246,248,250,251,253,253,254,254,255}   '  duty 0 - 255

b0 VAR BYTE   ' array's pointer
Dir VAR BIT       ' pointer direction
Selector VAR BIT       ' phisical branch selection
RB2 -> Selector

MAXIT = [MAX SineWave Count]   '
dir =0
b0=0
´Apagar PINs pendiente

MAIN:
'BRANCH 1
Selector = 0
DO HALF_CYCLE
pauseus 40   'histéresis para OFF de IGBTs

'BRANCH 2
Selector = 1
Do HALF_CYCLE
pauseus 40   'histéresis

GOTO MAIN

HALF_CYCLE:         ' each cycle = 1/195 pulses
FIN=0
WHILE FIN=0
ON= SineWave[b0]

HPWM chan1, ON, 11718    ' send pulse by chan1, duty as table elem.
'pulse width 1/11,700 + calc

IF Dir = 0 THEN      ' increment or decrement pointer
b0 = b0 + 1
ELSE
b0 = b0 - 1
ENDIF

IF (b0 = MAXIT)  THEN   'changes pointer direction or ends half second of one branch
Dir = 1
ENDIF
IF (b0 = 0) AND (Dir = 1) THEN
Dir = 0
FIN = 1
ENDIF

WEND
RETURN

RESUME

'--------------------