PWM output appears to falter at 100%

Thread Starter

urb-nurd

Joined Jul 9, 2014
269
Hey guys, i am having an issue with my pwm output.
It appears that when the duty should be at 255, it is more like 254 or 253.
This can be seen on the gate drive waveform of my MOSFET that i am controlling via the PWM output of my Ready for Pic board.



When i change the input for my opto-coupler from the Pwm output to VCC i get a solid dc level at my gate.
From this test, i assume the problem is with the code or micro-controller rather than the circuit.

Code:
//LCD module connections
sbit LCD_RS at LATD4_bit;
sbit LCD_EN at LATD5_bit;
sbit LCD_D4 at LATD0_bit;
sbit LCD_D5 at LATD1_bit;
sbit LCD_D6 at LATD2_bit;
sbit LCD_D7 at LATD3_bit;

sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD0_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D7_Direction at TRISD3_bit;
// End Lcd module connections
unsigned short current_duty, new_duty, duty_cycle;
unsigned int  oldstate, oldstate2, adc_rd;
double adc, adc1;
char txt1[4];
char txt2[] = "Duty =";
char txt4[] = "Temp =";
char txt3[14];
void InitMain() {
   ANSELA.B0  = 1;  // configure port a pin 0 as analogue (disable digital buffer)
   PortA = 255;
   TRISA = 255;                      // Configure AN pins
  ANSELB = 0;
  ANSELC = 0;
  ANSELD = 0;
  PORTB = 255;            // Set RB0 pin as input
  TRISB = 255;            // Set RB1 pin as input
  C1ON_bit = 0;               // Disable comparators
  C2ON_bit = 0;               // (for pwm function)
  PORTD = 0;
  TRISD = 0;
  PORTC  = 0;                          // set PORTC to 0
  TRISC = 0;                          // designate PORTC pins as output

PWM1_Init(25000);                    // Initialize PWM1 module at 5KHz
}
void LCD(){
    Lcd_Init();                        // Initialize Lcd
    Lcd_Cmd(_LCD_CLEAR);               // Clear display
    Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
    }



void main() {
  InitMain();
  LCD();
current_duty  = 0;                 // initial value for new_duty
  duty_cycle = 0;
 PWM1_Start();                       // start PWM1
 PWM1_Set_Duty(current_duty);        // Set current duty for PWM1*


  do {
      adc_rd = ADC_Read(1);
      adc = (adc_rd);
      adc1 = ((((adc)/1024)*3.3)-1.25)/0.005;


      BYTEToStr(current_duty, txt1);
     // wordtostr(adc_rd, txt3);
       floattostr(adc1,txt3);

      Lcd_Out(1,7,txt1);                 // Write text in first row
      Lcd_Out(1,1,txt2);
      Lcd_Out(2,7,ltrim(txt3));                  // Write text in second row
      Lcd_Out(2,1,txt4);

    if (Button(&PORTB, 0, 100, 1)) { // detect logical one to logical zero transition
      current_duty++;          // Incremenet Duty
     PWM1_Set_Duty(current_duty);        // Set new duty for PWM1
      Delay_ms(3);
    }
    if (Button(&PORTB, 1, 100, 1)) { // detect logical one to logical zero transition
      current_duty--;                          // set current duty
      PWM1_Set_Duty(current_duty);        // Set new duty for PWM1
      Delay_ms(3);
    }
  } while(1);
}
Any help is greatly appreciated!
Thanks
 

ErnieM

Joined Apr 24, 2011
8,377
Lots of code. LOTS! Way to much.

Just give your PWM a fixed number of 255 and see what happens.

I'm not a big fan of MikroC as it hides too much stuff (like what chip you are using and what libraries have been selected) so I don't know who good the PWM1_Set_Duty() function works. Later day PICs use a 10 bit period to set 8 bits here and 2 bits there; I would expect MikroC to get this correct but may be a glitch.

I'd also turn on the debugger to see if the proper period bits make it to the register(s).
 

JohnInTX

Joined Jun 26, 2012
4,787
Its hard to tell from the scope pic what the freq/duty is but some observations:
PWM1_Init parameter is 25000Hz but the comment says 5000Hz - which is it.
You are running the PWM output through an opto? A schematic would be nice but if the collector of the opto out is what you are measuring, it looks like you need more pullup resistor (slow rise time). Need a schematic to be sure.
I echo ErnieM's comments about MikroC. Which PIC are you running, what's the oscillator?

If you are splitting hairs between 253-254 is your scope setup accurate enough? I would have a hard time with the trace shown.

I'd also turn on the debugger to see if the proper period bits make it to the register(s).
Me too. Set a breakpoint after changing current_duty, inspect the register value then work backwards using the PIC datasheet to confirm that the PICs raw period and duty registers are correctly set. Its not unlikely that some rounding error skins an LSB off here and there. You can also inspect the listing file to see how the library uses the hardware PWM and check its numbers.

Good luck.
 

GopherT

Joined Nov 23, 2012
8,009
If you are resetting your PWM frequency or duty cycle at the end of each Pwm interval, there may be a glitch as it resets. Also, check the datasheet. It may always go back to ground after each roll-over of the Pwm clock.

Try a short segment of code where you turn on 255 duty cycle only.
 
Top