modulate freq output based on freq input and voltage input

Absolute newbie, any advice appreciated:

I have a racecar Ecu that outputs a 0-5v square wave tacho pulse between 0 and 13000rpm. This is my freq input. I also have a throttle position sensor voltage 0-5v analogue that is my second input. I need to output a frequency that is a derivative of both the inputs- effectively dividing my input frequency by my input voltage.

I figure this should be feasible using PulseIn() and a little maths? I have already built an optoisolator circuit on the analogue input as there is a lot of noise on this line.

The output from the arduino will be fed back into the engine ecu, where it gets used in a boost control algorithm.

Is this a bit much for a first project?

thanks, Paul

Is this a bit much for a first project?

a bit,

you should look at interrupts, far better for this application..

Try googling Frequency Counter for measuring a frequency (Tachometer) and the Analog input is easy.

Unless you have a more specific question about the math, I don't think we can help you much for that part. Just don't make it too complicated or you may not be able to finish your computations in time if you are doing it on the arduino (and depending on your sample time).

You might need to explore writing your own timer code to produce the output frequency. You'll need to investigate the timer code itself, and there may be limits. I'm not sure how the timers are allocated on the arduino

PS: This might be easier to do if you start from scratch and skip using the arduino software and instead use Atmel Studio or write your own code. Then you'll know what your timers are doing.

i would use a simple freq to volt converter, actually one capacitor and a diode is enough to get this.

I figure this should be feasible using PulseIn() and a little maths? I have already built an optoisolator circuit on the analogue input as there is a lot of noise on this line.


  1. Pulsein() works only with digital signals (via digital input pins) as in your tach signal. The throttle signal as you stated is a 0-5vdc analog voltage signal that would be processed with a analog input pin using analogRead() commands.

  2. Most opto-isolator are not designed easily to pass a analog voltage signal, but rather just on/off digital signals. Electrical isolation for a analog voltage is not as simple as just passing it through a simple opto-isolator chip.

Thanks for the replies, this site is a great place/resource for a novice like me!
Santa gave me an Uno and I now have a mostly working setup using an interupt for the frquency counter, using mostly cut’n’paste sketches. I have hooked the Uno up to my engine ECU and tested upto 10500rpm (I can’t test to the full 13k rpm in the garage!)
The toneAC() library is working well for my frequency output, but I have a small problem with the frequency counter: I can’t get a frequency reading less than 50Hz. I guess my frequency sample-read of 50ms is the problem, but I really need a fast response as the car gearbox is pneumatic-controlled and can change gear in 20-50ms.
Any suggestions for re-working of my sketch much appreciated.

// Frequency counter sketch, for measuring frequencies low enough to execute an interrupt for each cycle
// Connect the frequency source to the INT0 pin (digital pin 2 on an Arduino Uno)
// Analogue voltage input on A0 pin
// Frequency output both on digital pin 9, and out-of phase on digital pin 10
#include <toneAC.h>
volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile unsigned long numPulses;
int analogInPin = A0;    // select the input pin for the potentiometer
int TPS_Value = 0;  // variable to store the value coming from the sensor
void isr()
  unsigned long now = micros();
  if (numPulses == 1)
    firstPulseTime = now;
    lastPulseTime = now;

void setup()

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
float readFrequency(unsigned int sampleTime)
  numPulses = 0;                      // prime the system to start a new reading
  attachInterrupt(0, isr, RISING);    // enable the interrupt
  return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime);

void loop()
  TPS_Value = analogRead(analogInPin)/4;
  float freq = readFrequency(50);         // sample frequency every 50 milliseconds
  float freqout = freq/TPS_Value;         // output frequency calculated
  freqout = constrain(freqout, 10, 1500); // constrain the output between 10 and 1500hz
  Serial.print(millis());                 // print timestamp
  Serial.print(freq);                     // print input frequency
  Serial.print(freqout);                  // print output frequency
  Serial.println(TPS_Value);              // print analogue input voltage
  toneAC(freqout, 10, 0, true);           // output square wave at output frequency continously in the background