3 channel PWM with customize duty cycle


Results 1 to 40 of 57

Threaded View

  1. #34


    Did you find this post helpful? Yes | No

    Default Re: 3 channel PWM with customize duty cycle

    Hi,

    ive just test it on real physical PIC and found out that phase 1 and phase 2 works fine but phase 3 wont work very well.
    As you can see from the attached named Phase 1 shows the correct generated pwm, same as phase 2.
    However, file Phase 3 show that the signal from portb.3 always high as a result generating wrong pwm switching.
    ive recheck the circuit but nothing wrong with it.
    i also simulate the program using real PIC simulation and nothing was wrong.
    So, i guess maybe the code got something problem.
    below is my complete coding:


    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
    TRISC.2 = 0         ' Set PORTC.2 (CCP1) to output
    TRISC.1 = 0
    TRISB.5 = 0
    CCP1CON = %00001100 ' Set CCP1 to PWM 
    CCP2CON = %00001100
    CCP3CON = %00001100
    T2CON = %00000101   ' Turn on Timer2, Prescale=4
    PR2 = 249     		' Set PR2 to get 5KHz out
    
    ' 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] = 15 : Phase[2] = 30
    
    
    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:
      
      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 62 "steps" (120°) from each other.
    
      
      For i = 0 TO 2
        Phase[i] = Phase[i] + 1
        IF Phase[i] > 46 Then 
        Phase[i] = 0         			'When pointer is > 185 we need to wrap around to 0.
        GoSub ChangeBridgeDrive        'One phase is starting over, go change the outputs.
    EndIF
      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 = DutyCycle[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,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,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 1 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
    please help to advice.

    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