Searching \ for '[PIC]: Hardware PWM at low frequency?' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/ios.htm?key=pwm
Search entire site for: 'Hardware PWM at low frequency?'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Hardware PWM at low frequency?'
2001\10\29@140437 by Gary Neal

picon face
Guys,

       I've been working on using Hardware PWM to control the speed of a 12v dc
motor connected through a Mosfet.  I'm using 2 buttons to speed up and
speed down.
       It works really well with a PWM frequency above something like 4kHz.  If I
try to go below that frequency, it acts goofy.  For example, below is my
code for PWM at 3kHz.
       The way I understand it, I should get 0% - 100% for a CCPR1L from 0 -
333.  For these lower frequencies, if I slowly increase the DUTY cycle up
to about CCPR1L =75 it ramps up to 100%.  They it stays at 100% until
~CCPR1L =260 at which it instantly drops to 0%.  From CCPR1L =260 to 333 it
again ramps up to 100%.  It does the exact opposite when I ramp down in speed.
       Does anyone have a clue why this is happening?  If I reset the code for
anything from like 4kHz and up to work exactly as it's suppose to.  I
really think it's a software issue, but I'm not sure.  I really want to run
at lower frequency (don't care about audible noise) to minimize switching
losses.  Help?!?!?!

Thanks,

Gary


________________________________________
duty            var     word
btnwk           var     byte
clr             con     1               'LCD clear screen instruction
I               con     254             'Instruction prefix value

'******** Initialize ***************************************

TRISA = %000000         'Set porta   = output
TRISB = %11111100               'set RB2:RB7 = input
TRISC = %00000000               'Set portc   = output

btnwk=0
PORTC.2=0                       'try to keep it from jumping when 12v connected

OPTION_REG = %10000111  'set timer source as internal instuction cycle clock
                               'assign prescaler to tmr0 (not WDT)
                               'set prescaler to 1:64
INTCON = %10100000              'enable the tmr0 interrupt (intcon)
                               'Enable Global Interrupt Enable bit
                               'Disable RB0 interrupt
ADCON1 = %00000110      'Make PortA into digital I/O instead of analog I/O

PR2=332                         'Set PR2 to 3 kHz

TRISC.2=0                       'Set CCP1 bit as output
T2CON=%00000100                 'Timer on prescale is 1
CCP1CON=%00001100       'Set to PWM Mode
duty=0
CCPR1L = duty           'Set Pulse width - CCPR1L must be less than PR2.
                               'Lower number(pulse width)
                               'PR2 value is 100% duty cycle.
                               'PR2/2 = 50% duty cycle.

'******** Main Program *************************************

DEFINE BUTTON_PAUSE 50          'change button pause to 50 milliseconds

main:
       if duty > 60000 then            'did this b/c if <0, it rolls over to 65676
               duty = 0
       endif

       if duty > 333  and duty < 1000 then     'for 3khz operation
               duty = 333
       endif

       CCPR1L = duty   'Set Pulse width - CCPR1L must be less than PR2.
                               'Lower number(pulse width)
                               'PR2 value is 100% duty cycle.
                               'PR2/2 = 50% duty cycle.

       serout 1,n9600,[I, clr]         'Clear LCD screen
       serout 1,n9600,[" ", #duty]     'Display seconds variable on LCD

       button PORTB.3, 1, 255, 255, btnwk, 1, speedup
       button PORTB.2, 1, 255, 255, btnwk, 1, speeddown

goto main

speedup:

       duty=duty+15            'for 3khz operation
       goto main

speeddown:

       duty=duty-40            'for 3khz operation
       goto main


--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\10\29@160645 by Olin Lathrop

face picon face
>         The way I understand it, I should get 0% - 100% for a CCPR1L from
0 -
> 333.  For these lower frequencies, if I slowly increase the DUTY cycle up
> to about CCPR1L =75 it ramps up to 100%.  They it stays at 100% until
> ~CCPR1L =260 at which it instantly drops to 0%.  From CCPR1L =260 to 333
it
> again ramps up to 100%.

I haven't looked at any of your code, but this makes perfect sense.  CCPR1L
is an 8 bit register, so it can only hold 0 to 255.  If you try to write 256
into it, you will only write the low 8 bits in reality, which are 0.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, spam_OUTolinTakeThisOuTspamembedinc.com, http://www.embedinc.com

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\10\29@171515 by Gary Neal

picon face
Olin,

        Yes, you're right.  Both the PR2 and the CCPR1L registers are 8
bit (0-255).  So, does that mean it's impossible to get a PWM frequency
less than ~3,900 Hz (PR2=255)?  If so, that seems pretty stupid!  Any way
around it?
        Doh!  I just answered my own question - TMR2 Prescale value.  So,
instead of setting it to 1, I could set it to like 4.  This fixes the problem.

Thanks OLIN!!!

Gary



At 04:04 PM 10/29/2001 -0500, Olin Lathrop wrote:
{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\10\29@175058 by Bob Blick

face
flavicon
face
Hi Gary,

Even though PWM is 10 bits, the registers to control it are only 8 bits.
You write the highest 8 bits to CCPR1L and the lowest 2 bits squeeze into
bits 4 and 5 of CCP1CON. You already know about CCP1CON since you had to
set bits 2 and 3 to enable PWM, just remember not to clear them when you
are writing the low PWM bits. Usually what I do is SWAPF the pwm value,
then OR it with 0x0F, then write that to CCP1CON.

If you only need 8 bit PWM then don't worry about it and write straight to
CCPR1L and only write 8 bit values!

Cheerful regards,

Bob Blick

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\10\30@090059 by Lawrence Lile

flavicon
face
I'd agree with Olin.  In the 16F87x series you have two registers, CCPR1l and CCPR1H that affect the duty cycle.  You will need to break your DUTY word up into two bytes, and assign them to the low and high byte separately.  
If you need help in how to accomplish this, just ask.
--Lawrence Lile
 {Original Message removed}

2001\10\31@125802 by Bob Blick

face
flavicon
face
On Tue, 30 Oct 2001, Lawrence Lile wrote:

> I'd agree with Olin.  In the 16F87x series you have two registers,
> CCPR1l and CCPR1H that affect the duty cycle.  You will need to break
> your DUTY word up into two bytes, and assign them to the low and high
> byte separately.

No, as I mentioned in my post, you put the high byte of 10 bits into
CCPR1L and the low two bits into CCP1CON 4:5. When in PWM mode CCPR1H is
not a register you can use, it becomes read-only and is a buffer for
CCPR1L(or something like that - it's NOT writable).

PWM is not something you just glance at the data sheet and use, it's
tricky how they did it. Not user-friendly.


Cheerful regards,

Bob Blick

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


More... (looser matching)
- Last day of these posts
- In 2001 , 2002 only
- Today
- New search...