Bench NotesUno handbook

Three-Zone Potentiometer Servo Indicator

A servo rests at 90° and repeatedly waves toward 45° or 135° depending on which third of the knob is selected.

IntermediateServoPotentiometer

Overview

The potentiometer range is divided into three zones. In the middle zone the servo simply holds 90°. In the left or right zone it performs a signal gesture: it sweeps from 90° toward 45° or 135° over about one second, sweeps back over about one second, waits one second, and repeats for as long as the knob stays in that zone.

You will need

  • Arduino Uno R3 and USB cable
  • 10 kΩ potentiometer (5 mm leg pitch)
  • Hobby servo such as an SG90
  • Jumper wires; optional separate servo supply

Wiring

Uno pinConnects toNotes
A0Potentiometer outer legSketch sets A0 as an OUTPUT, LOW. This is the pot's 0 V end.
A2Potentiometer wiper (middle leg)Analog input. Reads 0–1023.
A4Potentiometer other outer legSketch sets A4 as an OUTPUT, HIGH. This is the pot's 5 V end.
10Servo signal wire (orange or yellow)Servo library pulse output.
5VServo V+ (red)Only for one small, lightly loaded micro servo. Otherwise use a separate supply; see the power note.
GNDServo GND (brown or black)Must be shared with any external servo supply.
Wiring for Three-Zone Potentiometer Servo IndicatorArduino Uno A0 (driven LOW) to 10 kΩ potentiometer outer leg 1; Arduino Uno A2 (input) to 10 kΩ potentiometer wiper (middle); Arduino Uno A4 (driven HIGH) to 10 kΩ potentiometer outer leg 2; Arduino Uno D10 to Servo signal (orange/yellow); Arduino Uno 5V to Servo V+ (red); Arduino Uno GND to Servo GND (brown/black).Connections (each line is one wire)Arduino Uno10 kΩ potentiometerServoA0 (driven LOW)outer leg 1A2 (input)wiper (middle)A4 (driven HIGH)outer leg 2D10signal (orange/yellow)5VV+ (red)GNDGND (brown/black)
Original wiring diagram. Each line is one jumper wire; boxes on a line are series resistors.

How the pins are arranged

Read before wiring

This project powers the potentiometer from analog pins instead of the 5V and GND sockets. A 10 kΩ potentiometer has three legs about 5 mm apart, which matches every second socket on the Uno's analog header. Push its outer legs into A0 and A4 and its wiper into A2. The sketch sets A0 as a LOW output (0 V) and A4 as a HIGH output (5 V), so the pot sees a full 0–5 V span and the wiper on A2 reads anywhere from 0 to 1023.

This works because a 10 kΩ pot draws only about 0.5 mA, far below what a pin can supply. Do not use this trick with a pot under about 5 kΩ, and keep in mind that A4 is also the I²C data line (SDA): the pot and an I²C device cannot share it. See Using analog pins as digital outputs for the details.

A single micro servo such as an SG90, moving freely with nothing attached to its horn, can usually run from the Uno's 5V pin while the board is on USB. Any bigger servo, more than one servo, or a servo pushing against a load can pull several hundred milliamps in bursts. That causes the board to reset, the USB connection to drop, or the servo to jitter. In those cases power the servo from a separate regulated 5–6 V supply and connect that supply's ground to the Uno's GND. See Powering servos safely.

Diagrams

Potentiometer zonesreadings 0 to 340: → wave to 45°; readings 341 to 681: hold 90°; readings 682 to 1023: → wave to 135°.→ wave to 45°0hold 90°341→ wave to 135°6821023analogRead(A2) value
How the reading on A2 selects the behaviour.
One gesture (raised = arm away from 90°)Left or right zone: sweep out ~1 s, then sweep back ~1 s, then hold at 90° ~1 s.Left or right zonesweep out ~1 ssweep back ~1 shold at 90° ~1 s0 ms3010 ms
About 3 seconds per gesture: ~1 s out, ~1 s back, ~1 s hold.

The sketch

three_zone_servo_signal.ino
#include <Servo.h>
Servo servoMotor;

int potentiometerPin = A2;
int potentiometerReading;
int targetAngle;
int directionSign;

void setup() {
  pinMode(A2, INPUT);
  pinMode(A0, OUTPUT);
  pinMode(A4, OUTPUT);
  digitalWrite(A0, LOW);
  digitalWrite(A4, HIGH);
  servoMotor.attach(10);
  servoMotor.write(90);
}

void loop() {
  potentiometerReading = analogRead(potentiometerPin);

  if (potentiometerReading < 341) {
    targetAngle = 45;
  }
  else if (potentiometerReading < 682) {
    targetAngle = 90;
  }
  else {
    targetAngle = 135;
  }

  if (targetAngle == 90) {
    servoMotor.write(90);
    delay(20);
  }
  else {
    if (targetAngle == 45) {
      directionSign = -1;
    }
    else {
      directionSign = 1;
    }

    // Move from 90 toward the chosen endpoint over ~1 second
    for (int stepIndex = 1; stepIndex <= 45; stepIndex++) {
      servoMotor.write(90 + stepIndex * directionSign);
      delay(22);
    }
    delay(10);

    // Return to 90 over ~1 second
    for (int stepIndex = 44; stepIndex >= 0; stepIndex--) {
      servoMotor.write(90 + stepIndex * directionSign);
      delay(22);
    }
    delay(10);

    delay(1000); // Hold at 90 for ~1 second
  }
}

How the code works

The thresholds 341 and 682 split 0–1023 into three nearly equal zones. A single directionSign of −1 or +1 lets one pair of loops handle both directions: 45 steps of 1° with 22 ms each is 990 ms per sweep.

The gesture is blocking. The potentiometer is read only between gestures, so after you move the knob it can take up to about three seconds for the servo to respond. To react instantly you would rewrite the sweep with millis() timing.

Review result: no changes were needed. We checked both sweeps end exactly at the target and back at 90°, and that the timings match the comments.

What you should observe

  • Knob in the middle third: the servo sits at 90°.
  • Knob in the A0-side third: the arm sweeps to 45°, back to 90°, pauses, and repeats.
  • Knob in the A4-side third: the same gesture toward 135°.
  • Moving the knob mid-gesture has no effect until the gesture and its pause finish.