HI All,
This explanation has been the best one that I have found concerning the use of the PCPWM. That said, there still seems to be a bit of mystery surrounding it's use, at least to me. I mapped out the formulas in Excel, but I am still having trouble getting my head around the details. I'm trying to make a generic H-bridge for low frequencies and keep running into the wall. An 18F1330 with two pots, a switch, and the FETs with drivers. One Pot is for Frequency, the other is for Duty. The switch controls if the output is pulsed DC or cycles both ways. I'm not understanding the interaction of the frequency to the Duty. I can control the Freq just fine, but it makes a mess of the duty. Currently, the application needs it to run from 3 Hz to 100Hz with control from low power to high power (~5%-95% duty). I can see that there is a dependency with the PWM resolution, but I'm not sure how to manage it. I can get the PTPER values within 0-4096, but the resolution gets out of range. I'm thinking I need to find some way to scale the Duty to the PTPER values, and adjust accordingly, but I haven't managed to make it click. Any suggestions?
Code:
'****************************************************************
'*  Name    : PCPWM_1330_H-bridge84.BAS                         *
'*  Author  : Mark Rokus                                        *
'*  Notice  : Copyright (c) 2012 Controlled Surroundings Inc.   *
'*          : All Rights Reserved                               *
'*  Date    : 6/9/2012                                          *
'*  Version : 1.0                                               *
'*  Notes   : 18F1330 to drive H bridge:                        *
'*          : (2)L6378 drivers to (4) FDP22N50N N-FETs          *
'* used PCPWM_1330_H-bridge5 to test Hardware on separate FETS
'* New rewrite using ints
'* moved switch to RB3, rewire drivers complementary
'* NOTE: Int not working, Not going into AC
'*          Freq and Duty not correct
'****************************************************************
'                            18F1330                                                             
'              ---------------------u----------------------
'    Freq    -1|RA0/AN0/INT0                  RB3/INT3/CMP1|18-   Switch      
'    Duty    -2|RA1/AN1/INT1                  RB2/INT2/CMP2|17-   Pad      
'    Pad     -3|RA4/TOCKI/AN2                 RA7/OSC1/CLKI|16-   Pad     
'    Vpp     -4|RA5/MCLR/vpp              RA6/OSC2/CLKO/AN3|15-   Pad           
'    Gnd     -5|-- VSS                                VDD++|14-   5 vdc         
'    Tx      -6|RA2/TX/CK                      RB7/PGD/PWM5|13-    PGD      
'    Rx      -7|RA3/RX/DT                      RB6/PGC/PWM4|12-    PGC      
'   Pad      -8|RB0/PWM0                           RB5/PWM3|11-   Q1/Q4 PWM      
'   Pad      -9|RB1/PWM1                           RB4/PWM2|10-   Q2/Q3 PWM        
'              |___________________________________________|

#CONFIG
    CONFIG OSC = INTIO2        ;Internal oscillator, port function on RA6 and RA7
#ENDCONFIG
DEFINE OSC 4                  ' Actually @ 2MHz 
OSCCON  = %11011100         ' INTOSC primary, 2MHz
'****** Hardware Serial Setup ***************
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 8   ' 57600 Baud @ 2MHz, -3.55%
SPBRGH = 0
BAUDCON.3 = 1         ' Enable 16 bit baudrate generator
'***************************************
TRISA   = %00000011          ' PortA : outputs except RA.0/RA.1= AN
TRISB   = %00001000          ' all outputs ex: RB.3 switch i/p  
INTCON    = 0                      ' 
INTCON2 = 0                     
CMCON   = 0                      ' Comparators off
clear
'**** Analog setup   ****
    ADCON1 = %00001100   ' AN0,AN1 Analog: VDD ref. RA4 & RA6 DIO
    ADCON2 = %10010001   ' Right justified, 8 Tad, Fosc/8
'***** PWM Setup ? ********************
    PTCON0 = %00001110      ' 1:1 post, Fosc/256 (1:64) pre, UpDown(...00 free)
    PTCON1 = %11000000      ' PWM Time Base timer on, Count Down      
    PWMCON0 = %00110111     ' 0-3 PWM,  complementary
    PWMCON1 = 1             ' 1:1 postscale, updates enabled, overrides sync 
    DTCON = 0               ' zero dead-time  
    PTCON1 = %10000000      ' PWM time base is ON, counts up
    FLTCONFIG = 0           ' disable fault A 
    OVDCONS      =    %00000000    ' 
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    '   Variable definition
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
PORTB = 0                   ' clear port latch
Fraw         var    word          ' Raw reading for Frequency
Freq         var    word        ' Frequency of PWM
Draw         var    word        ' Raw reading for Duty
Duty         Var    Word        ' Duty of PWM
Sw             var    PORTB.3        ' switch input for AC or Positive only
'************************************************
Start:
    hserout  ["1330_H-bridge83",13,10]
    pause 500    
'*************************************
PosOnly: 
    If sw = 0 then ac            ' mode check                
  ADCON0 = %00000011            ' Start conversion on AN0
    WHILE ADCON0.1=1             ' Wait for it to complete 
    WEND   
     Fraw.HighByte = ADRESH     ' get result from AN0
     Fraw.LowByte = ADRESL      '     
  ADCON0 = %00000111            ' Start conversion on AN1
    WHILE ADCON0.1=1             ' Wait for it to complete 
    WEND    
     Draw.HighByte = ADRESH     ' get result from AN1
     Draw.LowByte = ADRESL      '      
     Freq = (Fraw) max 3        ' 
     Duty = (Draw*3) max 1        '   
         PTPERH = Freq.highbyte 'load timer: Freq low byte
         PTPERL = Freq.lowbyte     ' Freq low byte
           PDC1H = Duty.HighByte  ' PWM duty on Out1
         PDC1L = Duty.LowByte
          OVDCOND = %00001000         ' enable PWM3 OUT1 (Q1/Q4 on RB5)           
        hserout ["Duty ",dec duty," PosFreq ",dec Freq]
        goto PosOnly                ' Loop 
'***************************************************************************
AC:        ' sequence for generating Alternating pulses     
PosAlt:                                'drive Positive pulse on bridge      
        If sw = 1 then posonly    ' mode check
        PIR3.4 = 0               ' reset PWM Int flag
          while PIR3.4 = 0
         OVDCOND = %00001000       ' enable PWM3 OUT1 (Q1/Q4 on RB5)
          ADCON0 = %00000011     ' Start conversion on AN1
         WHILE ADCON0.1=1      ' Wait for it to complete 
         WEND    
         Fraw.HighByte = ADRESH ' get result from AN0
        Fraw.LowByte = ADRESL  '     
        Freq = Fraw max 3           ' 
         PTPERH = Freq.highbyte  'load timer: Freq low byte
          PTPERL = Freq.lowbyte     ' Freq low byte
        wend                       ' one cycle until Int 
NegAlt:                              ' drive Negative pulse on bridge
        PIR3.4 = 0                ' reset PWM Int flag
          while PIR3.4 = 0
         OVDCOND = %00000100    ' enable PWM1 OUT2 (Q2/Q3 on RB4)               
           ADCON0 = %00000111     ' Start conversion on AN0
         WHILE ADCON0.1=1       ' Wait for it to complete 
         WEND
        Draw.HighByte = ADRESH     ' get result from AN1
         Draw.LowByte = ADRESL      '         
          Duty = (Draw) max 1        ' 
            PDC1H = Duty.HighByte  ' PWM duty on Out1
         PDC1L = Duty.LowByte
         wend                       ' one cycle until Int    
        hserout ["Duty ",dec duty," ACFreq ",dec Freq]
        goto AC                  ' Loop         
end
So I guess the question is: Can anyone explain the relationship between PTPER and PDCx in this dynamic environment in a way that I'm not seeing?
Thanks
Bo