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,617


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Like I said, it turns ON again because YOU turn it on in your main loop - continously. If you don't want it to turn on again then stop turning it on. Set it one time, before you enter the loop.

    If you want it to trig (turn off the LED) with an interrupt but then start "working" again as soon as the fault signal "goes away" then simply read the state of the pin in your Main routine and turn on the LED once it's high:
    Code:
    Main:
    If PortB.0 = 1 THEN     'Turn on LED only when signal is high.
      HIGH LED
    ENDIF
    'Do whatever else needs to be done.
    Goto Main
    If want it to trig with an interrupt and stay off untill another input "restart it" then use a flag/semaphore:
    Code:
    FAULT VAR BIT
    LED VAR PortC.4
    Restart VAR PortC.5   'Pulled up thru resistor, pull to GND to "activate"
     
    High LED
     
    Main:
     If Fault = 1 then            'If we are in fault state...
      If Restart = 0 then        '...we check the restart button....
       HIGH LED                '....if it's pressed we turn LED on again...
       Fault = 0                '...and reset the fault flag/state
      ENDIF
     ENDIF
    'Do whatever else here.
    Goto Main
    Then, in your interrupt routine you turn off the LED and set the Fault flag, like:
    Code:
    LOW LED
    Fault = 1    'Set flag
    Finally, be careful with the word Loop as a label, in newer versions of PBP that is a reserved word and can't be used as a label, what version are you using.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,

    thank you for the example.
    Then, i add-up CCP1CON = %00000000 in the interrupt handler in order to turn off the pwm for a while. Turns out that after it come back to normal operation, the pwm keep turning off.

    Code:
    DEFINE OSC 20
    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
    led            VAR PORTC.4
    TRISC.2 = 0         ' Set PORTC.2 (CCP1) to output
    TRISC.1 = 0
    
    CCP1CON = %00001100 ' Set CCP1 to PWM 
    CCP2CON = %00001100
    
    T2CON = %00000101   ' Turn on Timer2, Prescale=4
    PR2 = 249             ' Set PR2 to get 5KHz out
    TRISB.0 = 1 'set port bo to input
    
    ' The lookup table has 45 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. 45/3=15 so first phase starts at 0, second phase at 15
    ' and third phase at 30.
    ' Initilise pointers.
    Phase[0] = 0 : Phase[1] = 15 
    
    
    High PORTC.3    'Set the initial state for portc.3
    Low PORTC.0        'Same
    High PORTC.6    'Same
    Low PORTC.5        'Same
    High PORTC.4
    
    ON INTERRUPT GoTo faultsignal     
    INTCON = %10010000             'Enable RB0 INTERRUPT
    OPTION_REG.6 = 0                  'Interrupt on rising edge of RB0/INT pin
    
    
    Main:
      
     IF PORTB.0 = 1 Then     'Turn on LED only when signal is high.
     Low LED
     GoSub GetDuty               ' Retrieve the dutycycle values for all three phases
     GoSub SetDutyCycle          ' Set the three PWM modules accordingly
    EndIF
    
    
    ' Now increment the individual table pointers and make sure they wrap
    ' around to zero when they reach the end of the table. That way they
    ' will always stay 62 "steps" (120°) from each other.
    
      
      For i = 0 TO 1
        Phase[i] = Phase[i] + 1
        IF Phase[i] > 44 Then 
        Phase[i] = 0                     'When pointer is > 44 we need to wrap around to 0.
        GoSub ChangeBridgeDrive         'One phase is starting over, go change the outputs.
        
    EndIF
      Next
    
      PauseUs 200
    
    
    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
    
    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 15 "steps" appart so that a 120° phase shift is preserved.
    
    For i = 0 TO 1
      LookUp2 Phase[i], [0,70,137,208,275,341,408,470,529,588,643,694,745,788,827,866,898,925,_
    953,968,984,996,1000,996,984,968,953,925,898,866,827,788,745,_
    694,643,588,529,470,408,341,275,208,137,70,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
    
    ChangeBridgeDrive:
     
    ' When we come here the value i contains the phase counter that just got reset so we
    ' can use that to determine for which phase we should switch the outputs.
     
    Select Case i
        Case 0                          ' It was Phase 1 that rolled over
            Toggle PORTC.3        ' Invert the state of the pin
             Toggle PORTC.0      ' Invert the state of the pin          
                       
     
        Case 1                          ' It was Phase 2 that rolled over
            Toggle PORTC.5              ' Invert the state of the pin
            Toggle PORTC.6              ' Invert the state of the pin
     
     
        End Select
     
    Return
    
    Disable                                  'Disable interrupts in handler
    
    faultsignal: 
    High led
    CCP1CON = %00000000
    INTCON.1 = 0                 'Clear INTERRUPT flag
    
    Resume                         'Return TO main program
    Enable                         'Enable interrupts after handler
     
    
    End
    seem like it wont go back to main program.

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


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,
    I'm starting to get frustrated here.... The PIC won't do anything you don't tell it to. If you shut down the PWM it will stay off until you turn it on again. Obviously you must turn it back on again when you want it to turn back on.

    Right now you retrive the dutycycle values and set the dutycycle registers but the PWM is left off because you don't turn it on.

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    hi,

    long time no see

    after many times checking on my pwm using osiloskope, i found out that the pattern of the pwm isnt fixed according to the lookup table value while the PIC is running.
    this definitely affecting my inverter output and produce too many harmonics..
    as you can see for the attached file:

    both screen shot should have same length and pattern of pwm but when the PIC is running, the PWM seem keep expanding and de-expanding repeatedly thus changing the pattern.

    sumting wrong with the codes or my osiloskope resolution??i dont think so

    Code:
    ClearWDT
    DEFINE OSC 20
    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
    TRISC.2 = 0                   ' Set PORTC.2 (CCP1) to output
    TRISC.1 = 0                   ' Set PORTC.1 (CCP2) to output
    TRISB.5 = 0                   ' Set PORTB.5 (CCP3) to output
    CCP1CON = %00001100           ' Set CCP1 to PWM 
    CCP2CON = %00001100           ' Set CCP2 to PWM
    CCP3CON = %00001100           ' Set CCP3 to PWM
    T2CON = %00000101             ' Turn on Timer2, Prescale=4
    PR2 = 249                       ' Set PR2 to get 5KHz out
    ADCON1 = 7                      ' Set All PortB to Digital port
    
    
    ' The lookup table has 50 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. 50/3=15 so first phase starts at 0, second phase at 15
    ' and third phase at 30.
    ' Initilise pointers.
    
    Phase[0] = 0 : Phase[1] = 17 : Phase[2] = 34
    
    
    High PORTC.3    'Set the initial state for portc.3
    Low PORTC.0        'Same
    High PORTC.6    'Same
    Low PORTC.5        'Same
    High PORTB.4    'Same
    Low PORTB.3        'Same
    
    Main:
    
    if portb.2=1 then  
      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 the end of the table. That way they
    ' will always stay 17 "steps" (120°) from each other.
    
      
      For i = 0 TO 2
        Phase[i] = Phase[i] + 1
        IF Phase[i] > 50 Then 
        Phase[i] = 0                     'When pointer is > 50 we need to wrap around to 0.
        GoSub ChangeBridgeDrive         'One phase is starting over, go change the outputs.
    EndIF
      Next
    
      PauseUs 77    'Use each duty cycle for 85us before going to another            
      endif
      
    if portb.2=0 then
      gosub GetDutyWhenFault
      endif
    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 = DutyCycle[2]              ' Same procedure.
        CCP3CON.4 = Temp.0 
        CCP3CON.5 = Temp.1 
        CCPR3L    = Temp >> 2
    Return
    
    GetDutyWhenFault:
    
        Temp = 0             ' Set dutycyle for phase 1 to 0%.
        CCP1CON.4 = Temp.0           ' Set the LSB's 
        CCP1CON.5 = Temp.1 
        CCPR1L    = Temp >> 2         ' Set the 8 high bits
    
        Temp = 0             ' Same procedure for phase 2
        CCP2CON.4 = Temp.0 
        CCP2CON.5 = Temp.1 
        CCPR2L    = Temp >> 2
        
        
        Temp = 0             ' Same procedure for phase 3
        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 15 "steps" appart so that a 120° phase shift is preserved.
    
    For i = 0 TO 2
      LookUp2 Phase[i], [0,60,130,190,250,310,370,430,480,540,590,640,690,730,770,810,840,870,_
    910,930,950,970,980,990,1000,1000,1000,990,980,970,950,930,910,870,840,810,770,730,690,_
    640,590,540,480,430,370,310,250,190,130,60,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
    
    ChangeBridgeDrive:
     
    ' When we come here the value i contains the phase counter that just got reset so we
    ' can use that to determine for which phase we should switch the outputs.
     
    Select Case i
        Case 0                          ' It was Phase 1 that rolled over
            Toggle PORTC.3                ' Invert the state of the pin
             Toggle PORTC.0              ' Invert the state of the pin          
                       
     
        Case 1                          ' It was Phase 2 that rolled over
            Toggle PORTC.5              ' Invert the state of the pin
            Toggle PORTC.6              ' Invert the state of the pin
     
     
        Case 2                          ' It was Phase 3 that rolled over
            Toggle PORTB.4              ' Invert the state of the pin
            Toggle PORTB.3              ' Invert the state of the pin
     
     
        End Select
     
    Return
    
    
    End
    thanks
    Attached Images Attached Images   

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