ATMega168 Tachometer help using LM2907 chip

Thread Starter

StealthRT

Joined Mar 20, 2009
317
the clear() allows it to "refresh" with other values. Without it, it will only display the first numbers it finds and never anything thereafter.

David
 

Thread Starter

StealthRT

Joined Mar 20, 2009
317
Ok i get 10, 9 and 8 once i put the key into ACC. Once started i get maybe 90? or it might be 900. But i cant really tell for sure.

David
 

bill2009

Joined Apr 17, 2009
31
it should be changing hundreds of times a minute so it could be a bit hard to track!

Here goes some more code:
Rich (BB code):
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 11, 7, 6, 5, 4, 3);
 
void setup()
{
while (analoglRead(0)>350) {} //spin til no tach pulse
while (analogRead(0)<=350) {} //spin til 1st tach pulse begins
unsigned long pulse1=millis(); //track time when 1st pulse begins
while (analogRead(0)>350) {} //spin til 1st tach pulse ends
while (analogRead(0)<=350) {} //spin til next tach pulse begins 
unsigned long pulse2=millis(); 
int rpms=30000/(pulse2-pulse1);  
lcd.clear();
    lcd.print(rpms);
}
 
void loop () { 
}
we're taking the rpm calculation out of the loop so it only runs once. with the engine running you should be able to reset the arduino as often as you like and get sample readings.
 

Thread Starter

StealthRT

Joined Mar 20, 2009
317
Alright, here are my readings:
Rich (BB code):
    Off: 0
    ACC: 114, 38, 114, 314, 28..
Running: 1250, 5788, 1304, 1363, 1428, 1363, 1304, 1428...
Revving: 2500, 2700....
Looks like its working ok?

I also added a delay in the code as so:
Rich (BB code):
lcd.clear();
 lcd.print(rpms);
 delay(300);
And i pretty much got the same results as the other code pushing the reset button.

David
 
Last edited:

bill2009

Joined Apr 17, 2009
31
hey great. I'm puzzled by the ACC numbers though - I can see getting a reading or two when you switch the circuit on but not if the whole thing is just sitting there and the arduino is cycling thru that code - does it stop after a while? Maybe you do need the little capacitor. I would actually expect the arduino to "hang" if the car is not running - never produce a result because it needs to see that tach lead go low, high, low and if the engine's not running there should be no pulses.

Also, it's possible that you are getting multiple pulses per engine revolution. On my car idle is <1000 rpm. You should probably poke at the edges of this till you can trust the reading.

You certainly have the hardware for your solution though. Do you need any more help with the software? I would envision you making a function called RPMS that returns an int of the engine speed or 0 if it's not running. To handle the case where it's not running you will have to add code to limit the 2nd, 3rd, and 4th while loops in the routine by testing against something derived from millis() so you don't sit there forever waiting for it. In the main code I would call the thing, wait a while then call it again before I trusted that the engine was solidly running.
 

Thread Starter

StealthRT

Joined Mar 20, 2009
317
Hum.. well i take it i should get a 4.7uf tomorrow at radio shack and place it between the 330k and arduino pen?

I dont really understand your code. Could you let me know which each step is doing?

I like this code:
Rich (BB code):
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 11, 7, 6, 5, 4, 3);

volatile int tachCount = 0;
long time;
long rpm = 0;

void setup()
{
  attachInterrupt(0, tachPulse, RISING);
  time = millis();
}

void loop()
{
  //Runs every 1/4 second
  if (millis() - time >= 250)
  {
    // rpm = number of interrupts counted in 250ms
    //  *4 to make per second
    //  *60 to make per minute
    //  /3 for 3 pulses per rotation (6 cylinder)
    //  /10 for some reason???
    rpm = (((tachCount*4)*60)/3)/10;

    lcd.clear();
    lcd.print(rpm);

    tachCount = 0;
    time = millis();
  }
}

void tachPulse()
{
  ++tachCount;
}
I understand that a lot more :) I just dont know if the (((tachCount*4)*60)/3)/10; is the correct formula.

David
 

bill2009

Joined Apr 17, 2009
31
Hum.. well i take it i should get a 4.7uf tomorrow at radio shack and place it between the 330k and arduino pen?
No that wouldn't work. You need a small capacitor like 100pf, and it needs to be in parallel with the 330K. The small cap acts like a shock absorber in the circuit so if there's a momentary spike it will soak it up and the arduino doesn't see it. The 4.7uf would be too big.

I like this code:
I like that code too! That's using interrupts which is a fine idea but you need the arduino seeing digitalRead() highs and lows which we couldn't do the other day. You could try that code with the signal on pin 2 instead of analog 0 now that you know the basic circuit works. If that doesn't work try substituting a 470K for the 330K but make sure you get the 100pf capacitor first.

Just a note on the two resistors. The car is producing 14+ volts when it's running. If you hooked that straight to the 5V arduino it would blow up. When the 14V goes through the combination of the 1M and 330K in series it gets divided so only 1/4 of the voltage shows up across the 330K and the arduino sees a max of 14/4 or 3.5 volts. It would take a huge spike to hurt the arduino. If you change the 330K to 470K the arduino will see almost 1/3 of the voltage or nearer 5V - if the 3.5V wasn't enough for the arduino to consider it HIGH, this may work.
 

Thread Starter

StealthRT

Joined Mar 20, 2009
317
Alright, i placed the 100pf in parallel and tested it out. I get a constant 114 when on the ACC. RPM's look good once the car has started. However, i cranked it a could times and i did, from time to time, get vary high values 30,000+ but dropped down the the 1,000's quickly after.

David
 

bill2009

Joined Apr 17, 2009
31
so with the power on but the engine not running you press the button every few seconds and get the same 114 on the serial each time? That's genuinely odd.

The general nature of the problem is that we're timing only one tach pulse. That's bound to be erratic but the 114 is a mystery - it indicates a pulse coming every 1/4 second.

So, ways to go:
-double up the analog code so you're timing at least two pulses - be prepared for the fact that the arduino should seem to stall if the engine's not running.
-make the test for a pulse more stringent by changing the 2nd and 4th 350's in the code to maybe 700 - again the arduino should NOT give a result if the engine's not running.
-try the interrupt code with the 330K resistor changed to 470.
 

Thread Starter

StealthRT

Joined Mar 20, 2009
317
Ok i've tried the digital pin 2 and the following code with the 330k & the 470:

Rich (BB code):
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 11, 7, 6, 5, 4, 3);

volatile int tachCount = 0;
long time;
long rpm = 0;

void setup()
{
  attachInterrupt(0, tachPulse, RISING);
  time = millis();
}

void loop()
{
  //Runs every 1/4 second
  if (millis() - time >= 250)
  {
    // rpm = number of interrupts counted in 250ms
    //  *4 to make per second
    //  *60 to make per minute
    //  /3 for 3 pulses per rotation (6 cylinder)
    //  /10 for some reason???
    rpm = (((tachCount*4)*60)/3)/10;
    
    delay(300);
    lcd.clear();
    lcd.print(rpm);

    tachCount = 0;
    time = millis();
  }
}

void tachPulse()
{
  ++tachCount;
}
But i do not get anything (just 0) when hooking it up to the tach. However, i do get some values if i use the 12v test.

Ill need an example for the double up code... Did you mean something like this?:
Rich (BB code):
while (analogRead(0)>350) {} //spin til no tach pulse
while (analogRead(0)<=350) {} //spin til 1st tach pulse begins
unsigned long pulse1=millis(); //track time when 1st pulse begins
while (analogRead(0)>350) {} //spin til 1st tach pulse ends
while (analogRead(0)<=350) {} //spin til next tach pulse begins 
unsigned long pulse2=millis(); 
int rpms=30000/(pulse2-pulse1);  
while (analogRead(0)>350) {} //spin til no tach pulse
while (analogRead(0)<=350) {} //spin til 1st tach pulse begins
unsigned long pulse1=millis(); //track time when 1st pulse begins
while (analogRead(0)>350) {} //spin til 1st tach pulse ends
while (analogRead(0)<=350) {} //spin til next tach pulse begins 
unsigned long pulse2=millis(); 
int rpms=30000/(pulse2-pulse1);
It seems i may have had the 100pf in the wrong spot. i have it in paralle with the 1m. I moved it to be parelle with the 330k. I now get 22/56/33 in ACC.... See picture:


David
 
Last edited:

bill2009

Joined Apr 17, 2009
31
yes, so in that pic the green jumper on the right is from the tach, orange is going to the arduino and the yellow is to ground - right?

A number like 22 rpm would mean you were getting a pulse after 3 seconds. I imagine that's just an artifact related to pushing the button - remember that there should be NO pulses when the engine isn't running.

I don't know why the pin 2/interrupt doesn't work - you just see a 0 on the LCD - right?

for doubling up, I meant something like

Rich (BB code):
while (analogRead(0)>350) {} //spin til no tach pulse
while (analogRead(0)<=350) {} //spin til 1st tach pulse begins
unsigned long pulse1=millis(); //track time when 1st pulse begins
while (analogRead(0)>350) {} //spin til 1st tach pulse ends
while (analogRead(0)<=350) {} //spin til 2nd tach pulse begins 
while (analogRead(0)>350) {} //spin til 2nd tach pulse ends
while (analogRead(0)<=350) {} //spin til 3rd tach pulse begins 
unsigned long pulse2=millis(); 
int rpms=(30000/(pulse2-pulse1))*2;
remember that we expect this to stall if the engine isn't running. If you're not resetting the arduino between readings make sure the lcd gets cleared before you start this or you'll be looking at an old reading when it stalls.
 

Thread Starter

StealthRT

Joined Mar 20, 2009
317
alright, just tried the double up code and it shows nothing on the lcd.
Rich (BB code):
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 11, 7, 6, 5, 4, 3);
 
void setup()
{

}
 
void loop () {
while (analogRead(0)>350) {} //spin til no tach pulse
while (analogRead(0)<=350) {} //spin til 1st tach pulse begins
unsigned long pulse1=millis(); //track time when 1st pulse begins
while (analogRead(0)>350) {} //spin til 1st tach pulse ends
while (analogRead(0)<=350) {} //spin til 2nd tach pulse begins 
while (analogRead(0)>350) {} //spin til 2nd tach pulse ends
while (analogRead(0)<=350) {} //spin til 3rd tach pulse begins 
unsigned long pulse2=millis(); 
int rpms=(30000/(pulse2-pulse1))*2;

lcd.clear();
lcd.print(rpms);
delay(300);
}
the green is the tach wire / orange is to the andruino analog 0 and the yellow is ground.

Yes, i just see 0 when i run it using the tach but see different values when i use the 12v test here in the house on it and touch it then reset it and touch it, etc etc.

David
 

bill2009

Joined Apr 17, 2009
31
So with the engine running you should get something. All I can suggest is compare the circuit and code to where you were may 19 when it worked.

Honestly though, this has to be more trouble for you than it's worth. I don't mind continuing and maybe we could figure this out eventually but it just feels like it's going to be flakey. I would start looking for bullet proof ways to condition the tach signal before the arduino sees it.

Did you have this working originally with the separate 2907 chip? If that's reliable it has to be a better idea.
 

JimEli

Joined Jun 12, 2009
1
Thanks for all the work, i have been following this thread, and was wonder if you guys could give an update to the current code and schematics. It's slightly confusing at times to follow.
 
Top