Bar Graph LED tachometer, Help needed.

I looked at the code and found a few things. The big problem occurs in the readFrequency() function. It delays for the sample/observation time and while that’s happening the blinking won’t happen … as it’s not an interrupt but rather a polling type timer. It needs to run at <1 msec intervals in order to keep it’s claimed 1 msec (best) accuracy.

So here’s some incomplete code (read the comments) that’s a bit different from my prior description but simpler and should work. Basically the 2 timers always run (very quickly) and the Blink() function determines (every 35 or whatever msecs) whether to blink or not depending on the calculated RPM.

#include <SimpleTimer.h>
#include <SFEbarGraph.h>
#include <SPI.h>

SFEbarGraph BarGraph;
SimpleTimer blinkTimer;
SimpleTimer calcTimer;

const int rpmMax = 9900;
const unsigned long blinkTime = 35;
const unsigned long calcTime = 140;

volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile int numPulses = 0;
boolean blinkState = false;
int rpm = 0;

void setup() {
  BarGraph.begin(1, 12);
  blinkTimer.setInterval(blinkTime, Blink);
  calcTimer.setInterval(calcTime, calcRPM);
  attachInterrupt(0, isr, RISING);
}

void loop() {
  calcTimer.run();             //RPM calcs only run when timer dictates, every calcTime msecs
  blinkTimer.run();            //blink timing runs every blinkTime msecs
}

void isr()
{
  unsigned long now = micros();
  ++numPulses;                  //moved this line to here
  if (numPulses == 1)
  {
    firstPulseTime = now;
  }
  else
  {
    lastPulseTime = now;
  }
}

void calcRPM {
  noInterrupts();       //turn off interrupts so numbers don't change while computing RPM
  //calculate RPM from pulse count and timing
  rpm =  ;

  //reset the pulse count for the next calculation
  numPulses = 0;
  interrupts();          //re-enable interrupts and thus pulse counting
}

void Blink {
  if (rpm >= rpmMax) {
    ~blinkState;                      //oscillate blink on off
    if (blinkState) {
      BarGraph.barGraph(30, 0);       //turn on all LEDs if true
    } else {
      BarGraph.barGraph(ceil(rpm / 366.6667), 0);  //turn on only LEDs needed for RPM
    }
  } else {
    blinkState = false;
    BarGraph.barGraph(ceil(rpm / 366.6667), 0);     //turn on LEDs needed for RPM
  }
}

Wow, that is actually really close to what I thought you were originally meaning, albeit a whole lot easier to use and faster to run, hopefully.

I see you didn’t have the code for the rpm calculation in the calcRPM method, so I wrote this, and it compiled without errors, so it should work.

  //calculate RPM from pulse count and timing
  rpm =  ( numPulses < 2) ? 0 : ( 60 * 1000000.0 * (float)(numPulses - 1) ) / (float)( lastPulseTime - firstPulseTime );
}

Is that what you were going for?

also I contacted the manufacturer of the ECU I will be using to see how pulses affects frequency, hopefully it doubles frequency so that the timing between rpm calcs. can go down a lot. But I have to wait on their reply, which could be a week from now… :frowning:

BlindAssassin111:
Is that what you were going for?

Yup, that looks good. I left it out because I wasn't sure if you were going for 1 pulse/rev or 2 or 3 or 4 pulses/rev. Obviously if you go for more pulses/rev you'll need to divide that above RPM by the number of pulses to get the correct RPM.

What’s the highest RPM you’re expecting to see ? And the lowest to be displayed ? (did I already ask that ?) :shifty:

max would be unknown but I expect maybe 10,700 or so, but I planned on the tach. going up to 11,000, just to be a little safe. The lowest I would like to display is 900 rpm, just because it is above crank rpm and below the idle range, which makes it so you can always tell what is going on.

I just left the “-1” there to be the baseline for 1 pulse, I will change it if what I thought about the number of pulses increasing frequency is correct. You may have asked but I changed the lower limit I think…idk that number keeps changing in my head all the time, but I will keep it at that number from now on.

BlindAssassin111:
I just left the “-1” there to be the baseline for 1 pulse, I will change it if what I thought about the number of pulses increasing frequency is correct.

You mean the -1 in …

rpm = ( numPulses < 2) ? 0 : ( 60 * 1000000.0 * (float)(numPulses - 1) ) / (float)( lastPulseTime - firstPulseTime );

That’s correct and independent of the number of pulses/rev. The ‘timings’ record the 1’st and last pulse times and so if there’s 1 pulse/rev what those times mean can be thought of this way;

  • the number of pulses is set/reset = 0.

  • the 1’st pulse comes in and it’s time of arrival is recorded. Pulse count now = 1.

  • the second pulse comes in and signals the end of the 1’st rev, start of the 2’nd rev. Pulse count is now 2 but there’s only been 1 revolution and the ISR has recorded it’s start and stop times, aka it’s period (= 1/frequency).

  • the third pulse comes in and now the pulse count = 3 and you have got 2 periods recorded, the start and the end times after 2 periods.

  • more and more (perhaps) pulses come in and you always have 1 pulse more than you have periods.

Now it comes time to use that data to compute the RPM. RPM = 60*frequency. The end time - the start time is the total time for N periods. Divide that total time by the number of periods (= pulse count -1) and you have an average period. Do a 1/(ave period) … and account for the fact that you measured in usecs … and you’ve got frequency of pulses (pulses/second). Multiply by 60 to get pulses/minute = RPM. Now if you double or quadruple the pulses per rev then the above will yield an RPM that’s 2x or 4x too high. So the -1 stays and, perhaps, an additional division will be needed to get true RPM.

At least that’s my thinking. :twisted:

If you understand the above and how the last code worked, let me play the Joker and confuse the F out of you.

If you’re concerned about how fast the display will/can react to the tach output then another scheme might work (or might not). Instead of waiting a fixed time, independent of RPM, how about you have the code measure a fixed number of periods, perhaps just 1 … but likely some more. That way when the RPMs are low and the period is long, the bargraph update rate is also slow. But as the RPMs increase, the display update times fall. It’s different code to be sure and I’d recommend you try, and tweak, the above code before finding it unacceptable and try going down a different path.

Consider that at 900 RPM there’s no need to update the display any quicker than every 1/(900/60) secs = 66.66 msecs. IOW at 900 RPM (= 15 pulses/sec) there’s 66.667 msec between pulses … given 1 pulse/rev. So if you are content with whatever error there is in measuring just 1 period, you could get by with 66.67 msec between display updates. And much less as the RPMs rise. At 9000 RPM it’s a factor of 10 less, 6.67 msec between updates … faster than the blink rate. Of course you could always measure 2 or 3 or 4 periods … and even more, given more (than 1) pulses/rev.

I question how useful such a scheme is though. Let’s pretend that you’re not into the max RPM region yet. And the RPMs are bouncing between 2 displays on your bargraph display, N LEDs on and N+1 LEDs on. At low update rates you’ll see N LEDs on and then N+1 LEDs on, clearly bouncing back and forth. At higher update rates you’ll see the display flickering between N and N+1 LEDs on. And at even higher update rates you’ll see N LEDs on and then faintly one more LED more on (the N+1 LED). That LED is dimmed because it’s being PWM’ed at a rate faster than your visual system can respond to. All are ‘valid’ displays of the changing RPMs but what do you want in that case ? What display offers more usable info ?

FWIW upate rates > 100/sec (100 Hz) tend to be of the last variety. Your eyeballs and brain just can’t distinguish on/off happening at less than 10 msec (5 on/5 off) periods. It just looks dimmer. That’s how PWM works to dim LEDs.

I think I will stay with the set polling rate just because I like it and I prefer that style of coding.

I got a response from the ECU company and the ‘pulses per rev’ setting does increase the frequency by the given factor ( 1, 2, 4, 6, or 8, there is no 3, I thought there was but higher numbers are better anyways). With that said I think I might just go ahead and set it to 8 so that it has the fastest possible time between updates. So for 600 rpm the frequency would go from 10 to 80Hz!!! So the range I can read now is a whole lot larger I could even read cranking with this. So to read 900 rpm ( 120 Hz) I would need to have 16.6667ms in order to read that frequency, which is a whole lot better than 133.3333ms!!!

Only part I am going to change in the code to reflect the change in frequency is multiply the time by 8 and that will allow the correct RPM to be calculated. Hopefully in the next couple weeks I will be able to get the needed hardware to test all of this, but I am not sure how easy that will be.

Mee_n_Mac you are awesome! Thank you for all of the help you have given me with such an interesting task, I couldn’t have done the whole blinking thing or even how to limit the pulse voltage without your help.

You’re welcome and I want to see a vid when it’s done … or it didn’t happen. :mrgreen:

Mee_n_Mac:
You’re welcome and I want to see a vid when it’s done … or it didn’t happen. :mrgreen:

I wish I could update you with a video but, our team is in debt at the moment…So this project won’t be officially finished for a while now. But I do have some screen shots of the design in Solidworks so you can see what I have done so far, and hopefully soon I will be able to actually make it and test it out.

You also get a sneak peak at my paddle shifter design which took a while, this is version 2.1 (went from 1-1.5 last year and started over with 2.0 this year).

Ok so now that I am being told to also include a gear indicator, Just so I don’t have to open another thread and hope that someone reads it and replies to it, I will ask here. How would I wire this https://www.sparkfun.com/products/10103 with a pro mini powered by 9V(will be using a regulator but still a little confused on which GND pin to use when the 9V is soldered into the RAW pin). And I am assuming I would need to use the 3.3v version of the Pro Mini, Correct?

So now I have to make all of these projects fit into one assembly on the wheel( a Pro Mini will be in the housing along with the Bar graph breakout, a Neutral LED, the display driver, the display itself and the huge cable used for out MIL-SPEC connector…I hate having people wanting this much from such a small place, especially when they don’t realize how each project needs a separate board to do it and expects it to be really easy to do…

How would I go about making a circuit to sense when there it power put into it, when the paddle is hit(not sure how long it will be on but it will be as fast as fingers tense and relax when under the influence of adrenaline) but not affect the voltage that goes to the pneumatic solenoids for the shifter? I think what I am asking for is basically a voltage reference but I am not 100% sure if that is what is needed or what, and if so what is a very efficient way to do so? I will look into code a little bit later as I am trying to also focus on classes.

Thank you for helping in advance, if I am lucky enough to get more help that is :pray: :P.

BlindAssassin111:
How would I go about making a circuit to sense when there it power put into it, when the paddle is hit(not sure how long it will be on but it will be as fast as fingers tense and relax when under the influence of adrenaline) but not affect the voltage that goes to the pneumatic solenoids for the shifter? I think what I am asking for is basically a voltage reference but I am not 100% sure if that is what is needed or what, and if so what is a very efficient way to do so? I will look into code a little bit later as I am trying to also focus on classes.

Getting an interface to the IC you listed should be EZ. It uses a standard SPI protocol (Google it) and there's an Arduino library. What I see as "tricky" is getting the gear/shift info such that it can't get out of sync (display vs gear engaged). Can you describe the gear-train/tranny/shifter a bit more. You used the word 'paddle' which makes me worry that there's no easy way to know what gear is engaged.

Mee_n_Mac:
Getting an interface to the IC you listed should be EZ. It uses a standard SPI protocol (Google it) and there’s an Arduino library. What I see as “tricky” is getting the gear/shift info such that it can’t get out of sync (display vs gear engaged). Can you describe the gear-train/tranny/shifter a bit more. You used the word ‘paddle’ which makes me worry that there’s no easy way to know what gear is engaged.

So I forgot to save what I was going to type so hopefully I get everything this time around…

I realized after I posted that I already had the library and it allows all pins(minus GND and VCC obviously) to be programmed. So I will be doing: SDO to 9, CLK to 8, LE to 7, and OE to 6. But once again I get lost with how to wire the zener…If you would so kind as to edit the attached picture that I have drawn of the Pro Mini and the display driver, to include a way to read when the paddle switch makes contact(which would be 14.3-14.4V for a very small time period)so the board can pick it up, I would really appreciate it. I can’t figure out where the negative side of the zener goes I can calculate the resistance, but I just cant figure out the rest of that wiring.

I have another signal that needs to come in that is grounded when the transmission is in neutral, which is how the program can tell once, using a start-up sequence that requires you to downshift until in 1st (neutral being a half-shift between 1st and 2nd in a sequential transmission), the neutral signal is received and the the last paddle hit was the downshift, then the system is set and it will display 1. While during start up it will display an asterisk to show that the start up sequence is still in effect. For this signal I know I need a pull up resistor but what would be the best way of doing so?

Will upload later my internet at my apartment sucks and times out when trying to get the picture to work…

maybe this will work: https://www.dropbox.com/s/gigbneg546ncu … 5.png?dl=0

Let me be sure I’ve properly understood the situation. An up- or downshift will momentarily put “battery voltage” on a line and then that lines does what … go open circuit (no connection) or go to ground or ? Same question re: neutral … it gets grounded momentarily and then what ?

Mee_n_Mac:
Let me be sure I’ve properly understood the situation. An up- or downshift will momentarily put “battery voltage” on a line and then that lines does what … go open circuit (no connection) or go to ground or ? Same question re: neutral … it gets grounded momentarily and then what ?

Didn’t even think about having to supply that info…sorry about that.

Both go to open after, up/downshift goes from 14.4v when used to open, where as the neutral goes to open when in any gear, but stays grounded while in neutral. There will be a short blip of ground when going from 2 to 1 because of neutral being in between those gears. But both the paddle shifters and the neutral switch are separate, and the arduino will just look to see what each system is doing.

So after a while of thinking I may have figured out how to wire a zener finally…Do I put the input voltage going into the resistor then a split, one side goes to the pin to see the signal and the other section goes to the zener then to the GND pin?

BlindAssassin111:
So after a while of thinking I may have figured out how to wire a zener finally…Do I put the input voltage going into the resistor then a split, one side goes to the pin to see the signal and the other section goes to the zener then to the GND pin?

The idea is that when open, the circuit get's pulled down to ground and so presents a logic low to the digital input. Then when the "battery level voltage" is applied, the zener goes into "zener mode" and limits the voltage on the pin to a safe logic high level. I'd do something like this ...

While you could probably eliminate R2, I put it in to quickly drain off any voltage on any small cap that’s present. The zener value is picked to equal to or just under your MCU voltage, perhaps 4.9V in this case. R1 is chosen to allow 2-5 mA to flow into the zener. R2 is chosen to = R1.

Ok, so maybe it is just me but I don’t see how that would help me right this moment…If I have a pos./neg. attached to the arduino that goes to the ground bus for the car, and I have a pos. lead that goes from the switch on the paddle shifter to the solenoid that actuates the pneumatic piston. I need some way of telling when the switch closes but I only have that pos. lead, no ground from that. How would I go about this? I thought I would need a “voltage” reference style circuit that just splices in between the switch signal wire and regulates the voltage down to a usable value for the arduino. Because from the drawing that you posted the negative seems like you meant it came from the shifter, or maybe you meant it goes to the neg. wire for the arduino power.

As you can tell I have little understanding of how this works and seeing as I am taking Mech. E. courses right now I can only research in between homework assignments, and so far I have not been to sure of what to exactly look for, that is why I said I might need the voltage reference circuit thingy, but it may not even be correct, it just made since to me at the time. I can probably get the code for this project easier than I can the other project, but I have more trouble with the wiring of this one. Could you also label what each wire you have that ends, so that I can tell exactly what you are trying to say. I know this may be a lot to ask but I am in a little over my head and just cant seem to wrap my head around this voodoo right now… I appreciate all that you have done for me and I know you probably have better things to be doing with your time, and I am grateful that you choose to spend some of that trying to get me to understand what may be very simple, but just isn’t what my brain is geared towards.

I also have another Idea to run by you, If I were to make the neutral LED a separate circuit and just have the neutral signal somehow connected to the LED and power to get it to turn on would that be an easy job? Would I just put power to the anode with a resistor that dissipates the needed voltage and then the cathode attached to the neutral switch, so that when the switch is grounded, the LED turns on or will this not be a good idea? I have a different idea for the whole setup sequence, that no longer requires the neutral signal going to the arduino) but for right now I will just stick to figuring out wiring, then move on to coding.

BlindAssassin111:
Ok, so maybe it is just me but I don’t see how that would help me right this moment…If I have a pos./neg. attached to the arduino that goes to the ground bus for the car, and I have a pos. lead that goes from the switch on the paddle shifter to the solenoid that actuates the pneumatic piston. I need some way of telling when the switch closes but I only have that pos. lead, no ground from that.

Perhaps I should have labelled that schematic better but that bottom line is the common ground. The same reference point that ties the battery - terminal, the alternator (if there's one) - terminal and usually the vehicles frame together. It's the same ground reference for any voltage, including the paddle shifter. Since the Arduino GND pin is also tied to that common ground, you don't need another ground wire from the paddle shifter, all you need is the switched "battery voltage" (ranging from battery 12+V to the alternator 14+V).

So when the paddle switch is open, there’s no voltage applied to the top of R1. R2 makes sure there’s some (weak) path to ground for the Arduino digital input pin and so w/o any voltage, the pin will be read as a LOW. When there is 14+V applied, the R2 and R1 try to make a voltage divider. If the zener were not there, the voltage at the pin would be :

14+V * (R2/{R1+R2}). If R1 = R2, then you’d get 1/2 the applied voltage, which would be 7+V and that’s too high for a 5V input pin. So you get an ~5V zener (4.5-5.1V is OK). Now, if there’s enough current, the zener is said to “break over” and conduct current in what would be a reverse direction for any normal diode. The beauty of a zener is that this happens at a known voltage.

So let’s do some conservative calculations … I want at least 2 mA to flow through the zener under worst case conditions and that, for this part of the calcs, is at the lowest voltage. So let’s say the battery could get down to 12V and still run the vehicle. The current through R1 is set by the voltage difference btw the “battery” and the zener divided by R1 (Ohms law). Some of the current through R1 will flow through the zener and some through R2. The amount through R2 is the voltage set by the zener/R2 (Ohms law again) So :

(12V-5V)/R1 = (0.002A min + 5V/R2) and since we decided to have R1 = R2 :

7/R1 >= 0.002 + 5/R1 or …

7/R1 - 5/R1 >= 0.002 or …

(7-5)/R1 >= 0.002 or …

R1 <= (7-5)/0.002 <= 1000 ohms

1K ohms is a nice round number so let R1 = R2 = 1k ohms !!!

Now check on power dissipations at the highest expected voltage. Let’s have the alternator run to 15V. Since the zener will still be ~5V, the current through R2 is the same. By Ohms law I = V/R so IR2 = 5/1000 or 5 mA. Power is V*I and so PR2 = 5V * 0.005A = 0.025W, aka 25 mW. Since resistors are generally 1/10 or 1/8 W rated (100 or 125 mW), R2 is safe.

The voltage across R1 is now 15V - 5V (set by the zener) = 10V That’s 2X what R2 is seeing and since R1 = R2 it’s 50 mW and so R1 is just safe enough (safety factor of 2) for me.

What about the zener ? If at high voltage 10 mA is flowing through R1 and only 5 mA through R2, the rest must be flowing through the zener … that’s 5 mA. That’s the same as through R2 and so the zener must also be dissipating 25 mW. Since most are 500 mW, it’s safe too.

So all is good and even slight differences in the numbers above won’t change the analysis enough to make a distinction.

BlindAssassin111:
I also have another Idea to run by you, If I were to make the neutral LED a separate circuit and just have the neutral signal somehow connected to the LED and power to get it to turn on would that be an easy job? Would I just put power to the anode with a resistor that dissipates the needed voltage and then the cathode attached to the neutral switch, so that when the switch is grounded, the LED turns on or will this not be a good idea? I have a different idea for the whole setup sequence, that no longer requires the neutral signal going to the arduino) but for right now I will just stick to figuring out wiring, then move on to coding.

You certainly could have a neutral light independent of the Arduino. You could just stick any 12V bulb between the neutral switch and the "battery". When the ground is applied, the light comes on. If you want to be hi-tech, use a resistor and an LED. One end of the resistor goes to the "battery" (12-15 V). The other end is connected to the + end of the LED. The - end of the LED goes to the neutral switch. Same as before, when the ground happens (in neutral) the circuit is complete/closed and current flows from the "battery" through the resistor and LED to ground. The LED lights up. The value of the resistor depends on the LED chosen. There are online calculators for this. But in general most LEDs are "happy" w/20 mA flowing through them, 30 mA MAX ! LEDs have a nominal voltage, called Vf, that varies w/the color of the LED. Red LEDs have the lowest Vf, perhaps ~ 1.8V. Blue and "white" LEDs, the highest, about 3.2V. Similar to the calcs above, you determine R from the current (20 mA) and the voltage difference (highest battery - Vf). So R might range from (15-1.8 )/0.02 = 660 ohms to (15-3.2)/0.02 = 590 ohms. A standard value of 620 ohms might be a good compromise. Higher values if you want a dimmer LED for night time vision.

Okay, so me not 100% knowing what I am doing, I was stupid and assumed that the switches actually have the battery voltage running through them… Well just looked at the wiring diagram from last year and I just realized that the paddle shifter switches just grounded the solenoids to allow the current to flow. So now that I know this and am actually forced to use the old setup, I have to use a digital input on the ECU for shift ignition-cut on a pin that has to be brought low, which is the only digital input left so that has to be done that way. And the shift ignition-cut is actuated by the upshift switch so I believe this would be a whole lot easier but I am not sure exactly how to do this safely because I have never built a circuit that use switches to ground other things and needing those signals to be read…

Basically just to make sure you understand my babel just now, I will simplify it to make more sense.

  1. There are 2 switches in the shifter system, 1 that actuates both downshift and clutch, and the other actuates both upshift and shift ignition-cut.

  2. All signals ground when used.

  3. I would need to be able to read a ground signal that comes from the upshift and the downshift/clutch switch while not interfering with the shift ignition-cut circuit(in the manual it states that the shift ignition-cut needs to be grounded to battery negative, don’t know if this makes it more difficult or if it isn’t a problem)

  4. The arduino is a bystander in this situation and just looks to see when things are used and then tells the display what to, you know, display…while not interfering with the operation that the switches have to do in the first place.

I thank you for that drawing and explanation for the zener because that actually did help me understand the whole thing better, so it wasn’t for nothing!!

BlindAssassin111:
I just realized that the paddle shifter switches just grounded the solenoids to allow the current to flow. So now that I know this and am actually forced to use the old setup, I have to use a digital input on the ECU for shift ignition-cut on a pin that has to be brought low, which is the only digital input left so that has to be done that way. And the shift ignition-cut is actuated by the upshift switch so I believe this would be a whole lot easier but I am not sure exactly how to do this safely because I have never built a circuit that use switches to ground other things and needing those signals to be read…

From the above I would think that the 2 solenoid ends, prior to be grounded, are at "battery voltage" when no current is being drawn through the solenoids. So I would opto-isolators to allow that end and the ground switches to signal the Arduino on a non-interfering basis. So that's a 620 ohm resistor btw the "battery voltage" and the + LED (anode) input of the opto. The - LED (cathode) pin of the opto goes the above switch. The emitter pin of the opto goes to the ground nearest to the Arduino and the open collector pin of the opto goes to the Arduino input pin. The pin should be configured as an input w/pullup enabled.

http://arduino.cc/en/Reference/Constants

http://arduino.cc/en/Tutorial/InputPullupSerial

https://www.sparkfun.com/products/784

https://www.sparkfun.com/datasheets/Com … ps2501.pdf

So when the switch is activated and the ground applied to the solenoid, it also grounds the LED cathode and current flows through the internal LED. It’s photons effectively saturate the transistor, tying it’s collector to the (grounded) emitter. That grounds the Arduino pin, reading a LOW, which is otherwise pulled up to a logic HIGH via the internal resistor.

OK, I drew up an idea I had that might work, not 100% sure, but it seems viable. I can’t upload the drawing because the internet in my apartment sucks right now. I will have to upload while on campus tomorrow to see if it works.

https://www.dropbox.com/s/i750ik4y8aiax … 5.jpg?dl=0