CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PWM Questions....
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PWM Questions....
PostPosted: Fri Oct 26, 2018 4:31 pm     Reply with quote

Hi All,

I'm picking away at a PID controller project, and finding that I haven't quite got a handle on how the PWM should operate. This is a PIC 18F45K50 based project running at 16MHz. Compiler is PCH 5.050.

Here is my PWM setup for a 1 KHz frequency:

Code:

   // Here is the PWM setup code...
   // This code should output a 1000Hz PWM pulse train on CCP1 (Pin 36). We are using the full 10 bits of PWM control..
   setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 249, 1);   //Set PWM Frequency to 1000Hz ---> (1/16000000)*4*16*(249 + 1)= .001s or 1.0kHz


This code works like a champ, and I see a nice 1 KHz signal on pin 36 with my oscilloscope.

Here is some test code to set the duty cycle:

Code:

   set_pwm1_duty((int16)0);                   //Set 0% Duty Cycle
   fprintf(Console, "1000 Hz, 0 Percent Duty Cycle\n\r");
   delay_ms(5000);

   set_pwm1_duty((int16)250);                   //Set 25% Duty Cycle
   fprintf(Console, "1000 Hz, 25 Percent Duty Cycle\n\r");
   delay_ms(5000);
   
   set_pwm1_duty((int16)500);                   //Set 50% Duty Cycle
   fprintf(Console, "1000 Hz, 50 Percent Duty Cycle\n\r");
   delay_ms(5000);

   set_pwm1_duty((int16)750);                   //Set 75% Duty Cycle
   fprintf(Console, "1000 Hz, 75 Percent Duty Cycle\n\r");
   delay_ms(5000);

   set_pwm1_duty((int16)1000);                   //Set 100% Duty Cycle
   fprintf(Console, "1000 Hz, 100 Percent Duty Cycle\n\r");
   delay_ms(5000);


This code functions more-or-less as expected, with two exceptions. At 0% duty cycle I see a 5uS pulse repeating at 1 KHz, and at 100% duty cycle I see basically the same thing. It seems like the 100% is a 'wrap' issue of some kind because if I try 99% duty cycle, for example, that is what I get. So, what *should* 0% and 100% look like? I'm expecting a continuous 0V at 0%, and a continuous 5V at 100%. Why does 100% wrap around to a much smaller value?

Duty cycle is supposed to be:
Quote:

DC = Value/(4 * (PR2 + 1)) = Value/1000


So, the 0%, 25%, 50%, 75% and 100% duty cycles should be easily attained with the code above, but it's not quite correct.

What am I missing?

Thanks,

Jack
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 26, 2018 10:47 pm     Reply with quote

I can't duplicate your problem. Post a complete test program.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Oct 27, 2018 3:14 am     Reply with quote

Is your PWM period being given an 8 or a 10 bit value?

As I understand it the PWM period uses 10 bits made up of an 8 bit register and 2 bits from another one.

If you give the PWM an 8bit value the two LSBs are ignored and appear as the narrow pulses you're seeing.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sat Oct 27, 2018 3:42 am     Reply with quote

If you look, he is casting it to an int16, so it should be a 16bit value.
I've compiled the code, in a basic 'wrapper', and though I don't have one of those chips handy, on the simulator it is giving perfectly good values. I think PCM_Programmer has actually tried it!...
I was looking for 'other things', for instance could a deadband delay give an issue?. However the code on the nearest compiler I have (5.049), is correctly clearing the deadband register.
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Oct 27, 2018 7:32 am     Reply with quote

OK, I keep looking at this and wondering is the 16MHz clock the internal RC or a real xtal/2caps ? Maybe I'm wrong but if the clock isn't stable, the PWM will 'jitter' ?
If you have the right 'scope', you should look at both 16MHz clock and the PWM to see.
Then there's the 'math' aspect. It'd be nice to see the real numbers the program loads into the registers. Maybe 100% isn't loading the correct value ?

Heck I'm an 'old fart' so if I'm wrong please tell me...never too old to learn.

Be nice to see the complete test program....
Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sat Oct 27, 2018 1:59 pm     Reply with quote

Well, as I said, I haven't got 5.050, but have 5.049, and 5.051, and both are putting the right values into the right registers with the code posted.

A _real_ complete test program, that we can compile showing the problem is needed.
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Sat Oct 27, 2018 6:32 pm     Reply with quote

Hi All,

Thanks for the input! I’m traveling this weekend, so I’ll post a complete test program as soon as I’m back!

Thanks,

Jack
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Oct 28, 2018 1:46 am     Reply with quote

We will look forward to it. Hopefully something simple that shows the problem (probably the stuff you have already posted, just with the rest of the processor setup etc..).
Problem is that we are not seeing what you are describing, if we put that code into our own 'wrapper', so it suggests there is something else involved....
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Mon Oct 29, 2018 8:52 am     Reply with quote

Hi All,

Here is a complete test program that compiles without errors using PCH 5.050.

Code:

#include <18F45K50.h>
#fuses HSH,PLL3X,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOFCMEN,CPUDIV3
#use delay(crystal=16MHz, clock=16MHz, USB_FULL)

//Note the 16MHz becomes 48MHz for the USB peripheral by the PLL3X fuse. The processor runs
//at 16MHz by the CPUDIV3 fuse!

//-----< General Program Defines >-----
#define Pwr_LED Pin_B0         // Power LED
#define Serial_TxD Pin_C6      // Serial Tx data
#define Serial_RxD Pin_C7      // Serial Rx Data

//-----< Serial Port Definitions >-----
#use rs232(baud=9600, xmit=Serial_TxD, rcv=Serial_RxD, Errors, stream = Console)

//======================================
void main(void)
{
   unsigned int8 iIndex = 0;

   output_low(Pwr_LED);
    
   //Here we blip the Power LED at power-up to show that the interface is working
   for ( iIndex = 0 ; iIndex < 4 ; iIndex++ )
   {
      output_low(PWR_LED);
      delay_ms(250);
      output_high(PWR_LED);
      delay_ms(250);
   }
      
   //Here we leave the Power LED ON
   output_low(PWR_LED);

   // Here is the PWM setup code...
   // This code should output a 1000Hz PWM pulse train on CCP1 (Pin 36). We are using the full 10 bits of PWM control..
   setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 249, 1);   //Set PWM Frequency to 1000Hz ---> (1/16000000)*4*16*(249 + 1)= .001s or 1.0kHz

   set_pwm1_duty((int16)0);                         //Set 0% Duty Cycle
   fprintf(Console, "1000 Hz, 0 Percent Duty Cycle\n\r");
   delay_ms(5000);

   set_pwm1_duty((int16)250);                   //Set 25% Duty Cycle
   fprintf(Console, "1000 Hz, 25 Percent Duty Cycle\n\r");
   delay_ms(5000);
   
   set_pwm1_duty((int16)500);                   //Set 50% Duty Cycle
   fprintf(Console, "1000 Hz, 50 Percent Duty Cycle\n\r");
   delay_ms(5000);

   set_pwm1_duty((int16)750);                   //Set 75% Duty Cycle
   fprintf(Console, "1000 Hz, 75 Percent Duty Cycle\n\r");
   delay_ms(5000);

   set_pwm1_duty((int16)1000);                   //Set 100% Duty Cycle
   fprintf(Console, "1000 Hz, 100 Percent Duty Cycle\n\r");
   delay_ms(5000);

   //Here we prevent the code from running off the end....
   while (1){} //While(1)

}


When I run this program, I see the following on my oscilloscope:

0%: constant 5V signal <--- this seems different than before???
25%: 25% duty cycle at 1000 Hz
50%: 50% duty cycle at 1000 Hz
75%: 75% duty cycle at 1000 Hz
100%: Unchanged, 75% duty cycle at 1000 Hz

I played around a little bit more, and it seems like the nominal duty cycle command values aren't correct at the terminal duty cycle values.

If I substitute the following, it does seem to work!

Code:

set_pwm1_duty((int16)0); becomes set_pwm1_duty((int16)1);   


and

Code:

set_pwm1_duty((int16)1000); becomes set_pwm1_duty((int16)999);   


Thanks,

Jack
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Oct 29, 2018 9:17 am     Reply with quote

You could be seeing 'rounding' or 'math' errors. Remember computers like nice binary type numbers. I recall finding this out 2 decades ago while using a 16F877 for a realtime 3DOF helicopter program, I had to force 0 to be zero, full on to be all ones.
Depending on the compiler version and whatever 'math' you're using, you need to be aware of potential 'errors' like this creeping in.

You could look at the listing to see what is being computed and how.

Jay
jeremiah



Joined: 20 Jul 2010
Posts: 1314

View user's profile Send private message

PostPosted: Mon Oct 29, 2018 10:25 am     Reply with quote

You might also consider using

Code:
#use pwm()


to setup the PWM and then

Code:
set_pwm_duty_percent()


to set your duty. I've used it with PIC24 parts with a more recent compiler (5.078) without any issue.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Oct 29, 2018 3:23 pm     Reply with quote

I've just compiled the code as posted, with just the processor changed to a 25K50 (haven't got the 45K50 on the shelf), using 5.049, programmed it, and it runs correctly. Must admit I'm starting to wonder if the poster has a faulty chip...
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Oct 30, 2018 4:32 am     Reply with quote

I can confirm, the code does not do what is being described....

Now I don't have 5.050, but have tried with both 5.049, and 5.051.

Dug in my parts box, and found a 45K50. Plugged it into a basic breadboard, with just power & MCLR pulled up.
Compiled the code as posted, except used the internal oscillator at 16MHz. So
Code:

#include <18F45K50.h>
#fuses NOWDT,NOPROTECT,NOLVP,NODEBUG,NOFCMEN,
#use delay(INTERNAL=16MHz)


It merrily boots, and after flashing the power LED, holds the CCP1 output solidly low for 5 seconds, then has a 25% duty train for the same time, then a 50% train, and a 75% train. Then goes solidly high. No unexpected pulses.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Oct 30, 2018 8:48 am     Reply with quote

One comment. Do you have the capacitor connected on Vusb3v3?. This is _required_, even if you are not using the USB. I remember seeing some significant oddities with these chips if this is not connected. From the data sheet:
Quote:

The on-chip voltage regulator must always be
connected directly to either a supply voltage or to an
external capacitor.


Note the 'must'.....
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Tue Oct 30, 2018 9:51 am     Reply with quote

Hi Ttelmah,

Yes, I am using USB - which is working - and the Vusb3v3 pin is connect to a 0.22uF capacitor to Gnd.

Jack
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group