![]() |
Open Source Flex Fuel
***It works***
I filled up at a United station close next to work yesterday and they now have E85 supply there which they didn't have 6 months ago, and do not advertise it on their website. Having implemented Hybrid Speed Density and Boost Limit Fuel Cut for my car, this is a logical next project which I'll develop openly and collaboratively until we have a solution or I lose interest or my car. I do this for a hobby, so it need not be said, but ***TRY EVERYTHING AT YOUR OWN RISK*** My time is my own to waste on this project and I do not earn money as a tuner - having said this, I'm happy to take donations via PayPal at esltan@yahoo.com if you find any of the info that I've posted useful. To do: Source Hardware: tips at http://www.ecmtuning.com/wiki/ethanolsensorparts Define Flex Fuel Sensor input method - Posts #3, #5, #11 Develop code to: Hook the sensor routine - Post #14 Read and scale input to E% - Post #15 Scale PI and GDI separately or together based on E% - Post #31 Scale cranking PW based on E% - Post #32 (v.1), #46 (v.2), #49 (v.3) Interpolate fuel and timing based on E% - Post #36 (fuel), Post #42(timing) Apply scaling to display multiplier - Post #50 Extras: Send E% data to PLX gauge - Post #11, #48 TRAC switch double click to turn off traction control or default to TRAC off - Post #30 email me if you want a copy of any of my files along the way. |
Flex Fuel Hardware + Controller.
Starting reference: http://www.ecmtuning.com/wiki/ethanolsensorparts
The most commonly available Flex Fuel sensor around the market are the GM ones that send a 50Hz square wave out at E0 and 150Hz out at E100. 190Hz is output for water contamination. We can buy a controller off the shelf to read the square wave frequency and convert it to a voltage signal that the ECU can read easily: available from any one of the vendors at the moment - saves a lot of time, but where's the fun in that? Alternates are to make our own frequency to voltage controller box or code the ECU to do the frequency analysis internally. |
Sensor input connection to ECU
5 Attachment(s)
Having seen the E85 at the station yesterday, I went back home and pored over the wiring diagrams and the car.
The two commonly used sensor inputs are the rear oxygen sensor (O2S2) and the Evap pressure sensor. ECU pins as per diagram below (the wiring manual has the connectors as if you were looking end on at the harness plug - they are mirror-imaged when you look at them plugged in to the ECU. I had a look at the connector AD2 (which is more accessible than the ECU) which joins the ECU to the fuel pump and Evap cannister harness: the wires were not there for the Evap cannister (A01G ROM). It turns out that I am in luck and the ECU does not interrogate Evap Pressure in my A01G car, so I don't need to compensate for losing the signal. Moving on to connector A35 on the ECU, pin 20 was empty and I decided to hook a wire up to it. Pulled the connector out - it turns out that I could use the Molex pin from a scrap IDE type ribbon cable on this. To do this, lift the retainer on the IDE plug with a pick and pull the connector out. The A35 connector has a horizontal locking tab in the middle - that needs to be pulled out about 2mm, then the IDE Molex pin slides all the way down the barrel and does not come out when the locking tab is replaced. See last picture for new wire placement. |
@ztan have you seen this thread opensource ethanol analyser
http://www.ft86club.com/forums/showthread.php?t=79865 |
Sensor input RAM address
A while ago, I had a look at the A01G disassembly to chase down a RAM value for MAF Voltage.
I had listed a whole bunch of potential RAM addresses from disassembling the sensor pull routines still available and did some logging with them all to trace the Evap pressure sensor ADC pin. Logging all these for A01G: Evap pressure sensor from 20(A35) voltage 16 bit value is stored at FFF842F8 and the float value sits at FFF87C7C after scaling. Scaling: Multiplier at 0011CC38: 137.62 Offset at 0011CC3C: 253.90 Without a connection to a sensor, the voltage is pulled up and logs ~5V (~940mmHg). O2S2 from 21(A34) sends a 16 bit voltage value to FFF842FA. I have not verified for other ROMs but the RAM addresses for the sensor pull bit of code tend to be uniform between calibration IDs that I've looked at. If I'd known that the Evap pressure sensor line was unused in my car prior to installing my wideband, and knew I already had the RAM address sitting in a file to test, I'd have routed it there. |
I wonder if its possible to hijack the ECU routine that sends the instantaneous L/100km to the dash display and send the ethanol content instead ?
|
This would be awesome!
|
ECU to measure frequency
I've been looking at the ECU datasheet to see if there is a way to use the counter in the ECU to directly measure pulse width off a square wave using the advanced timer unit (ATU III).
Unfortunately, the Evap line 20(A35) connects to the A/D converter at AN_B43 and I can't see that it has a trigger for the ATU directly. Does anyone know of which pins in the ECU connectors are available to trigger the timer, or does anyone have a disused ECU to post to Australia which I can disassemble to try to trace one? Even a bricked one ok as I just need to trace connector pins to the chip. |
So I bricked my ECU testing a routine that would read frequency over the ADC line. Didn't check my programming work thoroughly by running each step through HEW as I have in the past. Part of the routine made a bad call and sent my ECU into a loop as soon as the sensor scan routine is run (almost immediately).
Lesson learned with a new idea - it would be easy enough when testing any new routine to switch into it via defogger switch: if it hangs, the ECU will still communicate for a re-flash with defogger switch off. Have a new ECU in from dealer recoded to my keys. Will resume this project when a suitable unbrick solution available - I'll start that thread. |
Wow. Sorry to hear that. I would offer help, but am light years behind you on messing with the ecu.
|
1 Attachment(s)
Having gotten my bricked ECU to talk on the bench again (but not 100% functional) using SHBoot, time to get back up developing.
The Evap sensor routine that I hooked polls the sensor at 60-80ms intervals - too slow to use to read frequency properly in the 50-150Hz range that the GM FlexFuel sensor uses - will convert to 0-5V output to make this work easier on the Evap A35-20 input. Having a PLX DM6 gauge for wideband display, I decided to use an Arduino Nano ($3 on eBay) to do the following: 1. Read Hz signal from FlexFuel sensor 2. Output 0-5V signal to ECU. The Evap pin is pulled up to 5V without anything attached, so I have initially coded E0 to send 5V and E100 to send 0V 3. Output serial PLX iMFD packet to PLX daisy chain (using Fuel Level sender ID code as I could not find any device ID for a Flex Fuel sensor for the DM6). This needs to be the terminal device in the PLX chain and will display E% as "Fuel Level" on the gauge. 4. Flex fuel sensor can be calibrated using pure gasoline and E85 inputting the frequency reads into the E0 and E85 values in the code before sending to Arduino. The Continental 13577429 sensor that I have reads 55 Hz with gasoline and 131 Hz with E85. I also have a couple of Chinese made 13577379 eBay sensors which have linear output but calibrations are off (80 Hz with gasoline, 150Hz with E85) if anyone wants a cheap working sensor with calibration data, PM me. Frequency read is based on FreqMeasure library at PJRC Arduino code and Nano circuit diagram (it all works): Code:
//Flex Fuel sensor code |
Awesome Work! Glad to hear you got the ECU up and (sorta) running. Excited for the results.
|
Keep up the good work Ztan have been watching your work for a while now . p.s thanks for the help you gave Shiv with my tune.
|
Hooking new code into existing routines.
This is an example of how to hook code into an existing routine. Not 100% elegant, but there is plenty of free space to work with in our ECUs so I haven't optimized it for space.
Be careful when using the delayed slot instructions (jsr, rts, bra...) if you have any delayed instructions that reference addresses, the results can be quite screwy. The 32 bit instructions instructions in a delayed slot also are not reliable. Use of jsr/n, rts/n makes code more reliable, even though it takes up an extra clock cycle. Example: In the A01G ROM, the routine at 2B0E8 in the stock ROM scales sensor voltage data in fr4 according to multiplier and offset (Throttle angle, Accelerator angle, Batt Voltage, MAP sensor, Evap Pressure sensor) Evap pressure sensor data is read when r6 = 06 and r13 = 0B. At the end of this block of code, the program then branches to 2B100 with the scaled value stored in fr9. Code:
ROM:0002B0E8 loc_2B0E8: ; CODE XREF: Scale_16_bit_sensor_data_in_tableCode:
ROM:0002B0E8 loc_2B0E8: ; CODE XREF: sub_2B0A2Code:
ROM:000B97C0 sub_B97C0: ; CODE XREF: sub_2B0A2 |
Coding for Ethanol based scalings
1 Attachment(s)
Coding for Ethanol based scalings (A01G ROM base)
The code below returns and stores a few values based on ethanol content; will describe how to modify ROM and do cranking comp to use these later on: The clutch switch has been added to use as a failsafe in case the code added after is no good for testing purposes so fewer ECUs get bricked - the code only executes if clutch is depressed. Change the "branch if true" instruction at B97E6 to "00 09" (nop) to turn this switch off. Initially the ethanol value in fr9 in passed to fr4 and this value is limited by the Check_Bounds routine at 011260 (max value in fr6 and min value in fr5) The value returned in fr0 (Ethanol content) is stored to RAM_Ethanol and a Fuelling Multiplier is looked up from that table (E0=1.00, E85=1.40 in linear scale) This value is used to multiply the PI Injector Flow Scaling BRZ value for Port injector operation and a GDI multiplier that works on GDI pressure multiplier tables A and B (I call this GDI multiplier C). An interpolating value is then looked up in a table to scale between 2 Primary OL fuelling tables (E0=0.00, E85=1.00). A further interpolating value is looked up for use between 2 base timing tables (E0=0.00, E85=1.00) which are then added to the Knock Correction advance table which remains un-modified. This interpolation value is multiplied by the AVCS active value (0.00 = AVCS not active (looks up Base Timing A), 1.00 = AVCS active (looks up Base Timing B) to use the E0 map as a AVCS inactive map also. Theoretical table values input in image below. Please feel free to contribute data to discussion as to how best to scale these multipliers or interpolants to hit optimal fuelling and MBT with the 12.5:1 compression ratios with or without boost. Code:
000B97DE |
@ztan
Any reason you chose to use the DI fuel pressure signal instead of the injector PW to mass scaling like you plan to do for PFI? |
Quote:
|
Quote:
Previous open source E85 implementations have multiplied the result in the GDI pressure multiplier tables A and B (Axes are engine load and fuel pressure) to come up with a value that, I understand, approximates DI quantity. I did disassemble the ROM to find the derivation of the axes in another post: http://www.ft86club.com/forums/showthread.php?p=2387636 The value from the GDI pressure multipliers A and B then gets multiplied by a scaling factor (GDI pressure multiplier C which I am using to scale for E85). I believe that this is the scaling factor that changes the number from a fuel quantity to a pulsewidth value. This raw DI pulsewidth value is then passed to the GDI flow rate table which is what is used to finalize the DI pulsewidth (compensations for quantity on one axis and fuel pressure on the other). |
Quote:
From experience the MBT spark timing does not shift so much for E85 to command any attention. It is just the actual spark timing that shifts. Some OEMs have MBT spark timing as a table in the ECU which makes it easy for tuners to tune for E85 because you just have to make the Base spark = MBT spark. |
@ztan
So theoreticly on an A01G rom i could test this without a flex kit by making up a simple circuit to feed in 0 to 5 volts onto the evap input pin. Or just a switchable voltage divider with say 0 ,2.5 and 5 v and effectivly map switch between E85 e40 and petrol. assume you have added an extra Base TimingB and OL fuel map somewhere ? |
ztan is a freakin' rock star :party0030:
|
Quote:
All to be revealed after more testing etc... but in short: Base Timing A only gets used when AVCS off. FFF8ADB8 reads 0 when inactive (after ECU reset for a couple of minutes) and 1.0 when AVCS active. The value at FFF8ADB8 is use to interpolate between Base Timing A and Base Timing B. My plan is to hijack Base Timing A as E0 and Base Timing B as E85. Primary OL Fueling map is added to by the OL Fueling additive map on the basis of IAM value (no additive applied when IAM = 1.0, full additive when IAM=0.0). I am going to assume, rightly or wrongly, that folks who are applying this have the nouse to be monitoring IAM and that IAM will not drop far enough below 1.0 to require extra fuel. Hence I would plan to use Primary OL Fueling map for E85 and OL Fueling additive map for E0 with above interpolant values. It would be quite easy to add in completely new tables for the above, but this is the way I am thinking. |
Quote:
Unfortunately MBT spark is not visible in the ROM that I can find. I assume Shiv's E85 NA ROM will be pretty close on the money and hopefully we get some more data on where MBT lies higher in the load range on boosted engines in the future. |
@ztan
For E85 cranking @Wayno s tables are very reliable even on united E85 E85 Cranking changes 0C/32F stock values multiplied x 1.5 10C/50F stock values multiplied x 2.0 20C/68F stock values multiplied x 2.0 30C/86F stock values multiplied x 1.3 40C/104F stock values multiplied x 1.2 50C/122F stock values multiplied x 1.1 60C/140F stock values multiplied x 1.05 http://www.ft86club.com/forums/attac...1&d=1442118398 For Dash fuel display multiply be 33% ie same ratio as GDI pressure multiplier offset or PI injector scaling offset. http://www.ft86club.com/forums/attac...1&d=1442115733 |
Quote:
My idea is to hijack the IAT cranking compensation table (returns 1.0 across the board for all IAT values) part of the routine and use that as an ECT cranking compensation. This sits just below the accel cranking compensation in the code (the latter table returns 0.0 when the accelerator is fully down when cranking and no fuel is delivered). I am thinking: We want a cranking multiplier of 1.0 with E0 and ECT compensation to be applied with higher E%, based on the Flex scaling multiplier. One way to do the maths is to return a multiplier of 1.0+((Flex scaling multiplier - 1.0)*ECT cranking multiplier). At E85 with a Flex scaling multiplier of 1.4, this would give us a cranking multiplier of 1.4 at 20C with the table that I posted in post #15. A table value of 2.5 would return 2.0 as a cranking multiplier. |
Quote:
|
Quote:
It might be easier to rescale and offset the IAT vs Cranking IPW table rarther than the cranking Vs Coolant tables. have you seen kodename47 defs he has intergrated the opensource stuff with Ecutek stuff http://www.ft86club.com/forums/showp...&postcount=411 |
Quote:
That IAT cranking compensation table that reads 0.0 in Kodename47's def means 0% compensation applied. When looking at the disassembly and running that bit of code through the HEW simulator, that table returns a value of 1.0 (scaling factor 1.0 = 0% compensation). I changed my def to suit as well as started thinking in terms of scaling factors rather than % compensation. |
Quote:
As you say, it's also how the tables actually are in the ROMs so it's easier when looking through the likes of ScoobyROM or WInOLS to pick out the tables. In case you didn't have it this is my up-to-date A01G with ratios and metric values. |
TRAC switch doubleclick
2 Attachment(s)
Off topic, but related.
With the Arduino Nano going in as a FlexFuel Sensor controller, there is space for much more to be added on. I decided to make a doubleclick TRAC control switch so I don't have to hold down the TRAC switch down for 3+ seconds to turn if off. Simple code and adds 2 resistors and an NPN transistor to the circuitry. If you want it on by default, set initial button state to 4, which acts as a doubleclick a certain time (TRAC_initializeDelay) after power on. Why not the full pedal dance? Mine is a street car and we in Australia can't use the speeds on road which people have issues with VSC activating brakes at, requiring the pedal dance to be used or sent over CANBUS like with OFT. Out of interest, can anyone share the CAN sequence needed for pedal dance active? Code, schematic, and picture of controller box with FlexFuel sensor leads, TRAC switch leads, PLX serial interface. Updated Arduino code: Code:
//Flex Fuel sensor code |
Applying scalings to injector routines
Having calculated a fuelling multiplier based on E% and scaling the stock PI (Injector scaling BRZ) and DI (DI pressure multiplier C) multiplier values in the routine described above in post #15, we need to get these values read in the fueling routines.
In the previous code, the following values are shown in the data segment following the code: Code:
000B98B0 FF F8 D4 18 off_B98B0: .data.l RAM_Flex_PI_Scaling ; DATA XREF: sub_B97C0What we need to do is find where in the ROM these values exist to be referenced and change them to point to our Flex Fuel scalars in RAM (FFF8D418 for PI and FFF8D41C for DI). This is as simple as searching for 0010C680 and replacing with FFF8D418 (6 instances) and 0010C614 and replacing with FFF8D41C (1 instance). All these instances are referenced by code appropriately: Code:
Address Function Instruction |
Cranking Compensations
Edit ***This v.1 code has not worked the way I thought - I get an appropriate multiplier and this does not get applied to the cranking fuel. Error due to delay in Arduino reading ethanol. v.2 code in Post #46, v.3 code in Post #49. ***
For this, we'll hijack the IAT cranking compensation lookup table which normally returns 1.0 for all IAT temperatures. There are two references to the IAT cranking compensation lookup table and we'll hook both to insert an ECT based cranking multiplier which is scaled by the Flex Fuelling multiplier. Stock code location A: Code:
ROM:00057880 loc_57880: ; CODE XREF: Cranking_Fuelling_CompCode:
00057880 loc_57880: ; CODE XREF: Cranking_CompensationsCode:
ROM:00057F4C D4 18 mov.l #Table_Cranking_Fuel_IPW_Compensation_Accelerator, r4Code:
00057F4C D4 18 mov.l #Table_Cranking_Fuel_IPW_Compensation_Accelerator, r4 |
@ztan I wish I could help out but this is way over my league.. Keep up the great work!!!
|
Beta testing
2 Attachment(s)
It Works!!!
Early beta testing, still need to post up fuelling and timing interpolation code, verify reasonable use of multipliers. Have filled up to E20 (up to E35 with E85 sitting in the tank before mixing in with residual fuel) and using a E85 multiplier of 1.35, trims look quite stable at present. |
Great job man, this is also way out of my league but great to have contributors like yourself and steve99 on this forum.
|
Flex Fuel Primary OL fuelling
1 Attachment(s)
This one is tricky.
I've used the routine for Primary OL enrichment lookup and assigned that to E85. The OL additive is a table that gets used normally when IAM < 1.0 and I've used that for an E0 table. The modified code is also a bit longer than the original and overlaps (by 2 bytes) a routine that is not used in stock A01G. Stock code: Code:
ROM:00061420 D6 67 mov.l #byte_114663, r6 ; Move Immediate Long DataCode:
00061420 D6 01 mov.l #RAM_Flex_Fuelling_Interpolant, r6Stock table defs: Code:
ROM:000B5854 00 0D 00 17 Table_Primary_Open_Loop_Fueling:Table_Type <h'D, 0, h'17>Code:
000B5854 00 0D 00 17 Table_Primary_OL_Fueling_E85:Table_Type <h'D, 0, h'17> |
Awesome progress man. Keep up the good work!
|
Amazing!
|
Gangster!
|
Excited to see this so close. Great Job!!
|
| All times are GMT -4. The time now is 07:32 PM. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
User Alert System provided by
Advanced User Tagging v3.3.0 (Lite) -
vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.