Analog joystick drifts at rest: centre value is not 512

A joystick centre is rarely exactly 512. Read it at start-up and ignore small changes around it.

What the message means

The potentiometers inside a cheap joystick do not rest at exactly half the range, and the reading shifts a little with the supply.

Fix it in this order

  1. Read the value at start-up with the stick untouched and store it as the centre.
  2. Add a dead zone of about 20 to 40 counts around the centre.
  3. Map the two sides of the centre separately so full travel gives full speed.
  4. Power the joystick from the same supply the ADC uses as reference.
  5. Average a few readings to reduce noise.

Why it happens

A joystick is two potentiometers. At rest each one sits near the middle of its travel, but parts differ and the exact position varies, and the reading also moves with the supply voltage. A centre of 512 is the ideal for a 10-bit reading, not something the part promises.

Reading the centre at start-up with the stick untouched records the value for your own joystick. A small dead zone around it then stops tiny changes from being treated as movement. Pick the width by watching your own readings.

If you see this, do this

You seeDo this
Robot creeps at restDead zone or centre.
Reading jumpsNoise. Average or add a small capacitor.

Uno power, serial monitor shows nothing.

Last reviewed: November 2026. These are the usual causes and the order that finds them fastest. Test on your own board; clones and cables differ.

Why this happens

A joystick has two potentiometers. At rest, each wiper sits wherever the spring and the track happen to put it. A 10-bit ADC has a midpoint of about 511.5, but the stick’s real rest point is commonly a few tens of counts away from that, and it differs from one stick to the next. The code that assumes exactly 512 therefore sees a steady offset and moves the robot when nobody touches the stick.

The reading also moves with the supply. The analog pins compare against the board’s reference, which is usually the 5 V rail on an Uno. If the stick is powered from the same rail the ratio is stable, but a sagging rail or noise on it shifts the centre by a few counts.

How to confirm the cause

  • Leave the stick untouched and print 100 raw readings from each axis. Note the minimum, maximum and average. The average is your real centre; the spread is your noise.
  • Push the stick to each end and note the extremes. Often the distance from centre to one end differs from the other end.
  • Measure the supply voltage at the stick and at the board. A difference means wiring or a weak supply.
  • Wiggle the wires while watching the numbers. Jumps point to a loose pin or a worn track.

Worked example

Measure the centre once at start-up while the stick is released, then apply a dead zone.

const int PIN = A0;
int centre;

void setup() {
  Serial.begin(9600);
  long sum = 0;
  for (int i = 0; i < 64; i++) { sum += analogRead(PIN); delay(5); }
  centre = sum / 64;
}

void loop() {
  int d = analogRead(PIN) - centre;
  if (abs(d) < 30) d = 0;      // dead zone, tune for your stick
  Serial.println(d);
  delay(20);
}

Common mistakes

  • Holding the stick while the board starts, which records a false centre.
  • Making the dead zone so wide that fine control is lost.
  • Mapping 0 to 1023 straight onto a speed range, so the offset becomes constant motion.
  • Treating both halves as equal when the stick travels further on one side; map each side to its own end point.
  • Reading an ESP32 analog pin and using the 512 figure; a 12-bit reading has its middle near 2048.

If this did not fix it

  • A worn or dirty potentiometer track, which gives noisy readings that move as you tap the stick.
  • Noise from motor wires running alongside the signal wires.
  • An unstable reference voltage on a board powered from a weak USB port.
  • A button press on the stick that shares the pin through a wiring fault.