Interfacing TM1637 4-Digit 7-Segment Display with ESP32

Whether you are making a digital clock, a timer, a counter, or a simple sensor project, you need an easy way to show numbers clearly. That is where the TM1637 display module becomes very useful. It gives you a bright 4-digit 7-segment display that can work nicely with the ESP32, while keeping the wiring and coding simple.

In this tutorial, you will learn how to connect the TM1637 module to an ESP32, install the required library, and write code to display numbers and simple symbols.

Let’s dive in!

TM1637 Module Hardware Overview

The TM1637 module combines two parts in one package: a 0.36-inch 4-digit 7-segment display with the TM1637 LED driver chip made by Titan MicroElectronics. This cool combination lets you control all four digits using just two pins from your microcontroller.

TM1637 Hardware Overview LED Display

This module is great for projects where you want to display numbers clearly, such as clocks, timers, counters, scoreboards, temperature displays, or sensor readings. Many TM1637 modules also include a colon in the middle, which is especially helpful when making a digital clock.

One reason the TM1637 module is so popular is that it takes care of the hard work of refreshing the display by itself. That means the ESP32 does not need to constantly update every segment again and again. As a result, your program stays simpler and the ESP32 can spend more time doing other important tasks.

TM1637 Hardware Overview Chip

Another nice thing is that the TM1637 module can work with both 3.3V and 5V. This makes it compatible with both 3.3V microcontrollers like the ESP32 and 5V microcontrollers like the regular Arduino.

The amount of power the module uses depends on how many segments are lit and the brightness level you set. When all segments are lit at maximum brightness, the module uses about 80 mA of current. You can save power by adjusting the display’s brightness to a lower level.

The module uses its own special two-wire communication protocol. While this isn’t a standard protocol like I2C, there are easy-to-use Arduino libraries available that hide all the complicated stuff and make it simple to communicate with the display.

Technical Specifications

Here are the specifications:

Operating voltage3.3 – 5 VDC
Maximum Current Draw80mA
Reverse polarity protectionYes
Display Size42 mm x 24 mm (1.65″ x .95″)
Display Height12 mm (0.47″) (typical)
Character Height9.14 mm (0.36″)

For more detailed information about the TM1637 driver chip, please refer to the datasheet below.

TM1637 Module Pinout

The TM1637 module has only four pins, making it very simple to use. Here is the pinout:

TM1637 4 Digit 7 Segment Display Module Pinout

CLK is the clock input pin.

DIO is the data input/output (I/O) pin.

VCC is the power supply pin. Connect it to a 3.3V to 5V power source.

GND is the ground pin.

Wiring the TM1637 Module to an ESP32

Connecting the TM1637 module to an ESP32 is simple because the module only has four pins. Two pins are used for power, and the other two are used for communication.

Start by connecting the VCC pin of the TM1637 module to the VIN pin of the ESP32. Then connect the GND pin of the module to a GND pin on the ESP32. After that, connect the CLK pin of the module to GPIO 26 on the ESP32, and connect the DIO pin of the module to GPIO 25.

Here’s a quick reference table for the pin connections:

TM1637 ModuleESP32
VCCVIN
GNDGND
DIO25
CLK26

This diagram shows you exactly how to connect everything:

wiring tm1637 module to an esp32

Setting Up the Arduino IDE

We will be using the Arduino IDE to program the ESP32, so please ensure you have the ESP32 add-on installed before you proceed:

Library Installation

To communicate with the TM1637 chip, you will need to use a library. A great option is the TM1637Display library created by Avishay Orpaz. This library has many built-in functions that make controlling the display simple and straightforward.

To install the library,

  1. First open your Arduino IDE program. Then click on the Library Manager icon on the left sidebar.
  2. Type “tm1637” in the search box to filter your results.
  3. Look for the TM1637 library by Avishay Orpaz.
  4. Click the Install button to add it to your Arduino IDE.
tm1637 display library installation

Once the library is installed, you’re all set and ready for programming!

Example – Basic Display Test

Now let’s try a simple test program. This example helps you check that your TM1637 display is wired correctly and working with the ESP32.

The program will show different patterns and numbers on the display, such as turning all segments on, counting from 0 to 9, showing negative numbers, lighting the colon, and finally displaying the word “dOnE.”

#include <TM1637Display.h>

// TM1637 connections to ESP32
#define CLK 26
#define DIO 25

// Create display object
TM1637Display display(CLK, DIO);

// An array that turns every segments ON
const uint8_t allON[] = { 0xff, 0xff, 0xff, 0xff };

// An array that sets individual segments per digit to display the word "dOnE"
const uint8_t done[] = {
  SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,          // d
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,  // O
  SEG_C | SEG_E | SEG_G,                          // n
  SEG_A | SEG_D | SEG_E | SEG_F | SEG_G           // E
};

// An array that displays the °C symbol
const uint8_t celsius[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // degree symbol
  SEG_A | SEG_D | SEG_E | SEG_F   // C
};

void setup() {
  // Start with a medium brightness
  // Brightness range is 0 (dimmest) to 7 (brightest)
  display.setBrightness(5);

  // Set every segments ON
  display.setSegments(allON);
  delay(2000);

  // Clear the display
  display.clear();

  // Count from 0 to 9
  for (int i = 0; i < 10; i++) {
    display.showNumberDec(i);
    delay(200);
  }
  delay(1000);
  display.clear();

  // Show negative numbers
  display.showNumberDec(-12);  // shows " -12"
  delay(2000);
  display.clear();

  display.showNumberDec(-999);  // shows "-999"
  delay(2000);
  display.clear();

  // Show number without leading zeros
  display.showNumberDec(31, false);  // shows "  31"
  delay(2000);
  display.clear();

  // Show number with leading zeros
  display.showNumberDec(31, true);  // shows "0031"
  delay(2000);
  display.clear();

  // Show number in the middle
  display.showNumberDec(14, false, 2, 1);  // shows " 14 "
  delay(2000);
  display.clear();

  // Show a negative number in the middle
  display.showNumberDec(-5, false, 2, 1);  // shows " -5 "
  delay(2000);
  display.clear();

  // Show 12:34 using the colon
  display.showNumberDecEx(1234, 0b01000000, false, 4, 0);
  delay(2000);
  display.clear();

  // Show 15°C
  int temperature = 15;
  display.showNumberDec(temperature, false, 2, 0);
  display.setSegments(celsius, 2, 2);
  delay(2000);
  display.clear();

  // Show dOnE
  display.setSegments(done);
}

void loop() {
}

Upload this code to your ESP32. If everything is connected properly, the display should go through a short test sequence and end by showing dOnE.

tm1637 test output

Code Explanation:

We begin by including the TM1637 library, and telling the program which two ESP32 pins are connected to the display module — one for the clock (CLK) and the other for the data input/output (DIO).

#include <TM1637Display.h>

// TM1637 connections to ESP32
#define CLK 26
#define DIO 25

Next, we create a display object from the TM1637Display class. This object lets us send commands to the TM1637. When we create the object, we have to tell it which two pins we are using.

// Create display object
TM1637Display display(CLK, DIO);

The TM1637 library lets us control each segment of the display individually. This is how we can show numbers, letters, and even a few simple symbols on the screen.

To demonstrate this, we prepare three arrays. These arrays store the segment patterns that tell the display which LEDs should turn on.

The first array turns on all the segments. The second array creates the word “dOnE”, and the third creates the “°C” symbol. We use a function called setSegments() to send these arrays to the display and show them.

There are two ways to define these arrays.

1. Using hexadecimal numbers: When you use this method, you create the hex number following a specific order for the segments: (dot) G F E D C B A. Each letter stands for one segment on the display, and each segment can either be on (1) or off (0).

For example, the hex number 0xFF (which is 11111111 in binary) turns on all the segments, including the dot. On the other hand, 0x00 (which is 00000000 in binary) turns off all the segments.

If you want to display the letter “C,” you would use the hex number 0x39. In binary, that’s 00111001. This pattern turns on segments A, D, E, and F, while leaving the others off.

// An array that turns every segments ON
const uint8_t allON[] = { 0xff, 0xff, 0xff, 0xff };

2. Using segment names: The second way to create these arrays is even simpler. We can just list the segment names we want to turn on, using names like SEG_A, SEG_B, SEG_C, and so on.

// An array that sets individual segments per digit to display the word "dOnE"
const uint8_t done[] = {
  SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,          // d
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,  // O
  SEG_C | SEG_E | SEG_G,                          // n
  SEG_A | SEG_D | SEG_E | SEG_F | SEG_G           // E
};

// An array that displays the °C symbol
const uint8_t celsius[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // degree symbol
  SEG_A | SEG_D | SEG_E | SEG_F   // C
};

In the setup() section of the code, we use several functions from the TM1637 library:

setBrightness(brightness,on)

This function controls the brightness of the display. You can choose any value between 0 (very dim) and 7 (very bright).

There’s also an optional second part you can add: if you pass false, it will turn off the display; if you pass true or leave it out, the display stays on. So when you write display.setBrightness(5), you are setting the brightness to a medium level. If you write display.setBrightness(5, false), you are actually turning the display off, even though you chose a brightness level.

setSegments(segments[],length,position)

This function lets you control individual segments of the display. We give it three pieces of information: the array that holds the information about which segments to light up, how many digits we want to update (from 0 to 4), and where the number should start on the display (position 0 is the leftmost digit, and position 3 is the rightmost).

Note that the second and third arguments are optional. If you want to update the entire display without worrying about length or position, you can just skip them. For example, when we want to display the word “dOnE,” we are lighting up all 4 digits starting from the leftmost position (position 0). So, we simply call the function like this:

// Prints dOnE
display.setSegments(done);

But sometimes we don’t want to update all four digits. For example, when we want to show the “°C” symbol, we only want to update the last two digits. In that case, we also tell the function how many digits (2) and from which position (2) to start.

// Prints __°C
display.setSegments(celsius, 2, 2);

showNumberDec(number,leading_zeros,length,position)

Another very important function we use is showNumberDec(). This function is great for quickly displaying numbers. We just tell it which number we want to show, and it figures out which segments to light up. For example, if you want to count from 0 to 9, you can use a loop with showNumberDec() like this:

// Show counter 0-9
int i;
for (i = 0; i < 10; i++) {
  display.showNumberDec(i);
  delay(50);
}

You can also use this function to display negative numbers. It will automatically add the minus sign in the right place:

display.showNumberDec(-12);  // Prints _-12

display.showNumberDec(-999);  // Prints -999

The second argument controls whether or not you want to add leading zeros. If you set this to true, the display will add zeros in front to make the number fit all four digits. If you set it to false, it will just show the number as-is.

display.showNumberDec(31, false);  // Prints __31

display.showNumberDec(31, true);  // Prints 0031

The third and fourth arguments work the same way as before. They let you decide how many digits you want to update and where the number should start on the display. So, if you want the number to appear centered in the display, you would write:

display.showNumberDec(14, false, 2, 1);  // Prints _14_

display.showNumberDec(-5, false, 2, 1);  // Prints _-5_

showNumberDecEx(number,dots,leading_zeros,length,position)

This function is an extended version of showNumberDec(). The main difference is that the second argument now controls the dots or colons on the display, which is perfect for showing times or decimal numbers. To control these dots, you use a binary number that tells the display exactly which dots to turn on. Each position in the binary number corresponds to a specific dot on your display. For example:

If you have a display with dots between each digit, here’s how it works:

ArgumentDotsExample
0b10000000 .   1.234
0b01000000  .  12.34
0b00100000   . 123.4
0b11100000 . . . 1.2.3.4

Some TM1637 displays have a colon instead of dots. In this case:

ArgumentDotsExample
0b01000000  :  12:34

There are even displays that have both dots and a colon. On these displays:

ArgumentDotsExample
0b11100000 . : . 1.2:3.4

Let’s say you want to make a digital clock that shows “12:34”. You would use the function like this:

// Prints 12:34
display.showNumberDecEx(1234, 0b01000000, false, 4, 0);

First, you’d tell it to display the number 1234. Then, you’d use the binary code 0b01000000 to turn on the colon in the middle. The last few arguments tell the function not to add leading zeros, to update all four digits, and to start at the first position.

Since there’s nothing that needs to run repeatedly in this example, we leave the loop() function empty.

void loop() {
}
#include <TM1637Display.h>

// ESP32 pins connected to the TM1637 module
#define CLK 26
#define DIO 25

// Create the display object
TM1637Display display(CLK, DIO);

// An array that turns every segments ON
const uint8_t SEG_ALL_ON[] = {0xFF, 0xFF, 0xFF, 0xFF};

// An array that sets individual segments per digit to display the word "dOnE"
const uint8_t WORD_DONE[] = {
  SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,         // d
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
  SEG_C | SEG_E | SEG_G,                         // n
  SEG_A | SEG_D | SEG_E | SEG_F | SEG_G          // E
};

// An array that displays the degree celsius symbol
const uint8_t SYMBOL_CELSIUS[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // degree symbol
  SEG_A | SEG_D | SEG_E | SEG_F   // C
};

void setup() {
  // Start with a medium brightness and display enabled.
  // Brightness range is 0 (dimmest) to 7 (brightest)
  display.setBrightness(5, true);
}

void loop() {
  // Set every segments ON
  display.setSegments(SEG_ALL_ON);
  delay(1500);

  // Clear the display
  display.clear();

  // Show decimal numbers
  // Demonstrates positive, negative, leading zeros, length and position
  display.showNumberDec(42, false);        // "  42"
  delay(1500);
  
  display.showNumberDec(42, true);         // "0042"
  delay(1500);

  display.showNumberDec(-18, false);       // " -18"
  delay(1500);

  display.clear();
  display.showNumberDec(14, false, 2, 1);  // "_14_"
  delay(1500);
  
  display.clear();
  display.showNumberDec(4, true, 2, 0);    // "04__"
  delay(1500);
  
  display.clear();
  display.showNumberDec(-5, false, 3, 0);  // "_-5_"
  delay(1500);

  // Show hexadecimal numbers
  display.showNumberHexEx(0x1A2F);         // "1A2F"
  delay(1500);
  
  display.showNumberHexEx(0x2c);           // "__2C"
  delay(1500);
  
  display.showNumberHexEx(0xd1, 0, true);  // "00d1"
  delay(1500);
  
  display.clear();
  display.showNumberHexEx(0xd1, 0, true, 2);  // "d1__"
  delay(1500);

  // Show decimal number with colon control
  display.showNumberDecEx(1234, 0b01000000, true);   // "12:34"
  delay(1500);
  
  // Show temperature
  display.setSegments(SYMBOL_CELSIUS, 2, 2); // put "°C" on the right
  display.showNumberDec(25, false, 2, 0);    // "25°C"
  delay(1500);
  
  // Brightness Test  
  for (int i = 0; i < 7; i++) {
    display.setBrightness(i);
    display.setSegments(SEG_ALL_ON);
    delay(1000);
  }

  // Final screen
  display.setSegments(WORD_DONE);
  
  while (true) {
    // Stop here
  }
}

Going further

Now that you know how to connect and control a TM1637 display with the ESP32, you can start building more useful real-world projects with it. One great next step is to make a Wi-Fi digital clock that automatically gets the correct time from the internet using NTP. If you want to try that project next, check out the tutorial below.

Amrit Prabhu

Amrit Prabhu

Amrit is an Electronics Engineer who loves making complex programming and hardware concepts accessible. He has more than 15 years of experience, having worked as a Senior Programmer Analyst at Mindtree Ltd. and Symantec on major projects like Windows 8, Wolters Kluwer CCH and NSE. Since 2018, he has authored hundreds of tutorials and guides for Last Minute Engineers, helping readers master everything from basic circuits to IoT. You can find him on LinkedIn