Designing the code was simple, I decided to use pure Assembly language
and assemble with MPASM,
I used an easypic3 development board from Mikroelektronika
and chose a PIC12F675 as it had the following attributes.
1) Cheap
2) 10 bit A/D
3) A TTL port for communication
4) A TTL port for relay drive
5) Small 8 pin dil package
6) Had flash properties
7) No wastage of resources
The program listing ( Assembly file )
; V8 Relay controller for SOE2152
; Written by Graham Medland gm236@ex.ac.uk
;
; RA0 = SDA LINE (serial data)
; RA1 = RELAY output
; RA2 = Analog in
; the rest are tied up internaly
;sda protocols
;
;search for 500 uS logic HIGH.
;wait for low transition (wait 10uS)
;now wait 25uS for center of sample point and read D0
;wait 50uS and read d1
;wait 50uS and read d2
; ---- --- --- --- ---
;wait 50uS and read d9
;this marks the end of the packed
;which consists of 10 bit a/d value
;*************************************************************************
; MPASM
;*************************************************************************
LIST p=12f675
#include ..\..\MPASM\p12ce674.inc
__config _WDT_OFF & _CP_OFF & _INTRC_OSC_NOCLKOUT
;*************************************************************************
; DATA
;*************************************************************************
cblock 020
gpio_pins ; duplicate of port pins
ad_val:2 ; 10 bit ad value
ad_val_t:2 ; copy of 10 bit ad value for data stream
l_bound:2 ; lower bound voltage 2 byte
u_bound:2 ; upper bound voltage 2 byte
tmr:2 ; lsb=initial value : msb=the counter
temp ; temporary dump for variables
eocp ; end of code page (linear store of data)
endc
;*************************************************************************
; CODE
;*************************************************************************
; Initialise the A/D
; setup variables
; this gets done on a POR
movlw 0
movwf gpio_pins ; fan is off initialy
movlw 091
movwf l_bound
movlw 01
movwf l_bound+1 ; 70 Ohms cut off point, fan comes on if any lower
movlw 0A0
movwf u_bound
movlw 01
movwf u_bound+1 ; 75 Ohms cut off point, fan switches off
bcf 03,6
bsf 03,5 ; bank 1
movlw 04 ; RA0,1 = OUTPUT RA2 = INPUT
movwf 05 ; trisa
movlw 0
movwf 01 ; option
movwf 0b ; no interupts
movlw 014 ; an2 = analog, rest are digital,fosc/8 with 4mhz internal osc = 2us
movwf 01f ; ANSEL
bcf 03,5 ; bank 0
movlw 089 ; right justified,vref vdd, AN2, 0 , 1
movwf 01f ; ADCON0
goto main ; all setup so go do main loop for ever !!!!!
;**************************
; Start the main sequence
; check A/D and switch
; the Fan On/Off
main:
call do_pins ; output the pins
call get_ad ; read ad, value in w
call test_lower ; test for upper bound
andlw 0ff ; -1 or zero ?
btfsc 03,2
goto fan_on ; if here adval < lower bound ( < 70 ohms)
call test_upper ; test lower bound
andlw 0ff ; -1 or zero ?
btfss 03,2
goto fan_off ; if here adval > upper bound( > 75 ohms)
goto main
;**************************
; Upper and Lower bounds
; for A/D values
test_lower:
movf ad_val+1,w ; get high bit
subwf l_bound+1,w
btfss 03,0 ; skip if positive
retlw 0ff ; oh dear high bit no good
btfss 03,2
retlw 0 ; definately high no point checking low
movf ad_val,w ; get low bit
subwf l_bound,w
btfss 03,0 ; skip if positive
retlw 0ff ; oh dear high equal and low bit bit no good
retlw 0 ; high bit equal and low bit ok !!!!! yeah !
test_upper:
movf ad_val+1,w ; get high bit
subwf u_bound+1,w
btfss 03,0 ; skip if positive
retlw 0ff ; oh dear high bit no good
btfss 03,2
retlw 0 ; definately high no point checking low
movf ad_val,w ; get low bit
subwf u_bound,w
btfss 03,0 ; skip if positive
retlw 0ff ; oh dear high equal and low bit bit no good
retlw 0 ; high bit equal and low bit ok !!!!! yeah !
;**************************
; Virtual to Real
; Outputs the pins
do_pins:
movf gpio_pins,w
movwf 05 ; Real output to pins
retlw 0
fan_on: ; Virtual output to pins
movlw 02
iorwf gpio_pins,f
goto main
fan_off:
movlw 0fd
andwf gpio_pins,f
goto main
dta_high:
movlw 01
iorwf gpio_pins,w
movwf 05
movwf gpio_pins
return
dta_low:
movlw 0fe
andwf gpio_pins,w
movwf 05
movwf gpio_pins
return
;**************************
; on exit
; ad_val = d7-d0 ad value
; ad_val+1 = d9-d8
get_ad:
movlw 2 ; mask for DONE/GO
iorwf 01f,f ; start conversion
call send_data ; go do data bit stream while a/d is being done
bsf 03,5 ; bank 1
movf 01e,w
bcf 03,5
movwf ad_val ; save d7-d0
bcf 03,5 ; bank 0
movf 01e,w
movwf ad_val+1 ; save
return ; ret true
;**************************
;serial data routines
send_data: ; fosc=0
call dta_high ; start initial high
clrf tmr ; longest possible wait state
call wait_state ; long high (porch)
movf ad_val,w
movwf ad_val_t ; copy lsb movf ad_val+1,w
movf ad_val+1,w
movwf ad_val_t+1 ; copy msb
movlw 0a ; 10 bits of a/d to send
movwf temp ; use temp as it is available fosc=0314
call dta_low ; this is the trigger for BIT 0 fosc=031c
send_data1:
bcf 03,0
rrf ad_val_t+1,f ; finger in a woodpeckers hole
rrf ad_val_t,f ; all ten bits shifted,c=1 for high, c=0 for low
btfsc 03,0 ; test the carry flag
goto send_data_H ; send a high
goto send_data_L ; send data low
goto 0 ; this never gets done,
send_data2:
decfsz temp,f ; done all 10 bits ?
goto send_data1 ; if not then keep going
return ; else return (1 packet sent)
send_data_L: ; output a logic low fosc=039
call dta_low
movlw 0a
movwf tmr
call wait_state
goto send_data2
send_data_H: ; output a logic high fosc=039
call dta_high
movlw 0a
movwf tmr
call wait_state
goto send_data2
;*******************************
;delay routine to stretch signal
wait_state:
movf tmr,w ; get the start counter
movwf tmr+1 ; copy to the timer
wait_state1:
decfsz tmr+1,f ; decrement and repeat
goto wait_state1
return ; else return
;******************************************************************************
END
The assembly program was debugged using my own simulator PICDEBUG which can be found here And runs in a windows DOS box
Screen shot of debugging. (Note the symbols which have been imported from the Bytecraft .COD file
The program was Assembled using MPASM which created the following HEX file
The HEX file was loaded into the PIC12F675 using the EASYPIC3 software
|
 |
Screen shot of hardware debugging. (Note the scope probes and signal generator leads for simulating the engine
This processs was repeated until I was happy with both the software and hardware configuration.
Screen shot of hardware and Software development process. (Note that the device being programmed stays STATIC in the board and can be programmed while it is in circuit. The whole process of Assembling and programming the pic can be done in under 30 seconds.
With the hardware working I then injected an analog signal into the A/D pin simulating the rise and fall of engine temperature.
Frequency of 0.232 Hz or 1/4 Hz Actual frequency from Engine temperature is about 1/160 Hz With only 35 Seconds from good to overheating |
 |
|
Volts Peak to Peak of 2v This gives a nice 1 Volt up/down about the mean voltage triggering the fan on/off about the peaks |
 |
|
DC Offset voltage of 2.1v this is the MEAN value of temperature during normal running of engine. |
 |
|
|
please view the video footage by clicking Here where you can see the analog signal (bottom trace) and the TTL output for the fan control (top trace)
|
|
With the hardware working
I then took a standard car indicator relay
removed the components except the relay and free wheeling diode
then mounted the componts where I could (utilising the old tracks left behind) .
| Screen shot of Relay packed with the components. (Note the PIC micro glued vertically in anh 8 pin dil socket which is just above the 7805 regulator.
|
 |
| Here it is with the case going on ! |
 |
This unit was fitted to the land rover and is still working very well !!
I then wrote a small demo routine
in x86 assembly language to decode the 10bit serial data
Here is the laptop coupled to the pic it is nice to see the bargraph and serial bit stream on the laptop screen change as the engine warms |
 |
Here is an osciloscope trace taken from the pic SDA pin showing an alternating bit pattern representing the value 01_0101_0101 or 0155 Hex |
 |
Here is the x86 listing which requires my favourite assembler and is targeted for MSDOS under a windows dos box or real mode
The program listing ( Assembly file )
; V8 Relay controller for SOE2152
; Written by Graham Medland gm236@ex.ac.uk
; use A386/D386 to assemble
; MSDOS application to extract 10 bit A/D
; from 12f675. and runs in v86 or real mode
; for the intel x86 processor
mov ax,040
push ax
pop fs
fs mov dx,w[08]
mov al,0ff ; all data high
inc dx ; get EPP port
mov ax,013
int 010
start:
call draw_data ; draw the bit stream
in al,060
cmp al,03d ; until F3 is pressed
jnz start
mov ax,0
int 016
start1:
call draw_data ; draw the bit stream
call draw_sp1 ; mark the ten sample points under track
in al,060
cmp al,01c ; until RET is pressed
jnz start1
mov ax,0
int 016
call vga_cls
start2:
call draw_data ; draw the bit stream
call draw_sp2 ; mark the ten sample points over track
in al,060
cmp al,03d ; until F1 is pressed
jnz start2
mov ax,0
int 016
call vga_cls
start3:
call draw_data ; draw the bit stream
call draw_sp ; mark the ten sample points over track
in al,060
cmp al,01C ; until F1 is pressed
jnz start3
mov ax,0
int 016
call vga_cls
start4:
call get_bar_graph ; draw a bar garaph
in al,060
cmp al,03d ; until F1 is pressed
jnz start4
mov ax,0
int 016
start5:
call draw_data ; draw the bit stream
call draw_sp ; mark the ten sample points over track
call get_bar_graph ; draw a bar garaph
call draw_bar_graph
in al,060
cmp al,01c ; until F1 is pressed
jnz start5
mov ax,03
int 010
mov ax,0
int 016
mov ax,04c00
int 021
;-----------------------------
draw_data:
mov es,0a000
mov di,16000
mov cx,320
get_porch: ; on exit we have bit 0 transmitted
in al,dx
in al,dx
in al,dx
in al,dx
cmp al,07f ; is it a high ?
jz get_porch_1 ; if it is do the count
mov ebp,0 ; if not then reset the counter
get_porch_1:
inc ebp ; increment the counter >300 is the porch
cmp ebp,070
jb get_porch
get_porch_2: ; wait for high/low transition
in al,dx
cmp al,03f ; is it low ?
jnz get_porch_2 ; keep repeating
get_porch_3:
in al,dx
in al,dx
xor al,040
stosb
loop get_porch_3
ret
;------------------------------------------------------------
draw_sp:
mov di,16971
mov cx,10 ;10 bits of data
draw_spa:
es mov w[di],0ffff
es mov w[di+320],0ffff
add di,17
push cx
and cx,1
add di,cx ; fudge factor for linear tracking of bit stream
pop cx
loop draw_spa
ret
;------------------------------------------------------------
draw_sp1:
mov di,16971
mov cx,10 ;10 bits of data
draw_sp1a:
es mov w[di],0ffff
es mov w[di+320],0ffff
add di,17
loop draw_sp1a
ret
;------------------------------------------------------------
draw_sp2:
mov di,16971
mov cx,10 ;10 bits of data
draw_sp2a:
es mov w[di],0ffff
es mov w[di+320],0ffff
add di,18
loop draw_sp2a
ret
vga_cls:
mov di,16971
mov cx,320
mov ax,0
rep stosw ;clear the line
ret
;------------------------------------------------------------
get_bar_graph:
mov di,16011 ; point to center of data bit 0
mov cx,10 ; 10 bits of data
mov bx,0 ; bx will hold the 10 data bits
get_bar_graph1:
es mov al,b[di]
es mov b[di],0ff
es mov b[di+320],0ff
es mov b[di-320],0ff
sal al,2
rcr bx,1
add di,17
push cx
and cx,1
add di,cx ; fudge factor for linear tracking of bit stream
pop cx
loop get_bar_graph1
not bx ; 1s complement
shr bx,6 ; 10 bit allign
and bx,03ff
cs mov w[082],bx
shr bx,2 ; 0-255 for bar graph, 10bit to 8bit
cs mov w[080],bx
ret
;-------------------------------------------------------------
draw_bar_graph: ; draws both bargraphs
cld
cs mov cx,w[080] ; draw scaled line (0-3ff) ---> 0-0ff
or cx,1
mov al,0ff
mov di,3200
rep stosb
mov al,0
mov cx,320
rep stosb
cs mov cx,w[082]
cmp cx,01a0 ; upper bound
ja ret
cmp cx,0191 ; lower bound
jb ret
sub cx,0190 ; draw magnified line
mov ax,0ffff
mov di,6480
rep stosw
mov al,0
mov cx,128
rep stosb
ret
With everything working as it should
I started creating the PCB
Original artwork with very thin tracks Sorry ROGER
|
 |
| Final artwork |
 |
| Actual PCB |
 |
Populated PCB with connections.
|
 |
After the wires have been pushed into the sockets on the PCB
the whole circuit will be potted with just the colour coded wires
poking out of the box
Allowing easy connections to any rover v8 cooling system
Now that the Landrover no-longer overheats Everyone is HAPPY and my kids think it is COOL
If you have any questions or comments please email me me
It would be nice to hear from you
gm236@ex.ac.uk