Controlling a Hella VNT-actuator using PWM

I’ve had a couple of Garrett turbochargers laying around for some time now, a GT2056V from a E60 525d and a GT2260V from a E46 330d Euro4 to be specific. I originally bought these for my 320d as upgrade-turbos, but with so many other projects and stuff to do, i just haven’t got the time to swap in a bigger turbo. I’m working on my summer car at the moment, and it needs an actuator to control a flap/valve, so i thought why not borrow one from these turbos as they’re just wasting space at the moment.

The Actuator

I dismantled the actuator from the GT2056V, took it apart, and gave it a quick cleanup. Looking inside, everything looked OK. No excessive wear on the mechanical parts, and no broken solder joints or melted components on the circuit board.

VNT-actuator inside

Once put back together, it was time for some googling around. The actuator i have is labeled 6NW 008 412, which is the same number as most of these actuators seem to be. Another identification found on the plastic case is the number 2, and there is also a G-****-tag on the metal casing, these two identify the OEM manufacturer and type of the actuator.

VNT-actuator cover

It seems there are two ways of controlling a actuator like this, PWM and CAN. The control method depends on how the unit is programmed upon manufacturing, and cannot be easily changed. Some sources tell that the actuator can be controlled with either one, but i tested this with my PWM-controlled actuator, and it definitely didn’t send out any messages on the CAN-bus, as it’s manufactured for a PWM-application.

Actuator Pinout

Pin # Function
1 12V+

Well, how do you find out which type of actuator you have? In my case it was easy as the connector & a bit of stripped wiring was supplied with the turbocharger & actuator. On the connector, pins 1,2 and 4 were connected, in other words, +12V (red), GND (brown) and PWM (grey). If you don’t have the connector, Google will be your best friend.

VNT-actuator connector

Controlling the actuator

The PWM control signal depends on the OEM manufacturer request. Some actuators need a 140Hz PWM signal, while others accept 300Hz. There might also be other frequencies, but these two are the most typical ones on this type of Hella actuator. The signal is of grounding type, which means that the actuator outputs a steady signal on the PWM pin which is then modulated by a microcontroller grounding that pin in a timed sequence to achieve the desired PWM output.

I will ultimately control the actuator with my aftermarket ECU, but for testing purposes i hooked it up to my Arduino MEGA2560. Any Arduino or programmable microcontroller capable of PWM will be just fine though. Using Arduino, there are a couple things that needs to be taken into account:

  • The signal levels on the Arduino are 5V, while the VNT-actuator works with 12V, therefore some kind of level shifter has to be used. I used a TIP120-transistor.
  • With Arduino “real” PWM you cannot achieve 140Hz or 300Hz easily, or at least i couldn’t. I didn’t try to modify the timers/registers further, but used “software PWM” instead, manipulating the pins manually.
  • Wiring

    So, for connecting everything you need an Arduino, a transistor, a 1k resistor, a breadboard and some wires.

    Wiring the VNT actuator

    The power supply feeds power to the Arduino and VNT actuator. PWM-signal is applied through a current-limiting 1k resistor to the Base of the TIP120, this is the “control signal” for the transistor. The PWM signal from pin 4 on the actuator is routed to the Collector of the TIP120. When Arduino applies voltage to the Base of the TIP120, current will flow through the TIP120 from the Collector to the Emitter. As the Emitter side is tied to GND, the PWM line will be grounded. This sequence, done in correctly timed cycles, will produce the control signal needed for the VNT actuator to function.

    The Code

     * Simple sweep for testing a Hella VNT-actuator @ 300Hz.
     * Uses digital pin 13 for PWM.
    void setup() {
      pinMode(13, OUTPUT);
    void loop() {
        for (int sweep = 0 ; sweep <=3333 ; sweep += 6) {
      digitalWrite(13, HIGH);
      digitalWrite(13, LOW);
      delayMicroseconds(3333 - sweep);
        for (int sweep = 3000 ; sweep >=166 ; sweep -= 6) {
      digitalWrite(13, HIGH);
      digitalWrite(13, LOW);
      delayMicroseconds(3333 - sweep);
            for (int sweep = 0 ; sweep <=3333 ; sweep += 33) {
      digitalWrite(13, HIGH);
      digitalWrite(13, LOW);
      delayMicroseconds(3333 - sweep);
        for (int sweep = 3000 ; sweep >=166 ; sweep -= 33) {
      digitalWrite(13, HIGH);
      digitalWrite(13, LOW);
      delayMicroseconds(3333 - sweep);

    The result

    As seen on the video, the actuator works just fine. It seems that this kind of actuator doesn’t like under 5% or over 95% duty cycle, and will possibly wind itself to start position if those limits are exceeded. Good to know if you’re controlling something critical.


    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 🙂