View previous topic :: View next topic |
Author |
Message |
CAP110874 Guest
|
PWM Resolution problem |
Posted: Thu Jun 11, 2009 11:39 am |
|
|
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
|
|
Posted: Thu Jun 11, 2009 11:51 am |
|
|
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
|
Re: PWM Resolution problem |
Posted: Thu Jun 11, 2009 11:55 am |
|
|
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 |
Posted: Thu Jun 11, 2009 12:05 pm |
|
|
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
|
|
Posted: Thu Jun 11, 2009 12:08 pm |
|
|
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 |
Posted: Thu Jun 11, 2009 12:08 pm |
|
|
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
|
|
Posted: Thu Jun 11, 2009 1:38 pm |
|
|
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 |
Posted: Sun Jun 14, 2009 3:49 pm |
|
|
Hi mkuang
This worked a treat.
You are a star - thanks for the support |
|
|
|