 |
 |
View previous topic :: View next topic |
Author |
Message |
JAM2014
Joined: 24 Apr 2014 Posts: 138
|
PWM Questions.... |
Posted: Fri Oct 26, 2018 4:31 pm |
|
|
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
|
|
Posted: Fri Oct 26, 2018 10:47 pm |
|
|
I can't duplicate your problem. Post a complete test program. |
|
 |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sat Oct 27, 2018 3:14 am |
|
|
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: 19732
|
|
Posted: Sat Oct 27, 2018 3:42 am |
|
|
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: 9426 Location: Greensville,Ontario
|
|
Posted: Sat Oct 27, 2018 7:32 am |
|
|
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: 19732
|
|
Posted: Sat Oct 27, 2018 1:59 pm |
|
|
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
|
|
Posted: Sat Oct 27, 2018 6:32 pm |
|
|
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: 19732
|
|
Posted: Sun Oct 28, 2018 1:46 am |
|
|
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
|
|
Posted: Mon Oct 29, 2018 8:52 am |
|
|
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: 9426 Location: Greensville,Ontario
|
|
Posted: Mon Oct 29, 2018 9:17 am |
|
|
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: 1371
|
|
Posted: Mon Oct 29, 2018 10:25 am |
|
|
You might also consider using
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: 19732
|
|
Posted: Mon Oct 29, 2018 3:23 pm |
|
|
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: 19732
|
|
Posted: Tue Oct 30, 2018 4:32 am |
|
|
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: 19732
|
|
Posted: Tue Oct 30, 2018 8:48 am |
|
|
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
|
|
Posted: Tue Oct 30, 2018 9:51 am |
|
|
Hi Ttelmah,
Yes, I am using USB - which is working - and the Vusb3v3 pin is connect to a 0.22uF capacitor to Gnd.
Jack |
|
 |
|
|
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
|