Adapter for analog Tach & Speedometer

I have an older car in which I've installed a modern engine & transmission. I'm working on building a converter to adapt signals from the ECU & transmission to drive the old-school analog gauges (Tach & Speedo). I've made some preliminary code for the Tach, and attached it below (just for fun - it works fine). The ECU outputs a nice variable-frequency 0-5V square wave, which was simple to convert to PWM analog voltage to directly drive the coil for the analog needle. The Speedo is a more complex matter. Instead of driving an analog meter directly, I'll need to drive a stepper motor to actually turn the old-school speedo mechanism. The problem I'm grappling with now is the signal output from the transmission. The trans has a VR sensor, which outputs an AC signal whose frequency and amplitude are proportional to the rotation speed of the output shaft. Unfortunately, this signal is centered around zero (has a negative value half the time), and at high rotation speeds, has very high voltage (less than +/-2V at a crawl, up to +/-100V at high speed). I've done a little research, and am thinking to install two 2.2V zeners across the signal leads (in opposite polarity). I think each zener will bleed off voltage over & under 2.2V, leaving me with a +/-2.2V signal. Questions for your consideration: - Do you think my zeners will behave as I've explained? Is there a better way to do this? - Will the negative voltage portion of the waveform hurt my Arduino? Anyone know of a way to clip off the negative voltage? - Other thoughts & ideas appreciated! Thanks for your advice!

//Define Variables 
  int rpm = 0;
  int spd = 0;
  volatile int rpmcount = 0;  // counts up the times the tach-in signal falls, volitile because the variable is manipulated during the interrupt
  volatile int spdcount = 0;
  unsigned long timeold = 0;  // used to calculate d_t= millis()-timeold;
  int d_t;  // delta_time
  int tachout = 9;  // Pin 9 is the PWM output to the analog Tach
  
void setup()
{
   pinMode(tachout,OUTPUT);  // define outputpin as an output (not needed?)
   Serial.begin(9600);  // open serial communications
   
   attachInterrupt(0, tach_counter, FALLING);  //Interrupt 0 is digital pin 2, so that is where the Input is connected
   attachInterrupt(1, speed_counter, FALLING);  //Speedo input is digial pin 3
}

void loop()
{
   d_t=millis()-timeold;  //sets delta_time to (current clock time - the clock time of the last fixed interval)
  
   if (d_t >= 150)  // after 150ms, stop endless loop & collection of interrupts & rpmcounts, and move to reporting
    {
      rpm = map(rpmcount, 0, 110, 0, 81);  //map instead of compute - was some concern about variable types being a problem...
      spd = map(spdcount, 0, 110, 0, 81);
      //Serial Port Output
//      Serial.print("Time(ms) ");
//      Serial.print(timeold);  //clock time as of this interval
//      Serial.print(" TicsPerInterval ");
//      Serial.print(rpmcount);  //number of interrupts & rpmcounts collected during the interval
//      Serial.print(" RPM PWM Out ");
//      Serial.println(rpm);  //mapped value from rpmcount
      analogWrite(tachout, rpm);
//add code to run stepper motor here
      rpmcount = 0;  //reset rpmcount in preparation for the next interval
      spdcount = 0;
      timeold = millis();  //records the clock time of the current interval
      d_t=0;  //reset delta_time   
    }
}

void tach_counter()  //This interrupt is run each time the processor senses a falling slope in the tach input
{
   rpmcount++; //update rpmcount
}

void speed_counter()  //This interrupt is run each time the processor senses a falling slope in the speedo input
{
   spdcount++; //update spdcount
}

The zener idea seems reasonable to me but I'll let others with more experience comment on that.

However, the negative voltage WILL damage your Arduino! The solution here is a rectifier. A half-wave rectifier will suffice for your purposes here (and actually makes software timing easier than a full-wave rectifier).

It's probably easiest to rectify first and then deal with the voltage issue via zener or whatever.

The problem with the zener solution is that 2.2v is not enough to drive a digital pin. I suggest the following circuit instead, which provides 5V to a digital input pin. You can then use frequency counter code and calculate the speed from that.

[EDIT: Note that the 10K resistor needs to be rated at 1W or more. Or you can use a 22K 0.5W resistor instead.]

dc42:
The problem with the zener solution is that 2.2v is not enough to drive a digital pin. I suggest the following circuit instead, which provides 5V to a digital input pin. You can then use frequency counter code and calculate the speed from that.

[EDIT: Note that the 10K resistor needs to be rated at 1W or more. Or you can use a 22K 0.5W resistor instead.]

Thanks for this detailed solution! I’m no EE, but I think this circuit does the following:

  • damp the waveform via the 10k R
  • bleed off negative voltages
  • use the transistor & 5V supply to make a 0-5V squarewave at the frequency of the original AC signal
    Have I got that right?
    Also, I don’t think I’m reading your writing well - the diode in the circuit is W448? or??? I can’t find a “W448” diode to buy… Alternately, how would you spec this diode performance for the circuit?
    Thanks!

KLattig: Thanks for this detailed solution! I'm no EE, but I think this circuit does the following: - damp the waveform via the 10k R

Me either, but I believe that's to protect the transistor from excessive base current.

  • bleed off negative voltages

I assume the diode is what takes care of this, but not sure how that works exactly. I'd love to learn the explanation. :)

You are both right. The 10K (or higher) resistor limits the base current to 10mA @ 100V input. The diode (I suggested type 1N4148 - sorry about my bad writing) provides a path for negative current, to avoid breakdown of the transistor base-emitter junction. The transistor amplifies and sharpens the signal to a 5V square wave.

dc42: The diode provides a path for negative current, to avoid breakdown of the transistor base-emitter junction.

Ah, got it. I knew transistors had "built-in" diodes but I failed to take into account it's maximum reverse bias breakdown voltage rating -- just like any other diode. Thanks!

Unfortunately, this signal is centered around zero (has a negative value half the time), and at high rotation speeds, has very high voltage (less than +/-2V at a crawl, up to +/-100V at high speed).

I'm going to guess that the voltage is the critical parameter (not the frequency). In that case, you don't want to clamp the voltage as much as you want to proportionally reduce it. Then you can run the voltage into an analog input.

A [u]Voltage Divider[/u] will do that. If you choose your resistor values to sum-up to about 100k Ohms you can use standard 1/4W resistors.

Then to protect the Arduino from unexpected voltages, a pair of [u]protection diodes[/u] is a good idea. Any diode should work.

tylernt:

dc42: The diode provides a path for negative current, to avoid breakdown of the transistor base-emitter junction.

Ah, got it. I knew transistors had "built-in" diodes but I failed to take into account it's maximum reverse bias breakdown voltage rating -- just like any other diode. Thanks!

Slightly off-topic; but many years ago, I remember a book or magazine article (I can't remember which) saying that the base-emitter junctions of cheap silicon small-signal transistors could be used as low-cost alternatives to zener diodes. I tried it, and it worked. The "zener" voltage of a BC182 was generally around 9V.

Modern transistors are typically rated at 5v absolute maximum reverse emitter-base voltage.

dc42: You are both right. The 10K (or higher) resistor limits the base current to 10mA @ 100V input. The diode (I suggested type 1N4148 - sorry about my bad writing) provides a path for negative current, to avoid breakdown of the transistor base-emitter junction. The transistor amplifies and sharpens the signal to a 5V square wave.

Ah - Thanks for clarifying! Is there anything in particular important about the transistor specs? My local sources don't have the one you suggested, but I see there are dozens of transistors on the shelf - Would most any NPN transistor work? 2n4401 maybe? Anyway, I'll give it a try as soon as I can round up the components, and post a reply... Thanks!

2N4401 would be OK, but a transistor with better hfe at low collector current would be preferred. What other NPN transistors can you source locally?

dc42: 2N4401 would be OK, but a transistor with better hfe at low collector current would be preferred. What other NPN transistors can you source locally?

Well, the local Radio Shack has a few, and the local Fry's electronics has many more. The trouble for me in each case is trying to sort out what the specs on the package mean. Can I go with the 'bigger is better' theory here? Perhaps a TIP31? Or NTE-11? I found an informative pdf on transistor basics that helps me understand Hfe; are there other key specs I should shoot for?

KLattig: The trouble for me in each case is trying to sort out what the specs on the package mean. Can I go with the 'bigger is better' theory here? Perhaps a TIP31? Or NTE-11?

No, you need a smaller (i.e. lower current) transistor in that application. Look for one that has a good hfe at Ic=5mA or thereabouts.

dc42: The problem with the zener solution is that 2.2v is not enough to drive a digital pin. I suggest the following circuit instead, which provides 5V to a digital input pin. You can then use frequency counter code and calculate the speed from that.

[EDIT: Note that the 10K resistor needs to be rated at 1W or more. Or you can use a 22K 0.5W resistor instead.]

Well, very impressive! I got lucky on the parts, and was able to get a 2N3904 trans & 1N4148 diode. I had to substitute two parallel 22k 1/2watt resistors for the 10k. On the car, it worked GREAT! I took 'scope shots at ~3.5MPH & ~30MPH (I'm unwilling to spin the tires faster while on jackstands, or drive while looking at the 'scope in the passenger seat!). Unfortunately, I can't figure out how to paste the 'scope shots in to this note. Anyway, In both cases, there's a nice 0-5V squarewave, which I expect will work great with my Arduino code. Amazing what a few correctly placed (and spec'd) parts will do for you! Thanks, dc42 for your help! As a side note, a comment about the amplitude of the signal: I stated originally that the frequency & amplitude of the raw signal was proportional to the rotation speed. While this is clearly true for the frequency, I'm not so sure it applies to the amplitude. I didn't go to the trouble of plotting a lot of datapoints, but I'm pretty sure the amplitude began to level off around +/-15V. An earlier comment suggested that simply rectifying & smoothing the voltage component of the signal might be easier. Because of this non-linear relationship, I don't think that idea would work. I note this in case someone digs up this thread in the future...

I'm glad you got it working! You will probably find that just one 22K resistor is sufficient. Regarding the amplitude leveling off as the speed increases, that may be due to the inductance of the sensor. What is the frequency at 30mph?

To post a picture, click on the "Additional Options" link when posting or when modifying your existing post.

This is exactly the issue I asked about here http://forum.arduino.cc/index.php?topic=185129.0 yesterday! I guess I presented it poorly.

Tell me about having the AC signal fed directly to the board damaging it?!?! I tried this while troubleshooting my assembly without knowing it would cause any great harm.

I'm glad this was brought up here. I never ran my drivetrain fast enough to cause the voltages you saw.

thanks Kyle

dc42:
I’m glad you got it working! You will probably find that just one 22K resistor is sufficient. Regarding the amplitude leveling off as the speed increases, that may be due to the inductance of the sensor. What is the frequency at 30mph?

To post a picture, click on the “Additional Options” link when posting or when modifying your existing post.

Ok, I think I got the 'scope shots posted this time. Interesting that the ‘Insert Image’ icon at the top doesn’t work…

If I’ve got the math right, the ~30MPH frequency is 74Hz (~3.7 cycles in 50ms). Knowing that I’ve got 3 magnets around the output shaft, an axle ratio of 3.9, and tire circumference of 71inches, that works out to 25.5MPH.

I’ll probably play around with other component values in the circuit later - if for no other reason than to learn a little more about what is going on in the circuit…

photo 1(16).JPG

photo 2(12).JPG

biggy238: This is exactly the issue I asked about here http://forum.arduino.cc/index.php?topic=185129.0 yesterday! I guess I presented it poorly.

Tell me about having the AC signal fed directly to the board damaging it?!?! I tried this while troubleshooting my assembly without knowing it would cause any great harm.

I'm glad this was brought up here. I never ran my drivetrain fast enough to cause the voltages you saw.

thanks Kyle

For what it's worth, I'd suggest creeping up on your solution, designing & testing each element thoroughly before moving on. Eventually, I expect my single arduino to read two frequency signals (one 'conditioned', and one raw), produce an analog (pwm) output (that will be smoothed with a low-pass RC filter), drive a stepper motor, and map two 0-5V analog input signals to two 0-5V (pwm) outputs that'll be smoothed & amplified to 0-10V. (all this to drive 4 old-school dash gauges). I see that you've already got a lot going on in your code, while you haven't really got a good understanding of your inputs. Get each element working, and incrementally build your solution. This approach also enables you to put a fine point on your questions in the forum.

Could you be more concise as to which input you feel I don't entirely grasp? I don't want to clutter up your thread so a reply to mine would be just as helpful. The only real error I was aware of with my inputs was syntax of naming the input and the redundancy I left in the code with those names.

Otherwise, yes, I should have been more concise in what I wanted to ask in my thread, and only included that code perhaps. I did want fine, experienced individuals to read through and point out the error in my ways.

I am a newbie with the same challenge, engine and transmission swap using a transmission with no mechanical speedometer drive. I had planned to use a brushless motor to drive the speedometer head, as they appear to have better speed control over the wide rpm range. I will be using a VR adapter/conditioner from http://jbperf.com/dual_VR/v2_1.html which converts the VR analog signal to a 0-5v pulse. Great price performer at $4.00 US.

What are thoughts on using a brushless motor?

Thanks in advance.