BMW E9x K-CAN-bus hacking with Arduino & MCP2515

Hi there!

Lately i’ve been busy working on a way to get some relevant information (like RPM, throttle position, torque, coolant temp. etc) from my 320d, as i want to build my own “info-screen” which will be displayed on the iDrive-display of my car.
The best way to get extensive amount of engine operational data on any E6x/E8x/E9x would surely be to hack into the DME/DDE K-Line and send BMW-specific polls (in the same way that INPA/ISTA/Testo works using EDIABAS), and at first i tried to go that way, but couldn’t get the communication between my Raspberry Pi and the DDE6.0 on K-Line to work, so i decided to try the K-CAN-bus instead. It turned out to be really simple, using only an Arduino and an MCP2515-CAN-module.

My setup

  • Arduino Mega2560
  • MCP2515 CAN-module
  • some jumper wires



I use the Mega2560 for testing, but if i’m about to mount one permanently, i will switch to a smaller board. I usually go for the Arduino Pro Mini, which is small in size but has a decent amount of I/O and is easy to program with an USB-to-TTL-programmer. The MCP2515 uses SPI, so it can be connected to about all Arduino-models, only pin numbers will be different.

The finished wiring looks like this:

Next, off to find a suitable spot to tap into the K-CAN-bus. I used the wiring at the iDrive-display power connector because i already was familiar with removing the display (really simple, undo 2x TX10 screws and the screen pops out). There are surely other better spots to tap into the wiring, but this is one way to do it.

Wiring for the arduino (Black/Red cable) tapped into the K-CAN.
CAN H+ Green/orange, CAN L- Green:

Screen back in, ready to be tested:


Next, the Arduino needs the correct software. Fortunately, there are many suitable CAN-libraries online that seem to work with the MCP2515. I used Cory J Fowlers MCP_CAN_lib. There is an example sketch in the library called CAN_receive which will work on the BMW K-CAN-bus with some minor modifications.

MCP_CAN CAN0(10); // Set CS to pin 10
MCP_CAN CAN0(53); // Set CS to pin 53
Because i’m using pin 53 on the Arduino Mega2560 for CS.

if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
if(CAN0.begin(MCP_ANY, CAN_100KBPS, MCP_8MHZ) == CAN_OK)
Because the bus on my pre-LCI E91 is 100kb/s K-CAN (the newer ones from 2007 onwards have D-CAN @ 500kb/s). The frequency change from 16MHz to 8MHz is because my MCP2515-chip has an 8MHz oscillator, your module could be different.

After sketch was uploaded and ignition turned on, there was a nice continous stream of K-CAN-bus data on my serial terminal.

Standard ID: 0x130 DLC: 5 Data: 0x41 0x51 0x2D 0x00 0x01
Standard ID: 0x0AA DLC: 8 Data: 0xAD 0x81 0xFC 0x00 0x00 0x00 0x84 0x00
Standard ID: 0x1B8 DLC: 6 Data: 0x0F 0xC0 0x83 0x02 0xA0 0x21
Standard ID: 0x4A7 DLC: 8 Data: 0x40 0x52 0xFF 0x01 0xFF 0xFF 0xFF 0xFF
Standard ID: 0x1A6 DLC: 8 Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x60 0xF8
Standard ID: 0x0C0 DLC: 2 Data: 0xFE 0xFF
Standard ID: 0x1B8 DLC: 6 Data: 0x0F 0xC1 0x83 0x02 0xA0 0x21
Standard ID: 0x349 DLC: 5 Data: 0x90 0x1A 0x9A 0x20 0x00
Standard ID: 0x1B4 DLC: 8 Data: 0x00 0xC0 0xE2 0xF9 0x00 0x30 0xFC 0x80
Standard ID: 0x0CE DLC: 8 Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Standard ID: 0x1A0 DLC: 8 Data: 0x00 0x80 0x00 0x00 0x80 0x00 0xC8 0x6B
Standard ID: 0x1D0 DLC: 8 Data: 0x61 0xFF 0x42 0xC5 0x00 0x00 0xCD 0xB0

I was surprised how much data is actually passing through all the time!
So how about interpreting the data? That’s something i will write about later. 😉

If you’re in a hurry, this site will get you started in understanding the data in the K-CAN-bus.


Tuning for economy

Nowadays, modern Common Rail diesel-engines are equipped with all kinds of anti-pollutant devices, eg. DPF, EGR. While these may bring pollutants down to a level that passes regulations, they inevitably also put more strain on the engine, and are also prone to break and cause problems with clogging etc. The software of the ECU is also designed to work with these devices, and the engineers have to find a compromise between pollutants, power and consumption. I have ditched the first one, and concentrated on the last two on my daily driver.

DISCLAIMER: Don’t take my words for granted, i do not have a degree in Automobile Engineering or diesel engine development. This is only my personal experience that i’ve gained on the subject in the last two years while studying the Bosch EDC16 ECU via trial and error. Engine tuning is also a very broad topic, so i’m not going to go deep into details.

While tuning for power on a EDC16-equipped BMW is relatively easy and information is easy to find online, there seems to be relatively big differences in ways that people tune for economy. Most popular tuners/companies don’t touch anything in the cruising speed area in the software maps, which is the area that you spend most of the time driving the car. This means they simply are not tuning for economy. Customers are nevertheless reporting a decrease in fuel consumption, but rarely with any hard evidence to support their claims. I have spent the last year trying out different setups to get my fuel consumption down, and i think i can say i’ve been somewhat successful.

In my opinion, there are a couple of things that make tuning for economy difficult.

  • 1. Not having access to a dynamometer
    • When making adjustments, the test conditions should always be exactly the same, so that any positive or negative change can be observed. The most accurate tests one can make without a dynamometer is driving the same route at same speed and in exactly the same weather conditions (temperature/wind/humidity). This is rarely achieved in real word. The problem is not that big when measuring power and performance, but when it comes down to identifying a 0.1-0.2ltr/100km difference in consumption, you really can’t tell if you can’t be sure that the testing conditions are 100% equal.
  • 2. Understanding the function principles of the engine
    • What happens when EGR (Exhaust Gas Recirculation) is turned off? Does the engine benefit from running with less boost on cruising-areas? Does the VE (Volumetric Efficiency) of the engine suffer from pumping losses generated by closed VNT on the turbocharger? One has to understand the functions of different parts.
  • 3. Everything affects everything
    • There is not a single adjustment to make the engine consume less fuel, but many small changes in the right places can make a big difference.

I have over 100 000km worth of average consumption data from my daily driver. The car is a BMW E91 320d (M47B20TÜ) 6-speed manual with approximately 380 000km on the clock and tuned to 208hp/497nm. The average consumption is calculated everytime i fill up, and can be easily tracked in a smartphone app.

As you can see, the all-time average consumption is 6.6 l/100km at the moment, while the last fill-up was 5.4 l/100km and all-time best 5.1 l/100km.Looking at all charted fuel-ups from the past three years, you can clearly see a downward trend during the last 12 months.

Earlier, no matter how i drove (urban or city-driving) the consumption was always between 6.5-6.9 l/100km. Now, it seems i’m averaging at about one liter less, 5.5-6.0 l/100km.

So, what are the modifications made to achieve this? Here you go:

  • Air/Boost
    • From the factory, lambda is >3 at cruise areas, which means that the amount of air going into the engine can be halved, and the engine will still be running lean and efficient.
    • Lowering boost helps to a certain amount, the theory behind this is simply that the engine is running “lighter” because of opened VNT-vanes on the turbocharger
    • With only lowered boost/too much lowered boost, the engine will perform well on a straight road, but response will be affected, since the turbo has to spool up from a lower pressure than before. This leads to noticeably higher fuel consumption during transient operation (eg. when accelerating to maintain speed up a hill).
    • Some tuners actually put more boost on cruise areas, i assume that’s not for economy but for better throttle response. With more air, the engine is able to inject more fuel instantly, not having to wait for the turbo to spool up.

Conclusion: Lower the amount of air/boost, but not too much, or it will affect things in a negative way.

  • Rail Pressure
    • Decreasing rail pressure makes the high pressure pump rotate easier (because of less pressure build-up), and therefore the engine should also rotate easier. The downside is that the duration of injection will be longer to maintain the same injection quantity. With less pressure, the spray from the injector nozzle will not be as good as with higher pressure.
    • Increasing rail pressure makes the high pressure pump rotate heavier, but the duration period will be shorter, which means a bigger bang (higher cylinder pressure) in the cylinder. The spray pattern of the injector / atomization of the fuel will also be better.

Conclusion: Raise the rail pressure on cruise areas up to 10-20%. The extra strain that the high pressure pump puts on the engine is easily defeated by the benefits of better and faster combustion.

  • SOI (Start Of Injection)
    • Advancing SOI is a sensitive topic, as over-advancing will destroy the engine really quick. The burning process in the cylinder is a very difficult thing to predict, and there are a lot of variables that comes into play when thinking about best SOI.
    • In areas where EGR normally is active (i assume EGR is turned off), there usually is a noticeable dip/valley in the SOI-maps. This dip can be smoothened out optimal consumption.
    • Furthermore, it is possible to add more SOI for the whole cruise area, but it really is guessing as long as one doesn’t have access to a cylinder pressure measurement device or a decent dynamometer.

Conclusion: Advance SOI in EGR areas (if EGR is turned off) to get rid of the dip in maps, if there are any. SOI can furthermore be safely advanced about 1-2 degrees at cruise areas, more than that will require a dynamometer or a cylinder pressure measurement device, if you don’t want to risk damaging your engine.

Your comments are welcome, feel free to agree or disagree 🙂