A slicker way to be constantly changing the duty cycle?


Closed Thread
Results 1 to 15 of 15

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    Hi Hank,
    Usually it's done like this:
    Code:
    CCP2CON.4 = Duty.0       'Bit 0
    CCP2CON.5 = Duty.1       'Bit 1
    CCPR2L = Duty >> 2        'Bit 2-7
    Now, the resolution you'll actually get depends on the frequency you're using as well as the prescaler ratio. You MAY end up with 9 or 10 bits resolution in which case you must scale up "your" 8 bit dutycycle value to match the resolution of the hardware. Otherwise you might not be able to "swing" the dutycyle all the way to 100% - if that's what you need.

    Have you checkes out Darrels MIBAM routine? Never played with myself but it's supposed to do wonders for multiple fading LEDs.

    /Henrik.

  2. #2
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    Quote Originally Posted by HenrikOlsson View Post
    Hi Hank,
    Usually it's done like this:
    Code:
    CCP2CON.4 = Duty.0       'Bit 0
    CCP2CON.5 = Duty.1       'Bit 1
    CCPR2L = Duty >> 2        'Bit 2-7
    Now, the resolution you'll actually get depends on the frequency you're using as well as the prescaler ratio. You MAY end up with 9 or 10 bits resolution in which case you must scale up "your" 8 bit dutycycle value to match the resolution of the hardware. Otherwise you might not be able to "swing" the dutycyle all the way to 100% - if that's what you need.

    Have you checkes out Darrels MIBAM routine? Never played with myself but it's supposed to do wonders for multiple fading LEDs.

    /Henrik.
    Many thanks Henrik........Deep down I knew the answer would be splendidly (embarrasingly!) simple - thanks for the lightning response.

    Sigh, as one case closes another opens.... I'm running a 16f1824 @4mhz oscillator, and I need the frequency of the PWM to be inaudible (therefore say about 20khz+) ....how can I be sure that my resolution remains at 8 bits.

    No, I was not aware of Darrels MIBAM routine....I'll seek it out.

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    Hi Hank,
    I usually cheat and use MisteE's PICMultiCalc tool to determine things like prescaler ratio and PWM resolution but I'll try to explain it. If nothing else as a learning exercise for myself....

    The PWM period start when TMR2 is 0 and ends when TMR2 matches PR2. When you're running at 4MHz TMR2 "ticks" at 1MHz (with a prescaler of 1:1) so if you write 100 (or 99 actually because we're starting at 0) to PR2 you'll get a PWM period of 100us so the PWM frequency is 10kHz. Put 49 in PR2 and you'll get a PWM period of 50us (20Khz) and so on.

    Now, you would think that if you put 99 in PR2 there are 100 "steps" to the "cycle"/period and that you therefor get 100 discrete dutycyles but this is not the case because TMR2 creates the 8 high order bits and the internal instruction clock creates the 2 low order bits of a 10bit timebase (alternatively 2 bits from the prescaler when using anything but 1:1).

    What this means is that the number of discrete dutycyles ratios you get is basically (PR2+1)*4 so if you put 99 in PR2 (for a PWM frequency of 10kHz) you'll get (99+1)*4=400 "steps" which you'll have to have 9 bits to store. If you put 49 in PR2 the frequency will be 20kHz and the number of dutycycle ratios will be (49+1)*4=200 which fits nicely in a byte.

    If you want to maximize the resolution while still keeping it inside a byte you could set PR2 to 63 which will give you a frequency of 15625Hz and a resolution of 8 full bits ( (63+1)*4=256 )

    Well, I hope I've got this close to reallity (if not I hope someone will correct me) and that it makes at least a bit of sense.

    /Henrik.

    PS. If "all" you're doing with the PWM output is fading LEDs why do you need it to be inaudible?

  4. #4
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    Thanks Henrik...really gracious of you to make the effort - I'm gonna have to read that one a few times, but in the meantime, here's something I can answer...

    Quote Originally Posted by HenrikOlsson View Post
    PS. If "all" you're doing with the PWM output is fading LEDs why do you need it to be inaudible?
    .....because ultimately (after I've got on top of all this by playing/dabbling), I intend integrating what I've learnt in some audio circuits (ie using PWM'ed LEDs for visual indicators - flashing/fading, on/off etc) ....the little bit of playing I done with HPWM to date, I've noticed the HPWM carrier can find/bleed its way into the audio signal chain ...hence wanting to put it the HPWM carrier outside the hearing band. I'm quite shocked at the audible clicking too, so I'm trying to dial the clicking out by ramping up HPWM very quickly rather than hard off/on switching.
    Last edited by HankMcSpank; - 23rd April 2011 at 13:59.

  5. #5
    Join Date
    May 2007
    Posts
    604


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    This contest http://www.picbasic.co.uk/forum/showthread.php?t=14652 contains some elements of what you are wanting to do.

    I did it using PWM and here is a video of 2 of those channels. The contest requires 4 independent, variable on-the-fly (blink-rate) channels.



    The timebase is 10uS so the PWM frequency 25KHz. The duty cycle of the upper trace is ramped from 0-100-0% - to give pulsating effect - at about 0.5Hz. The lower one is at 1.0Hz. The required blink rate should be continuously variable in the range of 0.5-8.0Hz on each of the 4 channels/LEDs for the contest.
    Last edited by rmteo; - 23rd April 2011 at 15:34.
    Why pay for overpriced toys when you can have
    professional grade tools for FREE!!!

  6. #6
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    thanks rmteo...just seen your reply, I shall look at all tha tomorrow.

    ok, so I got too big for my boots, thought I'd go hardcore & try to get HPWM working with the PIC's regsiters (vs the HPWM command) - eeeugghh! (it was worth doing - just to remind myself that I'll always be the type who graps in the dark!)

    I've got it working, but only by directly loading the PWM 'period' registers directly like this (important bits in red)

    Code:
               
    PR2= 63                               'THIS SETS THE PWM FREQUENCY (15.625KHZ @4MHZ)
    CCPTMRS0 = %11110011     'CCP Timer select register - select CCP2 USING TIMER2
    T2CON = %00000100           'TIMER2 ON 1:1 PRESCALER 1:1 POSTSCALER
    TRISC.3 = 0                         'Enable the CCP2 pin output driver by setting the bit
     
    temp:
    CCP2CON.4 = 1       ' these three lines set the duty cycle to be 255   
    CCP2CON.5 = 1       ' these three lines set the duty cycle to be 255  
    CCPR2L = 255         ' these three lines set the duty cycle to be 255 (2 MSBs ignored)
    pause 1000
    CCP2CON.4 = 0       ' these three lines set the duty cycle to be 0   
    CCP2CON.5 = 0       ' these three lines set the duty cycle to be 0  
    CCPR2L = 0             'these three lines set the duty cycle to be 255 (2 MSBs ignored)
    pause 1000
    goto temp
    the problem with that method (& it works - get a flashing LED at about 1 sec on, 1 sec off), is that setting the duty cycle is brainache. So I wanted to use the method discussed earlier with Henrik (where I map the bts to my easier to massage variable called "duty")...

    Code:
    Duty var byte
    CCP2CON.4 = Duty.0       'Bit 0
    CCP2CON.5 = Duty.1       'Bit 1
    CCPR2L = Duty >> 2       'Bit 2-7
     
    temp:
    duty = 255         ' these three lines set the duty cycle to be 255 (2 MSBs ignored)
    pause 1000
    duty = 0           'these three lines set the duty cycle to be 255 (2 MSBs ignored)
    pause 1000
    goto temp
    Problem is now ...the LED he no flashee!!

    Anyone got a clue why I can't map the PWM 'period' bits to my variable called Duty? (or more to the point why it doesn't appear o work, whereas the top code does)

    Edit: Ok, think I've got a kludge, but this isn't working how I'd imagined...

    Code:
    temp10:
    DUTY = 0
    CCP2CON.4 = Duty.0       'Bit 0
    CCP2CON.5 = Duty.1       'Bit 1
    CCPR2L = Duty >> 2       'Bit 2-7
    pause 1000
    DUTY = 1
    CCP2CON.4 = Duty.0       'Bit 0
    CCP2CON.5 = Duty.1       'Bit 1
    CCPR2L = Duty >> 2       'Bit 2-7
    pause 1000
    goto temp10
    in other words, I'm having to update the 'mapped' period register bits every time I change the duty variable? (I'd have thought Henrik's way of mapping them would mean if I change the contents of the duty variable then the mapped bits would automatically change too?)
    Last edited by HankMcSpank; - 24th April 2011 at 01:18.

  7. #7
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: A slicker way to be constantly changing the duty cycle?

    Hi Hank, Let me take a stab at this for you.

    In your first example, you set the duty directly with constants. No surprizes there I don't think.

    In the second example, you are changing the variable named DUTY, but this is not associated with the ccp reg's, so they never get changed.

    In the third example, you are using a variable named DUTY to to assign values to the ccp reg's. This is the method I would use as it seem the easiest to me. It takes care of all the bit switching and all your code needs to do is change the value of DUTY.

    To combine the second and third example, make the ccp assigns in the third example a subroutine. Then in the second example, before each pause, call the sub. I think in this way it will seem like it does exactly what you want.

    To do what I think you are trying, I think you need to alais the ccp reg's. for example:

    Code:
    CCP2CON.4    VAR Duty.0       'Bit 0
    CCP2CON.5    VAR Duty.1       'Bit 1
    CCPR2L.0    VAR Duty.2
    CCPR2L.1    VAR Duty.3
    CCPR2L.2    VAR Duty.4
    CCPR2L.3    VAR Duty.5
    CCPR2L.4    VAR Duty.6
    CCPR2L.5    VAR Duty.7
    Now I have NO idea if this will actually work, Try at you own risk
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts