PWM2
SwordfishUser.PWM2 History
Hide minor edits - Show changes to output
April 26, 2023, at 02:23 PM
by - restore image and tablewriter download
Changed line 6 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]]. A screenshot of this utility is provided below.
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 [[Attach:pwm_tablewriter.zip | PWM WRITER]]. A screenshot of this utility is provided below.
Changed line 8 from:
to:
Attach:pwm_tablewriter.png
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
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 =]
-----
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
=]
* 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 - PWM2 - More PWM Functions
September 30, 2007, at 05:42 PM
by - PWM2 - More PWM Functions