Pages: [1] 2
Author Topic: MED9.1 – Changing the effective values in maps in real-time  (Read 28291 times)
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« on: December 24, 2014, 06:42:41 AM »

Edit. Flash. Log. Repeat.

What about a way to change the output of maps dynamically? Maybe reducing the amount of time spent flashing just very small tweaks when narrowing down towards an optimal setting?

I haven’t done any modifications for a while now. I’ve been reading a lot of books instead (which is perhaps what I should have done to begin with…). I gather certain aftermarket systems let you alter the maps dynamically which is nice if you have a load holding dyno. For ME7 I understand there are emulators as well which achieve the same thing. Although I’ve never actually seen an aftermarket ecu or emulator either Smiley

Now I can’t dynamically change the map values in my MED9.1 and I don’t have an emulator, but what about the output of the map? This is a variable anyway and by simply adding or subtracting a bit, it’s effectively the same as changing the map.

For example, let’s say at 3000 rpm and 190% load, KFZW is 1.5 degrees. At those conditions, this is the output of the map (1.5 degrees) and is contained in a register. I could add this register to a second register that contains a dynamic value of my choice (say 1 degree) and put the sum of the two (2.5 degrees) back in the original register. Now the ecu would carry on and faithfully process this, just as though it had looked up 2.5 degrees to start with. If torque increases, that’s good and you should add 1 degree to that cell in the bin next time you flash (for a total of 2.5 degrees) . If knock increased, that’s bad and you should leave that cell alone.

So how is this dynamic? Well, what about changing the contents of that second register by turning a dial?



I used the CANBUS to implement this. I discovered that the messages received on the CANBUS by the ecu populate a table in RAM. By creating my own CANBUS message, I could change the byte values in the RAM table. I could then use those RAM addresses in some custom ASM to add two registers together as described above.

Bit of background on the CANBUS.

1)   In the flash there is a table containing the CANBUS ID’s that the ECU will actually receive. There are a lot of CANBUS messages floating around on the bus. Normally CANBUS nodes don’t listen to all messages by default since they’d spend all their time processing interrupts and discarding irrelevant message ID’s instead of getting on with the job. So there’s usually an access filter which only allows certain messages. Only if one of these permitted messages is received does the node process it. Here’s the table in flash. There are three sections (lining up with the three TouCAN modules in the MPC562 processor). This is nicely documented in the FR as well which describes exactly what each message ID is used for. Have a look at sections CAN_CONF and CANECUR. In my S3 the configuration table starts at 0xA09F4.





2)   So the message ID’s are contained in a table in the flash and that table also has spare entries (the ones marked 7FF). Here’s the equivalent table in an A6 MED9.1 ecu. You can see extra entries, presumably for equipment that I don’t have in my S3. I’m guessing I can add my own message ID’s that I wish to receive in the spare lines of the table.



3)   Ok, but where do the received messages pop out then? I used my RAM logger and took a snapshot of the ecu RAM. Lo and behold, nestled away was a table containing the CANBUS ID’s and the received CANBUS data bytes. Could it be this simple? Add my own message ID to a spare line in the flash table, transmit a message with that ID on the powertrain bus and it pops out on the corresponding line in the RAM table? Not quite Smiley






« Last Edit: December 24, 2014, 06:55:29 AM by Basano » Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #1 on: December 24, 2014, 06:57:23 AM »

4)   By trial and error I discovered that not only do you need to put your own CANBUS ID in a spare line in the flash table, you then need to read that table entry. I’ll try and explain the code snippet below. Basically it’s saying load #1 into a register (#1 means first row of the flash table), then call a function that does the reading 585C2C. Then load #2 into a register (#2 means the second row of the flash table) and call the same reading function 585C2C. Repeat for each row of the table. This is the important bit, you don’t need to mess about with anything else, just give the row number to the function 585C2C and it does everything else for you. The data bytes will pop out in the RAM table. I found the code that reads the table rows by searching on cross-references to the configuration table (at 0xA09F4).



5)   So where is the best place to load and call this reading function? In my S3 flash, table row #7 is free and thus not called anywhere (there are no lines of assembler that refer to row #7). I compared that against the A6 bin where row #7 is actually in use. I saw that in the A6 bin, row #7 is called each time after row #1. So what I did in my S3 bin, each time row #1 is loaded and passed to the function, I added in a couple of lines that load row #7 and pass it to the function as well. I only had to add 12 lines of assembler. The OEM code calls table row #1 three times, I don’t know why but I copied it faithfully.



6)   There are also codewords (CW_CAN_R, CW_CAN_RA, CW_CAN_RB, CW_CAN_C) that turn on and off the monitoring and reception of CAN messages, but these messages actually need to be compiled into the flash to begin with. What I’m doing above is adding messages that never ever existed in the first place, they weren’t compiled in and there’s no lines of assembly relating to them. Thus the code words don’t really apply – it’s happening at a layer below any of that. Worth mentioning as well is that there’s no monitoring or message timeouts resulting in fault codes either – if one of my bespoke messages goes missing, well it’s gone. All I did was patch in a few lines that piggyback the reading of table row #7 on the back of another table row read. That’s why there are far more lines of assembler in the A6 bin to read row #7 than just my 12 lines. I think all the other code takes into account monitoring and timeouts and codewords, but I put in the bare minimum to populate my CANBUS RAM table. It’s very simple.

Here’s how I implemented it

I used CANBUS ID 44A. This was free (unused) in my car and as far as I can determine, is related to the automatic transmission (read the FR, sections CAN_CONF and CANECUR). I have a manual, so I think I’m fairly safe.  

To tap into the powertrain CANBUS, I wanted a way that was non-invasive and didn’t require any modifications on the stock wiring harness. I wanted to be able to unplug any modifications in a matter of minutes if I needed to revert back to 100% OEM. I also wanted the diagnostic port to be free so I could use data loggers and diagnostic tools like normal. The CAN gateway was the easiest place for me. In my S3, it’s located just behind the glove box and is pretty straightforward to get to. I made a little pass-through box. Just unplug the 20 pin wiring harness connector from the gateway and plug it into the pass-through box. The pass-through box in turn has a short length of cable that plugs back into the gateway. The pass-through box also has a DB25 connector that all the buses (powertrain, infotainment, diagnostic, cluster, convenience) are available from. You can buy the plug housings from VW/Audi, but for the sockets I got a couple of cheap eBay CAN gateways and lifted the sockets off of them. To make the little stub cable between the pass-through box and gateway, I sourced the crimp pins from Farnell and got a wiring loom shop to crimp them up for me using their Tyco/AMP hydraulic tooling.














« Last Edit: December 24, 2014, 07:04:30 AM by Basano » Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #2 on: December 24, 2014, 07:05:13 AM »

To build my little CAN node that will transmit my bespoke CANBUS message ID and data bytes, I used an Arduino UNO and Sparkfun CANBUS Shield. I included an Adafruit Seven Segment I2C display and an incremental encoder from Bourns (EM14A1D-C24-L008S). I chose an optical encoder so I didn’t have to spend time troubleshooting switch debounce. I specifically used these parts as they are readily available off the shelf, all over the world. There’s no point in bespoke hardware at all. How would you share it? Use something that anyone can get a hold of and you can collaborate Smiley Plus it’s really cheap as well and there’s loads of user contributed stuff. Use whatever processor you like

https://www.sparkfun.com/products/10039
http://www.adafruit.com/product/879
http://www.bourns.com/pdfs/em14.pdf

https://github.com/adafruit/Adafruit-LED-Backpack-Library
https://www.pjrc.com/teensy/td_libs_Encoder.html

I’ve also attached the libraries and Arduino sketch as loaded onto the encoder box.















Wire to board connectors, Tyco/AMP HE14 series. So tiny Smiley That's a TE crimper I got of eBay. No ways I can afford that stuff new!


« Last Edit: December 24, 2014, 07:22:07 AM by Basano » Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #3 on: December 24, 2014, 07:11:48 AM »

The software is very easy, in fact I used readily available libraries for the Seven Segment display and incremental encoder. The encoder has a detent, so when you twist it there’s click to provide some tactile feedback. When you turn the encoder dial, the first data byte of the transmitted CANBUS message changes. One click clockwise -> 01, another click clockwise -> 02. Turn it in the other direction and it decrements. One click anticlockwise -> 01, another click anticlockwise -> 00, another click anticlockwise -> FF, another click anticlockwise -> FE (two’s complement representation of negative numbers). The Seven Segment display shows the scaled value of what’s being sent in that first data byte. I’m transmitting eight data bytes, but only the first has a value and the remaining seven are zero



Pulling it all together then, I wanted to use this to change the output of KFZW and KFZW2. I added a bit of bespoke assembly that combines the output of the timing map with the correction value received over the CANBUS. This combined value is then used by the subsequent ecu assembly code, effectively as though the map value itself had been changed. There are five chunks of assembly – the original code has x1 reference to KFZW and x4 references to KFZW2. All I did was add code that takes the output value whenever KFZW/KFZW2 is read and combines it as described above.



Looking at an extract from a log of the memory locations, you can see the original output of KFZW, the value received via CANBUS and the new value (sum of original value and CANBUS value). I was storing the register values in RAM so I could log and check my workings, especially since the firing angle can be both positive and negative (BTDC and ATDC) and negative numbers means two’s complement maths. I didn’t want to mess it up, but all it needed was sign extension 

You’d log rpm and load and CF’s, turn the dial (which  increases the amount being added to the original map output) which increase the firing angle advance. Check CF’s or torque. If the CF’s are good then you can permanently add this much timing to the cell (next time you flash), else back the dial off a bit until things look better (new map entry = original map entry + correction).

In summary, this was a neat way of changing variables inside the ecu without too much hardware effort (extra wires or pins on the ecu). I used KFZW / KFZW2 as an example, but I’ve subsequently discovered there are many more timing maps than just those two. The same principles could be applied to other things, like LDRXN or even having a little toggle switch on the CAN node. Flicking the toggle switch could result in a RAM location being set to zero or one and activating or deactivating a function (ALS/NLS) or even hardware like cooling fans. Use your imagination 

IDA project attached, plus before and after versions of the bin so you can see what I changed.
« Last Edit: December 24, 2014, 07:16:56 AM by Basano » Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #4 on: December 24, 2014, 07:24:40 AM »

IDA project
Logged
Basano
Full Member
***

Karma: +90/-3
Offline Offline

Posts: 192


« Reply #5 on: December 24, 2014, 07:31:44 AM »

Installed in the car















« Last Edit: December 24, 2014, 07:35:03 AM by Basano » Logged
terminator
Sr. Member
****

Karma: +15/-4
Offline Offline

Posts: 425


« Reply #6 on: December 24, 2014, 07:45:49 AM »

You are a genius! Thanks for sharing. By the way I solved my problem)
Logged
adam-
Hero Member
*****

Karma: +122/-33
Offline Offline

Posts: 2178


« Reply #7 on: December 24, 2014, 10:13:42 AM »

This is so awesome!

A lovely, detailed write up too, well done sir!
Logged
dream3R
Hero Member
*****

Karma: +18/-8
Offline Offline

Posts: 1194


« Reply #8 on: December 25, 2014, 03:32:00 PM »

Well done Sir!

Logged



How to work out values from an A2L Smiley

http://nefariousmotorsports.com/forum/index.php?topic=5525.msg52371#msg52371


Starting Rev's http://nefariousmotorsports.com/forum/index.php?topic=5397.msg51169#msg51169

noobs read this before asking http://nefariousmotorsports.com/forum/index.php?topic=9014.0title=


ORGORIGINAL 05 5120 creator for Volvo
ORIGINAL Datalogger (Freeware) Author
ORGINAL finder of the 'extra' torque' limits
I don't have ME7.01 A2L I just use ID
technic
Full Member
***

Karma: +17/-5
Offline Offline

Posts: 227


« Reply #9 on: December 25, 2014, 03:51:48 PM »

You know, I just love these kind of things! Well done David!
I will try this approach using my NXP setup.
Logged
Aurélien
Full Member
***

Karma: +4/-0
Offline Offline

Posts: 60


« Reply #10 on: December 26, 2014, 04:16:51 AM »

Good job.

This method enable tuning up to 8 bytes of data. So 8 parameters with 8bit value or 4 with 16bit ( _w ) .

The implementation is easier than what I'm currently doing ( writing ram via TP20 ) and keep the OBD2 port free. Cool !

I will try porting this to my rom but I think I will start lacking space for code !  Cheesy
Logged
technic
Full Member
***

Karma: +17/-5
Offline Offline

Posts: 227


« Reply #11 on: December 26, 2014, 06:08:18 AM »

What is TP20? For me beeing an old hw designer, that is a testpoint Tongue
Logged
daniel2345
Full Member
***

Karma: +11/-7
Offline Offline

Posts: 188


« Reply #12 on: December 26, 2014, 11:52:01 AM »

Transport Protocol 2.0, some VAG CAN Stuff...
Logged
technic
Full Member
***

Karma: +17/-5
Offline Offline

Posts: 227


« Reply #13 on: December 26, 2014, 12:53:37 PM »

Ahhh...of course...
Logged
AngelPowy
Full Member
***

Karma: +1/-0
Offline Offline

Posts: 55


« Reply #14 on: January 14, 2015, 08:01:24 AM »

Dude I want you to know that  you are a HERO for this community. I've read all your post on MED 9.1. I've learn so much thing here in 1 week than in 2 month at school. Your job was just excellent. I am actually trying to adapt NLS and multimap on my uncle's golf. They is some things that I don't understand actually but I keep reading and searching then I will finally understand.
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Page created in 0.028 seconds with 16 queries. (Pretty URLs adds 0.001s, 0q)