This project aims to design and build a low-cost, high-precision magnetometer using MEMS technology, capable of detecting subtle variations in the Earth's magnetic field. The long-term goal is to monitor solar storms and subsurface anomalies through statistical noise reduction, sensor rotation, and embedded filtering directly on an ESP32 microcontroller.
Early experiments with the MMC5603 MEMS magnetometer revealed limitations due to 1/f noise, which led to a complete redesign using a better low-noise sensor, mechanical rotation, and Kalman filtering.
The device is designed to operate outdoors over long periods, with GPS timestamping, servo control, and a waterproof housing. Data will be processed locally, with the possibility of deploying small neural networks for real-time event detection.
This log-based story documents the full design journey — from first failures to upcoming field tests.
I’m grateful for the support of PCBWay in helping relaunch this
This PCB is designed to host several breakout boards and to simplify the assembly of a device intended to fit inside a 100 mm PVC tube. Its circular shape allows for direct mechanical integration into the lower part of the enclosure, with no wasted space.
Key features:
ESP32-S3 (WROOM module) mounted on headers, making replacement or reprogramming easy.
u-blox NEO-M6 GPS also mounted on headers (plus hot glue for mechanical security).
All other components (connectors, screw terminals, filters) are directly soldered for robustness.
Two separate ground planes: one for logic (ESP32, GPS, sensors), one for power (LM2596, servos), connected via a ferrite bead to limit electrical noise between sections.
LM2596 regulator to provide 5V required by the servos.
Connector for SPI display (ILI9341 controller).
SD card reader for data logging.
Connector for a magnetometer sensor.
Screw terminals for servos, with MOSFETs for power cut-off.
USB and JTAG connectors for programming and debugging.
This approach makes it easy to use standard modules (ESP32, GPS) while maintaining a solid, reliable structure suitable for integration in outdoor environments.
While revisiting the geometry and simulation of sensor excitation, I realized that rotating the sensor around the (1,1,1) axis is not sufficient to fully resolve the sensor bias — especially the component along the Z axis.
A single degree of freedom in rotation doesn’t provide enough information to separate sensor bias from the actual field vector in all three dimensions. In particular, the Z component remains insufficiently excited during this motion, making it difficult to reliably estimate its offset through averaging or Kalman filtering.
To overcome this, I’ve decided to add a second rotational axis. A second servo motor will be integrated into the base of the rotating assembly, and its motion will be transmitted to the upper turret via GT2 belts.
Mechanically, this second axis will rely on an aluminum shaft and a bronze sleeve, press-fitted into a PLA structure. This ensures mechanical rigidity while avoiding paramagnetic or ferromagnetic materials in motion near the sensor, which could otherwise corrupt the magnetic readings.
This upgrade should allow the sensor to explore a much larger portion of the 3D orientation space, improving the ability to identify and compensate for biases on all axes, including Z.
Eventually, after revisiting the literature, I found another sensor, the PNI RM3100 (a bit more expensive, ~€30 on AliExpress), characterized by:
✅ very low thermal drift,
✅ very low pink noise,
✅ and, most importantly, a native RMS noise of just 13 nT.
And that reignited the project!
Here’s my plan:
1️⃣ Still use the statistical approach: 1,000 measurements → noise reduced to about 0.4 nT.
2️⃣ Rotate the sensor around the (1,1,1) axis to eliminate internal biases.
3️⃣ Design a waterproof, robust enclosure capable of long-term outdoor measurements.
For points 1 and 2, I plan to implement data fusion with a Kalman filter directly embedded in the microcontroller, like I had already done in this Hackaday project.
Current Status: CAD and Mechanics
I’ve already purchased the sensor (not yet received) and completed the CAD for the mechanical parts.
The setup is designed to fit inside a 100 mm diameter wastewater pipe, offering both waterproofing and low cost.
Instead of NEMA17 motors (which generate too much magnetic disturbance due to their strong permanent magnets), I chose a GM995 servo, much smaller.
I also took care to minimize metallic parts in the assembly. Remaining metallic components include:
small 623ZZ bearings (to relieve the servo and ensure guided rotation),
and some metallic screws, but fixed relative to the frame (thus creating a static, acceptable perturbation).
I first explored low-cost MEMS sensors and came across the MMC5603, advertised with an RMS noise of 400 nT.
I even wrote an ESP32-compatible library: available here.
My idea was simple:
use a statistical approach → take massive numbers of measurements to reduce the noise.
For example, 10,000 measurements lower the variance by a factor of 10,000, and thus the standard deviation by a factor of 100 (thanks, law of large numbers!).
It’s a technique I had already used to measure Earth’s rotation with BMI160 sensors: explained here (FR).
So, on paper, by running 40,000 measurements (at 100 Hz → 100 seconds of measurements with 4 sensors in parallel), I should be able to reduce the noise from 400 nT to 2 nT.
Bingo, right?
Well… no.
While digging through the literature, I found Marcel Ochsendorf’s thesis: Development of a Permanent Magnet Characterisation Framework for Use in Low-Field MRI Systems.
He reports that the MMC5603NJ, in the context of ultra-low-field nuclear magnetic resonance (using the Earth’s magnetic field), exhibits a background noise of 15 nT, mostly due to 1/f noise.
And here’s the big problem: the statistical approach works well with white (Gaussian) noise, but not with 1/f noise. In this case, averaging does not reduce the standard deviation following the usual 1 / sqrt(N)
I’ve been dreaming for a long time about building a magnetometer precise enough to capture fine variations in the Earth’s magnetic field:
the daily variations linked to circadian cycles,
small local anomalies caused by buried metallic objects,
and, of course, the disturbances triggered by solar activity.
In the long run, I’d like to pair this magnetometer with an automated monitoring system capable of detecting solar storms, since they strongly disturb the magnetosphere and can be detected locally. Maybe I’ll even embed a small neural network directly on the ESP32 to analyze the time series data (I’ve already done something similar in another context, for example predicting frost events using a small weather CNN: https://selvasystems.net/deep-learning).
But I quickly discovered this isn’t an easy measurement.
To give an idea:
at my latitude, the Earth’s magnetic field is about 50,000 nT;
the daily variations are roughly harmonic, with an amplitude of about 10 nT, mainly due to the absence of solar radiation at night;
a metallic object buried 1 m deep (for example, a large piece of steel) can cause a local disturbance of a few nT;
and solar storms, depending on their intensity, can influence the field up to a few µT.
This kind of measurement is, in fact, almost impossible today for an individual. Normally, you’d need either a proton magnetometer (which measures total intensity but is heavy, fragile, and expensive) or a fluxgate magnetometer (precise, sensitive, but costly and not easily accessible). Trying this with low-cost MEMS components is a real challenge.
Hi! I love your project because I've already done a similar project myself with a Fluxgate FG-3+ magnetometer. I think you should use this magnetometer for your project. For the power supply, I used a 5V voltage regulator purchased on AliExpress. The assembly is simpler than with PCBs, but your PCB works perfectly. I also developed Python code to calculate the K index. I'd love to join your project with my current setup.
Have a good evening and good luck with your project.
Hi!
I love your project because I've already done a similar project myself with a Fluxgate FG-3+ magnetometer. I think you should use this magnetometer for your project. For the power supply, I used a 5V voltage regulator purchased on AliExpress. The assembly is simpler than with PCBs, but your PCB works perfectly. I also developed Python code to calculate the K index. I'd love to join your project with my current setup.
Have a good evening and good luck with your project.