Saturday, December 7, 2013

An Arduino DIY Tachometer Display

The goal of this project was to create some sort of display that would retrieve and display the rpm signal in an easy to read manor. I thought it would be nice to see this information while driving to see how the engine and the transmission react to different conditions. Though it maybe phased out by my custom touchscreen media center i'm working on now. That device would use a bluetooth OBDII reader that would give me much more than just rpm.

Retrieve The TACH Signal

Gas Engines

Diagnostic Port

Find the TACH signal from the ECU

IGN signal from diagnostic conenctor in engine bay

Negative connection on distributor (if applicable)

Wrap wire around a spark plug.

Diesel Engines

Diagnostic Port

TACH signal from ECU

Sensor on Alternator output (before the rectifier diodes)

Hall effect or IR sensor mounted behind a pulley. should be able to count how fast the holes in the pulley go by. (Technically this would work on a gas engine too)

There is more in depth info on the internet, of course, just search like: diesel rpm hall effect sensor. I've already tried the OBD method and it wont connect to my car (or any other car) for some reason, so i'm gonna try the second gas method: find an ECU TACH signal.

What You'll Need

Arduino (or any other micro, i guess)

I used an Arduino Leonardo and later a atmega 328p with uno bootloader to make it fit better in the car.

A method to get the tach signal as seen in the beginning of the post

I spliced the tach wire from the ECU

Assortment of small / pasive components

7 150 ohm resistors

4 1 kohm resistors

4 2N3409 NPNs rated 140ma or more.

Wire

Used some ribbon cable for the tach signal

Heavier stuff for gnd and power

PCB

Possibly used for final 328p build

Tools

Soldering iron

Multimeter

Wire stripper

Knife

Markers

screw drivers etc

Interface to show RPMs

LEDs (1 per 1000 rpm?)

Segment display

I used two 2 digit 7 segment displays for 4 digits total.

Serial character LCD

Some sort of DIY tach dial

Etc

Some Theory Crap

The Segment Display

Segment displays always have a shape of a number 8 while un-powered, but when of these segments are lit by a LED (that lights only that section) it can create any digit between 0 and 9. The color of the digit and the color of the LED changed the final illuminated color. They also generally have a common cathode (ground) or anode (positive). That means if it was common cathode, all the ground ends of the segment LEDs would be connected and would go to ground. To turn on a segment, you simply connect one anode of a segment LED to positive voltage and it will flow through to ground via the common cathode (but not any other segment). I must also note that most segment displays don't have resistors included, so you must have your own externally just like a regular 5mm LED.

Here is an example internal scheme of a common anode segment display. Positive voltage will always be applied to the anode point, but nothing will light until a ground is connected to one of the letter points.

In this image you can see how the segments are labeled. This is very important when it comes to programming.

This image helped figure out how to wire the segments and the correct orientation of the display. The left image is a top vied of the display. In all theses images of the display in this post you can see the DP or points and they are how i knew the orientation of the pins. It's kinda hard to explain but the bottom of the display has the points, of course, and we see that the scheme has 1 starting on the bottom left with the points on the bottom.

Multiplexing The Display

Ok, lets get to the MP (multiplex) explanation. MP works because of POV or persistence of vision. A good example of POV is a LED that is changing in brightness. By switching the LED on and off really fast it looks like the LED is changing in brightness. When its dimming the LED is blinking off more than it is blinking ON. So: full brightness = on all the time, off none of the time. half brightness = on half the time, off the other half. These "halves" are just fractions of seconds. The human eye cant see it blinking because its doing it so fast.

Lets say you have a scheme like above. All the "a" segments are connected and go to pin "a" on the Arduino and so on and so forth for b to g. All of the pins are currently "LOW". Then you turn "a" HIGH, but nothing happens. Then "digit 1" is HIGH and segment "a" of digit 1 lights up. Then digits 2, 3, and 4 are HIGH and now all the "a" segments are on. Lets say you wanted a 9 on digit 1 so "a", "f", "g", "b", and "c" are high, but now all the digits have a 9 so digits 2, 3, and 4 are LOW to make just digit 1 have a 9. but what if you want to have digit 2 have an 8 too. making all the segments and digit 2 HIGH would cause digit 1 to have a 8 too.

This is how you'd have a 9 on digit 1 and a 8 on digit 2: "a", "f", "g", "b", and "c" are HIGH and then digit 1 is high. Then digit 1 is LOW. "e" and "d" are HIGH. Then digit 2 is HIGH. Then digit 2 is LOW. "e" and "d"are LOW. REPEAT. That whole digit 1 off then digit 2 on thing is happening so fast it looks like digit 1 never turned off and digit 2 is being controlled separately.

In coding reality this is done much faster than on / off. The theory is the same for doing 4 digits. If enough digits are added either the Arduino (this first) or the electronics wouldn't be fast enough and it would look like some are off or dimming.

Using the TACH Signal

This greatly depends on what signal you use. If you're grabbing the signal from the ECU it will probably be a 12v square wave. The way i figured it out was partly do to forums and just simple logic of what the multimeter is reading. I put one lead to GND and the other to the TACH wire and then flipped through the multimeter settings. DC gave nothing (so not PWM), AC gave nothing (would be strange anyways), but Hz did read something. It idled at about 150Hz and the Hz went up as i revved the engine, so from that I figured it out without a oscilloscope. This, this, or this would've been nice though.

Since the ECU is 12v, I will need to need to get it to a 5v level the arduino can comprehend without blowing up. A level converter could be used but for my first test ill just use a voltage divider. It uses two resistors in a ratio to "divide" the voltage. A calculator can be found here.

The Build

Segment Display

If the heading wasn't obvious enough, the first thing I did was to make the segment display module. Since I was doing this with only parts I had on hand and a segment display was one of the easier things to make (second to the LEDs, but that doesn't provide enough feedback). I was thinking of what my display should be and I remembered the segment displays I got from somewhere (no idea hah) and thought they'd do the job just fine. Then the debate was how many digits would I use? One and just do it per 1000 RPM? nah lame. I decided to go with the full number for ex: 4211 RPM. I cleaned off the solder blobs (I had previously used these) and glued the two displays together for the four in the picture. I also put a simple PCB underneath it to make it more stable and soldering easier. I also "sharpied" the white / red case to make it look better.

Here's a good ol' classic lesson for all of us (again). Test the parts before you put them together; apparently one of the LEDs went out on the display, so the project stopped for a bit. I ordered a combined 4 digit 7 segment display for about two dollars (connecting the two segments was a pain anyways). This one is a Common Cathode design so I used a ULN2003 instead of the annoying individual PNP transistors from the Common Anode display. Instead of going full speed ahead, this time I built just the segment display on a bread board with an arduino and the ULN2003.

void loop() {
//this needs to be on a seperate loop so the multiplexing can work
unsigned long currentMillis = millis(); // log where we are in terms of the next number
if(currentMillis - previousMillis > interval) //check if we want to get a new number
{
// save the last time you blinked the LED
previousMillis = currentMillis;

CalculateDisplayNumber(random(0,10000)); //I can put in any number i want here
}

DigitUpdate();
delayMicroseconds(100); //make digits show proper brigtness. with out this the lighting looked uneven
}

Then I got some code working (see below) that picks a random number and displays it on the segments. Now i just have to get the motivation to go out in the cold and get the arduino reading the tach signal. I did go with the ECU method, so its just 12v, GND, and the tach signal wires hanging out of my dash.

well its pretty much 90% done. its cold outside and im too lazy to carry all my electronic shit cross campus (im in college) to do the final "fitting" (5v for the arduino from the car, and the level shifting 12v signal to a 5v arduino compatible one).

so do you have your tach signal sorted out on the car ? do you know where it is or what type of signal it is?