;********************************************************************* ; File: LiIon_1s_Lader.ASM ; Author: Ottmar ; Date: 21.05.2022 ;********************************************************************* NOLIST ; PROJEKT ; Laden von 1zelligem LiPo-Akku, mit Ladezustandsabhängiger Steuerung ; des Ladestromes, automatische Abschaltung bei Ladeende. ; ; FUNKTIONSÜBERBLICK ; Der Ladevorgang beginnt mit Tastendruck (KEY_START). Sodann werden ; die Parameter ; Vdd - Versorgungsspannung der gesamnten Schaltung ; Vdrn - Spannung ueber Drain IRFZ34 ; Vbat - aktuelle Akkuspannung = Vdd - Vdrn ; Ishnt - Ladestrom ; P0W - Wiperposition MC4151 ; ausgegeben. ; Vbat wird fortlaufend berechnet und der Ladestrom mittels der ; Wiperposition so eingestellt, dass die maximale Vbat=4200mV-20mV ; nicht überschritten wird. ; Die Programmierung einer Ladespannungskurve ist Aufgabe eines ; späteren, fortführenden Projekts ;********************************************************************* ; Hardware PIC16F1627 Int. Osz 4MHz9 ; LCD 4x20 ; 2-Wire-Adapter für LCD ; Ladeschaltung auf Steckbrett ; MCP4151-SPI DigiPot Ladestromeinstellung ; LM358 OPA Ladestromregelung ; IRFZ34N MOSFET-Treiber Ladestrom ; LiIon (Nokia BL5CA (1 Zelle aus Handy) ;********************************************************************* ; Files: 00 HEADER_LiIon.INC ; 01 ISR_LiIon.INC ; 02 INIT_LiIon.INC ; 03 LCD_LiIon.INC ; 04 ADC_LiIon.INC ; D:\MPLAB_PROJEKTE\z_LCD\HD44780_2Wire.INC ; PIC16F1827.INC ; Schaltplan_LiPo-Lader ;********************************************************************* ; SUBROUTINES ; File: LiIon_1s_Lader.ASM ; main: ; ADC_Control ; WiperValue_Set: ; Math_Vakku: ; ; ; File: 03_LCD_LiIon.INC ; Out_ADC: ; B2D: ; Sub16: ; ADD_16: ; Leading_Zero: ; LcdOut_Table_1: ; Out_ChargeStart: ; Out_ChargeEnd: ; Out_ChargeTime_Start: ; Out_ChargeTime: ; ; ; File 04_ADC_LiIon.INC ; ADC: ; Vref_1024: ; Vref_4096: ; Mult10Bit_8: ; Mult10Bit_10: ; ; ADD_16_Test: ; ; ; File: 05_CHARGE_LiIon.INC ; ChargeStart: ; Charge_Ctrl ; Charge_Values: ;********************************************************************* #INCLUDE <00_HEADER_LiIon.INC> ;********************************************************************* ORG 0x0004 ;INTERRUPT-VECTOR #INCLUDE <01_ISR_LiIon.INC> ;********************************************************************* #INCLUDE <02_INIT_LiIon.INC> ;********************************************************************* main: ; #IFDEF __DEBUG ; GOTO main_charge_start ; gleich mit Charge_Ctrl starten ; #ENDIF ; ;1.Bei Ladeende hier auf Tastendruck zum erneuten Start warten btfss Flags,CHRG_END ;b5=0 charge accu enabled? GOTO main_start ;YES CALL Out_ChargeEnd btfsc KeyPress, KEY_START ;NO wartet auf Tastendruck GOTO main ; main_start: ;2.Vdd, Vdrain,Vbat,Vref,Ishunt,P0W ausgeben ; und auf Tastendruck für Ladebeginn warten bcf Flags,CHRG_END ;b5=0 charge accu enabled movlw .10 ;guter Startwert, auch bei restart movwf WiperValue CALL Meas_Vdd ;supply voltage to LCD CALL Meas_Vdd_Out ;Ausgabe Vakku im LCD CALL Meas_Vdrain CALL Meas_Vdrain_Out CALL Meas_Vakku ;Vdd-Vdrain=Vakku CALL Meas_Vakku_Out CALL Meas_Vref CALL Meas_Vref_Out CALL Meas_Vshunt CALL Meas_Vshunt_Out CALL WiperValue_Out ;Actual Wipervalue (MCP4151.P0W) ; btfsc KeyPress,KEY_START ;wartet auf Tastendruck GOTO $-1 ;3. Startbeginn, Ladezeit ausgeben "00:00:00" main_charge_start: CALL Out_ChargeTime_Start ;Ladezeit läuft VREF_ON ;RB4(10) high Vref ON movf WiperValue,w ;Startwert CALL WiperValue_Set ;Ladevorgang beginnt. ; main_charge_loop: btfss Flags,CHRG_END ;b5=1 Laden beendet? GOTO main_charge_sec ;NO VREF_OFF CALL Out_ChargeEnd ;YES GOTO main_end ;Laden ist beendet, letzte Messwert- ; ;4.1 Je Sekunde erfolgt 1x Zustandsmessung und Ladestromanpassung main_charge_sec: btfss Flags,NEW_SEC ;Messung jede Sekunde freigeben GOTO $-1 ;zugleichauch Arbeitstakt Ladevorgang btfsc Flags,NEW_SEC GOTO $-1 ; CALL Out_ChargeTime CALL Out_All_Measurments ;Vdd, Vdrain,Vbat,Vref,Ishunt,P0W CALL Charge_Ctrl btfss Flags,CHRG_END ;b5=1 Ladeende! (WiperValue=0) GOTO main_charge_loop main_end: GOTO main ;********************************************************************* ; SUBROUTINES ;********************************************************************* Charge_Ctrl: #IFDEF __DEBUG ;Vmax= 0x1068 = 4200mV ; ;1. Vakku1 > V_MAX1, Vakku0 = V_MAX0 ; movlw 0x11 ;Vist =0x0F3C = 3900mV ; movwf Vakku1 ; movlw 0x68 ;Vist KLEINER als VMAX! ; movwf Vakku0 ; ;2. Vakku1 > V_MAX1, Vakku0 > V_MAX0 ; movlw 0x11 ;Vist =0x0F3C = 3900mV ; movwf Vakku1 ; movlw 0x70 ;Vist KLEINER als VMAX! ; movwf Vakku0 ; ;-------------------------------------------- ; ;3. Vakku1 = V_MAX1, Vakku0 > V_MAX0 ; movlw 0x10 ; movwf Vakku1 ; movlw 0x70 ; movwf Vakku0 ; ;-------------------------------------------- ;4. Vakku1 = V_MAX1, Vakku0 = V_MAX0 movlw 0x10 movwf Vakku1 movlw 0x68 movwf Vakku0 ; ;-------------------------------------------- ; ;5. Vakku1 < V_MAX1, Vakku0 = V_MAX0 ; movlw 0x09 ; movwf Vakku1 ; movlw 0x68 ; movwf Vakku0 ; ;-------------------------------------------- ;6. Vakku1 = V_MAX1, Vakku0 < V_MAX0 movlw 0x10 movwf Vakku1 movlw 0x68 movwf Vakku0 ; ;-------------------------------------------- ; ;7. Vakku1 < V_MAX1, Vakku0 < V_MAX0 ; movlw 0x9 ; movwf Vakku1 ; movlw 0x67 ; movwf Vakku0 ; ; ; ;1.WiperValue>WIPER_MAX (WIPER_MAX=150) ; movlw .255 ;2.WiperValue=IPER_MAX ; movlw .150 ; ;3.WiperValue=1 movlw .150 movwf WiperValue ; GOTO chrg_wpr_ctrl #ENDIF ; Vakku - VMAX -> C=1 Wenn Vakku > VMAX ; -> C=0 Wenn Vakku <= VMAX ; -> Z=1 Wenn Vakku = VMAX ; -> Z=0 Wenn Vakku <> VMAX ; IF 1.0 Vakku1 < V_MAX1 then INCREMENT Wipervalue ; GOTO charge_wiper_ctrl -> test wiper in allowed range ; IF 2. Vakku1 = V_MAX1 ; THEN 2.1.Vakku0 = V_MAX0 -> JA -> DECREMENT Wipervalue ; GOTO charge_wiper_ctrl -> test wiper in allowed range chrg_vakku1_ctrl: movlw V_MAX1 ;maxwert ins Wreg subwf Vakku1,w ;subtract istwert-maxwert btfsc STATUS,Z ;test Vakku1 = V_MAX1? GOTO chrg_vakku0_ctrl ;Z=1 -> Vakku1 = V_MAX1 test Vakku0 ; ;Z=0 -> Vakku1 <> VMAX1 btfss STATUS,C ;Test C-Flag GOTO chrg_wiper_incr ;Z=0 Vakku1 <> V_MAX1 movlw V_MAX1 ;C=1 Vakku1>_MAX1, Vakku0>V_MAX0 movwf Vakku1 ;GOTO chrg_wiper_decr ; ; 2.2 Vakku1=V_MAX1, TEST Vakku0<=>V_MAX0 chrg_vakku0_ctrl: movlw V_MAX0 subwf Vakku0,w btfsc STATUS,Z ;test Vakku0 = V_MAX0? GOTO chrg_wiper_decr ;Z=1 -> Vakku1/0 = V_MAX01/0 ; btfss STATUS,C ;Test C-Flag GOTO chrg_wiper_incr ;C=0 Vakku0 < V_MAX0 movlw V_MAX0 ;C=1 Vakku0>_MAX0 movwf Vakku0 GOTO chrg_wiper_decr ; chrg_wiper_incr: incf WiperValue,f GOTO chrg_wiper_ctrl chrg_wiper_decr: decf WiperValue,f ;WiperValue <5 LadeEnde movlw .5 subwf WiperValue,w btfsc STATUS,C GOTO chrg_wpr_set bsf Flags,CHRG_END ;b5=1 Ladeende! (WiperValue=0) GOTO chrg_wpr_set ;LADEENDE ; decfsz WiperValue,f ; GOTO chrg_wiper_ctrl ;P0W-Position setzen, weiter Laden ; bsf Flags,CHRG_END ;b5=1 Ladeende! (WiperValue=0) ; GOTO chrg_wpr_set ;LADEENDE ; chrg_wiper_ctrl: ;WiperValue im Bereich =< WIPER_MAX? movlw WIPER_MAX ;Prüfen: WiperValue <> WIPER-MAX subwf WiperValue,w btfss STATUS,C GOTO chrg_wpr_set ;C=0 WiperValue < WIPER_MAX-prüfen movlw WIPER_MAX-.1 ;C=1 WiperValue => WIPER_MAX movwf WiperValue ; chrg_wpr_set: movf WiperValue,w ;adjust WiperValue MCP4151,P0W CALL WiperValue_Set ; charge_ctrl_end: RETURN ;********************************************************************* Meas_Vdd ; Returns Vdd1:0, the actual supply voltage movlw ADC_VDD ;AN2/RA2 für +Spannung Akku CALL ADC ;200us Convertierungszeit CALL Mult10Bit_8 ;mutiply 8 x (ACb1:0) with RLF movfw ACb1 movwf Vdd1 ;globale Variable movfw ACb0 movwf Vdd0 ;Vakku1:0 = Vdd1:0 - Vdrain1:0 RETURN ;----------------------------------- Meas_Vdd_Out: ;send Vdd1:0 to LCD CALL B2D ;convert binär to decimal CALL Leading_Zero ;Führende Nullen unterdrücken movlw LINE1+.4 ;Ausgabezeile+Digit im LCD CALL Out_ADC ;Ergebnis im LCD ausgeben RETURN ;********************************************************************* Meas_Vakku: ; Returns Vakku1:0 actual LiIon-cell voltage ; Difference of Vdd-Vdrain CALL Meas_Vdd CALL Meas_Vdrain CALL Math_Vakku ;Resul ACb1:0=Vakku1:0 RETURN ;----------------------------------- Meas_Vakku_Out: CALL B2D CALL Leading_Zero movlw LINE2+.4 CALL Out_ADC ;Ergebnis im LCD ausgeben RETURN ;********************************************************************* Meas_Vdrain: CALL Vref_4096 ;Umschalte zu Vref=4096mV movlw ADC_DRAIN ;AN4/RA4 CALL ADC CALL Vref_1024 ;switch back to ADC-Vref=1024mV ; bcf STATUS,C ;Multiply ADC-reslut RLF ACb0,f ;ACb1:0 x 4 = mV RLF ACb1,f RLF ACb0,f RLF ACb1,f movf ACb1,w movwf Vdrain1 ;Vdrain1:0 globale Variable movf ACb0,w movwf Vdrain0 RETURN ;----------------------------------- Meas_Vdrain_Out: ;send Vdd1:0 to LCD CALL B2D ;convert binär to decimal CALL Leading_Zero ;Führende Nullen unterdrücken movlw LINE1+.14 CALL Out_ADC ;Ergebnis im LCD ausgeben RETURN ;********************************************************************* Meas_Vshunt: ; Returns Vshunt1:0, as actual voltage(mV) over shunt resistor (1Ohm) ; Value ist also equivalent to the charging current mA) movlw ADC_SHUNT ;AN3/RA3 Berechnung des Ladestroms CALL ADC movf ACb1,w movwf Vshunt1 movf ACb0,w movwf Vshunt0 RETURN ;----------------------------------- Meas_Vshunt_Out: CALL B2D ;convert binär to decimal CALL Leading_Zero ;Führende Nullen unterdrücken movlw LINE3+.4 CALL Out_ADC RETURN ;********************************************************************* Meas_Vref: ; Returns Vshunt1:0, as actual voltage(mV) over shunt resistor (1Ohm) ; Value ist also equivalent to the charging current mA) movlw ADC_VREF ;AN8/RB4 CALL ADC RETURN ;----------------------------------- Meas_Vref_Out: CALL B2D ;convert binär to decimal CALL Leading_Zero ;Führende Nullen unterdrücken movlw LINE2+.14 CALL Out_ADC RETURN ;********************************************************************* WiperValue_Out: clrf ACb1 movf WiperValue,w movwf ACb0 CALL B2D bcf Flags,ERR ;Wiperausgabe Sub16 keinen Fehler erzeugen CALL Leading_Zero ;Führende Nullen unterdrücken movlw LINE3+.14 CALL Out_ADC ;Ausgabe im LCD RETURN ;********************************************************************* WiperValue_Set: ; 16-Bit Command, used to set wiper position ; Bit 15:8 Data1 Address (4bits), Command(2bits), Data (2bits) ; Bit 7;0 Data0 = value to be written to wiper-memory, ; is handed over through WREG ; Übergabe: Wiper_Value wird vom im WREG in Data0übernommen ; movwf Data0 ;LowByte copy WREG -> wipervalue bcf PORTA,SS2 ;b2=1 ENABLE Chip Select Output (LOW) ; movlw WIPER0_WRITE ;b7:4="0000" wiper0 memory-address movwf Data1 ;b3:2="00" Command "Write Data" ;1:0="00" b9:8 Databits WiperValue_Send: ;SEND COMMAND BYTE movwf Data1 ;16Bit-Comand Bit 16:9 WREG -> Data1 BANKSEL SSP2BUF ;bank4 movwf SSP2BUF ;copy Data to be send from WREG->SSP2BUF ; #IFDEF __DEBUG bsf SSP2STAT,BF ;BF-Flag wird im Debug-Modus nicht gesetzt #ENDIF ; wipervalue_buf1: btfss SSP2STAT,BF ;b0=1? Data transfer complete? (Buffer Full?) GOTO wipervalue_buf1 ;NO, check again movf SSP2BUF,w ;Get Data from SSP2BUF, throw it away ;------------------ BANKSEL 0 movf Data0,w ;16Bit-Comand Bit 7:0 Data0->WREG BANKSEL SSP2BUF ;bank4 movwf SSP2BUF ;ccopy Data to be send from WREG->SSP2BUF ; #IFDEF __DEBUG ;Für Debugging muß das BF-Flag gesetzt bsf SSP2STAT,BF ;werden da der SPI-Verkehr nicht erfolgt #ENDIF ; wipervalue_buf0: btfss SSP2STAT,BF ;b0=1? Data transfer complete? (Buffer Full?) GOTO wipervalue_buf0 ;NO, check again movf SSP2BUF,w ;Get Data from SSP2BUF, throw it away BANKSEL 0 ;bank0 bsf PORTA,SS2 ;b2=1 Disable Chip Select Output (high) CALL WiperValue_Out ;Actual Wipervalue (MCP4151.P0W) RETURN ;********************************************************************* Math_Vakku: ;16 Bit Subtraktion, bei Überlauf (neg. Ergebnis) ist C gesetzt ; ;16 bit f:=f-xw movf Vdd1,w movwf ACb1 movf Vdd0,w movwf ACb0 movf Vdrain1,w movwf BCb1 movf Vdrain0,w movwf BCb0 ; CALL Sub16 ; movf ACb1,w movwf Vakku1 movf ACb0,w movwf Vakku0 RETURN ;********************************************************************* #INCLUDE <03_LCD_LiIon.INC> #INCLUDE <04_ADC_LiIon.INC> #INCLUDE ;********************************************************************* END