; ******************************************************************* ; coolant heater for ev cars ; ; C:\dokumente\Richard\KFZ\Astra_elektro\Einbauten\Heizung\Microcontroller\heater11.asm ; max temperature reduced, see "lookup temp current11.xls" ; circuit diagram: see C:\dokumente\Richard\KFZ\Astra_elektro\Einbauten\Heizung\ev_coolant_heater_11.vsd ; ; ******************************************************************* ; input: ; AN2 - pin 17 - current feed-back ; AN4 - pin 16 - temp sensor 1 ; RB4 - pin 13 - heat lo/hi ; RB5 - pin 12 - heat on/off ; RB7 - pin 10 - /shutdown ; C12in0- - pin 18 - feedback 14V ; C12in1- - pin 15 - feedback 100V branch A ; C12in2- - pin 14 - feedback 100V branch B ; ; output: ; RA5 - pin 2 - status (yellow LED, in the heater knob): see check_exceptions subroutine for ; explanations of the different blink sequences ; RC7 - pin 9 - debug1 (green LED): is lit when heat is on (RB5 high) ; RC6 - pin 8 - debug2 (yellow LED): is lit when heat is high (RB4 high) ; RC3 - pin 7 - debug3 (red LED): is lit when output is shut down - see check_exceptions ; RC4 - pin 6 - debug4 (blue LED): is lit when system tries to increase control voltage, and dark when ; system tries to decrease control voltage. Will blink quickly during normal operation. ; P1A - pin 5 - control (PWM output) ; ;further LEDs: ;green (separate from debug LEDs, next to blue LED): 5v supply is ok ;blue (on the piggyback board on the heat exchanger): shutdown due to overcurrent, needs 12V power cycle to reset ; ; programming: ; PicKit 1 = VPP/MCLR - pin 4 ; PicKit 2 = VDD Target - pin 1 ; PicKit 3 = VSS (ground) - pin 11 ; PicKit 4 = ICSPDAT/PGD - pin 19 ; PicKit 5 = ICSPCLK/PGC - pin 18 ; PicKit 6 = Auxiliary ; note rh: basic structure: main loop is cycled continuously ; heat off: status LED off, "control" low ; normal operation: status LED is constantly lit, "control" active ; status LED is constantly lit, "control" active ; routine temp2volt: read temperature from temp1/AN4, map to target feedback voltage "feedback_target", depending also on RB4 - pin 13 - heat lo/hi ; routine set_control: set "control" to zero at first cycle after power-on, then increase or decrease to make "current feedback" meet "feedback_target" ; heat on and /shutdown is low: status LED is flashing shortly , "control" low ; routine "shutdown": keep "control" inactive, flash the "status" LED = 1000 0000 ; low voltage exceptions: ; 14V supply too low (<10,6V): keep control at zero, flash the "status LED = 1010 0000 ; 100V branch A AND/OR 100V branch B too low (<78V): keep control at zero, flash the "status LED = 1010 1000 ; note that currently the "100V low" exception occurs when either 100V supply is too low, needs to be checked #include __config ( _INTRC_OSC_NOCLKOUT & _WDT_OFF & _BOR_ON & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _FCMEN_OFF) ; (from a different configuration!) ; _FCMEN_OFF ; -- fail safe clock monitor enable off ; _IESO_OFF ; -- int/ext switch over enable off ; _BOR_ON ; default, brown out reset on ; _CPD_OFF ; default, data eeprom protection off ; _CP_OFF ; default, program code protection off ; _MCLR_OFF ; -- use MCLR pin as digital input ; _PWRTE_OFF ; default, power up timer off ; _WDT_OFF ; -- watch dog timer off ; _INTOSCIO ; -- internal osc, OSC1 and OSC2 I/O ; ; parameters: cblock 0x20 clock1 ; Define three file registers for the clock2 ; delay loop ;clock3 clock4 ; counter to slow down "status" display I_target ; target transistor current (according to lookup table) controlH controlL disp_stat ; 8 bit pattern to be displayed by status LED disp_sc ; counter for reading "status" display endc org 0 ; ******************* start of main program ***************** Start ; initialize pins banksel 0x00 ; select Bank 0 - required for initializing PORTA, PORTB, PORTC, CCP1CON, ECCPAS, ADCON0 CLRF PORTA ; init PortA CLRF PORTB ; init PortB CLRF PORTC ; init PortC ; PWM Output Configuration: see page 132 - set PR2 (bank1!), T2CON, CCPR1L, CCP1CON (all bank0) MOVLW B'00001100' ; 7,6: PWM out= single out, P1A modulated, others assigned as port pins ; 5,4: lsbs of the PWM duty cycle MOVWF CCP1CON MOVLW B'00000000' ; initialize PWM output msbs MOVWF CCPR1L BCF PIR1,1 ; Timer2 to PR2 Interrupt Flag bit TMR2IF - necessary? MOVLW B'00000100' ; Timer2 control register - Timer2 is on, Timer2 clock prescaler is 1 MOVWF T2CON ; init of PWM pulse period PR2 see bank 1 MOVLW B'00010001' ; left justified, reference=VDD, select AN4=0100-pin16-current, dont start conversion, enable ADC MOVWF ADCON0 ; set P1B and P1D tri-state (to avoid interference, P1B is same pin as RC4) BSF ECCPAS,1 banksel ANSEL ; select Bank 2 - required for setting ANSEL, CMCON, VRCON MOVLW B'00010100' ; analog inputs: AN4, AN2 MOVWF ANSEL ; CLRF ANSELH ; analog input AN8 disabled (interferes with RC6) BSF CM1CON0,7 ; C1ON enable comparator1 (voltage check) BCF CM1CON0,5 ; C1OE disable comparator1 output so as not to interfere with AN2 BCF CM1CON0,4 ; C1POL 0-polarity is not inverted BSF CM1CON0,2 ; C1R 1 - C1Vin+ connects to C1VREF BCF CM2CON0,7 ; disable comparator2 (it is not used) BCF CM2CON0,5 ; disable comparator2 output so as not to interfere with RC4 BCF VRCON, 7 ; C1VREN 0 = 0.6 Volt constant reference routed to C1VREF input of Comparator C1 BSF VRCON, 4 ; VP6EN 0.6V Reference Enable bit, 1= enabled banksel ADCON1 ; select Bank 1 - required for setting TRISx (RA 5..0, RB 7..4, RC 7..0), ADCON1, MOVLW B'00011111' ; select which PORTA ports (RA5..RA0) will be an input: RA5=out, others in MOVWF TRISA MOVLW B'11110000' ; select which PORTB ports (RB7..RB4) will be an input: all "in" MOVWF TRISB MOVLW B'00000111' ; select which PORTC ports (RC7..RC0) will be an input: all except 7,6,4,3 MOVWF TRISC ; bit 5 must be zero to enable P1A (PWM output) MOVLW B'11111111' MOVWF PR2 MOVLW B'00010000' ; -,Fosc/8=001 , ---- MOVWF ADCON1 BCF STATUS,RP0 ; BCF STATUS,RP1 ; select Bank 0 MOVLW B'00000000' MOVWF controlL MOVWF controlH MOVWF I_target movwf disp_stat movlw B'00001000' movwf disp_sc loop ; main loop, should be executed around every 50 milliseconds BCF STATUS,RP0 ; BCF STATUS,RP1 ; select Bank 0 MOVLW B'00010001' ; left justified, reference=VDD, select AN4=0100-pin16-temp, dont start conversion, enable ADC MOVWF ADCON0 call ADC_read ; reading temperature call map_I_to_T ; in this subroutine, I_target will be mapped to the actual T (the value now stored in ADRESH) and hi/lo bit banksel ADCON0 MOVLW B'00001001' ; left justified, reference=VDD, select AN2=0010-pin17-I_feedback, dont start conversion, enable ADC MOVWF ADCON0 call ADC_read ; reading current call adjust_control ; returns in/decremented controlH, controlL call check_exceptions call control_to_PWM call display_status GOTO loop ; ******************* end of main program, subroutines below ***************** ; ---------------------------------------------------------------------- check_exceptions ; checks whether heat off, /shutdown, 14V supply / 100V A or B too low, ; in case, disp_stat will be set accordingly and controlL / H will be kept zero banksel 0x00 movlw B'11111111' ; normal operation movwf disp_stat BSF PORTC,7 ; green LED "power on" bcf PORTC,3 ; red LED BTFSC PORTB,5 ; check whether heat is on / off. If off, reset controlH, clear green LED, disp_stat goto check_shutdown ; "on" - else "off": movlw B'00000000' movwf disp_stat BCF PORTC,7 ; green LED is cleared when heat off BCF PORTC,4 ; blue LED is suppressed when heat off goto shutoff check_shutdown btfsc PORTB,7 ; /shutdown (i.e. thyristor has triggered due to overcurrent on any transistor) goto check_U14_low ; no /shutdown = high movlw B'10000000' movwf disp_stat goto exception check_U14_low banksel CM1CON0 BSF CM1CON0,C1CH1 ; 10 = C1VIN- of C1 connects to C12IN2- pin (14) BCF CM1CON0,C1CH0 call wait10 BTFSS CM1CON0,C1OUT goto check_U100A_low banksel 0x00 movlw B'10100000' movwf disp_stat goto exception check_U100A_low banksel CM1CON0 BCF CM1CON0,C1CH1 ; 00 = C1VIN- of C1 connects to C12IN0- pin (18) BCF CM1CON0,C1CH0 call wait10 BTFSS CM1CON0,C1OUT goto check_U100B_low banksel 0x00 movlw B'10101000' movwf disp_stat goto exception check_U100B_low banksel CM1CON0 BCF CM1CON0,C1CH1 ; 01 = C1VIN- of C1 connects to C12IN1- pin (15) BSF CM1CON0,C1CH0 call wait10 BTFSS CM1CON0,C1OUT goto ece banksel 0x00 movlw B'10101000' movwf disp_stat goto exception banksel 0x00 goto ece exception banksel 0x00 bsf PORTC,3 ; red LED "shutdown or low voltage exception" shutoff MOVLW B'00000000' MOVWF controlL MOVWF controlH ece banksel 0x00 return display_status banksel 0x00 decfsz clock4 ; cycle this counter goto s1 movlw B'00011000' movwf clock4 ; #rh set clock4 to above value to control speed decfsz disp_sc,1 ; cycle this counter next7 movlw B'00000111' xorwf disp_sc,0 btfss STATUS,Z goto next6 bcf PORTA,5 btfsc disp_stat,7 ; set STATUS LED if this bit of disp_stat is "1" bsf PORTA,5 goto s1 next6 movlw B'00000110' xorwf disp_sc,0 btfss STATUS,Z goto next5 bcf PORTA,5 btfsc disp_stat,6 bsf PORTA,5 goto s1 next5 movlw B'00000101' xorwf disp_sc,0 btfss STATUS,Z goto next4 bcf PORTA,5 btfsc disp_stat,5 bsf PORTA,5 goto s1 next4 movlw B'00000100' xorwf disp_sc,0 btfss STATUS,Z goto next3 bcf PORTA,5 btfsc disp_stat,4 bsf PORTA,5 goto s1 next3 movlw B'00000011' xorwf disp_sc,0 btfss STATUS,Z goto next2 bcf PORTA,5 btfsc disp_stat,3 bsf PORTA,5 goto s1 next2 movlw B'00000010' xorwf disp_sc,0 btfss STATUS,Z goto next1 bcf PORTA,5 btfsc disp_stat,2 bsf PORTA,5 goto s1 next1 movlw B'00000001' xorwf disp_sc,0 btfss STATUS,Z goto next0 bcf PORTA,5 btfsc disp_stat,1 bsf PORTA,5 goto s1 next0 movlw B'00000000' xorwf disp_sc,0 btfss STATUS,Z goto s1 bcf PORTA,5 btfsc disp_stat,0 bsf PORTA,5 movlw B'00001000' movwf disp_sc s1 return ; ---------------------------------------------------------------------- ADC_read call wait100 BSF ADCON0,1 ; start conversion BTFSC ADCON0,1 ; this bit will change to zero when the conversion is complete GOTO $-1 RETURN ; ---------------------------------------------------------------------- adjust_control banksel ADRESH MOVF ADRESH,W ; actual current is not stored, just compared with I_target! BCF STATUS,C SUBWF I_target ; (subtract W from F) will set carry bit when target current is still bigger BTFSS STATUS,C ; in this case next instruction is skipped -> increase control GOTO ac1 INCF controlL ; count up the 2 LSBs of control, reset and increase controlH if "carry" BTFSS controlL,2 GOTO ac01 CLRF controlL INCF controlH,1 ; 1 makes the result being stored back in F (instead of W) ac01 BSF PORTC,4; blue LED on means "counter being increased" GOTO ac2 ac1 DECF controlL ; count down the 2 LSBs of control, reset and decrease controlH if "carry" BTFSS controlL,2 GOTO ac02 MOVLW B'00000011' MOVWF controlL DECFSZ controlH,1 ; DECFSZ skips the next instruction if result is zero) goto ac03 ; if the goto is skipped, controlH will be increased to avoid underrun INCF controlH,1 ac03 ac02 BCF PORTC,4 ; blue LED off means "counter being decreased" ac2 RETURN ; ---------------------------------------------------------------------- wait100 movlw B'00000101' ; #rh write into working register movwf clock2 ; #rh set clock2 to above value to control time OndelayLoop12 OndelayLoop11 decfsz clock1,1 ; first decreases clock1 from 00 to FF (so it is not 0), then further goto OndelayLoop11 ; The Inner loop takes 3 instructions per loop * 256 loops = 768 instructions decfsz clock2,1 ; goto OndelayLoop12 ; return ; ---------------------------------------------------------------------- wait10 movlw B'00001000' movwf clock1 OndelayLoop21 decfsz clock1,1 goto OndelayLoop21 return ; ---------------------------------------------------------------------- control_to_PWM banksel CCP1CON MOVF controlH,W ; copy controlH to 8 MSBs of PWM module MOVWF CCPR1L BCF CCP1CON,DC1B1 ; copy the 2 LSBs of controlL to the 2 LSBs of PWM module BTFSC controlL,1 BSF CCP1CON,DC1B1 ; bit 5 BCF CCP1CON,DC1B0 ; bit 4 BTFSC controlL,0 BSF CCP1CON,DC1B0 return ; ---------------------------------------------------------------------- map_I_to_T MOVLW D'0'; enter I_target corresponding to below temp here MOVWF I_target banksel 0x00 ; also A,C BCF PORTC,6 ; orange LED (heat high) BTFSS PORTB,4; heat high if RB4 is set GOTO heat_low BSF PORTC,6 ; orange LED lit (when heat high + heat on) banksel ADRESH BCF STATUS,C ; cleared only once MOVLW D'0'; enter I_target corresponding to below temp here MOVWF I_target MOVF ADRESH,W SUBLW D'39' ; sub W from literal! enter actual voltage (temperature) here - ;will set carry bit when literal was smaller than the voltage (i.e. temp is lower!) BTFSC STATUS,C ; else (literal bigger), I_target will remain the value set above GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'40' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'45' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'50' BTFSC STATUS,C GOTO I2T_finished MOVLW D'36' MOVWF I_target MOVF ADRESH,W SUBLW D'56' BTFSC STATUS,C GOTO I2T_finished MOVLW D'73' MOVWF I_target MOVF ADRESH,W SUBLW D'63' BTFSC STATUS,C GOTO I2T_finished MOVLW D'80' MOVWF I_target MOVF ADRESH,W SUBLW D'70' BTFSC STATUS,C GOTO I2T_finished MOVLW D'87' MOVWF I_target MOVF ADRESH,W SUBLW D'78' BTFSC STATUS,C GOTO I2T_finished MOVLW D'95' MOVWF I_target MOVF ADRESH,W SUBLW D'87' BTFSC STATUS,C GOTO I2T_finished MOVLW D'102' MOVWF I_target MOVF ADRESH,W SUBLW D'96' BTFSC STATUS,C GOTO I2T_finished MOVLW D'116' MOVWF I_target MOVF ADRESH,W SUBLW D'117' BTFSC STATUS,C GOTO I2T_finished MOVLW D'131' MOVWF I_target MOVF ADRESH,W SUBLW D'141' BTFSC STATUS,C GOTO I2T_finished MOVLW D'146' ; full power MOVWF I_target MOVF ADRESH,W SUBLW D'164' BTFSC STATUS,C GOTO I2T_finished MOVLW D'146' MOVWF I_target MOVF ADRESH,W SUBLW D'187' BTFSC STATUS,C GOTO I2T_finished MOVLW D'146' MOVWF I_target MOVF ADRESH,W SUBLW D'207' BTFSC STATUS,C GOTO I2T_finished MOVLW D'146' MOVWF I_target MOVF ADRESH,W SUBLW D'250' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'252' ; unplausible temp voltage - cable break BTFSC STATUS,C GOTO I2T_finished GOTO I2T_finished ; just in case ... heat_low MOVLW D'0'; enter I_target corresponding to below temp here MOVWF I_target MOVF ADRESH,W SUBLW D'39' ; sub W from literal! enter actual voltage (temperature) here BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'40' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'45' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'50' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'56' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'63' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'70' BTFSC STATUS,C GOTO I2T_finished MOVLW D'36' MOVWF I_target MOVF ADRESH,W SUBLW D'78' BTFSC STATUS,C GOTO I2T_finished MOVLW D'73' MOVWF I_target MOVF ADRESH,W SUBLW D'87' BTFSC STATUS,C GOTO I2T_finished MOVLW D'87' MOVWF I_target MOVF ADRESH,W SUBLW D'96' BTFSC STATUS,C GOTO I2T_finished MOVLW D'102' MOVWF I_target MOVF ADRESH,W SUBLW D'117' BTFSC STATUS,C GOTO I2T_finished MOVLW D'109' MOVWF I_target MOVF ADRESH,W SUBLW D'141' BTFSC STATUS,C GOTO I2T_finished MOVLW D'109' ; full power MOVWF I_target MOVF ADRESH,W SUBLW D'164' BTFSC STATUS,C GOTO I2T_finished MOVLW D'109' MOVWF I_target MOVF ADRESH,W SUBLW D'187' BTFSC STATUS,C GOTO I2T_finished MOVLW D'109' MOVWF I_target MOVF ADRESH,W SUBLW D'207' BTFSC STATUS,C GOTO I2T_finished MOVLW D'109' MOVWF I_target MOVF ADRESH,W SUBLW D'250' BTFSC STATUS,C GOTO I2T_finished MOVLW D'0' MOVWF I_target MOVF ADRESH,W SUBLW D'252' ; unplausible temp voltage - cable break BTFSC STATUS,C GOTO I2T_finished I2T_finished end