Hi group,
I found an instructables article on creating a boost mode power supply based on a PIC. Its programmed in MikroBasic so I thought Id try and convert it to PBP PRO.
There are a couple of questions I have and a few issues. I'd also like to add the ability to have pushbutton up and down dimming and soft start/soft stop too.
Anyway, here is the original program:
Code:
dim temp as word
dim final_period, final_duty, high_duty, low_duty, last_adjust as byte
dim supply_multiplier, period_multiplier as float
dim v_feedback, v_supply, t_rise, SMPS_duty, t_period, SMPS_period as float
dim EE_pointer, EE_data as byte
'set values
const v_ref as float=3.8 'float 5.1 in the example
const supply_ratio as float=11.35 'float
const osc_freq as float=8 'integer or float
const L_Ipeak as float=67 'float
const fb_value as word=443 'word 225 in the example
sub procedure PRE_CALC
'precalculations
supply_multiplier=v_ref*supply_ratio
period_multiplier=(4/osc_freq)
end sub
sub procedure UPDATE_SMPS
'take Vss reading
temp=0
temp=ADC_read(ANS0) ' ADC conversion
'convert to voltage
v_feedback=temp 'put ADC in float
v_supply=v_feedback/1024 'find supply % of vref
v_supply=v_supply*supply_multiplier 'find supply volts
'calculate rise time
t_rise=L_Ipeak/v_supply 'find rise time @ supply volts for L/Ipeak
'calculate CCPR1L:CCP1CON<5:4>
SMPS_duty=t_rise*osc_freq 'find duty cycle value
final_duty=SMPS_duty 'convert to byte
'calculate period
t_period=(t_rise*1.33) 'dutycycle = .75period
'calculate PR2
SMPS_period=(t_period/period_multiplier) 'find period value
final_period=SMPS_period-1.0 'put in byte
'put in register masks
high_duty=(final_duty>>2) 'high 6 bits in CCPR1L
low_duty=(final_duty<<6) 'low two bits for CCP1CON
low_duty=(low_duty>>2) 'shift back to CCP1CON<5:4>
low_duty.3=1 'PWM configuration bit
low_duty.2=1 'PWM configuration bit
'LOG TO EEPROM
'only write if we measure somthing,
'prevents false writes durring programming b/c MCLR is disabled
if temp > 0 then
EE_data=word(temp>>8) 'high 8 bits first address
Eeprom_Write(EE_pointer, EE_data)
EE_pointer=EE_pointer+1
EE_data=temp 'low 8 bit second address
Eeprom_Write(EE_pointer, EE_data)
EE_pointer=EE_pointer+1
'put final_duty in eeprom
Eeprom_Write(EE_pointer, final_duty)
EE_pointer=EE_pointer+1
'put final_period in eeprom
Eeprom_Write(EE_pointer, final_period)
EE_pointer=EE_pointer+1
'reset write pointer if needed
if EE_pointer > 197 then EE_pointer=1 end if
'update the write pointer
Eeprom_write(0, EE_pointer)
end if
end sub
main:
'set ADC
GPIO = 0
CMCON0 = 7
TRISIO = 0 ' designate gpio as output
TRISIO.ANS0 = 1 ' pin ANS0 as input (Supply feedback)
TRISIO.ANS1 = 1 ' pin ANS1 as input (HV-feedback)
ANSEL.ANS1=1
ANSEL.ANS0=1
ADCON0.VCFG = 0 ' Vdd as Vref
'Low Voltage Indicator Light
GPIO.4=1 'indicator light on
'delay and take Vss reading
EE_pointer=Eeprom_read(0)
delay_ms(1000)
PRE_CALC
UPDATE_SMPS
'setup PWM
PR2=final_period 'sets PWM frequency
CCPR1L=0 '8 most sig. duty cycle bits =0
CCP1CON.5=0 'least significant bits = 0
CCP1CON.4=0 'least significant bits = 0
CCP1CON=12 'turns on PWM (set CCP1CON=0 at any time to turn off PWM)
T2CON=4 'turns on TIMER2 module (required for PWM timing)
last_adjust=0
while true
temp=0
temp=ADC_read(ANS1) ' ADC conversion
if temp > fb_value then 'feed back OVER set voltage
if last_adjust=1 then 'if 0 then already off
CCPR1L=0
CCP1CON.5=0
CCP1CON.4=0
GPIO.5=1
GPIO.4=0
last_adjust=0
end if
else
if last_adjust=0 then
CCPR1L=high_duty
CCP1CON=low_duty
GPIO.5=0
GPIO.4=1
last_adjust=1
end if
end if
wend
end.
And here is my PBP PRO conversion so far:
Code:
define OSC 48temp VAR word
final_period var byte
final_duty var byte
high_duty var byte
low_duty var byte
last_adjust var byte
supply_multiplier var word 'as float
period_multiplier var word 'as float
v_feedback var word
v_supply var word
t_rise var word
SMPS_duty var word
t_period var word
SMPS_period var word
EE_pointer var byte
EE_data var byte
v_ref var byte
supply_ratio var byte
osc_freq var byte
L_Ipeak var byte
fb_value var word
'-------------------------------------------------------------------------------
'set values
v_ref = 38/10 'float 5.1 in the example, 3.8 here
supply_ratio = 1135/100 'float, 11.35 here
osc_freq = 8 'integer or float
L_Ipeak = 67 'float
fb_value = 443 'word 225 in the example
'-------------------------------------------------------------------------------
ADCON1 = %00001011
ADCON2 = %10000111
TRISA = %00011111
TRISB = %00000000
TRISC = %00000111
CMCON = 7
'-------------------------------------------------------------------------------
PRE_CALC: 'precalculations
supply_multiplier=v_ref*supply_ratio
period_multiplier = 4/osc_freq
return
'-------------------------------------------------------------------------------
UPDATE_SMPS:
'take Vss reading
temp=0
ADCIN 0, temp
'convert to voltage
v_feedback=temp 'put ADC in float
v_supply=v_feedback/1024 'find supply % of vref
v_supply=v_supply*supply_multiplier 'find supply volts
'calculate rise time
t_rise=L_Ipeak / v_supply 'find rise time @ supply volts for L/Ipeak
'calculate CCPR1L:CCP1CON<5:4>
SMPS_duty=t_rise*osc_freq 'find duty cycle value
final_duty=SMPS_duty 'convert to byte
'calculate period
t_period=t_rise*133/10 'dutycycle = .75period
'calculate PR2
SMPS_period=(t_period/period_multiplier) 'find period value
final_period=SMPS_period-1 'put in byte
'put in register masks
high_duty=(final_duty>>2) 'high 6 bits in CCPR1L
low_duty=(final_duty<<6) 'low two bits for CCP1CON
low_duty=(low_duty>>2) 'shift back to CCP1CON<5:4>
low_duty.3=1 'PWM configuration bit
low_duty.2=1 'PWM configuration bit
'LOG TO EEPROM
'only write if we measure somthing,
'prevents false writes durring programming b/c MCLR is disabled
if temp > 0 then
EE_data=(temp>>8) 'high 8 bits first address
Write 0,EE_pointer, 10,EE_data
EE_pointer=EE_pointer+1
EE_data=temp 'low 8 bit second address
Write 0,EE_pointer, 10,EE_data
EE_pointer=EE_pointer+1
'put final_duty in eeprom
Write 0,EE_pointer, 20,final_duty
EE_pointer=EE_pointer+1
'put final_period in eeprom
Write 0,EE_pointer, 30,final_period
EE_pointer=EE_pointer+1
'reset write pointer if needed
if EE_pointer > 197 then
EE_pointer=1
endif
'update the write pointer
write 0, EE_pointer
endif
return
'-------------------------------------------------------------------------------
main:
'set ADC
'GPIO = 0
'CMCON = 7
'TRISa = 0 ' designate gpio as output
'TRISa.1 = 1 ' pin ANS0 as input (Supply feedback)
'TRISa.2 = 1 ' pin ANS1 as input (HV-feedback)
'ANSEL.ANS1=1
'ANSEL.ANS0=1
'ADCON0.VCFG = 0 ' Vdd as Vref
'Low Voltage Indicator Light
porta.4=1 'indicator light on
'delay and take Vss reading
Read 0, EE_pointer
'EE_pointer=Eeprom_read(0)
pause 1000
gosub PRE_CALC
gosub UPDATE_SMPS
'setup PWM
PR2=final_period 'sets PWM frequency
CCPR1L=0 '8 most sig. duty cycle bits =0
CCP1CON.5=0 'least significant bits = 0
CCP1CON.4=0 'least significant bits = 0
CCP1CON=12 'turns on PWM (set CCP1CON=0 at any time to turn off PWM)
T2CON=4 'turns on TIMER2 module (required for PWM timing)
last_adjust=0
while
temp=0
ADCIN 0, temp ' ADC conversion
if temp > fb_value then 'feed back OVER set voltage
if last_adjust=1 then 'if 0 then already off
CCPR1L=0
CCP1CON.5=0
CCP1CON.4=0
porta.5=1
porta.4=0
last_adjust=0
endif
else
if last_adjust=0 then
CCPR1L=high_duty
CCP1CON=low_duty
porta.5=0
porta.4=1
last_adjust=1
endif
endif
wend
end]
Ok, first thing, I have not set up the ADC or inputs/outputs yet, this isnt an issue at the moment. i have also not finished with the EEprom yet.
My first question is regarding the While - Wend loop.
If the program is stuck doing stuff in this loop it cant respond to any push button inputs to turn it on or off, or dim the brightness etc. This part of the program will have to be done at the same time as the buttons are monitored. So, do I have the buttons on an interrupt or does this loop run in the back ground somehow?
Bookmarks