Building a magnetic control: how do sensor readings become movement?

You have a shape in mind for a custom controller: a thumb control for an instrument, a flight-simulator stick, or a handle that moves something on screen. A magnetic sensor is appealing because it reads a magnet without rubbing against it. The hard part comes next: making a particular hand movement produce the same response every time, including when the user lets go.

That gap between a component and a usable mechanism shows up in a September 2026 r/HotasDIY thread, where a builder who already knew about custom PCBs and Hall sensors still wanted a buildable project, and the replies quickly turned to the magnet. The magnet, the mounting and the software have to be worked out together.

On our bench we connected a GraftSense MLX90393 three-axis magnetic sensor module to a GraftPort-RP2040 board and printed its readings. This note covers what that showed and what a first control mechanism still needs.

What the three numbers actually tell you

The sensor measures the magnetic field along three perpendicular axes, X, Y and Z, at the chip, in microteslas (µT). Those are three components of the field, not the magnet's coordinates in millimeters.

A controller needs a repeatable relationship between movement and those readings. Sliding a loose magnet sideways, lifting it and turning it all change the output. A mechanism that restricts the magnet's motion gives the software a much clearer problem.

Builders run into this regularly. In a May 2023 Arduino forum thread, someone wanted to turn MLX90393 readings into a direction on an LED ring. Getting numbers from the sensor was only the beginning; interpreting them was the real work.

The board connection

We used a four-wire cable from the module to the controller's I2C0 connector, with GP4 as SDA and GP5 as SCL. Check the supply against your board revision: the v1.0.0 schematic puts 5 V on the connector and regulates it to 3.3 V for the chip with an XC6206, and pulls SDA and SCL up to 3.3 V. Some descriptions of the module just say "3.3 V supply," which blurs the difference between the sensor rail and the connector input. Do not put 5 V on the signal pins.

A0 and A1 solder pads set the I2C address. Ours answered at 0x0C. If you change the pads, change both the address you scan for and the address you pass to the driver.

Get a readable baseline

We installed version 1.0.0 of a packaged MLX90393 driver based on José D. Montoya's MicroPython_MLX90393 (MIT, now archived). The package index page still showed 0.0.0 while the package itself was 1.0.0; record the version you actually install. Our loop, with the address made explicit:

ADDRESS = 0x0C  # must match the A0/A1 pads
i2c = SoftI2C(sda=Pin(4), scl=Pin(5))
if ADDRESS not in i2c.scan():
    raise RuntimeError("Expected MLX90393 address was not found")

sensor = mlx90393.MLX90393(i2c=i2c, address=ADDRESS)
while True:
    x, y, z = sensor.magnetic
    print("X: %.2f uT | Y: %.2f uT | Z: %.2f uT" % (x, y, z))
    time.sleep(1)

The terminal showed one device at 0x0C, successful initialization and changing values. One line read about X = 22.838 µT, Y = −20.434 µT, Z = −15.488 µT; another, X = 4.808 µT, Y = −3.606 µT, Z = 3.872 µT. The readings changed as we reoriented the sensor. That establishes connection and readout. It does not show a magnet held at measured positions or a calibrated control.

Keep units and response time consistent

Fix the sensor settings before turning values into control, and record them. The driver defaults to gain selection 7, resolution setting 3 on each axis, digital filter 7 and oversampling 3. Its gain constant is named GAIN_1X; go by the register value and the datasheet table, not the name.

In the Melexis datasheet (revision 007), the 25 °C table for HALLCONF 0xC with temperature compensation off gives 1.202 µT per count for X and Y and 1.936 µT per count for Z at those settings. That difference is why calculations should use properly converted physical units rather than treating every raw count alike.

This first example is deliberately slow. The driver's default conversion wait is about 220 ms, and the loop adds a one-second pause. Removing the pause will not make it a fast joystick. If the interaction needs quick response, measure the full read-and-update time and choose supported filter and oversampling settings for it. Some of the fastest combinations are not allowed; the Melexis MLX90393 application note explains the command and configuration model and lists the invalid ones.

The driver reads the chip's status byte, but its magnetic property does not reject every reported error before returning values. During mechanism testing, log communication failures separately so a bad sample is not mistaken for a user movement.

Give the magnet a repeatable path

For a first two-axis experiment, an XY sliding fixture is easier to reason about than waving a magnet by hand. Keep the board still, hold the magnet at a fixed height and orientation, and move it to marked positions. We have not built this fixture yet; it is the next experiment.

Melexis's application note on using a magnetometer in a position sensor describes how constrained magnet motion supports a two-axis control and why calibration is needed to turn fields into displacement. Its thumbstick example uses an MLX90392, so do not copy its dimensions or settings as proven for this board.

A useful first record looks like this. Fill it in from the real fixture before choosing a formula:

Fixture state Record What it helps you decide
Center, untouched Repeated X/Y/Z How much output moves while the control is still
Known left/right and forward/back positions Position marks and X/Y/Z Whether intended movements are distinguishable
Same point approached from opposite sides Both sets of readings Whether looseness or the return spring changes the result
Released back to center Several returns How big a neutral region is needed
Assembled in the housing with nearby parts The same sequence again Whether the layout changes what you calibrated

The neutral region around rest is usually called a dead zone. Size it from the mechanism's measured behavior. Too large hides a poor return to center; too small turns tiny variations into unwanted movement. Fitting a magnetic part and calibrating the complete input are separate jobs, and a replacement part can read off-center until the whole assembly is recalibrated.

Decide what the first prototype has to prove

Our bench session is enough to start learning how the module responds. For a custom control, the next deliverable is a simple mechanism with a recorded travel range, a repeatable center and a measured response time. Those results tell you whether this sensing arrangement fits the intended hand movement before you invest in a finished enclosure.

If the control tilts rather than slides, build and test that geometry specifically. If it only needs to distinguish a few positions, start with those states; a continuous millimeter readout may add work without improving the interaction. Neither answer follows from three changing numbers alone.