A TM1637 display on an Arduino: a countdown timer
Beginner
Or see every lesson.
- 455parts on the bench
- 43boards running now
- 1.00xreal time, on every board
The TM1637 module is the red four-digit display with a colon in the middle, on a small board with four pins. The chip on the back does all the work of lighting the segments, so the Arduino needs only two wires to show a number, and the TM1637Display library turns that into one line of code.
The circuit above is an Uno running a Pomodoro timer: twenty-five minutes of focus and five of rest, counted down on a TM1637, with a red lamp for work, a green one for breaks and a chime at every change. Press start to begin and watch the seconds tick down. It runs in your browser on the sketch below.
What you need
- An Arduino Uno
- A 4-digit TM1637 display module (the clock kind, with a colon)
- Two pushbuttons
- A red and a green LED, each with a 220 ohm resistor
- A passive piezo
- A breadboard and jumper wires
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| TM1637 CLK | A0 | Any pin works; the analog pins are digital pins too |
| TM1637 DIO | A1 | |
| TM1637 VCC | 5 V | Runs on 3.3 to 5 V |
| TM1637 GND | GND | |
| Start button | Pin 4 | Other side to GND; press to start or pause, hold to reset |
| Skip button | Pin 5 | Other side to GND |
| Red LED, through 220 ohm | Pin 2 | Focus |
| Green LED, through 220 ohm | Pin 3 | Break |
| Piezo | Pin 6 | Other leg to GND |
Two wires, but not I2C
The TM1637 has a clock line and a data line, so it looks like I2C, but it is not. It has no address, and it sends each byte backward compared with I2C. That is why you cannot use the Wire library or the A4 and A5 pins’ I2C hardware for it, and why it works on any two pins. This circuit uses A0 and A1, used here as plain digital pins.
The library sends three short messages for every update: "write data", then the four digits’ segments, then "display on at this brightness". You never see any of it. You call one function with a number.
The library calls you need
TM1637Display display(A0, A1) names the CLK pin first and the DIO pin second. setBrightness() takes 0 (dim) to 7 (bright); this sketch uses 4.
showNumberDec(1234) shows a plain number. showNumberDecEx(number, dots, leading_zero) adds two things a timer needs. dots = 0b01000000 lights the colon, because on this module the colon is wired to the second digit’s dot and nothing else. leading_zero = true pads with zeros, so 5 minutes shows as 05:00 instead of " 5:00".
For a time, multiply the minutes by 100 and add the seconds. 25 minutes and 0 seconds is 2500, which shows as 25:00 with the colon on. That is the whole trick behind every TM1637 clock and countdown.
#include <TM1637Display.h>
TM1637Display display(A0, A1); // CLK, DIO
uint32_t left = 25UL * 60; // seconds left in this session
bool running = false;
static void show()
{
int mmss = (int)((left / 60) * 100 + left % 60);
// The colon blinks once a second while it runs and stays on when paused.
bool colon = !running || (millis() % 1000) < 500;
display.showNumberDecEx(mmss, colon ? 0b01000000 : 0, true);
}
void setup()
{
display.setBrightness(4);
show();
}Counting down without delay(1000)
A countdown that calls delay(1000) between seconds cannot read its buttons while it waits. This sketch keeps the time a second is due in tickAt. Each time through loop() it reads the buttons, and when millis() passes tickAt it takes one second off and moves tickAt on by 1000. The colon blinks from millis() too, half a second on and half off.
Press start and the serial monitor says "Running". Press skip and it says "Skipped", then "Short break (1 session done)", the lamps swap to green, the display jumps to 05:00 and the piezo chimes up: 523, 659 and 784 Hz, the notes C, E and G. Hold start for a second and it says "Reset".
Show letters and your own shapes
Each digit is one byte, one bit for each of the seven segments, and the library names them SEG_A to SEG_G. To spell something, build the bytes and call setSegments(). SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G is an A, and SEG_D | SEG_E | SEG_F is an L. A display that says "done" at the end of a timer is four of those bytes.
clear() blanks all four digits. setBrightness(level, false) makes the next update turn the display off, and setBrightness(level, true) turns it back on.
Common mistakes
CLK and DIO swapped. The constructor wants CLK first. Swap the two wires in this circuit and the display stays dark, because the chip never sees a message it understands.
Using Wire.h. The TM1637 has no I2C address and sends its bits in the other order, so the Wire library cannot talk to it. Use TM1637Display on any two pins.
A missing leading zero. showNumberDec(905) shows " 905", not "09:05". Pass true for leading zeros and 0b01000000 for the colon.
Updating with delay(1000). It works until you add a button. Time the seconds with millis() as this sketch does.
Expecting the dots on other digits. On the clock module only the colon is wired; the other dot bits do nothing.
Questions
How do I show a time with a colon on a TM1637?
Use display.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true). The 0b01000000 lights the colon and true keeps the leading zeros.
Which pins does a TM1637 need on an Arduino Uno?
Any two digital pins, plus 5 V and GND. It is not I2C, so it does not need A4 and A5. This example uses A0 for CLK and A1 for DIO.
Which TM1637 library should I use?
TM1637Display by Avishay Orpaz is the one most tutorials use, and the sketch on this page uses it. Mokxi includes it, so #include <TM1637Display.h> works without installing anything.
Can I make a countdown timer with a TM1637?
Yes. Keep the seconds left in a variable, take one off each time millis() passes the next second, and show (left / 60) * 100 + left % 60 with the colon on. The Pomodoro sketch above is a complete one.
Keep going
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.