BMW E30's Shift Light

by palmbook in Workshop > Cars

313 Views, 3 Favorites, 0 Comments

BMW E30's Shift Light

How to Make Shift Light for BMW E30 Under $30
vlcsnap-2024-11-09-21h14m28s459.png

In this article, I am going to explain how to make a shift light for your BMW E30 (and similar models). Because of my height, my steering wheel will cover the top part of speedometer and tachometer. So, I wanted to make a shift light similar to what I have on my Logitech G29. I decided to mount it on the top of my dash, so I don't have to avert my gaze during my track day. However, you are welcome to modify this instruction and make a shift light for other locations, such as fuel economy gauge and SI light.

Supplies

IMG_20241031_145516.jpg
IMG_20241104_153314.jpg
  1. Arduino UNO or Arduino Nano (other boards may work too)
  2. WS2812 (a.k.a. Neopixel) LED strip
  3. 5,000-Ohm resistor (Approximately. I use 5,100 Ohm iirc)
  4. 7,000-Ohm resistor (Approximately. I use 6,200-Ohm and 1,000-Ohm resistors in serial, iirc)
  5. Wire Tap
  6. I know that taps are usually frown upon in automotive community. However, this is not a mission critical application and I don't fancy soldering in a cramp space.
  7. Still, I recommend finding Scotch-Lock taps or Positaps, as they are much sturdier than regular T-taps.
  8. Alternatively, you can splice/solder or crimp your connections.
  9. Some wires
  10. USB Cable that matches your Arduino

Mounting

I cut and glued some acrylic boards to make a bracket. I attached the shift light with a strong double-sided tape. The Arduino and circuit is enclosed in a plastic case.

You can design your own mounting hardware, or feel free to copy my design.

Optional supplies

  1. Strip Board
  2. Bread Board
  3. Jumper Wires
  4. Potentiometer
  5. Oscilloscope
  6. Block Terminals

Basics

e30_tach_diagram.PNG

If you are not familiar with how BMW E30's tachometer works, I have written a separate article that dives deeper into this topic. You can find the article here.

In my application, I decided to tap tachometer signal that feeds into my instrument cluster. This is not the only method though. Some other methods are tapping into ignition signals, tapping tachometer reading from diagnosis port, etc. However, due to my circumstance, this is the preferable method for me.

About Arduino

IMG_20241030_103647.jpg

I used Arduino Uno during prototyping. I decided to move to Arduino Nano for the final product, due to size constraint. You can start prototyping right away on Arduino Nano if you want. Conversely, you can make a final product with Arduino Uno too.

If you are new to Arduino, don't fret! You only need to learn how to install a library and upload code to Arduino to complete this project! There are excellent tutorials about Arduino on Internet. Here is one of them. Here is another. Try uploading Blink example code from Arduino IDE. Please note that Arduino comes with built-in LED, so you don't need to connect an external LED. But feel free to try!

A few words about Arduino Nano clone. I picked up this board for about $5. This is an Arduino Nano clone. It works well for my project. However, it comes with some hurdles. For starter, you may need to install a driver for CH340 chip. In addition, my board refuses to upload my code through USB3 ports. I had to switch to USB2 to get it to work. Finally, you must select "Board: Arduino Nano" (Tools > Board > Arduino Nano) and "Bootloader: ATmega328P (Old Bootloader)" (Tools > Board > Bootloader). You might also need to close serial monitor during uploading.

Your journey with Arduino will depend on the board you pick up. If you decide to go the cheaper clone route, you may have to jump through some hoops to get it to work.

You can choose Arduino with pre-soldered pins, or you can solder on your own.

About LED Strip

vlcsnap-2024-11-10-19h05m43s692.png

In this project, I used WS2812 LED strip, which is similar to Neopixel. These things come in many flavors - straight strip, circular strip, and matrix. My LED strip is 144 LEDs per meter with black background. I bought 1 meter, which cost me about $10.

Nice thing about these LED strips is that you can cut it wherever you want. I chose to cut at 24 LEDs, since this will give me about the same length as the flat part of my dash.

You only need 3 wires to control the strip - one 5V wire, one ground wire, and one signal wire. This is independent of your strip length.

Circuit

IMG_20241031_145516.jpg
IMG_20241031_154624_2.jpg
shift_light.drawio (1).png

The plan of attack is as followed:

  1. Reduce the signal peak voltage to about 5-7V. From my experiment, Arduino would need at minimum 3.5V signal and no more than 9V. Since the tach can take anywhere from 10V to a little more than 12V, I figure that halving the peak voltage would be an ideal solution, as to leave a little wiggle room.
  2. Feed this signal to Arduino
  3. The code will read and calculate the frequency of the signal, convert to RPM, and send output to the LED strip accordingly.

Connect your Arduino according to the diagram above. Please note that the diagram does not match the actual photo, because the original Arduino Nano's pin layout is different to the clone I got. Here are descriptions for all connections you need to make to Arduino:

  1. Connect the reduced Tach signal to A0 (or any pin of your choice)
  2. Connect the instrument cluster's ground to one of Arduino's GND
  3. Connect LED Strip signal line (Din) to D6 (or any pin of your choice)
  4. Connect LED Strip +5V to any 5V pin
  5. Connect LED GND to any Arduino's GND

Connecting Arduino Uno is similar. Just make sure to connect to correct pins.

Potentiometer

In my prototype, I used a potentiometer instead of the second resistor. This was a 10K potentiometer, meaning it can vary the resistance between 0 to 10,000 Ohm. Just connect the first pin and the second pin of the potentiometer. Leave the last pin hanging. When you turn the knob, you should get a different voltage to Arduino.

While it is possible to use a single potentiometer as a voltage reducer, I would advise against this approach. As the potentiometer can be turned to no resistance, this may cause damage to your circuit.

Additional Pins

If you look at my photo, you will see that I put a couple pins on many points of the strip board. This is for debugging purpose. I can hook up a multimeter or an oscilloscope to any point in the circuit to ascertain the correctness. You can do the same, or omit them entirely.

Capacitor and Resistance for LED

Depend on your design, you may need to add a capacitor and a resistor for your LED strip. I haven't really run into any issue with my design, but if you decided to run long wires to your strip, it might be necessary. Here is a guide.

Voltage Divider

In my first contraption, I used an opto-coupler to reduce voltage. Unfortunately, I screwed up the design and it did not work. Kind souls on r/Arduino pointed out my mistake and suggested that I use a voltage divider, which is far simpler.

Basically, you connect two resistors in serial and tap the electrical signal from somewhere between the 2 resistors. The voltage you get is V * R2/(R1+R2) where R1 is the Ohm value of the first resistor and R2 of the second and V is the original voltage.

I encourage you to read up on voltage dividers.

However, keen readers will notice that I am not using the same resistance to halve the voltage. While using the same resistance for R1 and R2 should halve the voltage, we are not dealing with DC, but rather a form of alternate current. Thus, we will need to account for some other stuff, which I don't want to dive into.

So, I simply put in a potentiometer (which is basically a variable resistor), dialed it until I get the output voltage I want, and measured the resistance. It came back at about 7000 Ohm. So, that's what I used.

Feel free to experiment with R1 and R2 values to get the voltage you want. However, please do not use too low combined resistance! We do not want to draw too much current away from tachometer. Keep R1+R2 above 10,000 Ohm and you should be OK.

Code

fastled.PNG
vlcsnap-2024-11-10-21h31m15s183.png

Open your Arduino IDE. First, you need to install FastLED library. This will allow you to easily control your LED strip.

Click on the library manager button on the left side. This will open your library manager. Type in "fastled" and press enter. It should pop up first in the list. Click install (I have already installed, so it is an update button instead).

Once you are done, copy and paste this code.

If you have kept everything the same (Same input pins, same number of LEDs, 4-cylinder engine), you should be able to simply compile and upload this code to your Arduino. If you have a 6-cylinder engine, or want to change something, read on!

Once uploaded, you can open serial monitor and serial plotter (don't forget to set baud rate to 250000) and you should see your current RPM.

Changing input pins

You will need to modify Line 4 and 14.

#define DATA_PIN 6 // Signal pin for neopixel

const int pulsePin = A0; // Tach signal pin

Line 4 defines the data pin for LED strip (Default is 6, which is D6).

Line 14 defines the tach signal pin. (Default is A0)

Changing Number of LEDs

#define NUM_LEDS 24 // LED strip/No of LEDs

Change Line 3 to the number you want. However, this number must be even, because this shift light will start lighting up from the left and right edge and converge to the middle. If you don't wish for this behavior, you will need to modify the code.

Changing Brightness

#define BRIGHTNESS 48 // Brightness 0-255

Change Line 5. Max value is 255. Please note that if your LED strip is long and you crank up the brightness, you may need to supply your LED strip with an external power source. I find that 48 or 64 is pretty bright already.

Changing RPM Range

#define MAX_RPM 8000 // Max RPM for your tachometer
#define MIN_RPM 500 // Min RPM, should be slightly lower than idle RPM
#define SHIFT_RPM 6500 // RPM at which the last light should be lit up

Change line 9-11, which should be self explanatory.

My display does not match Engine RPM!

#define MULT 30 // Multiplier to convert tach frequency to RPM

Change line 12. Try 20 for a 6-cylinder engine. Or simply adjusting this line until it matches your tachometer.

Changing Green to Orange Transition Point

if (led_pos <= 0.5) {

You will need to change 2 lines. Line 47 and 70 should be the same. Change 0.5 to the fraction of LED strip you want to be green.

Changing Orange to Red Transition Point

} else if (led_pos < 1 - (2.00 / (NUM_LEDS / 2))) {

You will need to change 2 lines. Line 50 and 73 should be the same. Change 2.00 to the number of LEDs you want to be red. Please keep the decimal point though to force the result to be a floating point number (i.e. change it to 1.00, 3.00, 4.00, etc.)

How to Stop Blinking

if (rpm >= SHIFT_RPM) {
blink();
} else {
display(rpm);
}

If you don't want your LED to blink when shift RPM is exceeded, you need to replace Line 118-122 (above) to the following single line:

display(rpm);

If your LED strip is very short

You will need to mess around with transition points. Refer to the Changing Green to Orange Transition Point and Changing Orange to Red Transition Point above.

I don't want my shift light to be mirrored

Replace Line 41 to 91 (display() and blink() functions) to the following:

void display(int rpm){
float lit_fraction = ((float)rpm - MIN_RPM) / SHIFT_RPM;

for (int i = 0; i < NUM_LEDS; i++) {
float led_pos = (float)i / NUM_LEDS;
if (led_pos < lit_fraction) {
if (led_pos <= 0.5) {
leds[i] = CRGB::Green;
} else if (led_pos < 1 - (2.00 / NUM_LEDS)) {
leds[i] = CRGB::DarkOrange;
} else {
leds[i] = CRGB::Red;
}
} else {
leds[i] = CRGB::Black;
}
}

FastLED.show();
}

void blink() {
for (int i = 0; i < NUM_LEDS; i++) {
float led_pos = (float)i / NUM_LEDS;

if (led_pos <= 0.5) {
leds[i] = CRGB::Green;
} else if (led_pos < 1 - (2.00 / NUM_LEDS)) {
leds[i] = CRGB::DarkOrange;
} else {
leds[i] = CRGB::Red;
}
}
FastLED.show();

delay(100);

for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();

delay(100);
}

Disclaimer I haven't tested this code, but it should work ;) (wink wink)

I use something other than WS2812/Neopixel

You will need to refer to FastLED documentation and change Line 35 in setup().

Installation

IMG_20241103_143144.jpg
IMG_20241104_152913.jpg
IMG_20241104_152931.jpg
IMG_20241104_153314 (1).jpg
IMG_20241104_153353.jpg

I bought a small plastic electrical box to put Arduino Nano. A few hacking and sawing later, my strip board sit in the box. I also added two terminal connectors, so I can easily attach/detach wires and LED strip.

Next, you would need to tap your wires to the instrument cluster. You can search for how to remove the instrument cluster. Once you have removed it, look for the blue connector. You will need to tap black (tach signal) and brown (ground) wires. In my case, there are two brown wires. Just pick the one closest to the black wire.

If you have an oscilloscope, you may want to confirm at this point that you have tapped correct lines.

Next, find a place to put your circuit. I put it on the dash, near the windshield, because I already have a few stuff there. Alternative locations are behind the instrument cluster and under the dash, next to ECU. You can use screws, double-sided tape, or zip ties.

If you decided to place your circuit near the windshield like I did, you can feed the tach signal and ground wires through the opening near the windshield, like in the picture above. Or if you placed your circuit elsewhere, you can feed your LED wires through the same opening, or you can route them through A-pillar.

I have fabricated a mount for LED strip from 3mm acrylic sheets. It is a simple design with two long acrylic strips forming a T shape. Then, I put 2 triangular braces behind for strength. Lastly, I put a 1mm translucent acrylic in front of LED strip.

I then attached the mount with double-sided tape to the top of the dashboard.

After connecting all the wires, you should be able to start the engine and see your shift light in action!

Future Ideas

Some ideas that you might find interesting to try:

  1. Shift light in place of fuel economy gauge
  2. Shift light in place of SI lights
  3. Shift light using individual LEDs.
  4. Shift light with digital 7-segment display