The first reading
Three wires, no library, and a sketch that measures SIGNAL with no magnet near, keeps that as zero, and from then on prints the field in gauss with its sign and the pole's name. SIGNAL goes to the analog pin the NTC and ambient light books use: A0 on an Uno, GPIO 34 on an ESP32, GPIO 4 on an ESP32-S3, GP26 on a Pico.
Three wires
GND to GND. VCC to your board's logic voltage: 3V3 on an ESP32, an ESP32-S3 or a Pico, 5V on an Uno. SIGNAL to an analog pin. NC stays unconnected.
The analog pin is the same in every sketch in this book, and the same as in the NTC thermistor and ambient light books: A0 on an Uno, GPIO 34 on an ESP32, GPIO 4 on an ESP32-S3, GP26 on a Pico. The two ESP32 pins are on ADC1, the converter that keeps working while Wi-Fi is on.
Zero first
The resting level differs from chip to chip and moves with the supply, so the sketch does not assume one. It measures it.
setup() waits half a second, then reads SIGNAL 64 times and keeps the
average as zeroMv. Every pass of loop() averages 16 readings, subtracts
the zero and divides by MV_PER_GAUSS, which is 3.25 on an Uno and 2.1 on
the 3.3 V boards. The result is the field in gauss, positive for the pole
that raises the output.
Readings go through readMilliVolts(). On an ESP32 that is
analogReadMilliVolts, which the chip corrects with its own calibration;
on an Uno or a Pico it is the count scaled to the ADC's full scale.
What you should see
At 115200 the serial monitor prints the zero once, something near
zero: 2500 mV on an Uno or zero: 1650 mV on a 3.3 V board. Then four
lines a second: 0 G or a few gauss either side with nothing near.
Bring a magnet's face to the front of the board over the chip, and the
number climbs, with north or south after it once it passes 5 G. Past
460 G it adds (past the linear range).
The sketch compiles for an ESP32-S3 and an Uno. Here is the block on the owner's own boards, a magnet brought to the chip:
The code
No library. setup() averages 64 readings with no magnet near and keeps them as zero; loop() averages 16, subtracts the zero and divides by the chip's millivolts per gauss. The #if picks 3.25 mV per gauss on an Uno and 2.1 on a 3.3 V board. Change HALL_PIN to the pin you wired SIGNAL to.
/*
Linear Hall Effect Sensor - first reading 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.
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
// Which pole, held to the front, raises the output. The data
// sheet's SOT-23 drawing says north. If a compass says otherwise,
// make this false.
const bool NORTH_RAISES = true;
float zeroMv; // SIGNAL with no magnet near: about half of VCC
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
}
// The average of n readings: steadier than one.
float averageMv(int n) {
float sum = 0;
for (int i = 0; i < n; i++) sum += readMilliVolts();
return sum / n;
}
void setup() {
Serial.begin(115200);
delay(500);
zeroMv = averageMv(64); // no magnet near, please
Serial.print("zero: ");
Serial.print(zeroMv, 0);
Serial.println(" mV");
}
void loop() {
float gauss = (averageMv(16) - zeroMv) / MV_PER_GAUSS;
Serial.print(gauss, 0);
Serial.print(" G");
if (fabs(gauss) >= 5) {
bool raised = gauss > 0;
Serial.print(raised == NORTH_RAISES ? " north" : " south");
}
if (fabs(gauss) > 460) {
Serial.print(" (past the linear range)");
}
Serial.println();
delay(250);
}Keep magnets away while it starts or resets. Positive is the pole that raises the output, north by the data sheet's drawing; flip NORTH_RAISES if a compass says otherwise. The sketch compiles for an ESP32-S3 and an Uno.
View on GitHub · blocks/tk70-linear-hall-sensor/arduino/hall_first_reading/hall_first_reading.ino @ v1.5The same sketch in MicroPython, for an ESP32, an ESP32-S3 or a Pico. On the ESP32s it reads calibrated microvolts; on a Pico it scales read_u16 to 3.3 V.
"""
Linear Hall Effect Sensor - first reading, 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.
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; a compass checks it
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
time.sleep_ms(500)
zero_mv = average_mv(64) # no magnet near, please
print("zero: %.0f mV" % zero_mv)
while True:
gauss = (average_mv(16) - zero_mv) / MV_PER_GAUSS
line = "%.0f G" % gauss
if abs(gauss) >= 5:
line += " north" if (gauss > 0) == NORTH_RAISES else " south"
if abs(gauss) > 460:
line += " (past the linear range)"
print(line)
time.sleep_ms(250)There is no Uno here: an Uno cannot run MicroPython. On an ESP32 the atten line widens the ADC's range to about 3.1 V; without it the resting 1.65 V is off the top. Stop it with Ctrl-C.
View on GitHub · blocks/tk70-linear-hall-sensor/micropython/hall_first_reading.py @ v1.5When it does not work
The zero was measured with something magnetic nearby: the magnet in your hand, a steel screw, a speaker. Move them away and press reset, and the sketch measures its zero again. A few gauss either way is jitter and the Earth's field; tens is something near the board.
The chip has no power, or SIGNAL is not on HALL_PIN. With power and no field it would print a zero near half of VCC, about 1650 mV on a 3.3 V board. Count from the square pad: GND, VCC, NC, SIGNAL.
Set Tools > USB CDC On Boot to Enabled and upload again. Without it the S3's USB port does not bring up a serial port at boot, so the sketch runs with nowhere to print.
Check the atten line is there. Without it an ESP32's ADC tops out near 1 V, the resting 1.65 V reads as full scale, and every number after is wrong. The sketch sets 11 dB, the range to about 3.1 V.
What one step of your board's ADC is worth, and how far away a magnet still counts.
How much field a count is →Edit this page — content/books/linear-hall-sensor/the-first-reading.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.