Build a dial thermometer with a servo needle

Turn the servo into the needle of a gauge: the DHT11 measures the room temperature and the servo points to it on a dial.
  • Level:Beginner
  • Duration: 40 min
  • Ages 10+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Build a dial thermometer with a servo needle – EEMENTOR STEM™ lesson

Numbers on a screen are precise, but a needle on a dial can be read from across the room. Old cars, kitchen thermometers and barometers all use one. In this lesson the DHT11 measures the temperature, and the servo turns a needle to the matching place on a scale from 0 to 40 °C. The needle moves smoothly, just like a real instrument.

What you'll learn

  • How to turn a measurement into an angle with a formula
  • How to move a servo smoothly, one degree at a time
  • How to make the scale of a dial match the code
  • How to keep a value inside a range with constrain()

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • DHT11 temperature and humidity sensor (UNO R3 Starter Kit)
  • Servo motor (UNO R3 Starter Kit)
  • A piece of card, a straw or toothpick for the needle, and tape
  • Breadboard and jumper wires (UNO R3 Starter Kit)

Make it real: draw a half circle on card with 0 °C on the left, 20 °C at the top and 40 °C on the right, with marks every 5 °C. Push the servo shaft through the middle and tape a straw to the servo horn as the needle.

Wiring

Breadboard wiring diagram: Build a dial thermometer with a servo needle
Breadboard view. Check each connection against the wiring table below.
From To
DHT11 S (signal) UNO pin 7
DHT11 + and − 5V and GND
Servo orange / yellow wire UNO pin 9
Servo red wire 5V
Servo brown / black wire GND

The sketch

Install the DHT sensor library by Adafruit (and Adafruit Unified Sensor when asked). The Servo library is built in.

#include <Servo.h>
#include <DHT.h>

DHT dht(7, DHT11);
Servo needle;

const float LOWEST = 0.0;     // temperature at the left end of the scale
const float HIGHEST = 40.0;   // temperature at the right end of the scale
int needleAngle = 90;

int angleFor(float celsius) {
  float t = constrain(celsius, LOWEST, HIGHEST);
  // cold = 180 degrees (left), hot = 0 degrees (right)
  return 180 - (int)((t - LOWEST) * 180.0 / (HIGHEST - LOWEST));
}

void moveNeedle(int target) {
  while (needleAngle != target) {
    needleAngle += (target > needleAngle) ? 1 : -1;
    needle.write(needleAngle);
    delay(15);                  // one degree every 15 ms: smooth like a gauge
  }
}

void setup() {
  Serial.begin(9600);
  dht.begin();
  needle.attach(9);
  needle.write(needleAngle);
}

void loop() {
  delay(2000);                  // the DHT11 needs 2 s between readings
  float celsius = dht.readTemperature();
  if (isnan(celsius)) {
    Serial.println("Sensor error");
    return;
  }
  int angle = angleFor(celsius);
  Serial.print(celsius, 1);
  Serial.print(" °C -> needle at ");
  Serial.print(angle);
  Serial.println(" degrees");
  moveNeedle(angle);
}

Line up the dial

  1. Upload the sketch. While it waits for the first reading, the servo goes to 90 degrees.
  2. Take the horn off, and push it back on with the needle pointing straight up at 20 °C.
  3. Warm the DHT11 between your fingers and check that the needle moves to the right. If it moves left, see Troubleshooting.

How it works

The dial covers 40 degrees Celsius on a half circle of 180 degrees, so each degree Celsius is 4.5 degrees of needle movement. angleFor() does that sum, and constrain() keeps the needle on the scale when it is colder than 0 or warmer than 40 °C. Because a servo's 0° is usually on the right when you look at it from the front, the result is reversed with 180 - … so that cold is on the left, as on most gauges.

servo.write() on its own makes the servo jump at full speed. moveNeedle() moves it one degree at a time instead, which looks like a real instrument and is gentler on the servo's gears.

Try this next

  • Change the scale to −10 … 30 °C for an outdoor thermometer, and redraw the dial.
  • Add a second dial for humidity from 0 to 100 %.
  • Light a red LED when the needle is in a "too warm" zone that you colour on the dial.

Troubleshooting

  • The needle moves the wrong way: remove 180 - from the return line, so it reads return (int)(…);.
  • "Sensor error": check the DHT11 signal wire on pin 7 and its power pins.
  • The servo buzzes at the end of the scale: it is pushing against its stop. Use 10 to 170 degrees instead of 0 to 180.
  • The board restarts when the servo moves: servos draw bursts of current. Use a good USB port or a powered hub, and check that the servo's red wire is on 5V.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

UNO R3 Starter Kit | Arduino IDE Compatible | Free Tutorials $56.00

Shop the kit