The Bresenham algotrithm is perfectly suited for this, can be very accurate, and is easy to understand and implement.
It may be easier to treat it as a
Digital differential analyzer instead. (The technical or mathematical differences are neglible here; I only mean that as a differential analyzer the approach is easier to understand and work with.)
Digital differential analyzer is a fancy name for accumulators whose overflow (or "carry") indicates an output event – a high pulse in the case of pulse density modulation, or a diagonal step (instead of a straight one) when rasterizing lines, and so on.
The root idea is anyway the same as for a 2D line, except the two axes are now both time: one is input time axis, and the other is output time axis. The slope of the "line" is the ratio of input time to output time – or, in the case of pulses, the number of input pulses to output pulses.
In the pulse count adjusting case, one detects say rising edges, and for
N rising edges generate only
M rising edges, with
M ≤
N. This is stupidly simple to implement even in a pin change interrupt handler – the biggest "problem" is to manage the opposite edge of the output pulse –, and amazingly accurate considering how little resources it takes to implement. However, the restriction
M ≤
N is a "hard one", and comes from the fact that each input event can generate at most one output event. In computer graphics speak, with
M >
N you get holes in your line.
When the tire diameter is larger than expected, the number of pulses from the drive train underestimates the distance traveled, so you actually need to generate
more pulses, not
fewer. So, we're firmly in the
M >
N land, and a pure free-running Bresenham/DDA pulse (edge) generator alone won't work.
Instead, a microcontroller implementation would need to be a pulse generator, whose pulse interval is adjusted based on the input pulse intervals. This is very similar to implement – not difficult at all even with simple AVR microcontrollers –, but with a core difference: the input and output are connected only by the control variable, and not by physical events. Usually, there is a small time delay, so that the output pulse rate is calculated based on more than one input pulse interval. Mathematically or design wise, it also matters whether we only care about the pulse frequency, or also about the total pulse count (for the odometer) – but this is more about where we can ignore "rounding errors" and where we need to consider more details, nothing "hard" per se.
The output side can be either PWM (with a small duty cycle, adjusting the base frequency instead), or use pulse density modulation with a simple DDA/Bresenham with less than 50% duty cycle, to generate a very stable and nicely behaving, but very responsive output pulse train. The input side is a basic pulse frequency or interval detector, with its time base tied to the time base of the output side, but otherwise free running (does not need to be calibrated at any specific frequency or anything, since the output is ratiometric; i.e. the number of output pulses in
any given interval is a specific constant ratio of the number of input pulses). If you have a microcontroller without interruptions running at say 10× or higher frequency (of main loop iterations, not instructions per second!) than the maximum input or output pulse rate, this can be made rock solid; one trick I'd like to see used is tracking transitions (both edges of the pulses), as then the state machine becomes amazingly simple.
(Personally, I'd implement this in two different parts: one being the pulse frequency unit itself, with just a standard ICSP connector, and the other reprogramming it whenever the ratio needs adjusting or calibrating, with a small display and a couple of buttons, to adjust/set the new ratio of speeds or distances.)
The problem is making it automotive grade, electronically! Paying $50 for something that
ought to be, doesn't sound bad at all to me.