3 channel PWM with customize duty cycle


Closed Thread
Results 1 to 40 of 57

Hybrid View

  1. #1


    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: 3079
Size:  117.5 KBName:  F0000TEK.JPG
Views: 3079
Size:  117.5 KB
    Last edited by photoelectric; - 20th April 2011 at 06:48. Reason: add attachment

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,626


    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.

  3. #3


    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

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,626


    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.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    Thanks again for the example. This is my 1st time using PIC Basic pro languange and im trying very hard to learn it. hope you can assist me more in the future.

    i test it and it works fine for all three phases.(according to my value of lookup)
    Phase 1 launch for 17.6ms
    Phase 2 launch at 7ms of the phase 1
    Phase 3 launch at 13.2ms of the phase 1

    now, im trying to add six signal from six port pin connected to the external AND gate so that i can control the the 3 phases.
    Attached is the schematic diagram.

    what should i adjust in the codes so that
    when
    RA1 is high and RA2 is low pwm from ccp1 is launch other word is Q1 is launch and then after 1 complete cycle,
    RA1 is low , RA2 is high Q4 is launch.

    and so on.

    thanks,
    photoelectric
    Attached Images Attached Images  

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,626


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    I'm not completely sure I understand but anyway.....

    You can use any of the phase counters, take Phase[0] for example. It'll count from 0 to 185 and then start over, count from 0 to 185 on and on and on. Every time it's 0 a new cycle starts. Use that as your "trig" to change the output pattern to the external logic.

  7. #7


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,

    my explanation is same like coding below:

    Code:
    defineosc 20	
    DUTY1 var word	
    DUTY2 var word	
    FREK var word	
    
    frek=5000	
    Loop:		
    high port.1	
    
    	GOSUB FIRE	
    
    low portb.1	
    high portb.2	
    
    	GOSUB fire	
    
    low portb.2	
    gotoLoop
    
    fire:
    
    For DUTY1 = 0 TO 44
    
    LookUp DUTY1, [0,18,35,53,70,87,104,120,135,150,164,177,190,201,211,221,229,236,_
    243,247,251,254,255,254,251,247,243,236,229,221,211,201,189,_
    177,164,150,135,120,104,87,70,53,35,18,0],DUTY2
    
    hpwm 1,DUTY2,frek	
    next DUTY1
    
    RETURN
    end
    but that coding only applicable for 1 phase only.
    based on your coding example, i want it to be:
    The 1st time it count from 0 to 185 , portc.3 will be high and portc.0 will be low then 2nd time it count from 0 to 185, portc.3 will be low and portc.0 will be high.

    do i need to make new loop, let say:

    loop:
    IF Phase[0] =0 '1st time it count
    high portc.3
    low portc.0
    then Phase[0]=0 'second time it count
    high portc.0
    low portc.3
    goto loop

    please help advice

    photoelectric

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