# Inverted PWM using PIC18F4550

Status
Not open for further replies.

#### Ann0123

##### New Member
Hi everyone.
My project requires to send PWM signal to the MOSFET. I am using 6N137 Optocoupler. The output of this is inverted signal. One way is to use an inverting IC at the output of PWM pin of micrcontroller PIC18F4550. This got me thinking is there a way I can send inverted PWM signal to optocoupler since it inverts it in order to get original PWM? PWM frequency is 50kHz or 20us. I am using:
MPLAB X IDE v3.55
XC8 v1.44
PICkit 3
20MHz external oscillator

#### Triode

##### Active Member
Since there is just a timer and a comparator you can't just set something to invert the signal, if you're looking for a command like "Config PORTC.Inverted" but if you understand how the PWM module works this is easily accomplished. Looking at the datasheet it works like this:

It's actually a little circuit that's in the MCU, this isn't just a flow chart of a program, it's physically in there.

As you can see the comparator checks the timer against the duty cycle, which is set in CCPRxL (and used from CCPRxH, but that's a buffer, you don't write to it) when timer exceeds this value it switches from high to low, so that determines the time the output is high. To make the whole process repeat the timer resets when TMR2 reaches the value in PR2, so PR2 sets the period. If you want to control the low time, since you can only set CCPR, just set it to the period (total time, low + high) minus the time you want it to be low.

This website with a PWM calculator actually does this. They set the first, CCPR1L, to the value for their pulse width, dc, and they set the second one CCPR2L for 128 (which is close to what they set PR2 to) minus dc.

http://www.micro-examples.com/public/microex-navig/doc/097-pwm-calculator.html

Code:
void main()
{
unsigned char   dc ;

TRISC = 0 ;                     // set PORTC as output
PORTC = 0 ;                     // clear PORTC

/*
* configure CCP module as 4000 Hz PWM output
*/
PR2 = 0b01111100 ;
T2CON = 0b00000101 ;
CCP1CON = 0b00001100 ;
CCP2CON = 0b00111100 ;

for(;;)                         // forever
{
/*
* PWM resolution is 10 bits
* don't use last 2 less significant bits CCPxCON,
* so only CCPRxL have to be touched to change duty cycle
*/
for(dc = 0 ; dc < 128 ; dc++)
{
CCPR1L = dc ;
CCPR2L = 128 - dc ;
Delay_ms(10) ;
}
for(dc = 127 ; dc > 0 ; dc--)
{
CCPR1L = dc ;
CCPR2L = 128 - dc ;
Delay_ms(10) ;
}
}
}
In short CCPRxL is the number of timer tics of your pulse being high, PR2 is the time it is low+time it is high, so if you want to set a low time just subtract that time from whatever you set PR2 to and put that value in CCPRx.

#### Ann0123

##### New Member
I was comparing PWM output from MCU, function generator and opto-isolator. I realized that my MCU PWM output is inverted and a bit shifted as compared to function generators output. I have attached the picture. Did I do something wrong? My duty cycle code is:

#### ronsimpson

##### Well-Known Member
MCU PWM output is inverted and a bit shifted as compared to function generators output.
I don't know how you connected the 6N137.
There will be 50 top 100nS delay through the 6N137. Depends on how much drive current.

I do not have time to look....Can your PWM output pin pull up with as much current as it pulls down?
You can connect the 6N127 to supply or to ground. (this will invert)
.....Trying to say you can connect to supply so there is current when the pin is low.
OR
.....Connect to ground so the current flows when the pin is high.
In both cased there will be no current when the pin is in tri-state.

Status
Not open for further replies.