A pole finder
A sketch that says north pole, south pole or no magnet, with a bar that grows as the magnet comes closer. It names a pole once the field passes 20 gauss and lets go only below 10, so a magnet held at the edge does not flicker between a name and nothing. Use it to mark which face of a magnet is which.
Two thresholds, not one
A pole finder with one threshold, say 20 G, flickers. Hold a magnet where it makes about 20 G and the reading jitters by a gauss or two either side, so the name comes and goes several times a second. The fix is two thresholds: name a pole once the field passes 20 G, and let it go only once the field falls below 10.
Slide the field in and out. Between 10 and 20 G the finder keeps whatever it said last, so the edge is quiet. Flip the magnet over and it goes straight from one name to the other, because a field past 20 G the other way is a pole in its own right.
The sketch
The zero and the reading are the first sketch's. The new part is state,
0 for no magnet, 1 for north, 2 for south, and three lines that decide the
next one: past ENTER_G it is whichever pole the sign says; under
LEAVE_G it is nothing; in between it stays. The sketch prints the name
only when state changes, so the monitor shows one line per event
instead of five a second, and while a pole is named it adds a bar, one #
for every 20 G, that grows as the magnet comes closer.
What you should see
no magnet at the start. Bring a magnet's face to the front of the board
and, a few centimetres out with a neodymium disc, north pole or
south pole, then bars that lengthen as it comes in. Turn it over and the
name changes. Take it away and it prints no magnet once.
To mark a magnet, hold each face to the chip in turn and write the name on it. That is worth doing once, with a compass beside you, before you trust the names: see which pole, which way.
The code
No library. The same zero and the same reading as the first sketch, then a state: 0 for no magnet, 1 for north, 2 for south. It prints the name when the state changes and, while a pole is named, a bar of one # per 20 G. Change HALL_PIN to the pin you wired SIGNAL to.
/*
Linear Hall Effect Sensor - pole finder TK70 / /p/tk70
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 3V3 on an ESP32, ESP32-S3 or Pico; 5V on an Uno.
Your board's logic voltage: a strong field takes
SIGNAL up to about 0.8 x VCC.
NC -> nothing (unconnected on the board)
SIGNAL -> A0 on an Uno, GPIO 34 on an ESP32, GPIO 4 on an
ESP32-S3, GP26 on a Raspberry Pi Pico
Keep magnets away while it starts: it measures its zero then.
Hold a magnet's face to the front of the board, over the chip.
Arduino IDE
Tools > Board your board, e.g. ESP32S3 Dev Module
Tools > Port the one that appears when you plug in
Tools > USB CDC On Boot Enabled (ESP32-S3 only)
No library needed.
*/
// The analog pin SIGNAL is wired to.
// Uno: A0. ESP32: 34. ESP32-S3: 4. Pico: 26.
const int HALL_PIN = 4;
#if defined(ARDUINO_ARCH_AVR)
// Uno, VCC on 5V: 3.25 mV per gauss, typical; ADC full scale 5 V.
const float MV_PER_GAUSS = 3.25;
const float FULL_SCALE_MV = 5000.0;
#else
// VCC on 3V3: about 2.1 mV per gauss; Pico's ADC full scale 3.3 V.
const float MV_PER_GAUSS = 2.1;
const float FULL_SCALE_MV = 3300.0;
#endif
// The data sheet's SOT-23 drawing: north on the front raises it.
const bool NORTH_RAISES = true;
// Name a pole once the field passes ENTER_G; let it go only
// when it falls under LEAVE_G, so the edge does not flicker.
const float ENTER_G = 20;
const float LEAVE_G = 10;
const char* NAMES[] = {"no magnet", "north pole", "south pole"};
int state = 0; // 0 none, 1 north, 2 south
float zeroMv;
float readMilliVolts() {
#if defined(ARDUINO_ARCH_ESP32)
return analogReadMilliVolts(HALL_PIN); // calibrated in the chip
#else
return analogRead(HALL_PIN) * FULL_SCALE_MV / 1023.0;
#endif
}
float averageMv(int n) {
float sum = 0;
for (int i = 0; i < n; i++) sum += readMilliVolts();
return sum / n;
}
int poleOf(float gauss) {
return (gauss > 0) == NORTH_RAISES ? 1 : 2;
}
// One # for every 20 G: the bar grows as the magnet comes closer.
void printBar(float strength) {
int n = strength / 20;
if (n > 23) n = 23;
Serial.print(" ");
for (int i = 0; i < n; i++) Serial.print('#');
Serial.print(' ');
Serial.print(strength, 0);
Serial.println(" G");
}
void setup() {
Serial.begin(115200);
delay(500);
zeroMv = averageMv(64); // no magnet near, please
Serial.println(NAMES[state]);
}
void loop() {
float gauss = (averageMv(16) - zeroMv) / MV_PER_GAUSS;
float strength = fabs(gauss);
int next = state;
if (strength >= ENTER_G) {
next = poleOf(gauss);
} else if (strength < LEAVE_G) {
next = 0;
}
if (next != state) {
state = next;
Serial.println(NAMES[state]);
}
if (state != 0) printBar(strength);
delay(200);
}ENTER_G and LEAVE_G are the two thresholds; keep LEAVE_G below ENTER_G or it will flicker again. Keep magnets away while it starts. The sketch compiles for an ESP32-S3 and an Uno.
View on GitHub · blocks/tk70-linear-hall-sensor/arduino/hall_pole_finder/hall_pole_finder.ino @ v1.5The same pole finder in MicroPython, for an ESP32, an ESP32-S3 or a Pico.
"""
Linear Hall Effect Sensor - pole finder, MicroPython TK70 / /p/tk70
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 3V3 (never 5V: from 5 V a strong field takes SIGNAL
to about 4 V)
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 34 on an ESP32, GPIO 4 on an ESP32-S3,
GP26 on a Raspberry Pi Pico
Keep magnets away while it starts: it measures its zero then.
Hold a magnet's face to the front of the board, over the chip.
Thonny
Run > Configure interpreter MicroPython (ESP32) or
MicroPython (Raspberry Pi Pico)
Save it to the board as main.py to run it on every power-up.
Nothing to install: machine, sys and time are built in.
"""
import sys
import time
from machine import ADC, Pin
# The GPIO number SIGNAL is wired to. ESP32: 34. ESP32-S3: 4. Pico: 26.
HALL_PIN = 4
MV_PER_GAUSS = 2.1 # about, with VCC on 3V3
NORTH_RAISES = True # the sheet's SOT-23 drawing
# Name a pole past ENTER_G; let it go only under LEAVE_G.
ENTER_G = 20
LEAVE_G = 10
adc = ADC(Pin(HALL_PIN))
ESP = sys.platform == "esp32" # ESP32 and ESP32-S3
if ESP:
adc.atten(ADC.ATTN_11DB) # the full range, to about 3.1 V
def read_millivolts():
if ESP:
return adc.read_uv() / 1000 # calibrated in the chip
return adc.read_u16() * 3300 / 65535
def average_mv(n):
return sum(read_millivolts() for _ in range(n)) / n
def pole_of(gauss):
return "north pole" if (gauss > 0) == NORTH_RAISES else "south pole"
time.sleep_ms(500)
zero_mv = average_mv(64) # no magnet near, please
state = "no magnet"
print(state)
while True:
gauss = (average_mv(16) - zero_mv) / MV_PER_GAUSS
strength = abs(gauss)
new = state
if strength >= ENTER_G:
new = pole_of(gauss)
elif strength < LEAVE_G:
new = "no magnet"
if new != state:
state = new
print(state)
if state != "no magnet":
bar = "#" * min(int(strength / 20), 23)
print(" %s %.0f G" % (bar, strength))
time.sleep_ms(200)There is no Uno here: an Uno cannot run MicroPython. The atten line gives an ESP32 the range to about 3.1 V. Stop it with Ctrl-C.
View on GitHub · blocks/tk70-linear-hall-sensor/micropython/hall_pole_finder.py @ v1.5When it does not work
It needs 20 gauss to name a pole, which a small neodymium disc makes at a few centimetres and a weak magnet only close up. Lower ENTER_G for a weak magnet, and keep LEAVE_G about half of it, so there is still a gap between the two.
The two thresholds are too close together for your setup, or the zero was taken with a magnet near. Press reset with the magnet away first. Then widen the gap: ENTER_G at 20 and LEAVE_G at 10 suit a magnet held in a hand.
Hold the magnet at the front of the board; from behind, every name swaps. If it is still wrong against a compass, set NORTH_RAISES to false. The maker's drawings disagree about which pole raises the output.
Near 0, stuck at half, full scale, a field from nothing, swapped poles, and jitter.
When the reading is wrong →Edit this page — content/books/linear-hall-sensor/a-pole-finder.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Linear Hall Effect Sensor
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.