Notices
ECU Flash

how-to: control closed loop AFR with your wideband O2 system

Old Sep 20, 2008, 03:47 PM
  #1  
EvoM Guru
Thread Starter
iTrader: (50)
 
mrfred's Avatar
 
Join Date: Mar 2006
Location: Tri-Cities, WA // Portland, OR
Posts: 9,675
Received 128 Likes on 96 Posts
how-to: control closed loop AFR with your wideband O2 system

Update Sept 27, 2008: Added AFR16 scaling for people using older xml files.

Update Sept 25, 2008: I've uploaded a slightly revised base ROM. If you downloaded the "88590015_front-rear_O2_patched_v10t.zip" before 9/26/2008, please download the revised one (same file name), and recopy the values to your ROM. There is only one change to the revised ROM, so it will look the same except for one line.
-----
-----

how-to: Closed loop cruise AFR control for the 88590015 ROM

This is a revision to the original patch in this thread.

Both Innovate and Zeitronix provide simulated narrowband analog outputs that can be used in place of the front O2 sensor signal to make the car run at a single user adjustable AFR (usually leaner than 14.7:1 for better fuel economy) during closed loop cruise. This makes the ECU change the closed loop AFR value by causing the ECU to adjust the fuel trims to hit the target AFR programmed into the wideband controller. This is an "ok" method for controlling closed loop AFR, but it has two problems. First is that the car is limited to run a single AFR during closed loop cruise. For Evos with aftermarket cams or an aftermarket intake, a lean closed loop AFR may cause rough/unpredictable idle. It may also affect tip-in response from idle. Second is that for best control of AFR during closed loop cruise, the base fuel pulse needs to be set for the target AFR. The base fuel pulse is determined by the fuel map, but as we all know, in closed loop, the Evo ECU does not follow the fuel map. The base pulse is automatically for a 14.7:1 AFR.

My closed loop cruise patch addresses all these issues and provides several other handy features. With this patch, the following things can be done:

1) During closed loop cruise, the ECU will set the base fuel pulse from the fuel map.
2) I have written an algorithm to convert the wideband O2 signal into a narrowband O2 signal with a crossover point that is determined from the target AFR from the fuel map. This works in conjunction with feature #1 to provide optimum closed loop adjustable AFR performance. The result is that the ECU will precisely follow the fuel map during closed loop cruise. Rich values can be used in the idle cells to help stablize idle with big cams or aftermarket intakes, and lean values can be used in the cruise cells for optimum fuel economy.
3) To aid is cold engine performance, I have created a "cold engine" AFR setting. The cold engine AFR and coolant temperature value where the ECU switches from the cold engine AFR to following the fuel map are both adjustable.
4) The closed loop cruise patch can be enabled and disabled with ECUFlash (provided that the front O2 sensor signal remains plumbed into the ECU).
5) If you prefer to use the the front O2 ADC input for something else, I have created a unique RAM address and MUT port to read whatever is attached to the front O2 sensor ADC input.
6) This patch by necessity includes my rear O2 sim algorithm.

NOTE: At this time, I only have a patch for the 88590015 ROM. It will work for both the standard 88590015 ROM and the tephra v5.10 88590015 ROM. I'll port the patch to other ROMs as I have time.

Instructions for applying the patch:

NOTE: if you had installed the older patch from this thread, the new patch will disable and/or overwrite the old patch.

1) It is necessary to wire an analog output from a WBO2 controller into rear O2 ADC input the ECU. Instructions are here.

Skip the "ROM Modifications" part of that how-to, but do everything else. In the last part of that how-to, there are instructions for calculating the WBO2 scaling formula for EvoScan. The values from that formula will need to be used for the closed loop WBO2 patch. The example formula for EvoScan in that how-to is:

0.03137*x + 9.06

In that example, mL = 0.03137, and bL = 9.06. For this patch, you'll need 1/mL and bL/mL. For this example,

1/mL = 1/0.03137 = 31.9

bL/mL = 9.06/0.03137 = 289

2a) If you were running the original version of this patch, delete the old tables from your ECUFlash 88590015.xml file.

2b) Copy the following tables to your ECUFlash "88590015.xml" file:

------ (Don't copy the "-------")

<table name="Closed Loop Wideband On/Off" category="Front/Rear_02" address="8734" type="1D" level="1" scaling="uint8"/>
<scaling name="AFR16" units="AFR" toexpr="14.7*128/x" frexpr="14.7*128/x" format="%.1f" min="8" max="20" inc="0.1" storagetype="uint16" endian="big"/>
<table name="Cold Engine Closed Loop AFR" category="Front/Rear_02" address="8736" type="1D" level="1" scaling="AFR16"/>

<table name="Min Coolant Temp To Use AFR Table" category="Front/Rear_02" address="8738" type="1D" level="1" scaling="Temp"/>

<scaling name="mLinverse" units="1/mL" toexpr="x/8" frexpr="x*8" format="%.1f" min="0" max="100" inc="0.1" storagetype="uint16" endian="big"/>
<table name="Wideband AFR Correlation 1/mL Value" category="Front/Rear_02" address="873A" type="1D" level="1" scaling="mLinverse"/>

<table name="Wideband AFR Correlation bL/mL Value" category="Front/Rear_02" address="873C" type="1D" level="1" scaling="uint16"/>

<table name="AFR Table Multiplier High Word" category="Front/Rear_02" address="8740" type="1D" level="1" scaling="Hex16"/>
<table name="AFR Table Multiplier Low Word" category="Front/Rear_02" address="8742" type="1D" level="1" scaling="Hex16"/>

<table name="Front O2 (ADC 04) RAM variable" category="Front/Rear_02" address="c2ba" type="1D" level="1" scaling="Hex16"/>

<table name="Rear O2 (ADC 0A) RAM variable" category="Front/Rear_02" address="c2be" type="1D" level="1" scaling="Hex16"/>

<table name="MUT12 Value (To Read Wideband)" category="Front/Rear_02" address="3eece" type="1D" level="1" scaling="Hex16"/>

<table name="MUT19 Value (To Read Front O2 ADC)" category="Front/Rear_02" address="3eeea" type="1D" level="1" scaling="Hex16"/>


<table name="ADC Value Mod Hook" category="Front/Rear_02" address="c250" type="3D" level="1" scaling="Hex16">
<table name="Code" type="Static X Axis" elements="1" scaling="Hex16">
<data>Hex16</data>
</table>
<table name="Address" type="Static Y Axis" elements="10">
<data>C250</data>
<data>C252</data>
<data>C254</data>
<data>C256</data>
<data>C258</data>
<data>C25A</data>
<data>C25C</data>
<data>C25E</data>
<data>C260</data>
<data>C262</data>
</table>
</table>

<table name="Hook For Closed Loop Pulse Control Hex" category="Front/Rear_02" address="182e4" type="3D" level="1" scaling="Hex16">
<table name="Code" type="Static X Axis" elements="1">
<data>Hex16</data>
</table>
<table name="Address" type="Static Y Axis" elements="8">
<data>182E4</data>
<data>182E6</data>
<data>182E8</data>
<data>182EA</data>
<data>182EC</data>
<data>182EE</data>
<data>182F0</data>
<data>182F2</data>
</table>
</table>

<table name="Front/Rear 02 Sim Subroutine Part 1" category="Front/Rear_02" address="47f00" type="3D" level="1" scaling="Hex16">
<table name="Code" type="Static X Axis" elements="1" scaling="Hex16">
<data>Hex16</data>
</table>
<table name="Address" type="Static Y Axis" elements="40">
<data>47F00</data>
<data>47F02</data>
<data>47F04</data>
<data>47F06</data>
<data>47F08</data>
<data>47F0A</data>
<data>47F0C</data>
<data>47F0E</data>
<data>47F10</data>
<data>47F12</data>
<data>47F14</data>
<data>47F16</data>
<data>47F18</data>
<data>47F1A</data>
<data>47F1C</data>
<data>47F1E</data>
<data>47F20</data>
<data>47F22</data>
<data>47F24</data>
<data>47F26</data>
<data>47F28</data>
<data>47F2A</data>
<data>47F2C</data>
<data>47F2E</data>
<data>47F30</data>
<data>47F32</data>
<data>47F34</data>
<data>47F36</data>
<data>47F38</data>
<data>47F3A</data>
<data>47F3C</data>
<data>47F3E</data>
<data>47F40</data>
<data>47F42</data>
<data>47F44</data>
<data>47F46</data>
<data>47F48</data>
<data>47F4A</data>
<data>47F4C</data>
<data>47F4E</data>
</table>
</table>

<table name="Front/Rear 02 Sim Subroutine Part 2" category="Front/Rear_02" address="47f50" type="3D" level="1" scaling="Hex16">
<table name="Code" type="Static X Axis" elements="1">
<data>Hex16</data>
</table>
<table name="Address" type="Static Y Axis" elements="40">
<data>47F50</data>
<data>47F52</data>
<data>47F54</data>
<data>47F56</data>
<data>47F58</data>
<data>47F5A</data>
<data>47F5C</data>
<data>47F5E</data>
<data>47F60</data>
<data>47F62</data>
<data>47F64</data>
<data>47F66</data>
<data>47F68</data>
<data>47F6A</data>
<data>47F6C</data>
<data>47F6E</data>
<data>47F70</data>
<data>47F72</data>
<data>47F74</data>
<data>47F76</data>
<data>47F78</data>
<data>47F7A</data>
<data>47F7C</data>
<data>47F7E</data>
<data>47F80</data>
<data>47F82</data>
<data>47F84</data>
<data>47F86</data>
<data>47F88</data>
<data>47F8A</data>
<data>47F8C</data>
<data>47F8E</data>
<data>47F90</data>
<data>47F92</data>
<data>47F94</data>
<data>47F96</data>
<data>47F98</data>
<data>47F9A</data>
<data>47F9C</data>
<data>47F9E</data>
</table>
</table>

<table name="Front/Rear 02 Sim Subroutine Part 3" category="Front/Rear_02" address="47fa0" type="3D" level="1" scaling="Hex16">
<table name="Code" type="Static X Axis" elements="1">
<data>Hex16</data>
</table>
<table name="Address" type="Static Y Axis" elements="18">
<data>47FA0</data>
<data>47FA2</data>
<data>47FA4</data>
<data>47FA6</data>
<data>47FA8</data>
<data>47FAA</data>
<data>47FAC</data>
<data>47FAE</data>
<data>47FB0</data>
<data>47FB2</data>
<data>47FB4</data>
<data>47FB6</data>
<data>47FB8</data>
<data>47FBA</data>
<data>47FBC</data>
<data>47FBE</data>
<data>47FC0</data>
<data>47FC2</data>
</table>
</table>

<table name="Closed Loop Fuel Pulse Control Subroutine" category="Front/Rear_02" address="47fc4" type="3D" level="1" scaling="Hex16">
<table name="Code" type="Static X Axis" elements="1">
<data>Hex16</data>
</table>
<table name="Address" type="Static Y Axis" elements="16">
<data>47FC4</data>
<data>47FC6</data>
<data>47FC8</data>
<data>47FCA</data>
<data>47FCC</data>
<data>47FCE</data>
<data>47FD0</data>
<data>47FD2</data>
<data>47FD4</data>
<data>47FD6</data>
<data>47FD8</data>
<data>47FDA</data>
<data>47FDC</data>
<data>47FDE</data>
<data>47FE0</data>
<data>47FE2</data>
</table>
</table>


--------

3) Download the following ROM: 88590015_front-rear_O2_patched_v10t.zip

http://se30.dyndns.org:8080/evo/8859...tched_v10t.zip

4) Open the ROM in ECUFlash. Find the newly added entries in this patched ROM, and copy the values over to your ROM.

5) If your 1/mL and bL/mL values are different than the ones listed above, then insert your values into the corresponding tables.

6) Set your fuel table to whatever values you want for closed loop cruise. Also, feel free to try different values for "Cold Engine Closed Loop AFR" and "Min Coolant Temp To Use AFR Table". However, do not mess with the "AFR Table Multiplier" values.

7) Upload the ROM to your ECU, and that's it.

8) MUT12 will now read the wideband O2 analog signal value. EvoScan will read the wideband O2 signal if you followed the "Setting Up EvoScan" steps in the "how-to: Log AFR from the LC-1 w/o a serial cable" thread.

9) MUT19 will now read whatever analog signal is wired into the front O2 ADC input.

Last edited by mrfred; Sep 27, 2008 at 08:18 AM.
Old Sep 20, 2008, 04:19 PM
  #2  
EvoM Guru
Thread Starter
iTrader: (50)
 
mrfred's Avatar
 
Join Date: Mar 2006
Location: Tri-Cities, WA // Portland, OR
Posts: 9,675
Received 128 Likes on 96 Posts
Source code for the patch is in the attached Excel file.
Attached Files
Old Sep 20, 2008, 06:56 PM
  #3  
Evolved Member
iTrader: (17)
 
Jack_of_Trades's Avatar
 
Join Date: Jun 2007
Location: Opelika,AL
Posts: 3,523
Likes: 0
Received 2 Likes on 1 Post
Nice man. So what happens if you set the open loop load value to say...400, would the ECU do full closed loop tuning or is it not setup for such fast corrections for WOT operation? Definitely a step in the right direction

It'd be cool if you could use it to target a certain AFR and once its close you could 'save' the high load areas and run them in openloop. Basically what AEM's EMS 'autotune' feature is.
Old Sep 20, 2008, 07:48 PM
  #4  
EvoM Guru
Thread Starter
iTrader: (50)
 
mrfred's Avatar
 
Join Date: Mar 2006
Location: Tri-Cities, WA // Portland, OR
Posts: 9,675
Received 128 Likes on 96 Posts
Originally Posted by Jack_of_Trades
Nice man. So what happens if you set the open loop load value to say...400, would the ECU do full closed loop tuning or is it not setup for such fast corrections for WOT operation? Definitely a step in the right direction

It'd be cool if you could use it to target a certain AFR and once its close you could 'save' the high load areas and run them in openloop. Basically what AEM's EMS 'autotune' feature is.
I'm still utilizing the stock trim adjustment system which isn't fast enough for high loads. O2 sensor placement is important as well for speed. The WBO2 sensor would have to pretty much be in the same location as the stock front O2 sensor.

The open loop load could probably be raised to 160-180 though.

The autotune feature is a processor-intensive algorithm, and it requires access to the NVRAM. I think its more than the SH7052/SH7055 processor can handle.
Old Sep 21, 2008, 07:20 AM
  #5  
Evolved Member
iTrader: (15)
 
evo8dad's Avatar
 
Join Date: Apr 2003
Location: Sellersville, PA
Posts: 955
Likes: 0
Received 1 Like on 1 Post
Nice work Mr. Fred. I can't wait for this to be implemented into additional ROMS (94170015 - mine) so I can get some of my customers away from the gas pumps a little longer :-).
Old Sep 22, 2008, 06:30 AM
  #6  
Evolved Member
iTrader: (17)
 
dudical26's Avatar
 
Join Date: Nov 2005
Location: NNJ
Posts: 2,544
Likes: 0
Received 0 Likes on 0 Posts
have you had any experience setting the cold engine AFR? What have you set it to and has it helped the driveability on a cold motor?

Nice work by the way, and thanks for the MUT call for the now available ADC input
Old Sep 22, 2008, 06:56 AM
  #7  
EvoM Guru
Thread Starter
iTrader: (50)
 
mrfred's Avatar
 
Join Date: Mar 2006
Location: Tri-Cities, WA // Portland, OR
Posts: 9,675
Received 128 Likes on 96 Posts
When I had the stock cold engine ignition retard enabled, the cold engine AFR definitely helped. I usually set it to 14.7:1. Now that we can disable the cold engine ignition retard, the cold engine AFR setting might not be as important.
Old Sep 22, 2008, 08:06 AM
  #8  
Evolved Member
iTrader: (26)
 
travman's Avatar
 
Join Date: Oct 2005
Location: Pittsburgh
Posts: 1,712
Likes: 0
Received 0 Likes on 0 Posts
I just got my new zeitronix wideband installed this weekend - it replaced my LC-1 which I was tired of dealing with. The LC-1 was fine for logging/tuning but using it to control the car was a joke....it reset itself at random and everyday I had to carry my laptop just in case the day would be the day. So I finally had enough after one day it made me really late for work and stuck along the side of the road.

ok now that the back story is complete - on to the question at hand....

Do I use this same formula for the zeitronix? or is it something different? Looking for help from the ZT2 guys so I get the correct values...

(17.0-9.0)/255*x + 9.0 = 0.03137*x + 9.0

They range for the ZT2 is I believe 21.0-9.5 so would I plug those values into the above formula?

I also found a post "jack of trades" made using this formula (x/255*10+9.6) but not sure how to make it work to find the ML/BL for this patch

Thanks for any help (math was never my best subject)
Old Sep 22, 2008, 08:58 AM
  #9  
Evolved Member
iTrader: (17)
 
dudical26's Avatar
 
Join Date: Nov 2005
Location: NNJ
Posts: 2,544
Likes: 0
Received 0 Likes on 0 Posts
Originally Posted by mrfred
When I had the stock cold engine ignition retard enabled, the cold engine AFR definitely helped. I usually set it to 14.7:1. Now that we can disable the cold engine ignition retard, the cold engine AFR setting might not be as important.
disable the cold engine ignition retard - I didn't know we could do that. I just searched the forums and found nothing on that, do you have a link?
Old Sep 22, 2008, 09:03 AM
  #10  
Evolved Member
iTrader: (26)
 
travman's Avatar
 
Join Date: Oct 2005
Location: Pittsburgh
Posts: 1,712
Likes: 0
Received 0 Likes on 0 Posts
Originally Posted by dudical26
disable the cold engine ignition retard - I didn't know we could do that. I just searched the forums and found nothing on that, do you have a link?
The maps for 88590015:

https://www.evolutionm.net/forums/sh...5&postcount=76

and how to disable it in the periphery:

https://www.evolutionm.net/forums/sh...0&postcount=88

Last edited by travman; Sep 22, 2008 at 09:05 AM.
Old Sep 22, 2008, 07:03 PM
  #11  
EvoM Community Team
iTrader: (15)
 
fostytou's Avatar
 
Join Date: Sep 2006
Location: Aurora, IL
Posts: 3,143
Received 6 Likes on 6 Posts
FYI for anyone with an AEM wideband here is the equation and a chart:
http://thefrost.net/randomfiles/tuni...F+R_O2_Sim.xls

Base equation is 0.039137255*V+10

Code:
mL	        1/mL	         bL/mL
0.039137255	25.5511022	255.511022
Old Sep 23, 2008, 06:07 PM
  #12  
Evolved Member
iTrader: (17)
 
dudical26's Avatar
 
Join Date: Nov 2005
Location: NNJ
Posts: 2,544
Likes: 0
Received 0 Likes on 0 Posts
Trying to set this up using my ZT2 and I can not get the logging to be completely accurate.

Here is a screen shot of my external reading (digital) vs wideband AFR (analog via ECU)

I tweaked the formula a bit by changing the offset from 9.6 to 9.4 as that seemed to bring the readings closer to what I was getting via serial logging. Can anyone suggest how I might want to tweak the formula?

Formula - x/254*10+9.4



Where the cursor is highlighted, the difference is .3 ---- that too much in my opinion.

Last edited by dudical26; Sep 23, 2008 at 06:11 PM.
Old Sep 24, 2008, 06:53 AM
  #13  
EvoM Guru
Thread Starter
iTrader: (50)
 
mrfred's Avatar
 
Join Date: Mar 2006
Location: Tri-Cities, WA // Portland, OR
Posts: 9,675
Received 128 Likes on 96 Posts
When AFR is decreasing, the value read via the ECU is lower than the serial value, and when the AFR is increasing, the value read via the ECU is higher than the serial value. This is not an issue with refining the formula. Its due to a difference in how the two signals are created.

What range do you have setup for the analog value? From your formula it looks like you have 9.6:1 to 29.6:1, correct?
Old Sep 24, 2008, 08:38 AM
  #14  
Evolved Member
iTrader: (17)
 
dudical26's Avatar
 
Join Date: Nov 2005
Location: NNJ
Posts: 2,544
Likes: 0
Received 0 Likes on 0 Posts
the ZT2 does not allow you to set a logging range so I am using the default range.

according to the install doc, this is the range -

Code:
Analog Wideband Output (White Wire) Voltage vs AFR table
V 0.15 0.31 0.46 0.62 0.78 0.93 1.09 1.24 1.4 1.56 1.71 1.87 2.02 2.18
AFR 9.7 9.9 10.1 10.3 10.5 10.7 11.0 11.4 11.7 12.1 12.4 12.8 13.2 13.7

Last edited by dudical26; Sep 24, 2008 at 08:41 AM.
Old Sep 24, 2008, 09:02 AM
  #15  
Evolved Member
iTrader: (17)
 
Jack_of_Trades's Avatar
 
Join Date: Jun 2007
Location: Opelika,AL
Posts: 3,523
Likes: 0
Received 2 Likes on 1 Post
The analog signal is riddled with noise so you'll get variations. I spoke directly with Zeitronix on this and they pretty much said to always use the digital signal for anything "important" like datalogging and the analog signal is still adequate but don't expect the results to be a mirror image no matter what you do.

Thread Tools
Search this Thread
Quick Reply: how-to: control closed loop AFR with your wideband O2 system



All times are GMT -7. The time now is 06:28 PM.