TM1637 display/Two builds and a check/12. A voltmeter readout
Two builds and a check · 12 of 13

A voltmeter readout

A digit panel, an Uno and one analog pin: 4.98 across the room. The interesting part is the decimal point, because the obvious way to write it is right for 4.98 and nonsense for 0.05.

The number is easy

analogRead gives 0 to 1023 for 0 to 5 V. Multiply by 5000, divide by 1023, and you have millivolts. Divide by ten and you have hundredths of a volt: 0 to 500, which fits three digits.

All of that is one line. The display is the part with a trap in it.

Where the point goes

Putting the point in the right place
4.98 V
Voltage on A04.98 V
How it is written
Reads
4.98
Number sent
498
Untouched digit
none
Right for this value. Drag down below one volt and watch it stop being right: this way of writing it depends on the number being big enough to fill four digits. The third option does not.

The obvious call — four digits, a point after the second — is right for 4.98 and wrong everywhere below a volt. Drag the slider down and watch: at 0.05 V the number is 5, the library blanks the three digits it does not need, and the point ends up beside nothing at all.

Leading zeros fix the blanking and give you 00.05, which is readable and ugly.

The proper answer is to tell the library it only owns three of the four digits:

display.showNumberDecEx(centivolts, 0b10000000, true, 3, 1);
//                                               ^    ^  ^
//                                               |    |  starting at position 1
//                                               |    three digits
//                                               leading zeros on

Now the three digits always fill their field, the point is always after the first of them, and 0.05 and 4.98 both read correctly. The mask is 0b10000000 rather than 0b01000000 because it is counted from the start of this call, not from the left of the display.

Position 0 is never written, which is why setup() calls clear() once. It is also free real estate: a minus sign, a channel number, or a letter saying which input is being shown.

Reading it twice

A bare number on a display invites more trust than it deserves. Two habits are worth building in early.

Say when it is stale. If the reading comes from something that can stop — a sensor, a serial feed, another board — show dashes when it has not updated recently rather than leaving the last good value on the panel. The display will hold a two-hour-old reading forever and look exactly as confident as a live one.

Round where the precision is. This shows hundredths of a volt, and an Uno's ADC step is about five thousandths — so the last digit is real, just. A sketch that showed thousandths would be printing noise in a font a metre wide, which is the specific trap of a display this legible.

The code

voltmeter.ino

Reads A0 and shows it as volts to two decimals on a digit panel. The display is written as three digits starting at position 1, which is what keeps the point in the right place for readings under a volt.

// A voltmeter readout: the voltage on A0, to two decimals, on a digit panel.
//
// Wiring, display to board:
//   Display GND   -> board GND
//   Display VCC   -> board 5V
//   Display CLOCK -> D2
//   Display DATA  -> D3
// And the thing being measured:
//   Potentiometer outer pins -> 5V and GND, wiper -> A0
//   (or just a jumper from A0 to 5V, 3V3 or GND to test it)
//
// Arduino IDE: board "Arduino Uno", and "TM1637" by Avishay Orpaz from the
// Library Manager. Nothing else to set.

#include <TM1637Display.h>

#define CLOCK_PIN 2
#define DATA_PIN  3
#define POINT     0b10000000   // after the first of the three digits written

TM1637Display display(CLOCK_PIN, DATA_PIN);

void setup() {
  display.setBrightness(4);
  display.clear();             // position 0 is never written below
}

void loop() {
  long mv = (long)analogRead(A0) * 5000 / 1023;   // millivolts, against the 5 V rail
  int centivolts = (mv + 5) / 10;                 // 0 to 500, rounded

  // Three digits starting at position 1, leading zeros on, point after the
  // first of them. 0.05 and 4.98 both read correctly this way; four digits
  // with leading zeros off would blank what it does not need and leave the
  // point sitting beside nothing.
  display.showNumberDecEx(centivolts, POINT, true, 3, 1);
  delay(200);
}

It measures against the Uno's own 5 V rail, so it is only as accurate as that rail: a board on USB often sits at 4.8 V, and every reading is then about four percent high. Wire A0 to 5V and whatever it shows is your rail's real voltage — that number is the correction.

When it does not work

It reads 4.80 with A0 wired to 5V

That is the truth, not an error. The Uno compares against its own 5 V rail, and a board powered over USB commonly sits between 4.7 and 5.0 V. Whatever it shows with A0 on 5V is your real rail voltage; put that number in place of 5000 in the sketch and everything else lines up.

The reading jumps around by a few hundredths

A floating or high-impedance input picks up noise, and the last digit is worth about 5 mV anyway. Average eight readings before displaying, and leave the display alone unless the value actually changed — it is easier to read a number that is not flickering.

The first digit shows something left over

The sketch only ever writes positions 1 to 3, so whatever was in position 0 stays there. That is why setup() calls clear(). If you show something else on that digit later, it will persist until you overwrite it.

Can I do this on an ESP32?

Yes, but not with this arithmetic: the ESP32's ADC is 12-bit and not linear across its range. Use analogReadMilliVolts(pin), which applies the chip's own calibration, and drop the multiply-and-divide. The display half of the sketch is unchanged.

It shows 5.00 for anything above 5 V

The pin cannot read above its reference and nothing warns you. Anything higher needs a voltage divider in front of A0, and then the arithmetic has to scale back up by the same ratio.

Where this goes next

The six symptoms, and which half of the problem each of them is in.

When it shows nothing

Edit this page — content/books/tm1637-display/a-voltmeter-readout.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

This page covers several products. Choose yours to see the right 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.

Browse Modules and blocks on the forum