PIC PWM question - Page 1
Forum section: electronics / general

author: chilternview
author_rank: Frequent Contributor
timestamp: February 03, 2023, 11:23:46 am
content: I hope someone can help with what I thought was a simple task but for the life of me I can't see it.I am using a 12LF1572 to generate gate drive signals for a simple low frequency inverter. The signals are at 100Hz with a variable duty cycle 30-50%. So I'm using 2 PWM sources, I can set up the period and duty cycle correctly but I can't see how to get PWM2 to be lag by around half the period after PWM1 to give me a pair of non-overlapping pulses.I thought that varying PWM2PH would allow me to shift the second PWM's phase relative to PWM1 but no, that would be too easy... how is it done?Code so far below (ignoring config bits and trivial main() that calls init)pwm(duty_cycle) and then sits in a loop)#define _XTAL_FREQ 16000000 // Oscillator frequency.#define PERIOD 2500 // PWM period. With divide by 64 prescaler on// HFINTOSC, PWM period is 2500 cycles of 16MHz/64// i.e. freq = (16E6 / 64 / 2500) = 100Hz// Initialise the PWM to a specific duty cycle and periodvoidinit_pwm( int duty_cycle) {// Output PWM1 to pin 2 using RA5, PWM2 to pin 3 using RA4APFCONbits.P1SEL = 1;APFCONbits.P2SEL = 1;// Set PWM pin RA5 and RA4 to be outputTRISAbits.TRISA5 = 0;TRISAbits.TRISA4 = 0;// Set PWM input to HFINTOSC clock, prescaler = div-by-64PWM1CLKCON = 0b01100001;PWM2CLKCON = 0b01100001;// PWM control set to standard modePWM1CON = 0b11000000;PWM2CON = 0b11000000;// PhasePWM1PH = 0;PWM2PH = 0;// Duty cycle in %PWM1DC = duty_cycle * (PERIOD/100);PWM2DC = duty_cycle * (PERIOD/100);// PeriodPWM1PR = PERIOD;PWM2PR = PERIOD;// Start the PWM'sPWM1LD = 1;PWM2LD = 1;}

author: JPortici
author_rank: Super Contributor
timestamp: February 03, 2023, 11:38:02 am
content: Reread the datasheethttps://www.microchip.com/40001723using the phase registers require you to set one of the offset modes (current datasheet, revision E, is on section 22.3)However, it's possible that what you're really looking for is the complementary waveform generator? (takes a PWM output and generates the two phases with settable dead band)

author: chilternview
author_rank: Frequent Contributor
timestamp: February 03, 2023, 11:58:08 am
content: Thanks, I tried the offset trigger source register but I'm obviously missing something as if I do this:PWM2OFCON = 0b01000001;to set the offset mode to trigger on PWM1, then PWM2 never fires. I guess I'm not understanding how to set up offset mode as the documentation is as clear as mud - an example would be nice but I've had no luck googling it.I did try CWG but I don't want complementary signals, I want the same but just 180 degrees out of phase.

author: chilternview
author_rank: Frequent Contributor
timestamp: February 03, 2023, 02:14:36 pm
content: So after a bit more experimenting, this works:voidinit_pwm( int duty_cycle) {// Output PWM1 to pin 2 using RA5, PWM2 to pin 3 using RA4// Pin selection RA5APFCONbits.P1SEL = 1;APFCONbits.P2SEL = 1;// Set PWM pin RA5 and RA4 to be outputTRISAbits.TRISA5 = 0;TRISAbits.TRISA4 = 0;// Set PWM input to HFINTOSC clock, prescaler = div-by-64PWM1CLKCON = 0b01100001;PWM2CLKCON = 0b01100001;// PWM control set to standard modePWM1CON = 0b11000000;PWM2CON = 0b11000000;// Set PWM2 to continuous slave run (bits 6/5 = 11)// triggered by OF1 match (bits 1/0 = 01)PWM2OFCON = 0b01100001;// PhasePWM1PH = 0;PWM2PH = 0;// Set the offset match to half periodPWM1OF = PERIOD/2;// Duty cycle in %PWM1DC = duty_cycle * (PERIOD/100);PWM2DC = duty_cycle * (PERIOD/100);// PeriodPWM1PR = PERIOD;PWM2PR = PERIOD;// Start the PWM'sPWM1LD = 1;PWM2LD = 1;}Not sure exactly why!