3 channel PWM with customize duty cycle


Closed Thread
Results 1 to 40 of 57

Hybrid View

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


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    I've tried it here, on a real physical PIC, and it works just fine.

    I see that you've removed the Pause statement I had in there. If you don't have a delay there it will run thru the different dutycycles much faster then the actual PWM frequency. It tries to update the dutycycle registers several times during each PWM period which obviously won't work properly.

    Your PWM frequency is 5kHz so if you really do want to see "all the steps" you must have atleast 1/5000=200us between updates. I measured the execution time of the loop to around 25us with a 20Mhz oscillator so you're basically trying to update the dutycycle 8 times every PWM period.....

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    yes, i remove the pause statement because i think adding it causing the pwm duty longer then the original pwm duty, hence changing my pwm pattern.
    can we actually pause below 1 ms since i know pause statement can only be use for minimum 1ms right??
    correct me if im wrong

    when you tries on the real physical PIC, do you enable the pause statement??
    i will try on real physical PIC later and feedback to you tmrw.

    photoelectirc

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


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    The Pause statement won't effect the PWM since it's generated in hardware. If you have Pause 1 you'll basically get 5 periods of each dutycycle value.

    You can Pause with microsecond resolution by using PauseUs (again, it's in the green book....)

    When testing I used 300us and you can see the result in the attached screenshot. This is not a simulation, it's captured on real hardware.
    Attached Images Attached Images  

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    hi, yes you are correct, i test it on real physical and it works fine.
    But i dint really understand on how you calculate the execution of my FOR NEXT loop. Can you explain a liltle bit detailed on that.
    below is the previous quote on how you calculate the execution time.

    Quote Originally Posted by HenrikOlsson View Post

    Your PWM frequency is 5kHz so if you really do want to see "all the steps" you must have atleast 1/5000=200us between updates. I measured the execution time of the loop to around 25us with a 20Mhz oscillator so you're basically trying to update the dutycycle 8 times every PWM period.....

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


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,

    I didn't calculate it, I measured it - as it says in the message ;-)

    I put a TOGGLE PortC.0 just before the NEXT statement a put the scope on the pin. I got a 20kHz square wave which, because the pin is toggled each time thru loop, means it executes roughly 40000 times per second. 1/40000=25us

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    hi,
    thks for the explanation, now my pwm works fines.
    attached is my currently pwm pattern for ccp1 and ccp2.
    NOw, i want to shift the CH2 pwm about 1/3 of the duration of the CH1 pwm which is

    10.20ms/3 = 3.4ms

    so, i intend to put pause command at:

    Main1:
    'For duty1 = 0 TO 44

    'Go into the table AND retrieve the value pointed at by Duty1 AND put that value in Duty2
    LookUp2 duty1, [0,70,137,208,275,341,408,470,529,588,643,694,745,7 88,827,866,898,925,_
    953,968,984,996,1000,996,984,968,953,925,898,866,8 27,788,745,_
    694,643,588,529,470,408,341,275,208,137,70,0],duty2



    'Duty2 now contains the value from the lookup table that Duty1 points at. First time thru the loop it's 0 second time it's 18 and so on.

    CCP1CON.4 = duty2.0 ' Setup 10-bit duty cycle as
    CCP1CON.5 = duty2.1 ' a 10-bit word
    CCPR1L = duty2 >> 2

    Pause 4
    CCP3CON.4 = duty2.0
    CCP3CON.5 = duty2.1
    CCPR3L = duty2 >> 2

    PauseUs 210 'Use each dutycycle value 10ms before going to the next one.
    'Next duty1
    'PauseUs 100

    GoTo Main1


    but seem like ccp1 and ccp2 pwm duration increase above 10.20ms.
    SO, what should i adjuzt to make pwm CH2 shift 1/3 of the pwm CH1
    without increasing the duration?

    thks
    photoelectricName:  F0000TEK.JPG
Views: 2615
Size:  117.5 KBName:  F0000TEK.JPG
Views: 2615
Size:  117.5 KB
    Last edited by photoelectric; - 20th April 2011 at 05:48. Reason: add attachment

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


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    If you're trying to get the 120° phase shift you can't do that with a PAUSE. You have to remember that only the PWM is done by hardware, everything else, ie. the lookup and setting the dutycycle registers are done in software.

    If you put a Pause 4 in there the whole software loop will "hang" for 4ms and whatever the CCP module is outputting will keep getting output untill it gets updated again. The FOR-NEXT loop will NOT run while the pause statements executes.

    If you want 120° phase shift you could do that thru an offset into the loopup table. If the table is 45 entries you want entry 0, 14 and 29 the first time. Then you want 1, 15 and 30 and so on. I'd probably skip the FOR-NEXT loop and rewrite it to so that I'd have three counters, all counting from 0 to 44 but with an offset of 15 between them, these will then get the dutycycle from the table and assingn them to the proper CCPModule.

    /Henrik.

  8. #8


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,

    Im still trying to understand your explaination.
    So i have to use count command?
    can you give me an example of code for me to refer to?

    photoelectric

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


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    I'm sorry to say this but it sounds like you need to take a step back and work thru the basics of programming with PBP. We can keep giving you code here until we've basically written the whole thing for you and you still wouldn't understand how it works.

    Pause does just that - it pauses - no other code (except if you're using interrupts) is running while the Pause exeuctes. Like this:
    Code:
    Main:
      High PortB.0
      Pause 100
      Low PortB.0
      Pause 100
    Goto Main
    This will blink a LED connected to PortB.0 at 5Hz. If you put another pause in there, like:
    Code:
    Main:
      High PortB.0
      Pause 100
      Low PortB.0
      Pause 100
     
      Pause 1000
    Goto Main
    It won't blink at 5Hz because you just told it to pause for another second. The same thing happens with your 4ms pause. The FOR NEXT loop that is supposed to keep running and feeding the PWM module with a new dutycycle evert 210us will stop - completely - for the 4ms duration. But because the PWM is generated by hardware it will keep outputting whatever dutycycle it was last told to do.

    The count command is used to count pulses on a pin, I don't think that is what you want?

    The following is ONE way of doing it. This compiles fine but I have NOT tested it.
    Code:
    Phase       VAR BYTE[3]       ' Array used as pointers into lookuptable.
    DutyCycle   VAR WORD[3]       ' Array storing the dutycycles retreived from the table
    Temp        VAR WORD          ' Temporary variable to avoid hard to understand array indexing
    i           VAR BYTE          ' General purpose counter
     
    ' The lookup table has 186 entries long, to get 120° phase shift we need to
    ' "start" the second phase at 1/3 of the cycle and the third phase at 2/3
    ' of the table. 186/3=62 so first phase starts at 0, second phase at 62
    ' and third phase at 123.
    ' Initilise pointers.
    Phase[0] = 0 : Phase[1] = 61 : Phase[2] = 123
     
    Main:
      Gosub GetDuty               ' Retrieve the dutycycle values for all three phases
      GOSUB SetDutyCycle          ' Set the three PWM modules accordingly
     
    ' Now increment the individual table pointers and make sure they wrap
    ' around to zero when they reach then end of the table. That way they
    ' will always stay 62 "steps" (120°) from each other.
     
      For i = 0 to 2
        Phase[i] = Phase[i] + 1
        If Phase[i] > 185 then Phase[i] = 0         'When pointer is > 185 we need to wrap around to 0.
      NEXT
     
      PauseUs 300
     
    Goto Main
     
     
    SetDutyCycle:
        ' Get value from the array of dutycycles and put it in the dutycycle
        ' registers of the 3 PWM modules. We could have used the array directly
        ' but this way (using a Temp variable) is easier to understand.
     
        Temp = DutyCycle[0]             ' Get dutycyle for phase 1 from the array and store in temp.
        CCP1CON.4 = Temp.0              ' Set the LSB's  
        CCP1CON.5 = Temp.1  
        CCPR1L    = Temp >> 2           ' Set the 8 high bits 
     
        Temp = DutyCycle[1]             ' Same procedure.
        CCP2CON.4 = Temp.0  
        CCP2CON.5 = Temp.1  
        CCPR2L    = Temp >> 2
     
        Temp = DutyCyle[2]              ' Same procedure.
        CCP3CON.4 = Temp.0  
        CCP3CON.5 = Temp.1  
        CCPR3L    = Temp >> 2
    RETURN
     
     
    ' ------------------------------------------------------------------------------
    ' ---- Subroutine to retreive the three dutycycle values from the table.
    ' ---- Values will be stored in the DutyCycle array.
    ' ------------------------------------------------------------------------------
    GetDuty:
    ' This For-Next loop runs three times. Each time it gets the value from the lookuptable
    ' that Phase[i] is pointing at. The Phase array pointers are incremented in the main loop
    ' and are always 62 "steps" appart so that a 120° phase shift is preserved.
     
    For i = 0 to 2
      LookUp2 Phase[i], [0,18,34,52,68,85,102,119,137,152,170,187,203,220,236,253,267,285,302,_
         318,334,350,367,382,397,413,429,443,459,474,489,504,518,533,547,562,575,589,603,616,_
         630,643,655,669,681,693,706,718,729,740,752,764,774,785,795,806,815,825,835,844,853,_
         861,870,879,887,895,901,909,916,923,929,935,941,946,952,957,962,967,971,974,978,_
         981,984,987,990,992,994,996,997,998,999,999,1000,999,999,998,997,997,996,994,992,_
         990,987,984,981,978,974,971,967,962,957,952,946,941,935,929,923,916,909,901,895,_
         887,879,870,861,853,844,835,825,815,806,795,785,774,764,752,740,729,718,706,693,_
         681,669,655,643,630,616,603,589,575,562,547,533,518,504,489,474,459,443,429,413,_
         397,382,367,350,334,318,302,285,267,253,220,203,187,170,152,137,119,102,85,68,_
         52,34,18,0],Temp
     
     
         ' Lookup2 can't handle an array as the designator so we need to  
         ' put the value in a temporary variable first and then move
         ' it to the array of dutycycles.
     
         DutyCycle[i] = Temp
     
    NEXT
     
    RETURN
    /Henrik.

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