The Sensing Principle: Magnetic Flux to Voltage

When a current-carrying semiconductor is placed in a magnetic field, the Lorentz force deflects moving charge carriers to one side of the material, creating a measurable transverse voltage. In a linear Hall effect IC, an internal bias current is continuously applied to a thin epitaxial layer. As a magnet moves closer or further away along the sensor's sensitive axis, the changing magnetic flux density alters the magnitude of this Hall voltage, which is then amplified by an on-chip op-amp to produce a continuous analog signal.

Unlike digital Hall switches that snap high or low at a specific Gauss threshold, a linear Hall sensor outputs a ratiometric analog voltage that tracks magnetic flux density proportionally. At zero magnetic field (the null point), the output sits at exactly half the supply voltage (Vcc/2). Pushing a north pole toward the sensor face drives the voltage upward toward Vcc, while a south pole drives it downward toward ground, allowing you to measure both the magnitude and polarity of the magnetic field for precise bidirectional tracking.

Wiring the SS49E and Understanding the Analog Output

The output of a linear position Hall sensor is strictly an analog voltage. It is not a digital PWM signal, nor is it a current loop (unless you add a transmitter IC). Because the output is ratiometric, the voltage scales directly with your supply rail. If you power the sensor at 5.0V, the null point is 2.5V. If you power it at 3.3V, the null point is 1.65V.

ESP32 ADC Warning: The ESP32's internal ADC is notoriously non-linear above 3.1V and below 0.1V, and it is strictly limited to a 3.3V maximum input. If you power a 5V-rated sensor at 5V, its output could swing up to 4.5V, instantly destroying the ESP32 GPIO. The solution is to power the Honeywell SS49E directly from the ESP32's 3V3 rail. The SS49E operates reliably down to 2.7V, making 3.3V native operation perfectly safe and optimal.
Honeywell SS49E Pinout and Operating Specs (at 3.3V Supply)
PinFunctionConnection / RangeNotes
1 (Left)VCCESP32 3V3 (3.3V)Accepts 2.7V to 6.5V. Bypass with 100nF ceramic cap to GND.
2 (Center)GNDESP32 GNDMust share common ground with the microcontroller.
3 (Right)VOUTESP32 GPIO (e.g., GPIO 34)Analog output. Null voltage = 1.65V. Range: 0.3V to 3.0V.

The Raw-to-Unit Math: Scaling ADC Readings to Millimeters

Translating the raw ADC integer into a physical millimeter distance requires a three-step mathematical pipeline. First, we convert the raw ADC reading to voltage. Second, we convert voltage to magnetic flux density (Gauss). Third, we map the flux density to physical distance using the known gradient of your specific magnet.

For the ESP32 (12-bit ADC, 0-4095 raw range) running at 3.3V with 11dB attenuation, the math looks like this:

  1. Raw to Voltage: Voltage = (ADC_Raw / 4095.0) * 3.3
  2. Voltage to Gauss: The SS49E sensitivity is 1.4 mV/G at 5V. At 3.3V, it scales ratiometrically to 0.924 mV/G (0.000924 V/G). Gauss = (Voltage - 1.65) / 0.000924
  3. Gauss to Millimeters: Magnetic flux drops off non-linearly (inverse cube law for a dipole). However, over a short stroke (e.g., 10mm to 30mm), it approximates a linear gradient. If your calibration shows a drop of 50 Gauss per millimeter, Distance_mm = Gauss / 50.0

Here is the complete, compilable C++ calibration structure for the ESP32 using the Arduino core:

// Two-point linear interpolation for non-ideal magnetic fields
struct LinearPositionCal {
  float adc_near;   // ADC raw reading at minimum distance (e.g., 5mm)
  float dist_near;  // Physical distance at near point
  float adc_far;    // ADC raw reading at maximum distance (e.g., 25mm)
  float dist_far;   // Physical distance at far point

  float get_distance_mm(int raw_adc) {
    // Clamp to prevent extrapolation errors outside the magnetic field
    if (raw_adc <= adc_near) return dist_near;
    if (raw_adc >= adc_far) return dist_far;
    
    float slope = (dist_far - dist_near) / (adc_far - adc_near);
    return dist_near + slope * (raw_adc - adc_near);
  }
};

LinearPositionCal my_sensor = {3200, 5.0, 1100, 25.0}; // Calibrate these values!

void setup() {
  Serial.begin(115200);
  analogReadResolution(12); // Force 12-bit on ESP32
  analogSetAttenuation(ADC_11db); // Set 0-3.1V linear range
}

void loop() {
  int raw = analogRead(34);
  float mm = my_sensor.get_distance_mm(raw);
  Serial.printf("Raw: %d | Pos: %.2f mm\n", raw, mm);
  delay(50);
}

Calibration and Defeating Magnetic Interference

Theoretical math rarely survives the workbench. Magnetic fields are easily distorted by ferrous metals (like steel mounting screws or the breadboard's internal nickel strips) and adjacent current-carrying wires. Furthermore, the ESP32's ADC has inherent noise, often jumping ±15 counts on a quiet bench.

To achieve sub-millimeter accuracy, you must perform a physical two-point calibration. Mount your magnet on the moving carriage. Slide it to the exact physical minimum (e.g., 5.00mm measured with digital calipers) and record the average of 50 ADC reads. Slide it to the maximum (e.g., 25.00mm) and record the average again. Plug those values into the LinearPositionCal struct above. This bypasses the need to calculate exact Gauss gradients and compensates for local magnetic distortion.

Defeating EMI and Stepper Noise: If your sensor linear position setup is mounted near NEMA 17 stepper motors or switching buck converters, the high-frequency PWM noise will inject ripple into the Hall element. Fix this with a hardware RC low-pass filter (a 1kΩ series resistor on the VOUT pin followed by a 100nF capacitor to GND) or implement an Exponential Moving Average (EMA) in software: filtered = (0.2 * raw) + (0.8 * filtered_prev).

Decision Tree: Selecting Your Sensor Linear Position Technology

Not every project requires a magnetic sensor. If you are designing a linear actuator feedback loop or a custom MIDI fader, use this decision matrix to lock in the right component. Do not default to a slide potentiometer just because it is cheap; contact wear will ruin your calibration within months in high-cycle applications.

Linear Position Sensor Selection Matrix
Application ConstraintTechnologyConcrete Pick / Part NumberWhy it Wins
Budget is under $2, stroke is <100mm, low cycle count (e.g., DIY MIDI mixer) Linear Potentiometer (Slide Pot) Bourns PTV09A-4020F Dirt cheap, simple voltage divider, no magnetic math required.
Requires micron-level precision, stroke >200mm, harsh industrial environment Magnetostrictive (Time-of-Flight) Balluff BTL7 (4-20mA) Absolute position, zero drift, but requires 24V and specialized ADC.
High cycle count (1M+), non-contact, 3.3V microcontroller native, stroke 5-40mm Linear Hall Effect Honeywell SS49E Zero mechanical wear, ratiometric 3.3V operation, high EMI immunity.

The Default Recommendation: For 90% of maker, robotics, and embedded DIY projects requiring a robust sensor linear position feedback loop, the Honeywell SS49E paired with a 6x2.5mm neodymium cylinder magnet is the definitive choice. It eliminates the wiper noise and mechanical failure points of carbon-track potentiometers, operates natively on the ESP32's 3.3V logic without level shifters, and costs roughly $1.50 in single quantities. Buy the SS49E, run it at 3.3V, use the two-point calibration code provided above, and your position tracking will remain drift-free for the lifespan of the device.