This is a note about building an angle-guidance device for a dental handpiece, written from the firmware side. It is about the problems that turned out to be real, several of which were not the ones we expected.

The problem, stated precisely

A dentist or dental student wants to hold a handpiece at a particular orientation and know when they have drifted off it. That sounds like a measurement problem. In practice it is mostly a trust problem: a reading that is occasionally wrong is worse than no reading, because the user stops believing the device and stops looking at it.

That reframing drove most of the decisions below. The goal was never the tightest possible error figure. It was a number that behaves predictably enough that someone will keep glancing at it during a procedure.

Why a single sensor is not enough

An accelerometer measures the direction of gravity, which gives you absolute tilt with no drift — but only while the device is still. Every hand movement adds linear acceleration that is indistinguishable from a change in tilt. A gyroscope measures angular rate, which is smooth and immune to that problem, but you have to integrate it to get an angle, and integrating a small bias error produces an angle that slides away from truth over time.

Neither is usable alone for this. The accelerometer is right in the long run and wrong in the moment; the gyroscope is right in the moment and wrong in the long run. Fusing them is not an optimisation, it is the minimum viable approach.

What calibration actually fixes

The device takes an offset calibration while stationary before use. It is worth being precise about what this does and does not address.

It removes the standing bias of each axis — the non-zero reading a sensor gives when nothing is happening. That bias varies between individual sensor units and shifts with temperature, so it cannot be baked in at build time as a constant.

It does not fix scale-factor error, cross-axis sensitivity, or anything that changes during use. A calibration is a snapshot of the sensor at one moment in one thermal state. Treating it as permanent is a mistake we had to design around rather than remove.

Noise, and what we learned to leave alone

The instinct with a noisy signal is to filter harder. On this device that instinct is wrong, and it took us a while to accept it.

Heavier filtering buys a steadier number at the cost of lag, and lag is precisely what destroys the feedback loop. If the display trails the hand by a noticeable amount, the user corrects against stale information and overshoots — and then blames the device, correctly. A slightly restless reading that tracks the hand honestly is more usable than a smooth reading that arrives late.

What did help was rejecting readings that are not physically plausible rather than smoothing everything equally. The accelerometer's magnitude should sit near 1 g when the device is not being accelerated; when it does not, that sample carries little information about orientation and is better down-weighted than averaged in. A handpiece motor's vibration is exactly this case.

Drift, and being honest about it

Gyroscope drift never goes away. Fusion suppresses it by continuously pulling the estimate back toward the accelerometer's view of gravity, but the correction is only as good as the accelerometer readings available, and those degrade under sustained movement.

We track drift explicitly and slowly, on a long time constant, rather than hiding it. The useful design consequence: because the device works from a user-set reference rather than an absolute world frame, re-zeroing is cheap and always available. A workflow where re-establishing the reference takes one button press is a better answer to accumulated drift than any filter tuning.

Embedded constraints

Display, sensing and logic run as separate tasks. This is the single structural decision that mattered most. Redrawing a 128 × 128 colour screen takes real time, and if it happens on the same execution path as reading the sensor, the sampling interval develops a stutter that fusion interprets as motion. Separating them means a slow frame delays a frame, not a measurement.

The firmware carries explicit latency budgets and a monitor task that checks against them, so a regression shows up as a violated budget rather than as a vague feeling that the device got worse.

A note on what is deliberately absent here: this piece names no sensor part number and no sampling rate. We have run this device on more than one hardware configuration during development, and we would rather say nothing than publish a figure from a build that is not the one you would receive. Those numbers will appear when the shipping configuration is settled and we can state them against it.

Ergonomics decided more than the electronics did

The device attaches to an instrument that is already in someone's hand during precise work. That constrains everything: it cannot add meaningful mass, cannot shift the balance of the handpiece, and cannot put a control anywhere a finger might hit it by accident.

This is why there is one button. Not minimalism for its own sake — every additional control is another thing to press wrongly while holding something sharp near a patient. Click and hold, distinguished by duration, carry the entire interface.

Designing the feedback, not just the measurement

The part we underestimated. A screen is useless at exactly the moment the user most needs it, because their eyes are on the tooth. That single observation is why the device reports through three channels rather than one: the display for when you can look, a colour LED for peripheral vision, and a tone for when you cannot look at all.

Deciding when to alert was harder than deciding how. Alert too eagerly and the device becomes noise the user learns to ignore, which is worse than silence. This is why the deviation limit is user-selectable from 5° to 20° rather than fixed: the right threshold for a student rehearsing a movement is not the right threshold for someone working, and we are not in a position to pick for them.

What we would tell someone starting this

  • Decide what the user does with the number before choosing how precisely to measure it.
  • Latency is a feature. Trading it for smoothness is usually a bad trade in a feedback loop.
  • Make re-zeroing trivial. It solves more drift problems than filter tuning.
  • Separate the display from the sensing early. Retrofitting that separation is painful.
  • The alerting policy will take longer to get right than the estimator.