Okay, I've a little bit modified the Bruce's program.
It runs well in ISIS Proteus with my defined duty cycles, and all of the 6 PWM outputs works.
But there is a little problem :
As you can see, U and W phases are working properly, but not the V phase (the low-side PWM is not inverted like the others).
Here's my modified code :
Thanks in advance for any advice.Code:DEFINE LOADER_USED 1 DEFINE OSC 20 ' At 20MHz, to figure a PWM frequency of 19.455kHz ' TPWM = time period of PWM frequency ' PTPER = 12-bit period register PTPERL and PTPERH ' PTMRPS = PWM time base prescaler ' ' (PTPER+1)*PTMRPS 257 ' TPWM = ---------------- = ------------ = 0.0000514 ' Fosc/4 5000000 ' ' Frequency = 1/TPWM = 1/0.0000514 = 19.455kHz ' ' PWM resolution (bits resolution for duty cycle) ' ' log(20MHz/19.455kHz) 3.01 ' Resolution = ------------------ = ----------- = 10 bits ' .301 .301 ' so we'll need a word sized var for Duty uduty VAR WORD vduty VAR WORD wduty VAR WORD PORTB = 0 ' clear port latch TRISB = %11000000 ' PWM0,1,2,3,4,5 outputs TRISC = 2 ' RC1 = FLTA input (ground RC1 to halt PWM) ' RC1 should be pulled high for normal PWM operation ' when fault A is enabled. ' PCPWM init DTCON = %00000101 ' ~500nS dead-time (for complementary outputs only) PTCON0 = %00000100 ' 1:1 postscale, Fosc/4 1:1 prescale, free running mode ' PTCON0 = %00000100 would give 19.45kHz/4 PTPERL = 0 ' PTPERH = 1 ' PTPER = $0100 or 256d for ~19.45kHz ' PWM4,5 independent, PWM0,1,2,3 complementary PWMCON0 = %01010100 ' PWM[5:0] outputs enabled PWMCON1 = 1 ' updates enabled, overrides sync w/timebase PTCON1 = %10000000 ' PWM time base is ON, counts up FLTCONFIG = %00000011 ' enable fault A, cycle-by-cycle mode 'Phases duty test uduty = 800 ' ~50% vduty = 500 wduty = 300 pwmlp: ' PWM update loop 'PWM U phase PDC0L = uduty.LowByte PDC0H = uduty.HighByte 'PWM V phase PDC1L = vduty.LowByte PDC1H = vduty.HighByte 'PWM W phase PDC2L = wduty.LowByte PDC2H = wduty.HighByte goto pwmlp
Last edited by pxidr84; - 12th February 2011 at 00:38.
Hi,
Are you sure it's not the W-phase output that isn't complementary?
Look at the PWMCON0 register, you have it set to %01010100 which means that PWM0 and PWM1 is in complentary mode while PWM2 (the W-phase according to your code) is in independant mode.
/Henrik.
Thanks a lot, you guided me on the right way.
I've read the datasheet, and especially the "PWMCON0" register description. I've modified the value to PWMCON0 = %01000000, and now the 3 phases are working very well (the low-side V phase is now inverted properly).
Now, I've to modify the duty according to a sinus function. I think about it.
A last question : I've doubts about the duty cycle. What's the exact range of the duty cycle?
If I define a duty cycle between 0-10, the simulator oscilloscope gives me weird things (the inverted signal "jumps")...
If I define a duty cycle above 1023, same thing...
The code used :
Code:' At 20MHz, to figure a PWM frequency of 19.455kHz ' TPWM = time period of PWM frequency ' PTPER = 12-bit period register PTPERL and PTPERH ' PTMRPS = PWM time base prescaler ' ' (PTPER+1)*PTMRPS 257 ' TPWM = ---------------- = ------------ = 0.0000514 ' Fosc/4 5000000 ' ' Frequency = 1/TPWM = 1/0.0000514 = 19.455kHz ' ' PWM resolution (bits resolution for duty cycle) ' ' log(20MHz/19.455kHz) 3.01 ' Resolution = ------------------ = ----------- = 10 bits ' .301 .301 'PIC initialization DEFINE LOADER_USED 1 DEFINE OSC 40 'Port registers configuration PORTB = 0 ' Clear ports TRISB = %11000000 ' PWM 0,1,2,3,4,5 outputs TRISC = 2 ' RC1 = FLTA input (ground RC1 to halt PWM), pull-up resistor on RC1 'PCPWM registers configuration DTCON = %00001010 ' Deadtime (500ns) PTCON0 = %00000100 ' 1:1 postscale, Fosc/4 1:1 prescale, free running mode PTCON1 = %10000000 ' PWM time base is ON, counts up, 19.45kHz/4 PTPERL = 0 ' PWM low-side PTPERH = 1 ' PWM high-side 'PWM registers configuration PWMCON0 = %01000000 'PWM 0,1,2,3,4,5 set in pair mode PWMCON1 = %00000001 'PWM timer sync configuration FLTCONFIG = %00000011 'Fault configuration 'U, V and W duty variables uduty VAR WORD vduty VAR WORD wduty VAR WORD 'Phases duty uduty = 1 vduty = 1000 wduty = 1000 pwmlp: ' PWM update loop 'PWM U phase PDC0L = uduty.LOWbyte PDC0H = Uduty.HIGHByte 'PWM V phase PDC1L = vduty.LOWbyte PDC1H = vduty.HIGHByte 'PWM W phase PDC2L = wduty.LOWbyte PDC2H = wduty.HIGHByte goto pwmlp
Hi,
The available resolution depends on the actual PWM frequency, you can see in the code how Bruce has calculated it for you. If you haven't changed the code the resolution is 10 bits (0-1023).
The PCPWM module have a configurable dead-time generator which inserts a deadtime between turning off the upper switch and turning on the lower switch. When aproaching the "ends" of the available resolution this can distort the output waveform and I suspect that is what you're seeing.
If you don't need deadtime you can turn it off. If you do need deadtime you should make sure that the dutycyle never aproaches the values where you're starting to see distortion. You usually can't use extreme dutycycles anyway due to the MOSFET/IGBT highside drivers need to refresh its bootstrap capacitor charge.
Okay, the code is now capable to calculate 3 sine waves (one for each phase).
I can modify the frequency (by increasing or decreasing freqdiv), but I've difficulties to set a phase angle (0-120-240° for U, V and W respectively) and I've difficulties to set a sinus amplitude (for exemple, if I want a 0-50% dutycycle, I will write uduty=uduty*0.5, but PBP does not support float maths).
Thanks for your help. I use Darrel Taylor's interrupt system for sine-wave generation loop.
Code:'PIC initialization DEFINE LOADER_USED 1 DEFINE OSC 40 'DT interrupt system include INCLUDE "DT_INTS-18.bas" ' Base Interrupt System INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP interrupts 'PWM calculation variables uduty VAR WORD 'U phase duty vduty VAR WORD 'V phase duty wduty VAR WORD 'W phase duty t VAR byte 'Incremental value 'Inverter U/F variables freqdiv var WORD 'Frequency diviser FREQdiv=0 'Range : 0-65535 'Port registers configuration PORTB=%0 ' Clear ports TRISB=%11000000 ' PWM 0,1,2,3,4,5 outputs 'PCPWM registers configuration DTCON=%110 ' Deadtime (600ns) PTCON0=%100 ' 1:1 postscale, Fosc/4 1:1 prescale, free running mode PTCON1=%10000000 ' PWM time base is ON, counts up, 19.45kHz/4 PTPERL=%0 ' PWM low-side PTPERH=%1 ' PWM high-side 'PWM registers configuration PWMCON0=%1000000 'PWM 0,1,2,3,4,5 set in pair mode PWMCON1=%1 'PWM timer sync configuration 'Interrupt processor ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag INT_Handler TMR1_INT, _pwmint, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM 'Timer configuration T1CON=%10000001 ; Prescaler = 1:1, TMR1ON, 16-bit counter @ INT_ENABLE TMR1_INT ; Enable Timer 1 interrupts 'Main loop mainlp: pause 1000 goto mainlp 'PWM calculation and update interrupt pwmint: t=0 for T=0 to 255 step 1 'Frequency diviser pauseus freqdiv 'PWM U phase calculation uduty=((sin(t)+128)*4) 'PWM V phase calculation vduty=((sin(t)+128)*4) 'PWM W phase calculation wduty=((sin(t)+128)*4) 'PWM U phase update PDC0L=uduty.LOWbyte PDC0H=Uduty.HIGHByte 'PWM V phase update PDC1L=vduty.LOWbyte PDC1H=vduty.HIGHByte 'PWM W phase update PDC2L=wduty.LOWbyte PDC2H=wduty.HIGHByte next t @ INT_RETURN
Last edited by pxidr84; - 19th February 2011 at 12:13.
Bookmarks