; ******************************************************************* ; controller for cooler fans and coolant pump for ev cars ; ; G:\Astra_elektro\conversion\motor cooler\Microcontroller\coolerNN.asm ;drives coolers of motor and motor controller ; ;motor controller cooler: using the fan of the air condition (A/C) cooler. ;motor cooler: from Honda 250 scooter, with fan ; ;pump: Bosch ;Referenznummer(n) OE: 251965561B, 251 965 561 B; OEM: 0392020024, 0 392 020 024 ; ; microcontroller: PIC 12F690 * 2 (there is only one PWM output per PIC), identical software ; PIC1: motor controller cooler ; PIC2: motor cooler ; ; ;input: ; ignition ("Klemme 15A", i.e. ignition interrupted when starting) fused 30A from connector x7, pin H (black 2,5) ; ground ; temperature sensor 1 on motor (towards microcontroller) ; temperature sensor 2 on motor controller's heat sink (towards microcontroller) ; temperature sensor 3 on motor (towards temp gauge) ; ; heat on/off (determines which sensor's output is relayed to temp gauge) ; temp gauge output from heater - may be relayed to temp gauge ; (internal) push-button switch to cycle maintenance modes ; ; ;output: ; water pump (switched against +) ; motor cooler fan (switched against +), PWM 30..100% ; A/C cooler fan (switched against +) , PWM 30..100%. ; + Connector x7, pin H black 2,5 (already connected to supply!) ; - connector x7, pin E BN-WT 2,5 ; ; temp gauge (combined heater / cooler) ; ; ;LEDs: ; HW driven LEDs: ; power supply (i.e. operative state) (green) ; fuse 2,5A (red) ; PIC driven LEDs: ; PIC 1: ; A/C cooler fan (red) ; maintenance mode 2 indicator (yellow) ; PIC 2: ; motor fan (red) ; coolant pump (blue) ; maintenance mode 1+2 indicator (yellow) ; maintenance mode 2 indicator (yellow) ; ; ; ; ;behaviour: ; ; normal: ; with ignition on: ; for each PIC: ; >=50°C: water pump on (equipped only for motor cooler) ; 50°C: fan starts at 30% duty cycle ; 50..60°C: linearly increase fan speed ; >60°C: fan high ; ; ; ; display motor temp on temp gauge on dashboard. If heat is on, relay the temp output from coolant heater ; ; after startup: ; delay some seconds, then run coolant pump + both fans (30% speed) for 3 seconds ; ; ; maintenance (cycle modes by pressing button): ; 1) run coolant pump. return to normal mode after 1h. ; 2) run coolant pump + both fans at low speed. return to normal mode after 1h. ; 3) return to normal mode ; ; ;NTC: 1000R at 25°C ; RS 191-2263 ; R/T curve see motor_cooler_nn.xls ; ; ; ;PIC 16F690: ; inputs: ; RB7: maintenance switch. hi-> lo means "next mode" ; AN4: temperature sensor 1 on motor ; ; outputs: ; RC7: coolant pump (on when high) - blue LED ; P1A: motor fan (PWM output, active when high) - red LED ; RC6: maintenance mode indicator - lit in mode 1,2 ; RC3: maintenance mode indicator - lit in mode 2 ; ; ; ******************************************************************* ; ; programming interface: ; 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 #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 maint_mode ; 1: maintenance mode 1, 2: maintenance mode 2, 0: normal mode maint_age1 ; ageing counters for maint mode maint_age2 controlH ; 8 MSBs to control ADC controlL ; 2 LSBs to control ADC pump ; pump off if 0, on if 1 cs_W ; save content of W during interrupt cs_STATUS ; save content of STATUS during interrupt PORTC_S ; PORTC "shadow" port: directly writing single bits to PORTC may change other bits ; in the register! timing issue due to read-change-write procedure! keypressed ; actual state of key keypressed_h ; 'historic' status of key endc org 0 ; ******************* start of main program ***************** Start ; initialize variables CLRF PORTC_S ; init the PORTC shadow port CLRF keypressed CLRF keypressed_h CLRF pump CLRF controlL CLRF controlH CLRF maint_mode CLRF maint_age1 CLRF maint_age2 banksel ANSEL ; select Bank 2 - required for setting ANSEL, CMCON, VRCON MOVLW B'00010000' ; analog inputs: AN4 MOVWF ANSEL banksel 0x00 ; 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 ; configure ports 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 # not used MOVWF TRISA MOVLW B'11110000' ; select which PORTB ports (RB7..RB4) will be an input: all "in" # used: RB7 as input MOVWF TRISB MOVLW B'00000111' ; select which PORTC ports (RC7..RC0) will be an input: all except 7,6,4,3 # used: RC7, RC6, RC3 as outputs 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 ;CLRF PORTA ; init PortA ; !!! enabling these commands screws up everything !!! ;CLRF PORTB ; init PortB ;CLRF PORTC ; init PortC ; now the program really starts ..... call wake_up ; run pump and fans shortly loop ; ******* main loop ; check maint modes.if in maintenance mode, set indicator LEDs and override the settings for PORTC7 (pump), controlH and controlL ; reduce maint_age2 every maint_age 1 cycles and clear maintenance mode if zero ; maint_mode = 00 -> normal ; maint_mode = 01 -> mode1 ; maint_mode = 11 -> mode2 btfss maint_mode,1 goto mode1or0 ; maint mode 2 bsf PORTC_S,6 ; both LEDS lit bsf PORTC_S,3 MOVLW D'100'; controlH set to 100 (40% speed) MOVWF controlH BCF controlL,1 ; next 2 lines: controlL set for normal case BCF controlL,0 BSF pump,0 ; pump0 set to 1 call age_check goto finalize mode1or0 btfss maint_mode,0 goto mode_normal ; maint mode 1 bcf PORTC_S,3 ; only left LED lit bsf PORTC_S,6 MOVLW D'0'; controlH set to 0 MOVWF controlH BCF controlL,1 ; next 2 lines: controlL set for normal case BCF controlL,0 BSF pump,0 ; pump0 set to 1 call age_check goto finalize mode_normal bcf PORTC_S,6 ; clear RC6 (left) bcf PORTC_S,3 ; clear RC3 (right) call ADC_read call normal_set finalize call apply_values call wait1000 GOTO loop ; ******************* end of main loop ***************** ; ---------------------------------------------------------------------- check_key movf keypressed,w ; copy old status of keypressed to keypressed_h movwf keypressed_h bcf keypressed,0 ; copy new status of RB7 to keypressed btfsc PORTB,7 BSF keypressed,0 ; call kjp if historic is 1, and new is 0 btfss keypressed_h,0 goto ckc btfsc keypressed,0 goto ckc call kjp ckc return ; ---------------------------------------------------------------------- kjp ; keyjustpressed incf maint_mode,1 ;cycle maint modes ('1' here means write result back to file register) btfss maint_mode,1 ; if maint_mode would already be '11', reset it goto kjp_c btfss maint_mode,0 goto kjp_c clrf maint_mode kjp_c movlw D'3' ; initialize maint_age counters movwf maint_age2 clrf maint_age1 kjp_end return ; ---------------------------------------------------------------------- wait1000 movlw D'3' ; #rh write into working register movwf clock3 ; #rh set clock3 to above value to set wait time OndelayLoop decfsz clock1,1 ; first decreases clock1 from 00 to FF (so it is not 0), then further goto OndelayLoop call check_key ; The Inner loop takes 3 instructions per loop * 256 loops = 768 instructions decfsz clock2,1 ; goto OndelayLoop decfsz clock3,1 goto OndelayLoop return ; ----------------------------------------------------------------------- age_check decfsz maint_age1,1 ; first decreases maint_age1 from 00 to FF (so it is not 0), then further goto age_checkproceed decfsz maint_age2,1 goto age_checkproceed ; in case both counters become zero at the same time - reset maint mode clrf maint_mode age_checkproceed return ; ----------------------------------------------------------------------- ADC_read banksel ADCON0 bsf ADCON0,1 ; start conversion btfsc ADCON0,1 ; this bit will change to zero when the conversion is complete goto $-1 return ; ---------------------------------------------------------------------- wake_up ; run pump and fans shortly call apply_values ; with everything reset, otherwise PWM is not on 0?! call apply_values ; with everything reset, otherwise PWM is not on 0?! call wait1000 call wait1000 call wait1000 BSF pump,0 ; set bit 0 of 'pump' call apply_values call wait1000 call wait1000 call wait1000 call wait1000 call wait1000 BCF pump,0 movlw D'77' ; next 3 lines: set controlH for 30% fan speed (dont reset any more, main loop will immediately assign proper value) movwf controlH call apply_values call wait1000 call wait1000 call wait1000 call wait1000 call wait1000 return ; ---------------------------------------------------------------------- normal_set ; assign corresponding normal mode settings for pump (to set PORTC7), controlH and controlL banksel ADRESH BSF STATUS,C ; cleared only once MOVLW D'0'; enter controlH corresponding to below U here MOVWF controlH BCF controlL,1 ; next 2 lines: controlL set for normal case BCF controlL,0 BCF pump,0 ; pump0 set to 0 MOVF ADRESH,W ; copy result of A/D conversion into working register ;ADDLW D'1' ; rather cosmetic correction: to achieve the "or equal" below, so we can use values from the xls SUBLW D'150' ; sub W from literal! enter actual voltage (corresponding to temperature) here ;will CLEAR carry bit when literal was smaller than (voltage+1) = smaller or equal than voltage (i.e. voltage is >= temp is <= !) BTFSS STATUS,C GOTO nset_finished MOVLW D'77'; MOVWF controlH BSF pump,0 ; from here on, pump is switched on MOVF ADRESH,W SUBLW D'149' ; "carry" bit will be CLEARED if '149' is lower or equal than the value read by the ADC ;"ACHTUNG: Bei einer Subtraktion verhält sich das Carry-Bit genau verkehrt herum. 20-5=15 setzt Carry auf 1 aber 20-25=251 löscht das Carry-Flag." BTFSS STATUS,C GOTO nset_finished MOVLW D'85' MOVWF controlH MOVF ADRESH,W SUBLW D'148' BTFSS STATUS,C GOTO nset_finished MOVLW D'93' MOVWF controlH MOVF ADRESH,W SUBLW D'147' BTFSS STATUS,C GOTO nset_finished MOVLW D'101' MOVWF controlH MOVF ADRESH,W SUBLW D'146' BTFSS STATUS,C GOTO nset_finished MOVLW D'109' MOVWF controlH MOVF ADRESH,W SUBLW D'145' BTFSS STATUS,C GOTO nset_finished MOVLW D'117' MOVWF controlH MOVF ADRESH,W SUBLW D'144' BTFSS STATUS,C GOTO nset_finished MOVLW D'126' MOVWF controlH MOVF ADRESH,W SUBLW D'143' BTFSS STATUS,C GOTO nset_finished MOVLW D'134' MOVWF controlH MOVF ADRESH,W ; ADDLW D'1' SUBLW D'142' BTFSS STATUS,C GOTO nset_finished MOVLW D'142'; MOVWF controlH MOVF ADRESH,W SUBLW D'141' BTFSS STATUS,C GOTO nset_finished MOVLW D'150' MOVWF controlH MOVF ADRESH,W SUBLW D'140' BTFSS STATUS,C GOTO nset_finished MOVLW D'158' MOVF ADRESH,W SUBLW D'139' BTFSS STATUS,C GOTO nset_finished MOVLW D'166' MOVWF controlH MOVF ADRESH,W SUBLW D'138' BTFSS STATUS,C GOTO nset_finished MOVLW D'174' MOVWF controlH MOVF ADRESH,W ; ADDLW D'1' SUBLW D'137' BTFSS STATUS,C GOTO nset_finished MOVLW D'182' MOVWF controlH MOVF ADRESH,W SUBLW D'136' BTFSS STATUS,C GOTO nset_finished MOVLW D'190' MOVWF controlH MOVF ADRESH,W SUBLW D'135' BTFSS STATUS,C GOTO nset_finished MOVLW D'198' MOVWF controlH MOVF ADRESH,W SUBLW D'134' BTFSS STATUS,C GOTO nset_finished MOVLW D'206' MOVWF controlH MOVF ADRESH,W SUBLW D'133' BTFSS STATUS,C GOTO nset_finished MOVLW D'215' MOVWF controlH MOVF ADRESH,W SUBLW D'132' BTFSS STATUS,C GOTO nset_finished MOVLW D'223' MOVWF controlH MOVF ADRESH,W SUBLW D'131' BTFSS STATUS,C GOTO nset_finished MOVLW D'231' MOVWF controlH MOVF ADRESH,W SUBLW D'130' BTFSS STATUS,C GOTO nset_finished MOVLW D'239' MOVWF controlH MOVF ADRESH,W SUBLW D'129' BTFSS STATUS,C GOTO nset_finished MOVLW D'247' MOVWF controlH MOVF ADRESH,W SUBLW D'128' BTFSS STATUS,C GOTO nset_finished MOVLW D'255' MOVWF controlH BSF controlL,1 ; next 2 lines: controlL set for worst case BSF controlL,0 nset_finished return ; ---------------------------------------------------------------------- apply_values movf pump,w ; write contents of "pump" into working register BTFSS pump,0 ; next 4 lines: copy bit 0 of 'pump' to PORTC7 to switch on the pump BCF PORTC_S,7 BTFSC pump,0 BSF PORTC_S,7 banksel PORTC ; copy shadow PORTC to real PORTC movf PORTC_S,W movwf PORTC banksel CCPR1L MOVF controlH,W ; copy controlH to 8 MSBs of PWM module MOVWF CCPR1L banksel CCP1CON BCF CCP1CON,DC1B1 ; next 6 lines: 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 ; ---------------------------------------------------------------------- end