Motion Decoder Fail: Zero Delta Between Two Samples
I have wired up an Arduino Nano to a retired Canon Pixma MX340 multi-function inkjet, reading the position reported by a rotary motion quadrature encoder in its paper feed motor gearbox assembly. I want to learn how that mechanism worked, and thought it would be helpful to process raw encoder data into a list of movements undertaken by the mechanism.

Looking at the graph I plotted earlier, this looked pretty straightforward. I added code in my Arduino sketch to poll encoder value in a tight loop and, when two consecutive readings have zero delta between them, treat that as a stopped segment between two movements.
This approach did not work at all! But its failure taught me more about this system's behavior.
First lesson: as the print carriage moved around, it jostles the whole frame enough for this paper feed encoder to bounce one or two counts off target. I don't know if it's impossible/impractical to move this motor system by a single encoder position, or if the control system just decided it wasn't important enough to bother. Either way, there are small drifts that were too small for me to see in my earlier graphs but would falsely break up zero-delta periods.
A closely related observation: the motor decelerates as it approached its target position, and it doesn't always hit its target precisely by the time it coasted to a stop. (This is assuming a move of 1798 counts was intended to be a 1800 count move.)
Speaking of that coast phase, the graph shows it can take 20-30 milliseconds before everything comes to a stop. This is a problem, because the Arduino is polling encoder fast enough that it will see the same value multiple on consecutive polls. So if I'm deciding based on zero delta between two readings, it would prematurely conclude the gear train has stopped when it was merely at the very beginning of acceleration or the slow tail end of deceleration.
After one deceleration, the system might immediately start accelerating to execute another motion. One example is visible as the second and third movement in the graph above. From Arduino Nano's perspective, the delta between two consecutive readings never reached zero between those two movements. Maybe the printer control board decided "slow enough" and started the next move before things actually stopped, or maybe the Arduino is not polling fast enough to catch that brief moment of zero rotation.
I had a laugh at how my system managed to poll encoder value at a rate that is simultaneously too fast and too slow. But the conclusion from these new observations is clear: I can't get away with just two encoder samples and look for a zero delta between them, my code will have to base its decisions on more reliable factors.
This teardown ran far longer than I originally thought it would. Click here to rewind back to where this adventure started.
Captured CSV and Excel worksheets are included in the companion GitHub repository.