Convert from an input pulse frequency to output another in near real time?

Hi, I hope somebody can help me understand the structure of what I'm trying to achieve. I have a liquid flowmeter with a bad flow sensor. The flow sensor generates a 50% duty cycle variable frequency pulse output from a rotating vane in the liquid flow. The flow pulse output can be static high or low when there is no liquid flow.

The original flow sensor is faulty and obsolete, but I can find similar flow sensors and condition their output voltage levels to those required by the sensing head. I can determine the characteristics of the sensor input by measuring the flow meter with a pulse generator. I expect the flowmeter will be designed with an adaptation curve matching the sensor response used with it. In case anybody thinks designing the flowmeter to match the sensor is a solution, my flowmeter does more including accumulated total volume and other calculated values it logs in its NV internal memory.

In my head, I'm reading the time duration of input pulses, applying a variable to reduce (or increase?) that time then output a modified pulse sequence, changing the variable to match the law of the flowmeter. I'm not looking for huge accuracy and 10 corrected segments for the total expected flow (pulse frequency) range would be a sufficient curve approximation. Only low frequencies are involved from zero up to about 10Khz corresponding to maximum flow. The other idea is to sample and divide the relatively low speed input from the flow sensor into 1uS chunks, time how many in a (or half) cycle, then drop or add to create a modified output pulse stream? But this has to be done in near real time.

When I have characterised what the original sensor was doing for different flow (pulse frequency) rates I can then flow test my subsitute sensor and map it's charactersistics, corrected to follow the original sensor design curve.

Can anybody tell me what I am trying to do is called in the instrumentation world, or suggest a sketch resource that might help me?


If you think of a table of output values indexed by the input values, you will be able to get this going a lot faster.

Of course, a polynomial can be found to approximate almost any curve.

It is called a frequency shifter. It is used in things like auto tune to bring a singer’s voice back into key.

The simple ways of doing this are not accurate, and a lot of systems do not do it in real time. But record the sample and then apply sample scaling by interpolation of the samples to get more or less samples than the original.

In real time you can use the voice effect like I did in this project video.

Pico Voice

That's right - if the relationship is linear, you can just scale the frequency.

Thanks, it won't be linear because the small turbine has mass, then there are fluid losses around the vanes which means rotation speed isn't proportional to flow. As fluid flow increases the turbine runs slower than it should. it's quite a common thing with most rotating vane sensors. Ultrasonic flow measurement does it better but is more expensive to implement.

Thanks, I'm doing that now. I've got values for the flowmeter input, its readings and a 'standard' curve for the new impulse flow sensor. I shall do a physical check on that measuring the liquid volume, number of counts and use a stop watch. Where I'm blind is achieving a modified output pulse stream related to changing frequencies at the input? It's most important that the number of pulses output from the flow sensor over time puts the correct count into the meter, because these values are used to display accumulate total volume of liquid. If my new flow sensor produces more pulses I could count them, drop n in x pulses and send the result to an io port. Although it would be nice to get a continuous output pulse stream, it doesn't matter if there are timing gaps, as long as the total number of pulses counted by the flowmeter and therefore accumulated volume is correct.

Yes, but if the original turbine was non-linear in such and such a way, that is inherent to such turbines, substituting a different turbine may differ only in scale.
e.g. (x^2) -> m(x^2)
But shouldn't such systems operate via a calibration table anyway? Just how accurate is this supposed to be?

Here's a crucial question: Does the new flowmeter produce more, or less, pulses for the same flow?

Also, if in the end you want to know the total volume instead of the flow, why not just count pulses?

To use the pulses to determine flow p/t and then multiply by t to get volume, is going around the block for no reason...

I don't have any scale for the original faulty turbine. The only thing I can do is measure the flowmeter it was attached to using a pulse generator. Turbine flow sensors come in different shapes, sizes and can have 1 or more magnets attached to vanes for Hall sensing. They do follow similar curves which are usually non-linear for slow and very high liquid flowing through them. My flow meter is measuring fuel flow and accuracy in terms of total fuel volume used (and what remains!) is important both at engine idle and at maximum fuel flow rate.

So why not just count pulses? It's super easy to measure volume that way because it equals v/step * nsteps.

To account for the non-linearity you would simultaneously measure each pulse interval and apply the calibration factor.

The only thing I can do is measure the flowmeter it was attached to using a pulse generator.

That's actually just perfect, it will yield a calibration table.

Thanks you have given me some ideas. This flowmeter is designed as a 'Log' for marine use. It doesn't just read accumulated flow which as you say would be easy to do by replacing the flowmeter with an led display. It also takes starting fuel tank volume in NVRAM and counts down as fuel is used. This is probably the most important function for a boat. I know I could probably do all this from scratch, but the flowmeter I have is physically sized and sealed for boat dash mounting.

If I count pulses from any flow sensor I've still got to correct the result in the calculation to fit the curve whilst allowing for the ability to re-calibrate. This flow meter does that: You allow a measured amount of fuel to flow through, then apply a digital correction factor. Unfortunately it only works for the original sensor for a +-1-2% correction.

I'll go offline now and back to measuring, then come back when I have some substantive results.

Put the table in EEPROM

This could work. Modify the ConvertToHalfCycleTime() function for your desired mapping. It takes the microseconds between rising edges on the input and returns the microseconds in a half-cycle of the output. To have the output track the input, return inputCycleTime / 2.

const byte InputPin = 2;
const byte OutputPin = 3;

volatile unsigned long PreviousInterruptTime = 0;
volatile unsigned long InputCycleTime = 0;

void setup()
  pinMode(InputPin, INPUT);
  pinMode(OutputPin, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(InputPin), InputISR, RISING);

void InputISR()
  unsigned long thisInterruptTime = micros();
  InputCycleTime = thisInterruptTime - PreviousInterruptTime;
  PreviousInterruptTime = thisInterruptTime;

unsigned long ConvertToHalfCycleTime(unsigned long inputCycleTime)
  return inputCycleTime * 1.3333;  // Remember, going from full cycles to half cycles

void loop()
  unsigned long currentMicros = micros();
  static unsigned long lastOutputChangeTime = 0;

  unsigned long ict = InputCycleTime;
  unsigned long pit = PreviousInterruptTime;

  // Only pulse output if the time since the last interrupt is less than one second.
  if (currentMicros - pit < 1000000ul)
    unsigned long outputHalfCycleTime = ConvertToHalfCycleTime(ict);
    if (currentMicros - lastOutputChangeTime >= outputHalfCycleTime)
      lastOutputChangeTime = currentMicros;
      digitalWrite(OutputPin, !digitalRead(OutputPin)); // Toggle each half cycle

I'm back with a vengeance and sticking at the solution! I've now mapped the flow reader for 200 input pulse values and despite what I thought, its output reading V input frequency is precisely linear with <0.5% error. At the low flow end a 37Hz input needs to be 31.6 Hz (say 32 Hz?). The input frequency required for my maximum flow is 527 Hz.

From some research, what I am trying to create with Arduino is 'fractional clock frequency division', which I'm finding hard to understand and even contemplate coding. So with the above values I want to reduce the frequency output from a sensor by a factor of 0.865 throughout its range. The input frequency with a 50% duty cycle changes up and down in real time according to liquid flow rate and stops, but acceleration is relatively slow compared to microprocessing speeds?

I've also looked at phase locked loop options, but nervous about the loop staying locked and vco output frequency stability and jitter.

I put the Arduino nano back in its box for a while to investigate a non-Arduino solution. I breadboarded 3 X CD4089 Binary Rate Multipliers cascaded in add mode with binary coefficients 13,13,6. Fortunately for this application, the flow meter is only counting pulses for its totalizer. The realtime flow readings are extremely laggy and can easily tolerate some dropped pulses using a Binary Rate Multiplier. Fortunately, I had a dozen in my CMOS box. Using 3 CD4089s gives me sufficient granuality to get good conversion accuracy by setting DIP switches, I can fine tune the down conversion 'frequency' in terms of dropped pulse numbers. I'm also fortunate the replacement sensor output is a higher frequency and not far from what the flow meter head requires. The CD4089s would need to be battery supported and always on. Something to take account of for an Arduino solution?

I still want to get an Arduino software sketch solution for 'fractional clock frequency division' with a variable frequency clock rate. I thought this would be something others have needed, particularly for synthesisers? Ideally I'd like the down converted output frequency to be near a 50% duty cycle, but I think that might be hard to achieve.

I am grateful to johnwasser for your input. I'll try to understand your sketch snippet and get it working either simulated or real time. Onwards and upwards!

unsigned long ConvertToHalfCycleTime(unsigned long inputCycleTime)
  // To "reduce the frequency by a factor of 0.865" we
  // multiply the cycle time by 1.156 (inverse of 0.865).
  unsigned long outputCycleTime = inputCycleTime * 1.156;
  return outputCycleTime / 2;

Or a little faster:

unsigned long ConvertToHalfCycleTime(unsigned long inputCycleTime)
  // To "reduce the frequency by a factor of 0.865" we
  // divide the cycle time by  0.865.
  unsigned long halfOutputCycleTime = inputCycleTime * 1000 / 865 / 2;
  return halfOutputCycleTime;
1 Like

This is a low input frequency range for an Arduino, so I see no reason it couldn't do what you want in real time. That is, measure the microseconds period of each pulse then update the frequency of a PWM output by appropriately configuring its timer (register settings).

That's what I like about solving real world applications - things in practice that jump out at you. In this scenario a flow sensor with no flow outputs a logic high or low depending on where the vane magnet(s) is sitting in relation to the Hall sensor. When flow starts slowly, the input square wave increases in frequency from zero Hz. The 31.6 Hz low figure is the manufacturers starting point for linear operation. But the totaliser expects to see the low flow rate pulses and add them to total flow. This is what happens with a gasolene engine which can run with low flow at idle, then fuel flow increases to the level of maximum horsepower with up and down flow fluctuations due to throttle settings in between.

I'm focussed on this old obsolete flow meter because it is a common type type owned by many small boat users who have dead flow sensors. It is a unique product and no longer manufactured. Paddle wheel Flow sensors do not share a common standard for flow versus frequency/pulse count, some have more vanes, some with more than one magnet per vane and the vanes vary in diameter changing the pulse period. The maximum oprating frequency is usually around 1Khz, athough some for low speed high precision flow measurements can be higher. Arduino code offers a universal solution if I can get it to work and the library routines are on my side to help me. Thanks

P.S Even using interrupt routines can I assume the time spent executing code might only introduce a small error, compared to the maximum input pulse duration (e.g 1mS?).

MCU's don't lose clock time (i.e. timed events fall behind) just because some processing happens. That is the purpose of the several on chip hardware timers - they continue to run and keep track of time no matter what the processor is doing.

What you posted doesn't seem to have any response to reply #18 or the earlier #14 for that matter... just an explanation of why you want to do this...