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
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 onNow 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
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.
/*
TM1637 4-Digit Display - a voltmeter readout TK51 / /p/tk51
The voltage on A0, to two decimals, on a digit panel.
Wiring. No pad on this board is square, so go by the names
printed on the back: GND, VCC, clock, data. Seen from the
display side with the header on the left, GND is the top pin.
GND -> GND
VCC -> 5V
CLOCK -> D2
DATA -> D3
And the thing being measured, 0 to 5 V only:
a potentiometer's outer pins to 5V and GND, its wiper to A0,
or a jumper from A0 to 5V, 3V3 or GND to test it.
Arduino IDE
Tools > Board Arduino Uno
Tools > Port the one that appears when you plug in
Library: "TM1637" by Avishay Orpaz, from Tools > Manage
Libraries. It installs TM1637Display.h.
*/
#include <TM1637Display.h>
#define CLOCK_PIN 2
#define DATA_PIN 3
#define POINT 0b10000000 // after the first digit written
#define RAIL_MV 5000 // measure your 5V pin and put it here
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) * RAIL_MV / 1023; // millivolts
int centivolts = (mv + 5) / 10; // 0 to 500
// Three digits from position 1, leading zeros on, the point
// after the first of them: 0.05 and 4.98 both read right.
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 can sit a few percent under 5 V, and every reading is then that much high. Measure your 5V pin with a meter and put the millivolts in RAIL_MV.
View on GitHub · blocks/tk51-tm1637-display/arduino/voltmeter/voltmeter.ino @ v1.13The same readout in MicroPython on an ESP32, measuring GPIO 34, with tm1637.py saved to the board first. read_uv() applies the chip's own calibration, so there is no rail to correct for.
"""
TM1637 4-Digit Display - a voltmeter readout TK51 / /p/tk51
The voltage on GPIO 34 of an ESP32, to two decimals, on a
digit panel.
Wiring. No pad on this board is square, so go by the names
printed on the back: GND, VCC, clock, data. Seen from the
display side with the header on the left, GND is the top pin.
GND -> GND
VCC -> 3V3. Never 5V: the pull-ups would put 5 V on your
pins.
CLOCK -> GPIO 18
DATA -> GPIO 19
And the thing being measured, 0 to 3.3 V only:
a potentiometer's outer pins to 3V3 and GND, its wiper to
GPIO 34.
Thonny
Run > Configure interpreter MicroPython (ESP32)
Save tm1637.py from this folder to the board first.
"""
import time
from machine import ADC, Pin
from tm1637 import TM1637
POINT = 0b10000000 # after the first digit written
display = TM1637(18, 19)
display.brightness(4)
display.segments([0]) # position 0 is never written below
adc = ADC(Pin(34))
adc.atten(ADC.ATTN_11DB) # the whole 0 to 3.3 V range
while True:
mv = adc.read_uv() // 1000 # calibrated millivolts
centivolts = (mv + 5) // 10 # 0 to 330
# Three digits from position 1, leading zeros on, the point
# after the first of them: 0.05 and 3.21 both read right.
display.number(centivolts, POINT, True, 3, 1)
time.sleep_ms(200)An ESP32 pin takes 0 to 3.3 V, not 5 V, so the pot goes between 3V3 and GND. The display half is unchanged: three digits from position 1, leading zeros on, the point after the first of them.
View on GitHub · blocks/tk51-tm1637-display/micropython/voltmeter.py @ v1.13When it does not work
Then the sketch is right and the rail is not 5.000 V. The Uno compares against its own 5 V rail, and USB power often arrives a little low. Measure the 5V pin with a meter and put that in RAIL_MV; everything else lines up.
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 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.
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.
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.
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
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.