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 CCS Technical Support

PWM Resolution problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
CAP110874
Guest







PWM Resolution problem
PostPosted: Thu Jun 11, 2009 11:39 am     Reply with quote

Hi guys, I am running a pic 18f2525 with an H-bridge to control a motor.

My pic is running at 8mhz and the timer and the timer settings are:
Code:
setup_timer_2(T2_DIV_BY_16,25,10);

The timer used to be set at 250 but we neded to set this to 25 so we get a 10khz output to the pwm. The issue we are now facing is that the range for the pwm now only has 25 setps from full power to the off condition.

I have tried adding a int 16 variable called pwmduty which is set at 10000. Then use the code :
Code:

char c;
   if (kbhit(STREAM_UART))
   {
      c = fgetc(STREAM_UART);
      if (c == 'r')         {
         pwmduty = (10000);
         set_pwm1_duty(pwmduty / 100);
         }
         
      if (c == '+' )         
         {
         pwmduty = pwmduty +10;
         set_pwm1_duty(pwmduty / 100);
         }
       
      if (c == '-')
       {
         pwmduty = pwmduty -10;
         set_pwm1_duty(pwmduty / 100);
         }

I was assuming that because the calculation was being done in the command it would alter the pwm output on every value by using the decimal place. But actually the output is still very stepped. It seems that the calculation I added is still being rounded up when being processed by the set_pwm. Is there anyway to send numbers with decimal places to the set+pwm so it runs more smoothly ?

Thank you.....Chris
nostep



Joined: 04 Mar 2009
Posts: 16

View user's profile Send private message

PostPosted: Thu Jun 11, 2009 11:51 am     Reply with quote

It's been awhile, so I expect to get slammed if I don't get this right. The PWM uses the number "25" as the total amount of time for your period. This means that you only have 25 steps. You might try changing your "div_by_16" to something like "div_by_2", then restoring your 25 to 250. Play with that concept.

Last edited by nostep on Thu Jun 11, 2009 11:57 am; edited 1 time in total
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

Re: PWM Resolution problem
PostPosted: Thu Jun 11, 2009 11:55 am     Reply with quote

CAP110874 wrote:
Hi guys, I am running a pic 18f2525 with a h-bridge to control a motor.

My pic is running at 8mhz and the timer and the timer settings are:
setup_timer_2(T2_DIV_BY_16,25,10);

The timer used to be set at 250 but we neded to set this to 25 so we get a 10khz output to the pwm. The issue we are now facing is that the range for the pwm now only has 25 setps from full power to the off condition.

I have tried adding a int 16 variable called pwmduty which is set at 10000. Then use the code :
---------------------------------------------------------------------------
char c;
if (kbhit(STREAM_UART))
{
c = fgetc(STREAM_UART);
if (c == 'r') {
pwmduty = (10000);
set_pwm1_duty(pwmduty / 100);
}

if (c == '+' )
{
pwmduty = pwmduty +10;
set_pwm1_duty(pwmduty / 100);
}

if (c == '-')
{
pwmduty = pwmduty -10;
set_pwm1_duty(pwmduty / 100);
}
---------------------------------------------------------------------------
I was assuming that because tha calculation was being done in the command it would alter the pwm output on every value by using the decimal place but actually the output is still very stepped. It seems that the calculation i added is still being rounded up when being processed by the set_pwm. Is there anyway to send numbers with decimal places to the set+pwm so it runs more smoothly.

Thank you.....Chris

In your case pwmduty is either 10000, 10010 or 9990. Since pwmduty is an integer and you are dividing by 100, also an integer, you are going to get an integer back. That means 10000 / 100 = 100, 10010/100 = 100, and 9990 / 100 = 99. So you just get either 100 or 99.

I don't think you can send floating point numbers to the set_pwnx_duty function. It accepts either an 8 bit or 16 bit integer.
cap110874
Guest







not there yet
PostPosted: Thu Jun 11, 2009 12:05 pm     Reply with quote

Hi nostep
I tried setting the timer 2 as suggested but it won't compile when I set div by 16 to divide by 2. Gives error message unidentified identifier T2_DIV_BY_2. Do I need to set anything else to do this...........
Code:

void main()
{   
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128|RTCC_8_bit);                        //32uS, 8.1mS timeout
   setup_timer_1(T1_DISABLED);                                                  //setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 );
   setup_timer_2(T2_DIV_BY_2,250,1);                                           //PWM  needs to ne 24 for 10khz output 250 normal value outputs 1khz on timer 2  //   setup_timer_2(T2_DIV_BY_16,250,1);
   CountIn_time = 0;
   last_CountIn = input(CountIn);
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 11, 2009 12:08 pm     Reply with quote

Quote:
I tried setting the timer 2 as suggested but it won't compile.

Look in the .H file for your PIC. It lists the constants that are allowed to
be used with the CCS functions. Here's the file location:
Quote:
c:\program files\picc\devices\18f2525.h
cap110874
Guest







still trying
PostPosted: Thu Jun 11, 2009 12:08 pm     Reply with quote

hi mkuang
Seems like this is what is happening. I thought if I did 10010 / 100 it would pass 100.1 to the set_pwm but doesn't seem to be the case.

Wondered if anyone knows how to pass a number with 1 or 2 decimal places to the set_pwm.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Thu Jun 11, 2009 1:38 pm     Reply with quote

You can only pass an int8 or int16 to the CCS set_pwmx_function as explained on page 203 of the manual.

But here is something you can try. You are using an 8Mhz clock you say. So your instruction clock is 2Mhz or 0.5us between ticks if you set you pre and post scalers to unity. You want a 10 Khz pwm which means the period is 100us. Again if your pre and post scalers are unity that would be 100us/0.5us or 200. So you can do this:
Code:
setup_timer_2(T2_DIV_BY_1,200,1);

And now you want 50% duty cycle:
Code:

int16 duty_cycle =  400;

set_pwm1_duty(duty_cycle);

When the compiler see that it will know to use the 10 bit instead of the 8 bit mode. Your "effective" timer2 setting will be 200x4=800. So setting duty_cycle = 400 will give you 50%. If you want 25% you would set duty_cycle = 200, so on and so forth.

If you want only 8 bit mode you would do (for 50%):
Code:
char duty_cycle = 100;

set_pwm1_duty(duty_cycle);

The compiler sees that duty_cycle is eight bits and will use the 8 bit mode.

I didn't test the above so please do and check whether I did the math right.
CAP110874
Guest







Perfect
PostPosted: Sun Jun 14, 2009 3:49 pm     Reply with quote

Hi mkuang
This worked a treat.

You are a star - thanks for the support
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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