• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Comparator help please -tach/shift light project

mojozoom

Member
Ok, I did some testing with the scope and proved that the duty cycle is correct and the frequencies are very close to what they should be. Then I hooked up the DMM again and everything measured just as it should. I have no idea what the problem was yesterday but today it shows 20%-20.2% duty cycle and 53.3, 133.3, 266.3, 400.0, and 533.2 Hz. That's just about perfect, so I think we can consider the simulator to be working correctly.

Now I'll bring up your code and give that a shot to see how it goes - thanks!
 

Pommie

Well-Known Member
Most Helpful Member
Isn't 533 Hz equivalent to 32,000 RPM or is there more than 1 pulse per rev?

Mike.
Edit, if there is more than 1 pulse per rev then change the rpm*600 to rpm*600/pulsesPerRev.
 

mojozoom

Member
Yes this one has 4 pulses per rev as its a V8. It's the duck's guts.

I wonder what causes the rpm value to waffle around the target? I set the tone to 53.3 hz and revised the last line of the code to total*60/4 and it's trying to give out 800 rpm, but is varying from 795 to 810. It does the same thing when I hook it up to my simulator circuit, so it's not coming from the Tone function.

I'm still running into the calibration issue though. Now that I know the frequencies are correct, I need to figure out how to add a correction in to the output. Here's what it's looking like right now, between the true rpm, the reading on the tach, and the difference.

calibration.JPG
 

Pommie

Well-Known Member
Most Helpful Member
If you take 55.3Hz then that is 5.53 pulses every 10th of a second. This will result in two values being produce at roughly a 50/50 ratio. Those being 5 and 6 - 5*600/4 = 750 and 6*600/4 = 900. This is due to the low number of pulses in the sample period. I realized this would be the case yesterday and wrote the second bit of code which averages ten readings to give a moving average - averaging the above figures should give the correct value. A different approach would be to measure the time between pulses but this would need to be done in μS which I'm not sure the Uno can do.

If I have time later I'll do a bit of reading on timing pulses. I had a quick look at the pulsein code but it uses the millis function and is blocking. Hopefully there is a library that uses hardware to time pulses.

I've just realized that the figures you've given above are from the actual analogue tacho. This probably is the cause of the error as the mechanical tacho will automatically average the readings. If you like I could have a go at doing a "tweening" routine based on your table above.

Mike.
 

Pommie

Well-Known Member
Most Helpful Member
Just had a quick play and I think this should work.

call it by doing rpm=tween(rpm);

Mike.
Edit, if your wondering, tween is just short for inbetween and is also called interpolation.
Code:
uint16_t tween(uint16_t rpm){
  const uint16_t rpm_table[] = {0,800,1000,2000,3000,4000,5000,6000,7000,8000,65535};
  const int16_t  adj_table[] = {0,50,100,50,0,-50,-100,-100,-150,0,0};
  uint16_t low,high;
  int16_t adjLow,adjHigh;
  int32_t adjust;
  uint8_t p=0;
  while(!(rpm<rpm_table[p+1]))
    p++;
  //p now points to the lower of the two rpm values it's between.
  low=rpm_table[p];
  high=rpm_table[p+1];
  adjLow=adj_table[p];
  adjHigh=adj_table[p+1];
  adjust=rpm-low;                   //how far into the triangle are we?
  adjust=adjust*(adjHigh-adjLow);   //multiply by the height of the triangle
  adjust/=(high-low);               //divide by the width of the triangle
  return(rpm+adjust+adjLow);
}
Edit, fixed bug. Made adjust 32 bit to prevent overflow.
 
Last edited:

Pommie

Well-Known Member
Most Helpful Member
I put the above code in an online debugger which can be played with here. If you click "Fork this" then you will be able to edit it to change line 9 (rpm=1000) to test different values (just click run and the result will appear at the bottom). It's a good tool to learn as it enables you to single step through code and see all the variables.

Mike.
 

mojozoom

Member
That's awesome! All I could picture in my head was a bunch of nested if-thens. This is way better - kind of like INDEX/MATCH in Excel.

I'll give it a whirl tonight, and then it's on to the shift lights. I'll probably need to make a pot driven version of my MSD simulator so I can slowly increase the frequency instead of by fixed steps. That should be pretty easy.
 

mojozoom

Member
Ok, I got that code copied in and it works great. I've got rpm and rpmout now, and sending rpmout to the gauge. I'll go solder up some LEDs onto a bit of wire and start thinking over the shift light code

Here's the tach in action, at 800 rpm (approximately idle), and then every 1000 rpm up to 8000 rpm.


There's a bit of overshoot before the needle drops back to the correct rpm value, but that's to be expected for this type of meter. And also why this type of meter was replaced by the air core sin/cos style meter in the early 70s.
 

Pommie

Well-Known Member
Most Helpful Member
Looking good.

You can use a series of if statements to light your LEDs. Something like,
Code:
    if(rpm<6000){         //less that 6000
      //turn off both LEDs
    }else if(rpm<6400){   //between 6000 and 6400
      //light first LED and turn off second
    }else{                //above 6400
      //turn off first and light second
    }
If you want the set point variable then you can read an analogue pin and turn the 5V into 0 to 8,000 with,
Code:
    uint16_t setPoint=analogRead(potentiometerPin);
    setPoint+=8000;
    setPoint/=5;
For added accuracy you could use a 10 turn pot.

Mike.
Edit, If you want to get fancy then you could have a button that switches between set and run modes. When in set mode the tacho could display the setPoint.
 

mojozoom

Member
I get stuck on the easiest stuff....

Right now I'm trying to use a pot to vary the 0-12v square wave from the separate Arduino that I'm using as the artificial MSD signal. I have the pot connected and mapped to the range of on time that represents 800 and 8000 rpm, and it's tracking perfectly. But for some reason it doesn't give the correct frequency out any more, as it plateau's at about 1400 rpm. Time for bed.
 

Pommie

Well-Known Member
Most Helpful Member
I'm not clear what you're doing. If you're feeding 12V into a pin then that could be a problem. Can you post a schematic of what you are doing?

Mike.
 

mojozoom

Member
Certainly - I'm working up a sketch of what I've got going on and will attach that this afternoon as soon as I wrap it up.

I think my current problem is a current problem. I've been running the first Arduino from a wall wart that says 1000 mA but is as light as a feather. Maybe the 10k pot eats up too much? It seems odd, but the circuit works fine when I use the code that steps through the frequencies. I'll pull out a decent power supply and try that this evening.

Regarding setpoints for the shift lights, I'd like to do that via Bluetooth and an Android app. In fact I'd also like to enter the calibration curve datapoints that way. Then the only manual adjustment would be one trimpot to set the full scale 8000 rpm point, and everything else could be done via an app with the dash all back together. And it would be easy to change, and save the cost of pots and dilemma of where to put them in a classic car.

I need to go pick up a HC-05 module yet, the nice thing is that we have a local Micro Center shop that should have those in stock.
 

Latest threads

EE World Online Articles

Loading

 
Top