4r70w ford transmission controller. 20x2

ol boy

Member
I built for my capstone project before graduating ITT Tech a late model transmission controller. I'm a Ford guy and own several Ford Falcons. My daily driver is a1964 Falcon stationwagon. Controlling a 4r70w transmission is quite simple. 2 shift solenoids provide the 4 forward gear selection. A torque converter lock up solenoid allows control over when the converter is locked. And last is an EPC solenoid to control hydraulic line pressure.

In puts are TPS and vehicle speed. Throttle position is pulled from the megasquirt ecu which provides fuel and spark management. Vehicle speed is measured by rectifying the ac wave form coming out of the electronic speedo sensor mounted on the tail housing of the transmission. As speed increases so does the amplitude of the ac wave form. I installed a 10k pot and some caps to give a clean DC voltage and allow for a way to mechanically adjust the out put voltage. I was shooting for 2.5 volts at 70 mph and 5 volts at 140mph.

Please check out the link below to see pictures and a 3 minute video.

http://ryandenney.carbonmade.com
 

ol boy

Member
Here is the code. Fairly small at 961 bytes of flash and only 23 bytes or RAM. I might not have placed enough comments for a beginner to see whats being done and why. But for everyone else I hope the code is easy to follow. This is a major change from my first code version. This is much smaller and easier to make small changes to. Some of my labels might be confusing as the input and output pin names are being referred to my PCB and the names assigned there.

Code:
'4R70W alpha2.1  PIXACE 20x2   6 July, 2013 (961 bytes)
setfreq m8					'set ferq to 8MHz
let dirsc = %00000000			'set portC as inputs 
let dirsb = %11111111               'set portB as outputs, 
let adcsetup = %0000001100001000	'set ADC ports 3,8,9,  c.1,c.2,c.7
hpwm pwmdiv4, 0, 0, %1000, 99, 300		'b.4 hpwm out D 5000hz 75% duty  RU line pressure (8Mhz)

symbol EPC = w0	 		'b0, b1
symbol tpsadc = w1		'b2' b3, adc 9  pinc.1  AirCom input 130 to 880 count
symbol tps10 = w2			'b4, b5
symbol tccd = b6		
symbol oiltemp = b7	 		'
symbol tps = b8
symbol tpsold = b9		'returns 0 to 100% throttle value
symbol tpsbit = b10
symbol tpsdelta = b11 
symbol mph =  b12			'8bit value 0 to 255
symbol mphold = b13
symbol mphdelta = b14
symbol mphbit = b15
symbol gear = b16   
symbol ngear = b17
symbol outspeed =  b18		'adc 8  pinc.2  Front input
symbol mph10 =  b19
symbol counter = 	b20
symbol counter2 =  b21
symbol counter3 = b22

symbol ss1 = b.1			'output  AC
symbol ss2 = b.2			'output  FU
symbol tcc = b.3			'output  FD
'EPC out on B.4			'output  RU
let ngear = 2
let counter = 85	

main:
do
gosub readsen				'read sensor inputs and convert digital value to human values
gosub stuff					'lookup tables.  TPS to MPH and RPM
gosub setoutputs				'set PWM duty, gear selection and TCC lockup
loop

readsen:
	readadc 8, outspeed	'c.2FT'read speed input into 8 bit value
	readadc10 9, tpsadc	'c.1AT'read tps 10 bit. 130 to 880/...
	readadc 3, oiltemp	'c.7MAN'measure trans oil temp
	

	
	if tpsadc <= 125 then 		'sets a low and high limit for the tpsadc input
	tps = 0				'to 0 and 100%, if the input is within the range
	elseif tpsadc >=880 then 	'then solve tps%
	tps = 100
	else
	tps10 = tpsadc *10 		'125 0% 880 100%  10bit ADC count
	tps10 = tps10 - 1250
	tps = tps10 / 76			'converts to % tps into whole number change to match delta
	endif
	
	mph = outspeed * 5 / 9		' 2.5 volts = 70 mph, 5 volts = 140 mph, 1.25 volts = 35
						'2200 rpm,            4400 rpm,          1100 rpm
	counter2 = counter2 + 1
	if counter2 >= 41 then
	counter2 = 0
	endif
	
	if counter2 =  20 or counter2 = 40 then
	if tps >= tpsold   then		'check if new tps value is equal to or greater then the last stored 
	tpsdelta = tps - tpsold		'value.  If the throttle has been reduced we can set a bit in tpsbit
	clearbit tpsbit, 0	
	else	
	tpsdelta = tpsold - tps	
	if tpsdelta >= 2 then		'change this value to make the up shift more sensitive to throttle lift 
	setbit tpsbit, 0
	else
	clearbit tpsbit, 0
	endif
	endif
	tpsold = tps
	endif
	
	if counter2 = 40 then
	if mph >= mphold then		'check if new mph value is equal to or greater then the last stored 
	mphdelta = mph - mphold		'value.  If the speed has reduced we can set a bit in mphbit
	setbit mphbit, 0	
	else
	clearbit mphbit, 0
	mphdelta = 0
	endif
	mphold = mph
	endif	
   return
     	
stuff: 
select tps	' TPS in % 	
   case 0  
   
select mph
	case 0 to 6 
	EPC = 200
	ngear = 1
	case 7 to 18
	ngear =  2
	case 19 to 29	
	ngear = 3
	case > 30	
	ngear = 4
	endselect
	
   case 1 to 20  	   
	if gear = 1 and mph > 6 and mphdelta <= 5 then	  
	ngear = 2   
 	EPC = 200
 	elseif gear = 1 and mph > 12 then
 	ngear = 2
 	EPC = 200
	elseif gear = 2 and mphdelta <= 4 and mph > 22 then	
	ngear = 3
	counter3 = 0	
	EPC = 200
	elseif gear = 2 and mph > 36 then	
	ngear = 3	
	counter3 = 0
	EPC = 200	
	elseif gear = 3 and tpsbit = 1 and mph > 32 and counter > 30 then			
	ngear = 4 
	counter3 = 0   	
  	EPC = 200
  	elseif gear = 3 and  mph > 40 then			
	ngear = 4   
	counter3 = 0 	
  	EPC = 200
	endif	   	 
	
  case 21 to 35			'tps between 21 and 35% shift gears at these speed ranges
select mph
	case 0 to 15	
	ngear = 1
	case 16 to 28	
	ngear = 2
	case 29 to 55
	ngear = 3
	case 56 to 255
	ngear = 4
	endselect
	
	 case 36 to 55
select mph
	case 0 to 21	
	ngear = 1
	case 22 to 40	
	ngear = 2
	case 41 to 65
	ngear = 3
	case 66 to 255
	ngear = 4
	endselect	
	 
   case 56 to 74
select mph
	case 0 to 30	
	ngear = 1
	case 31 to 55	
	ngear = 2
	case 56 to 90
	ngear = 3
	case 91 to 255
	ngear = 4
	endselect	

   case 75 to 100
select mph
	case 0 to 40	
	ngear = 1
	case 41 to 70	
	ngear = 2
	case 71 to 110
	ngear = 3
	case 111 to 255
	ngear = 4
	endselect	
endselect
   return

setoutputs: 
	if counter > 250 then	'when count is higher than 250 load counter to 252, 12.5 second delay posible
	counter = 252
	else
	counter = counter + 1	'50ms loop time.  
	endif				'increment counter for time delay for tcc after shift.

	if gear >= 2 and EPC > 10 then
	EPC = EPC - 2 
	else 
	EPC = 200
	endif  
		
 	if EPC <= 12 then
 	EPC = 0
  	endif  	  	 	
	    
      if ngear <> gear and counter > 50 then	'check current gear selected and last gear commanded
								'time delay between shift before shifting again.
	if ngear = 1 then
	high ss1
	low ss2
	gear = ngear

	elseif ngear = 2 then
	low ss1
	low ss2
	gear = ngear	
	
	elseif ngear = 3 then
	low ss1 
	high ss2
	gear = ngear	
	
	elseif ngear >= 4 then
	high ss1
	high ss2
	gear = ngear
		
 	endif
 	counter = 0'once a shift is made reset counter to zero. 
 	endif 
 	 	
  	hpwmduty EPC '5000hz for fluid pressure regulation  350=82% low line pressure, 
 	 	
 	if gear = 4 and counter > 40 then 	'when gear 4 is selected increment counter
	if counter = 42 or counter = 44 or counter = 47 or counter = 50 or counter = 54 or counter = 58 then 
	low tcc
	else	
	high tcc 
	endif	
										'turn on TCC
     	elseif gear = 3 and counter > 50 and mph > 26 and tps <= 17 then
     	counter3 = counter3 + 1
     	if counter3 = 2 or counter3 = 4 or counter3 = 7 or counter3 = 10 or counter3 = 13 or counter3 = 15 then 
	low tcc
	else	
	high tcc 
	endif		
     	 
     	elseif gear = 2 and counter > 60 and mph > 11 and tps <= 20 then
     	high tcc 
     	else
     	low tcc
     	endif   
     	
     	if counter3 >= 20 then 
     	counter3 = 22
     	endif 	
     	     	     	
    return
As for the schematic
schemetics.png

Thanks Ryan
 

ol boy

Member
Shortened up the code a bunch today. Changed the logic to command an up shift to a slope formula. Each gear has its own slope and y intercept. A second set of slopes with a smaller y intercept provides down shift points and hysteresis. Checking current tps value to the slope result and then making decision if one is higher than the other. I'll post the code in a few days. Total size now is 548 bytes and 13 bytes of ram.
 

ol boy

Member
Code update.

I finally checked my messages and send out some replies. Here is the latest code revision I'm running.

Code:
'4R70W beta3.5.2bttps  PIXACE 20x2   16 June, 2014 ((923 bytes flash), 32 bytes of RAM, 4 bytes PROM)
eeprom 0, (1,255,2,1)  '511,513  
setfreq m8					'set ferq to 8MHz
let dirsc = %00000000			'set portC as inputs 
let dirsb = %11111110               'set portB as outputs, 
let adcsetup = %0000001000000000	'set ADC ports 9,  c.1
hintsetup %00000010	'falling egde trigger on B.0 input
setintflags or %10000010, %10000010  'hardware interrupt INT1, Timer over flow flag 
hsersetup b115200_8, %00001		'enable serial io for bluetooth coms background receive %00001

'**** RAM Locations********************
symbol upshift = w0	 	'b0, b1
symbol downshift = w1		'b2' b3
symbol tpsadc = w2		'b4, b5 adc 9  pinc.1  AirCom input 130 to 880 count
symbol tps10 = w3			'b6, b7	 		
symbol tps = b8			'returns 0 to 100% throttle value 
symbol mph =  b9			'8bit value 0 to 255
symbol gear = b10   
symbol ngear = b11
symbol outspeed =  b12		'adc 8  pinc.2  Front input
symbol counter = 	b13
symbol tccounter =  b14
symbol tccounter1 = b15
symbol tccon = w8			'b16, b17
symbol tccoff = w9		'b18, b19
symbol tccbit = b20		'w10
symbol countershift = b21	'w10
symbol bluetooth = b22		'w11
symbol manualmode = b23		'w11
symbol tpsmin = w12		'b24 b25
symbol tpsmax = w13		'b26 b27
symbol tpsd = w14			'b28 b29

symbol ss1 = b.1			'output  AC
symbol ss2 = b.2			'output  FU
symbol tcc = b.3			'output  FD

let gear = 2
let ngear = 1
let counter = 52
let timer = 65535
settimer 54535 ;49910			'0.352 counter	'0.5 second counter



'**********  Load EEPROM Data into Ram*****
read 0,b25				'tpsmin
read 1,b24
read 2,b27				'tpsmax
read 3,b26
tpsd = tpsmax - tpsmin / 10

'********** FLASH ********************
main:
do
gosub readsen				'read sensor inputs and convert digital value to human values
gosub stuff					'lookup tables.  TPS to MPH and RPM
gosub setoutputs				'set PWM duty, gear selection and TCC lockup serial data
loop 
  
readsen:
	'readadc 8, outspeed	'c.2FT'read speed input into 8 bit value
	readadc10 9, tpsadc	'c.1AT'read tps 10 bit. 130 to 880/...
		
	if tpsadc <= tpsmin then 		'sets a low and high limit for the tpsadc input
	tps = 0				'to 0 and 100%, if the input is within the range
	elseif tpsadc >=tpsmax then 	'then solve tps%
	tps = 100
	else
	tps10 = tpsadc - tpsmin *10 		'125 0% 880 100%  10bit ADC count
	tps = tps10/tpsd			'converts to % tps into whole number change to match delta
	endif
return


stuff: 
'Find slope for each function up shift, down shift and TCC lock up*******  
  ' y=mx+b  100/(max - min) * min, y=TPS and x=MPH   
'Check TPS valve against predicted max value******* 

if manualmode = 1 then
 goto bypass
 else
   'gear
  'case 1
  if gear = 1 then  
   upshift = mph * 100/33  - 21         	'1 to 2 (up shift)  
   downshift = 110
            
  'case 2  
  elseif gear = 2 then   
   upshift = mph * 100/61  - 30		'2 to 3 (up shift)
   downshift = mph * 100/29  - 17  		'2 to 1 threshold (down shift)
        
  'case 3 
  elseif gear = 3 then    
   upshift = mph * 100/85 - 35	 	 	'3 to 4 (up shift) 
   downshift =  mph * 100/49  - 33   	'3 to 2 (down shift)
           
  'case 4
  elseif gear = 4 then   
   upshift = 0
   downshift = mph *100/80 - 33    		'4 to 3 (down shift)  
  endif  
  
  if upshift >= 1000 then			'stops math over flow error
  upshift = 0  
  endif
   
  if downshift > 1000 then  			'stops math over flow error
  downshift = 0
  endif 
  
  if tps < upshift or tps >= downshift then	'make sure conditions are meet long enough to a shift
   inc counter   						'up or down to occure
   else 
   counter = 0   						'set to 0 if staying in current gear.
   endif
   
  	if counter > 10 then	'when count is higher than 10 load counter to 252, 12.5 second delay posible
	if tps < upshift then	'figure out which shift is true, up or down.
	ngear = gear +1 max 4
      elseif  tps >= downshift then 
	ngear = gear -1 min 1	 
	endif	 
   counter = 0
   
  endif   
   
bypass:   						'in manual mode we skip past slope and figure out TCC
  
  if gear = 1 then
  tccon = 0						'no lock up function in first gear.
  elseif gear = 2 then
  tccon = mph * 100/33 - 33	  		'2nd gear TCC Lock up
  elseif gear = 3 then
  tccon = mph * 100/61 - 34			'3rd gear TCC Lock up
  elseif gear = 4 then
  tccon = mph * 100/84 - 35			 '4th gear TCC Lock up  
  endif 
    
  if tccon > 1000 then 				'stops math over flow error
  tccon = 0 
  endif        
   endif 	 
return 

setoutputs:
	
'select new gear when a change in needed******
if ngear <> gear then       	'check current gear selected and last gear commanded
										
	if ngear = 1 then 		'new gear set outputs
	high ss1 
	low ss2	 	
	
	elseif ngear = 2 then		'new gear set outputs
	low ss1 
	low ss2	 	  
	
	elseif ngear = 3 then		'new gear set outputs
	low ss1 
	high ss2	 	 
  
	elseif ngear >= 4 then  	'new gear set outputs
	high ss1
	high ss2
	endif  	 
	
 gear = ngear				'match current gear to new gear 
 countershift = 0	  			
 tccounter = 0 				'reduces transmission wear.

 tccbit = 0
 endif	 	
 	
'tourque converter lock up function*******
if countershift > 50 then	'when count is higher than  50 load counter to  52, 12.5 second delay posible
	countershift = 52
	endif 

if tccon = 0 then     				'math over flow problem
tccoff = 0 
else 
tccoff = tccon + 4	 	 		'Sets the hystersis for TCC off
endif	 
	
	if tps < tccon and mph > 10 then	'create time for the conditions to be true
	inc countershift
	else
	countershift = 0
	endif
	
	if countershift > 40 then		'fixes the on/off enguagement of TCC function
	tccbit = 1
	elseif tps >= tccoff then
	tccbit = 0
	elseif tccoff = 0 or tccon = 0 then
	tccbit = 0
	endif
	
  	 if tccounter = 7 and tccbit = 1  then 
   	 high tcc    
    
  	 elseif tccbit = 1 and gear <> 1 then  	'counter >= 20 and 
  	   	if tccounter1 <> 4 then			'not equal to 4 then high tcc
  		inc tccounter1  				'80% duty cycle 6 times
   		high tcc  	
  		else
  		tccounter1 = 0
  		inc tccounter   
  		low tcc
  		endif  
    	 else 
  	 low tcc  	
  	 tccounter = 0 
  	 tccounter1 = 0   
  	 endif  
  	 
  	 	   	 
'***** Coms handler***********    
if hserflag = 1 then
   get 0, bluetooth 
	if bluetooth = 65 then	'ascii A 
	hserout 0, (#b8, #b9, #b10, #b20)
	'hserout 0, (71,101,97,114,32,#b10,32,84,80,83,32,#b8,37,32,77,80,72,32,#b9,32) 
	 			'Gear (#b10)  TPS (#b8)%  MPH (#b9) send to bluetooth
	 			
	elseif bluetooth = 81 then			'ascii Q request Signature
	'hserout 0, (82,121,97,110,39,115,32,84,114,97,110,115,32,67,111,110,116,114,111,108,108,101,114,32)
		'Ryan's Trans Controller
	hserout 0, (84,67,51,46,53,46,50)         'TC3.5.2	
		
	
	elseif bluetooth = 83 then			'ascii,S Revision 4R70Wbeta3.5.2bt 
	hserout 0, (52,82,55,48,87,98,101,116,97,51,46,53,46,50,98,116,32)
	
	
	elseif bluetooth = 84 then			'ascii T, tpscal mode
	hserout 0, (84,80,83,32,77,111,100,101,32)
	goto tpscal
									
	elseif bluetooth = 77 then			'ascii,M manual mode	
	manualmode = 1	
	hserout 0, (77,97,110,32,77,111,100,101,32)	'Man Mode 
	
	elseif bluetooth = 80 then			'ascii P quit
	manualmode = 0
	countershift = 52
	counter = 11
	hserout 0, (65,117,116,111,32,77,111,100,101,32)	'Auto Mode
	endif
      
	
	if manualmode = 1 then
	  if bluetooth = 85 then			'ascii U up
	  ngear =  gear + 1  max 4
	  hserout 0, (71,101,97,114,32,#b11,32) 	'display new gear
	  	  
	  elseif bluetooth = 68 then			'ascii D down
	  ngear =  gear - 1 min 1
	  hserout 0, (71,101,97,114,32,#b11,32)	'display new gear
	  endif
      
      endif
      
let hserflag = 0
let hserptr = 0
endif
return 

TPScal: 
tpsmax = 513			'default start values
tpsmin = 511

do
setintflags off
if hserflag = 1 then		'if serial data has been recieved then process it.
get 0, bluetooth
  if bluetooth = 80 then	'ascii P, quit  
  write 0, b25			'word tpsmin
  write 1, b24 
  write 2, b27			'word tpsmax
  write 3, b26
  manualmode = 0
  goto main
  else
  let hserflag = 0			'clear hardware serial flag
  let hserptr = 0				'reset scratch pad pointer back to zero address
  endif
endif

readadc10 9,tpsadc			'read tps adc 10 bit value
tpsd = tpsmax - tpsmin / 10		'find delta from min and max divide by 10

if tpsadc >= tpsmax then
tpsmax = tpsadc
elseif tpsadc <= tpsmin then
tpsmin = tpsadc
endif
	if tpsadc <= tpsmin then 	'sets a low and high limit for the tpsadc input
	tps = 0				'to 0 and 100%, if the input is within the range
	elseif tpsadc >=tpsmax then 	'then solve tps%
	tps = 100
	else
	tps10 = tpsadc - tpsmin *10 		
	tps = tps10/tpsd			'converts to % tps into whole number change to match delta
	endif
	
hserout 0, (32,#tps)			'report new tps value
pause 1000					'half second pause
loop    

interrupt:
if toflag = 1 then			'check if interrupt was caused by toflag.
  	settimer off			'turn off timer
  	mph = w15				'load w15 to MPH
  	let w15 = 0				'clear w15 value to zero
  	let toflag = 0   			'clear over flow flag
  	
elseif w15 = 0 then			'on first hardware input w15 will still be zero
	inc w15				'increment w15
	let hint1flag = 0	 		'clear hardware flag
	let timer = 65535			'preloads timer to overflow and set toflag when minor ticks finish counting
  	settimer 54535			'enable timer 0.352 seconds
else
	inc w15				'increment w15 
	let hint1flag = 0	 		'clear hardware flag
endif

 setintflags or %10000010, %10000010  'hardware interrupt INT1, Timer over flow flag	
  return
 

ol boy

Member
All right. I guess the max is 10000 character, I was 1700 over. Here is the rest of the reply.

I've since added support for Bluetooth for sending and receiving commands from my smart phone. There are several bluetooth/serial apps on the Google play store that allow you to configure a couple of buttons to send either an ASCII char or Hex value. This allows the calibration of the TPS to work on any setup as the min and max adc values were hard coded into flash. As of this revision one can calibrate the TPS, manual shift through the gears, and request the current TPS, Gear, MPH, and TCC conditons. I'd like to develop a simple android app to handle a few gauges and display the received data when asked for.

I commented as much as I could. Some stuff like the TCC function to output a really slow PWM to soften the TCC engagement needs a better explanation of how it works. I was surprised when I final got it sorted out but forgot to list what and how it works. This interrupt routine will work anywhere you have a count command. The only problem with the software count command is the processor just sits there and counts input pulses until the sample time expires. Since I have functions like the TCC lock up and other delays that are reliant on the main loop time I needed a way to keep the program running while counting input pulses at the same time.

Total size of just the trans controller was in the low 500 byte range before adding in all the bluetooth stuff.

*The only bug I have not worked out is right after start up I'll notice the controller switching back and forth between first and second gear until I drive off and the interrupt routine begins to operate. After that it operates normally without any issues. *

Hope this code is useful for the group. I think it uses just about every hardware function the 20x2 has. I'd like to get the HPWM working again to control the EPC valve.

Later Ryan
 

Dziku

New member
Hi, sorry for dig up this dinosaur, but coul you tell me, that is the latest working code? Could you also upload video of your falcon running with this controller? I've seen it somwhere but it wanished...
Thanks in advance
 
Top