Here you go, this is the code for my switching supply. I've made also a change to the hardware, a resistor of 10k with a condensator of 100pF in parallel is now used instead of the resistor of 680 ohms. That seems to work good enough.
Code: Select all;PIC 16F88 at 8MHz internal oscillator
;this is a macro:
t0p2 macro ;timer 0 instellen op prescaler 4
bcf OPTION_REG,PS2
bcf OPTION_REG,PS1
bcf OPTION_REG,PS0
endm
main
movlw .130 ; 13 volts is the wanted value, 0-25.5V makes it this easy
movwf U
mainlus
;put in whateaver you want to add to the regulator, for example I²C to receive wanted value
call regellus
goto mainlus
;This is the regulatig loop (= regellus) to measure the output, make an average of the
;measurements, and change the PWM according to the difference.
regellus
t0p2 ; this is a macro, to set prescaler of timer0 to 2
movfw U
movwf PWMv ;set wanted value in PWMv
movwf PWMverschil ;To use it, I put wanted value in PWMdifference(=verschil)
; Here the average is made out of 4 measurements, and I also measure I (current).
foutgemiddelde
call ad ; I measure
movwf Igemeten ; measured value in Imeasured
bcf ADCON0,5 ; U measure
bsf ADCON0,4 ; U measure
bsf ADCON0,3 ; U measure
t0p2
movlw 0FFh-.10 ; 10*4 instructies wait ==> 2Oµs
movwf TMR0
bcf INTCON,TMR0IF ; interrupt clearen
adwait
btfss INTCON,TMR0IF ; 20µs done
goto adwait ; then A/D
call ad ; U measure
movwf PWM1
call ad
addwf PWM1,f ; add both
rrf PWM1,f ; divide by 2
call ad ; U measure
movwf PWM2
call ad
addwf PWM2,f ; add both
rrf PWM2,f ; divide by 2
movfw PWM1
addwf PWM2,f ; optellen
rrf PWM2,f ; delen door 2
;next loop: first measure I
bsf ADCON0,5 ; Meet I
bcf ADCON0,4 ; Meet I
bcf ADCON0,3 ; Meet I
;/
movf PWM2,w ;set measured (and averaged) value
movwf Ugemeten ; save the value, to transmit later via I²C
subwf PWMverschil,f ;compare measured-wanted value
btfss STATUS,C ; if C is zero
goto negatief ; result negative
positief ; result positive: send out more
; depending on the difference measured/wanted, I mak e bigger/smaller change
movlw .3
subwf PWMverschil,w ; fill staturregister, don't change PWMverschil
btfss STATUS,C
goto pos0 ;difference less than 0,1V, no change
movlw .25
subwf PWMverschil,w ; statusregister vullen, PWMverschil blijft behouden
btfss STATUS,C
goto pos1 ;difference less than 2,5, change 1 step
movlw .50
subwf PWMverschil,w ; statusregister vullen, PWMverschil blijft behouden
btfss STATUS,C
goto pos2 ; verschil between 2,5V en 5V, change 2 steps
movlw .65
subwf PWMverschil,w ; statusregister vullen, PWMverschil blijft behouden
btfss STATUS,C
goto pos3 ;verschil tussen 5V en 6,5V, change 5 steps
posmax ; difference greater than 6.5V, then increase with half the difference
rrf PWMverschil,w
addwf PWMuit,f
goto poslus
pos1 ;verschil kleiner dan 1V
movf neg,f
btfss STATUS,Z
goto pos0
incf PWMuit,f ;verschil tussen 10 en 20, dan PWMuit 1 aanpassen
btfsc STATUS,Z ; if PWMuit is 0
decf PWMuit,f ; went too far
movlw .10
movwf neg ;10 next times there's a little change, don't do it
goto PWMaangepast
pos0 ;So if a change of 1 step is done, the next 10 times a change of 1 step would
;normally been done, it isn't done. So the regulator won't oscillate, value of 10 is
;experimentally found. Big changes on output (remove load for example) will not be influenced by this.
decf neg,f
goto PWMaangepast
pos2 ; verschil tussen 1,5V en 3,5V
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
goto poslus
pos3 ; verschil tussen 3,5 en 5V
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
incf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
decf PWMuit,f ; te ver gegaan
goto poslus
poslus
clrf neg
clrf pos
goto PWMaangepast
negatief ; resultaat negatief: minder uitsturen
;in negative, the max is decreasing 5 steps, because that's usually slower than
;increasing, so bigger steps would make it oscillate.
; negative result is inverted
COMF PWMverschil,w
ADDLW .1 ;+1 to compensate borrow
MOVWF PWMverschil
; /juiste uitkomst
movlw .3
subwf PWMverschil,w ; statusregister vullen, PWMverschil blijft behouden
btfss STATUS,C
goto neg0 ;verschil kleiner dan 0,1V, niet aanpassen
movlw .20
subwf PWMverschil,w ; statusregister vullen, PWMverschil blijft behouden
btfss STATUS,C
goto neg1 ; verschil kleiner dan 1,5V
movlw .50
subwf PWMverschil,w ; statusregister vullen, PWMverschil blijft behouden
btfss STATUS,C
goto neg2 ; verschil tussen 1,5V en 3,5V
goto neg3
neg1 ;verschil kleiner dan 1V
movf neg,f
btfss STATUS,Z
goto neg0
movf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
movlw .10
movwf neg ;aantal keer niet deze lus doen
goto PWMaangepast
neg0 ;na neg1 gedaan te hebben, moeten we een vertraging hebben,
;om oscillaties te voorkomen. Om toch snel te reageren op grote
;veranderingen doen we een aantal keer neg1 niet na neg1 gedaan te
;hebben, komen we in een andere lus dan neg1, wordt dit ongedaan.
decf neg,f
goto PWMaangepast
neg2 ;verschil tussen 1V en 3,5V
movf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
goto neglus
neg3 ;verschil tussen 3,5V en 7.5V
movf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
btfsc STATUS,Z ; als PWMuit 0 is
incf PWMuit,f ; 1 van maken (na dec weer 0)
decf PWMuit,f
goto neglus
neglus
clrf neg
clrf pos
goto PWMaangepast
PWMaangepast
call PWM
return
;/regellus
;analog reading of the value:
ad
bsf ADCON0,2 ;start de conversie
adklaar
btfsc ADCON0,2
goto adklaar ;wachten tot AD conversie gedaan is
movf ADRESH,w
return
;/ad
;hier volgt een routine om de PWM te sturen, in PWMuit moet een byte zitten die de
;duty-cycle aanduidt, 0 resulteert in 0V, .255 met 25.5V.
;De f(PWM) is 8kHz, en TMR2 wordt gebruikt voor PWM.
PWM
movf PWMuit,w
movwf CCPR1L ;duty-cycle juist zetten.
return
;/pwm