Built-in project · Arduino Uno R3

Pocket gaussmeter on an Arduino Uno

A 49E linear Hall sensor on A0 and a 16x2 I2C LCD: the field in gauss, which pole it is, and the strongest seen since power on. The whole build, an Arduino Uno and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

BeginnerRuns in your browser. Free, and no account needed.

Pocket gaussmeter · Arduino Uno R3live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Pocket gaussmeter: a 49E linear Hall sensor on A0, and the field on a 16x2
// I2C LCD.
//
//   A0      the 49E's OUT (its VCC on 5 V, GND on GND, printed face out)
//   LCD     SDA -> A4    SCL -> A5    VCC -> 5 V    GND -> GND
//
// The 49E puts out half its supply with no field, and moves 1.4 mV a gauss:
// up for a south pole at its printed face, down for a north pole. So
//
//   gauss = (mV - zero mV) / 1.4
//
// One ADC count on 5 V is 4.89 mV, about 3.5 G: that is the meter's
// resolution. Its range ends where the output does, 0.95 V from either rail,
// about 1100 G each way; a neodymium magnet held against the face reads
// "over".
//
// # Zeroing
//
// The null is 2.50 V typical, but anything from 2.25 to 2.75 V on the sheet.
// So the meter zeroes itself at power on, with no magnet near, from the
// average of 64 readings, as a real one does when you press its zero button.
//
// Everything is whole numbers: this board has no floating point to spare.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

const int HALL = A0;
// mV per count x 1000, on 5 V: 5000 / 1023.
const long UV_PER_COUNT = 4888;
// Sensitivity in microvolts per gauss.
const long UV_PER_GAUSS = 1400;
// Where the output stops: 0.95 V from either rail, as counts.
const int LOW_END = 195;
const int HIGH_END = 828;

LiquidCrystal_I2C lcd(0x27, 16, 2);
long zero4 = 0;  // the null, in quarter counts
long peak = 0;

long readQuarters(int n) {
  long sum = 0;
  for (int i = 0; i < n; i++) sum += analogRead(HALL);
  return sum * 4 / n;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: pocket gaussmeter");
  lcd.init();
  lcd.backlight();
  lcd.print("Zeroing...");
  zero4 = readQuarters(64);
  Serial.print("zero at count ");
  Serial.println(zero4 / 4);
  lcd.clear();
}

void loop() {
  long raw4 = readQuarters(8);
  int raw = (int)(raw4 / 4);
  bool over = raw <= LOW_END || raw >= HIGH_END;
  long gauss = (raw4 - zero4) * UV_PER_COUNT / 4 / UV_PER_GAUSS;
  long size = gauss < 0 ? -gauss : gauss;
  if (size > peak) peak = size;

  lcd.setCursor(0, 0);
  if (over) {
    lcd.print("over range      ");
  } else {
    lcd.print(size);
    lcd.print(" G ");
    if (size < 5) {
      lcd.print("no field    ");
    } else {
      lcd.print(gauss > 0 ? "SOUTH       " : "NORTH       ");
    }
  }
  lcd.setCursor(0, 1);
  lcd.print("peak ");
  lcd.print(peak);
  lcd.print(" G        ");

  Serial.print("field ");
  Serial.print(gauss);
  Serial.println(over ? " G (over)" : " G");
  delay(250);
}

Parts list

4 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

5 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Arduino Uno R3 pin 5V; Hall sensor, 49E linear pin VCC; Character LCD with I2C backpack pin VCC
  • Ground: Arduino Uno R3 pin GND; Hall sensor, 49E linear pin GND; Character LCD with I2C backpack pin GND
  • Arduino Uno R3 pin A0; Hall sensor, 49E linear pin OUT
  • Arduino Uno R3 pin A4; Character LCD with I2C backpack pin SDA
  • Arduino Uno R3 pin A5; Character LCD with I2C backpack pin SCL

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.