PWM2

SwordfishUser.PWM2 History

Hide minor edits - Show changes to output

Changed lines 6-8 from:
The '''SetFreqByTable()''' function uses a constants table of PR2 and Timer2 Prescaler load values so the user can switch easily between optimum frequencies and duty cycle resolution.  A small utility program has been created to simplify the creation of this array of constants which can be downloaded from [[http://circuit-ed.com/uplds/pwm_writer.exe | HERE]].
to:
The '''SetFreqByTable()''' function uses a constants table of PR2 and Timer2 Prescaler load values so the user can switch easily between optimum frequencies and duty cycle resolution.  A small utility program has been created to simplify the creation of this array of constants which can be downloaded from [[http://circuit-ed.com/uplds/pwm_writer.exe | HERE]].  A screenshot of this utility is provided below.

http://circuit-ed.com/uplds/pwm_table_writer.jpg
Changed lines 192-240 from:
=]
to:
=]
-----

Here is example code that uses some of the newly added functions.  This example uses an 18F2550 @ 48MHz.  Potentiometers are connected to AN2 and AN3 which create the variable duty-cycle for PWM1 and PWM2 outputs.  A pushbutton connected to GND and PORTB.0 is used to toggle between PWM frequencies of 11.75KHz and 5.8KHz which have resolutions of 1024 and 512, respectively.  These frequencies were determined from a constants table created with the PWM_Writer Utility.  The EasyPIC3 PIC development board was used for this test.

=code [=
Device = 18F2550
Clock = 48

' set up config for 8MHz crystal and USB
Config USBDIV = 2
Config CPUDIV = OSC1_PLL2
Config PLLDIV = 2
Config FOSC  = HSPLL_HS

Include "pwm.bas"
Include "adc.bas"

Dim adc0,adc1 As Word
Dim tt As Byte

  TRISA = 15
  TRISB = 1
  tt = 0
  ADCON1 = 11                  // AN0..AN3 active ADC's
  INTCON2.7 = 0                // RBPU active
  PWM.SetFreqByTable(tt)
  PWM.Start1
  PWM.Start2
  While true
      adc0 = ADC.Read(2)
      adc1 = ADC.Read(3)
      If tt = 0 Then
        PWM.SetDuty1(adc0)
        PWM.SetDuty2(adc1)
      Else
        PWM.SetDuty1(adc0 >> 1)
        PWM.SetDuty2(adc1 >> 1)
      End If
      If (PORTB And 1) = 0 Then
        Inc(tt)
        tt = tt And 1
        PWM.SetFreqByTable(tt)
        Repeat
          DelayMS(5)
        Until (PORTB And 1) <> 0
      EndIf   
  Wend =]       

Added lines 1-192:
This is a revision of David Barker's PWM Module posted previously.  This module makes the following changes:
* Added functions for control of the second PWM output connected to the CCP2 module
* Changes to the original SetFreq() function
* Added the '''SetFreqByTable()''' function. 

The '''SetFreqByTable()''' function uses a constants table of PR2 and Timer2 Prescaler load values so the user can switch easily between optimum frequencies and duty cycle resolution.  A small utility program has been created to simplify the creation of this array of constants which can be downloaded from [[http://circuit-ed.com/uplds/pwm_writer.exe | HERE]].
-----

!PWM.bas Revised 29.09.2007

=code [=
{
*****************************************************************************
*  Name    : PWM.BAS                                                        *
*  Author  : David John Barker & Warren Schroeder                          *
*  Notice  : Copyright (c) 2007 Mecanique                                  *
*          : All Rights Reserved                                            *
*  Date    : 23/08/2007                                                    *
*  Version : 1.0                                                            *
*  Notes  : 29/09/2007 - Added support for 2 PWM outputs                  *                   
*                      - Added FreqSetByTable() function                  *
*                      - PWM Table Writer Utility available at            *
*                          http://circuit-ed.com/uplds/pwm_writer.exe      *
*****************************************************************************
}                                                                                                               
Module PWM
Dim
  FMaxDuty As Word,
  FTMR2ON As T2CON.2
#if _device in (18F1220, 18F1320)
  Dim FPWM1Pin As PORTB.3    // RB3 connected to CCP1 module
#else
  Dim FPWM1Pin As PORTC.2    // RC2 connected to CCP1 module
  Dim FPWM2Pin As PORTC.1    // RC1 connected to CCP2 module
#endif
{
****************************************************************************
* Name    : Start1                                                        *
* Purpose : Start PWM Channel 1                                            *
****************************************************************************

Public Sub Start1()
    CCP1CON = $0C
    Output(FPWM1Pin)
    FTMR2ON = 1 
End Sub
{
****************************************************************************
* Name    : Start2                                                        *
* Purpose : Start PWM Channel 2                                            *
****************************************************************************

Public Sub Start2()
    CCP2CON = $0C
    Output(FPWM2Pin)
    FTMR2ON = 1 
End Sub
{
****************************************************************************
* Name    : Stop1                                                          *
* Purpose : Stop PWM Channel 1                                            *
****************************************************************************

Public Sub Stop1()
  Input(FPWM1Pin)
  CCP1CON = $00
End Sub
{
****************************************************************************
* Name    : Stop2                                                          *
* Purpose : Stop PWM Channel 2                                            *
****************************************************************************

Public Sub Stop2()
  Input(FPWM2Pin)
  CCP2CON = $00
End Sub
{
****************************************************************************
* Name    : SetDuty1                                                      *
* Purpose : The CCPR1L contains the eight MSbs And the CCP1CON<5:4>        *
*        : contains the two LSbs. This 10-Bit value is represented by    *
*        : CCPR1L:CCP1CON<5:4>.                                          *
****************************************************************************
}
Public Sub SetDuty1(pDuty As Word)
  CCP1CON.5 = pDuty.1
  CCP1CON.4 = pDuty.0
  CCPR1L = pDuty >> 2
End Sub
{
****************************************************************************
* Name    : SetDuty2                                                      *
* Purpose : The CCPR2L contains the eight MSbs And the CCP2CON<5:4>        *
*        : contains the two LSbs. This 10-Bit value is represented by    *
*        : CCPR2L:CCP2CON<5:4>.                                          *
****************************************************************************
}
Public Sub SetDuty2(pDuty As Word)
  CCP2CON.5 = pDuty.1
  CCP2CON.4 = pDuty.0
  CCPR2L = pDuty >> 2
End Sub
{
****************************************************************************
* Name    : SetDuty1Percent                                                *
* Purpose : Set the duty as a percentage for channel 1                    *
****************************************************************************
}
Public Sub SetDuty1Percent(pPercent As Byte)
  SetDuty1(FMaxDuty * pPercent / 100)
End Sub
{
****************************************************************************
* Name    : SetDuty2Percent                                                *
* Purpose : Set the duty as a percentage for channel 2                    *
****************************************************************************
}
Public Sub SetDuty2Percent(pPercent As Byte)
  SetDuty2(FMaxDuty * pPercent / 100)
End Sub
{
****************************************************************************
* Name    : MaxDuty                                                        *
* Purpose :                                                                *
****************************************************************************

Public Inline Function MaxDuty() As FMaxDuty
End Function
{
****************************************************************************
* Name    : SetFreq                                                        *
* Purpose :                                                                *
* Notes  : Initializes Freq settings                                      *
*        : Resets Duty Cycle To 0                                        *
*        : Requires PWM.Start afterward if PWM is not running            *             
****************************************************************************
}
Public Function SetFreq(pFrequency As LongWord) As Boolean
  Const Fosc As LongWord = _clock * 1000000
  Dim Prescale As Byte
  Dim PR2Value, PRConst As Word

  // loop through all the valid prescalers...
  PRConst = Fosc / pFrequency / 4
  Prescale = 1
  Result = false
  Repeat
      PR2Value = PRConst / Prescale - 1        // calculate a PR2 value
      If PR2Value < 256 Then                  // if it is a valid value, then...
        FMaxDuty = (PR2Value + 1) * 4        // determine maximum duty...
PR2 = PR2Value                        // initialise PR2               
        Select Prescale                      // configure T2CON prescale
            Case 1  : Prescale = %00000000    // prescale 1
    Case 4  : Prescale = %00000001    // prescale 4
    Case 16 : Prescale = %00000011    // prescale 16
        End Select
        SetDuty1(0)                          // output = 0V
        SetDuty2(0)                          //
        T2CON = (T2CON And 252) Or Prescale  // load prescaler value
        Result = true                        // function return true (success)       
        Exit                                  // exit the sub
      EndIf 
      Prescale = Prescale * 4
  Until Prescale > 16
End Function
{
****************************************************************************
* Name    : SetFreqByTable                                                *
* Purpose : Change PWM frequency settings by indexing table                *
* Notes  : Initializes Freq settings                                      *
*        : Resets Duty Cycle To 0                                        *
*        : Requires PWM.Start afterward if PWM is not running            *             
****************************************************************************
}
Public Sub SetFreqByTable(pIndex As Byte)
 Const pwmtbl(4) As Byte = (255,1,127,3)
  // (Fosc=48) 11719; 5859;
 Dim prv As Byte

  pindex = pindex * 2                          // table offset value
  prv = pwmtbl(pindex)                        // get new PR2 value from array for frequency value
  FMaxDuty = (prv + 1) * 4                    // maximum duty cycle resolution based on PR2 value 
  PR2 = prv                                    // load PR2
  SetDuty1(0)                                  // output = 0V
  SetDuty2(0)                                  //
  T2CON = (T2CON And 252) Or pwmtbl(pindex+1)  // load prescaler value from array
End Sub

// initialise the module
FMaxDuty = 0
=]
September 30, 2007, at 05:42 PM by xor - PWM2 - More PWM Functions
September 30, 2007, at 05:42 PM by xor - PWM2 - More PWM Functions