ESP32 with TM1637 4-Digit LED 7-Segment Display (Arduino IDE)

This is a guide on how to interface the TM1637 4-Digit LED 7-Segment display with the ESP32 programmed with Arduino IDE. You’ll learn how to wire the display to the ESP32 and how to write characters. As an example, we’ll show you how to build a digital clock and a temperature display.

ESP32 with TM1637 4-Digit LED 7-Segment Display Arduino IDE

Table of Contents

In this tutorial, we’ll cover the following topics:

Introducing the TM1637 4-Digit LED 7-Segment Display

The TM1637 4-Digit LED 7-Segment display is a display module that combines four 7-segment digits on a single display that can be controlled via the TM1637 driver. The particular module we’re using here has four digits separated by a colon between the second and third digits.

TM1637 4-Digit 7-Segment Display

There are similar modules with dots between the digits.

There are also similar modules with six 7-segment digits. These require a different library from the one we’ll use in this tutorial.

Note: I tried to use my six 7-segment display module, but it seems that there are many of those displays that come faulty by default. I couldn’t make mine work. So, this tutorial will be only about the one with four digits with a colon in the middle.

Where to Buy?

You can check our Maker Advisor Tools page to compare the TM1637 4-Digit 7-Segment Display module price in different stores:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Wiring the TM1637 4-Digit 7-Segment Display to the ESP32

TM1637 Display Module Pins CLK DIO VCC GND

Wiring the display to the ESP32 is quite simple, as it only requires two digital pins: CLK and DI/O.

TM1637 DisplayESP32
CLKAny digital pin (for example: GPIO 19)*
DIOAny digital pin (for example: GPIO 18)*
VCCVIN
GNDGND

* you can use any other suitable GPIOs. Check the ESP32 Pinout Guide:

We’ll connect the CLK pin to GPIO 19, and the DIO pin to GPIO 18, but you can use another combination of pins.

TM1637 Display - Wiring to the ESP32

Installing the TM1637 Library

There are several libraries to interface the TM1637 display with the ESP32. We’ll use the TM1637.h library by avishorp (even though it hasn’t been updated for several years, it still works well, and it’s very easy to use).

You can install the library via the Arduino IDE library Manager. Search for TM1637 and install the library by avishorp.

Install TM1637 Library in Arduino IDE

Testing the TM1637 Display (Basic Functions)

The following code is the one provided by the library to test the display. You’ll figure out if your display is working properly and see how to implement the basic functions to initialize, control the display, and write characters.

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
  Based on the TM1637Display library example: https://github.com/avishorp/TM1637/blob/master/examples/TM1637Test/TM1637Test.ino
*/
#include <Arduino.h>
#include <TM1637Display.h>

// Module connection pins (Digital Pins)
#define CLK 19
#define DIO 18

// The amount of time (in milliseconds) between tests
#define TEST_DELAY   2000

const uint8_t SEG_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
	};

TM1637Display display(CLK, DIO);

void setup()
{
}

void loop()
{
  int k;
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
  uint8_t blank[] = { 0x00, 0x00, 0x00, 0x00 };
  display.setBrightness(0x0f);

  // All segments on
  display.setSegments(data);
  delay(TEST_DELAY);

  display.showNumberDecEx(1230, 0b01000000);
  delay(10000);

  // Selectively set different digits
  data[0] = display.encodeDigit(7);
  data[1] = display.encodeDigit(6);
  data[2] = display.encodeDigit(5);
  data[3] = display.encodeDigit(9);
  display.setSegments(data);
  delay(TEST_DELAY);

  /*
  for(k = 3; k >= 0; k--) {
	display.setSegments(data, 1, k);
	delay(TEST_DELAY);
	}
  */

  display.clear();
  display.setSegments(data+2, 2, 2);
  delay(TEST_DELAY);

  display.clear();
  display.setSegments(data+2, 2, 1);
  delay(TEST_DELAY);

  display.clear();
  display.setSegments(data+1, 3, 1);
  delay(TEST_DELAY);


  // Show decimal numbers with/without leading zeros
  display.showNumberDec(0, false); // Expect: ___0
  delay(TEST_DELAY);
  display.showNumberDec(0, true);  // Expect: 0000
  delay(TEST_DELAY);
	display.showNumberDec(1, false); // Expect: ___1
	delay(TEST_DELAY);
  display.showNumberDec(1, true);  // Expect: 0001
  delay(TEST_DELAY);
  display.showNumberDec(301, false); // Expect: _301
  delay(TEST_DELAY);
  display.showNumberDec(301, true); // Expect: 0301
  delay(TEST_DELAY);
  display.clear();
  display.showNumberDec(14, false, 2, 1); // Expect: _14_
  delay(TEST_DELAY);
  display.clear();
  display.showNumberDec(4, true, 2, 2);  // Expect: 04__
  delay(TEST_DELAY);
  display.showNumberDec(-1, false);  // Expect: __-1
  delay(TEST_DELAY);
  display.showNumberDec(-12);        // Expect: _-12
  delay(TEST_DELAY);
  display.showNumberDec(-999);       // Expect: -999
  delay(TEST_DELAY);
  display.clear();
  display.showNumberDec(-5, false, 3, 0); // Expect: _-5_
  delay(TEST_DELAY);
  display.showNumberHexEx(0xf1af);        // Expect: f1Af
  delay(TEST_DELAY);
  display.showNumberHexEx(0x2c);          // Expect: __2C
  delay(TEST_DELAY);
  display.showNumberHexEx(0xd1, 0, true); // Expect: 00d1
  delay(TEST_DELAY);
  display.clear();
  display.showNumberHexEx(0xd1, 0, true, 2); // Expect: d1__
  delay(TEST_DELAY);

  
	// Run through all the dots
	for(k=0; k <= 4; k++) {
		display.showNumberDecEx(0, (0x80 >> k), true);
		delay(TEST_DELAY);
	}

  // Brightness Test
  for(k = 0; k < 4; k++)
	data[k] = 0xff;
  for(k = 0; k < 7; k++) {
    display.setBrightness(k);
    display.setSegments(data);
    delay(TEST_DELAY);
  }
  
  // On/Off test
  for(k = 0; k < 4; k++) {
    display.setBrightness(7, false);  // Turn off
    display.setSegments(data);
    delay(TEST_DELAY);
    display.setBrightness(7, true); // Turn on
    display.setSegments(data);
    delay(TEST_DELAY);  
  }

  // Done!
  display.setSegments(SEG_DONE);

  while(1);
}

View raw code

Let’s take a look at some of the relevant functions used in this example.

Initialize the Display

To initialize the display, you just need to create a TM1637Display instance with the pins you’re using to connect the module to your ESP32.

TM1637Display display(CLK, DIO);

Set the Display Brightness

To set the brightness of the display, you can use the setBrightness() method on the display object. You can pass one or two arguments to this function.

void setBrightness(uint8_t brightness, bool on = true);

The first is a number between 0 (min brightness) and 7 (max brightness), and the second argument sets the display on (true) or off (false).

In the code, this function is tested in the following snippet.

// Brightness Test
for(k = 0; k < 4; k++)
  data[k] = 0xff;
for(k = 0; k < 7; k++) {
  display.setBrightness(k);
  display.setSegments(data);
  delay(TEST_DELAY);
}
  
// On/Off test
for(k = 0; k < 4; k++) {
  display.setBrightness(7, false);  // Turn off
  display.setSegments(data);
  delay(TEST_DELAY);
  display.setBrightness(7, true); // Turn on
  display.setSegments(data);
  delay(TEST_DELAY);  
}

Set Segments

The TM1637 display comes with four 7-segment display digits. You can manually control individual segments of each digit with the setSegments() function using an array of bytes.

void setSegments(const uint8_t segments[], uint8_t length = 4, uint8_t pos = 0);
  • segments: an array of bytes that defines which segments are ON for a digit. Each bit in the byte corresponds to one LED segment;
  • length: how many digits to update (0 to 4) – this parameter is optional;
  • pos: start position (0 – leftmost, 3 – rightmost) – the default is 0. This parameter is also optional.
7-segment display

How the Segments are Encoded

Each segment corresponds to a bit in the byte. Take a look at the following table:

segmentbit
A0
B1
C2
D3
E4
F5
G6

Bit 1 turns a segment ON, and bit 0 turns a segment off.

For example, to turn on segments A, B, and C, you’d have a byte like 0b0000111.

The byte starts with the G and ends with the A. For example:

  • 0b0000110 turns segments C and B on.

Display Specific Numbers or Characters

To display a specific number, you need to use the correct combination of segments:

  • 0: a, b, c, d, e, f
  • 1: b, c
  • 2: a, b, g, e, d
  • 3: a, b, g, c, d
  • 4: f, g, b, c
  • 5: a, f, g, c, d
  • 6: a, f, g, e, d, c
  • 7: a, b, c
  • 8: a, b, c, d, e, f, g
  • 9: a, b, c, d, f, g

With this, you can also display other characters, not only numbers.

For example, to manually encode 0123 in the display, you would need an array of bytes like so:

uint8_t segments[] = {
  0b0111111, // 0 — all segments except G
  0b0000110, // 1 — segments B and C
  0b1011011, // 2
  0b1001111  // 3
};

For example, to test this function, you can use the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <Arduino.h>
#include <TM1637Display.h>

#define CLK 19
#define DIO 18
TM1637Display display(CLK, DIO);

void setup() {
  display.setBrightness(7); 

  // Custom segments (one byte per digit)
  uint8_t segments[] = {
    0b0111111, // 0 — all segments except G
    0b0000110, // 1 — segments B and C
    0b1011011, // 2
    0b1001111  // 3
  };

  display.setSegments(segments);
}

void loop() {
  
}

View raw code

Display a Decimal Number

To display a decimal number, you can use the showNumberDec() function on the display object.

void showNumberDec(int num, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);

This function accepts the following parameters:

  • num: the number to be shown
  • leading_zero: when true, leading zeros are displayed. Otherwise, unnecessary digits are blank.
  • length: the number of digits to set. The user must ensure that the number to be shown fits the number of digits requested (for example, if two digits are to be displayed, the number must be between 0 to 99)
  • pos: the position of the most significant digit (0 – leftmost, 3 – rightmost)

There are several use case examples of this function in the code. The comments show what each command will display.

display.showNumberDec(0, false); // Expect: ___0
delay(TEST_DELAY);
display.showNumberDec(0, true);  // Expect: 0000
delay(TEST_DELAY);
display.showNumberDec(1, false); // Expect: ___1
delay(TEST_DELAY);
display.showNumberDec(1, true);  // Expect: 0001
delay(TEST_DELAY);
display.showNumberDec(301, false); // Expect: _301
delay(TEST_DELAY);
display.showNumberDec(301, true); // Expect: 0301
delay(TEST_DELAY);
display.clear();
display.showNumberDec(14, false, 2, 1); // Expect: _14_
delay(TEST_DELAY);
display.clear();
display.showNumberDec(4, true, 2, 2);  // Expect: 04__
delay(TEST_DELAY);
display.showNumberDec(-1, false);  // Expect: __-1
delay(TEST_DELAY);
display.showNumberDec(-12);        // Expect: _-12
delay(TEST_DELAY);
display.showNumberDec(-999);       // Expect: -999
delay(TEST_DELAY);
display.clear();
display.showNumberDec(-5, false, 3, 0); // Expect: _-5_
delay(TEST_DELAY);

Display a Decimal Number with a Colon/Dot

There is another function that allows you to display a decimal number and control whether the colon or dot (depending on the display) is on or off. That’s the showNumberDecEx() function. Here are the parameters accepted:

void showNumberDecEx(uint16_t num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);

It is similar to the previous showNumberDec() function, but the second argument allows us to enable or disable the colon/dot.

  • num: the number to be shown
  • dots: dot/colon enable – see below how it works
  • leading_zero: when true, leading zeros are displayed. Otherwise, unnecessary digits are blank.
  • length: the number of digits to set. The user must ensure that the number to be shown fits the number of digits requested (for example, if two digits are to be displayed, the number must be between 0 to 99)
  • pos: the position of the most significant digit (0 – leftmost, 3 – rightmost)

Colon/dot control

The second argument of the showNumberDecEx() function is a bitmask, with each bit corresponding to a dot between the digits (or colon mark, as implemented by each module).

For example, for displays with dots between each digit:

  • 0.000 > (0b10000000)
  • 00.00 > (0b01000000)
  • 000.0 > (0b00100000)
  • 0.0.0.0 > (0b11100000)

In our case, it’s a display with just a colon. So, to display the colon, we can pass the following binary as a second argument:

  • 00:00 > (0b01000000)

Finally, here’s an example for displays with dots and colons:

  • 0.0:0.0 > (0b11100000)

For example, to display 12:30, you would call:

display.showNumberDecEx(1230, 0b01000000);

In the code, this is where the function is used:

// Run through all the dots
for(k=0; k <= 4; k++) {
  display.showNumberDecEx(0, (0x80 >> k), true);
  delay(TEST_DELAY);
}

Demonstration

Upload the code to the board. It will display a series of digits, characters, and segments on the display to test the library functions.

ESP32 with TME1637 Display Testing

If the example doesn’t work, double-check the wiring and the power supply.


Practical Examples with the TM1637 Display

Now that you know the basic functions to control the display, we’ll show you two practical examples that you can test with the TM1637 Display and the ESP32:

These two projects only require the ESP32 and the display. No extra hardware is needed, as all the information will be requested from the internet using the ESP32’s Wi-Fi capabilities.

ESP32 Digital Clock with the TM1637 Display (with timezone adjustment and DST)

The layout of the TM1637 4-Digit 7-Segment display with a colon between the second and the third characters is ideal for creating a digital clock, with the hour on one side of the colon and the minutes on the other side.

ESP32 TM1637 Digital Internet Clock

We’ll get the time for your timezone using NTP (network time protocol) with adjustment for daylight saving time.

To learn more about getting time with the ESP32 for your timezone and consider daylight saving time (if that’s the case), you can read the following in-depth guide:

Project Overview

Here’s a quick overview of the steps to create this project:

  • Initialize the display;
  • Initialize Wi-Fi and connect the ESP32 to your local network so that it can get data from the internet;
  • Initialize time for your specified timezone (takes into account daylight saving time);
  • Show the time on the display (blink the colon between the numbers every second).

Code – TM1637 Digital Clock

You can upload the following code to your ESP32 board. You need to:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include "time.h"
#include <TM1637Display.h>

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// TM1637 pins
#define CLK 19
#define DIO 18

TM1637Display display(CLK, DIO);

// Timezone (Lisbon / Portugal)
// Change if needed - See list of timezones strings: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
const char* TZ_INFO = "WET0WEST,M3.5.0/1,M10.5.0";

// Init Wifi
void initWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
}

// Initialize Time with the specified timezone
void initTime() {
  configTime(0, 0, "pool.ntp.org");
  setenv("TZ", TZ_INFO, 1);
  tzset();
}

// display the time on the screen
void displayTime() {

  // blinking colon
  static bool colon = false;
  colon = !colon;

  // get the current time
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    return;
  }

  int hours   = timeinfo.tm_hour;   // get hours (0–23)
  int minutes = timeinfo.tm_min;    // get minutes (0–59)

  // move hours to the left two digits
  int hourPart = hours * 100;

  // combine hours and minutes into HHMM
  int value = hourPart + minutes;

  // control the colon (for blinking colon)
  uint8_t colonMask;
  if (colon == true) {
    colonMask = 0b01000000;   // turn colon ON
  } else {
    colonMask = 0;            // turn colon OFF
  }

  display.showNumberDecEx(
    value,
    colonMask,   // blink colon
    true         // leading zeros
  );
}

void setup() {
  Serial.begin(115200);

  display.setBrightness(7);
  display.clear();

  initWiFi();
  initTime();
}

void loop() {
  displayTime();
  delay(1000);
}

View raw code

How Does the Code Work?

Let’s take a quick look at the code to see how it works.

Include Libraries

Start by including the required libraries.

#include <WiFi.h>
#include "time.h"
#include <TM1637Display.h>

Network Credentials

Insert your network credentials on the following lines.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Initialize the Display

Set the TM1637 pins and create an instance for the display called display.

// TM1637 pins
#define CLK 19
#define DIO 18

TM1637Display display(CLK, DIO);

Timezone

Insert your timezone string in the following line. You can find a list of timezone strings here. In my case, my timezone is Lisbon/Portugal, so it will look as follows:

const char* TZ_INFO = "WET0WEST,M3.5.0/1,M10.5.0";

Initialize Wi-Fi

The following function initializes Wi-Fi and connects the ESP32 to your local network. This will be called later on in the setup().

// Init Wifi
void initWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
}

You can learn more about the ESP32 Wi-Fi function in the following tutorial:

Initialize Time

The initTime() function initializes NTP time and adjusts it to your timezone—notice the setenv() and tzset() functions.

// Initialize Time with the specified timezone
void initTime() {
  configTime(0, 0, "pool.ntp.org");
  setenv("TZ", TZ_INFO, 1);
  tzset();
}

To learn more about getting the date and time with timezone adjustment, check out this tutorial:

The displayTime() function will display the date and time on the screen.

void displayTime() {

We have a boolean variable called colon to determine whether the colon is showing up or not (to create the blinking effect).

// blinking colon
static bool colon = false;
colon = !colon;

We get the current time and save it in the timeinfo structure.

// get the current time
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
  return;
}

Then, we can get the hour and minutes as follows:

int hours   = timeinfo.tm_hour;   // get hours (0–23)
int minutes = timeinfo.tm_min;    // get minutes (0–59)

Now, to display the numbers on the screen, we need to combine the date and time in a single number with four digits that will be split in the middle by the colon.

We can do that by multiplying the hour by 100 and then adding the minutes.

// move hours to the left two digits
int hourPart = hours * 100;

// combine hours and minutes into HHMM
int value = hourPart + minutes;

For example, imagine the hour is 12 and the minutes are 30. We want to get 12:30. So, we need to get the 1230 number and display the colon in the middle.

12*100+30 will give the desired 1230. This number is saved in the value variable.

Finally, we adjust the bitmask to display the colon depending on whether it is time to display the colon.

// control the colon (for blinking colon)
uint8_t colonMask;
if (colon == true) {
  colonMask = 0b01000000;   // turn colon ON
} else {
  colonMask = 0;            // turn colon OFF
}

We can use the showNumberDecEx() to display the time on the screen. Pass as an argument the value, the bit mask for the colon, and whether we have leading zeros.

display.showNumberDecEx(
  value,
  colonMask,   // blink colon
  true         // leading zeros
);

Now that we have all the essential functions declared, it is easy to set up our code.

setup()

In the setup() initialize the Serial Monitor, set the display brightness, initialize Wi-Fi, and time.

void setup() {
  Serial.begin(115200);

  display.setBrightness(7);
  display.clear();

  initWiFi();
  initTime();
}

loop()

Finally, in the loop(), you just need to call the displayTime() function to display the time on the 4-digit 7-segment display module.

void loop() {
  displayTime();
  delay(1000);
}

Demonstration

After inserting your network credentials and your timezone information, you can upload the code to the ESP32.

It should start displaying the current time for your timezone.

ESP32 TM1637 Digital Internet Clock

The colon should be blinking every second to resemble those old digital clocks.


ESP32 Temperature Display (TM1637) from Weather API

In this project, we’ll display the current temperature for your city on the display. We’ll get the temperature from the Weather API.

This API is free and provides useful information about the weather in almost any location in the world.

Weather forecaster example

We’ll get the temperature for your location and display it on the 7-segment display module.

Getting Your API Key

  1. Go to the Weather API website: weatherapi.com/
  2. Signup to create an account.
  3. After verifying your account, login into your account.
  4. On your dashboard at weatherapi.com/my/ , you’ll find your API key (even though it says the trial will end, you can continue using your API key freely).
Weather API Key

Copy the API key to a safe place because you’ll need it later.

To pull information on the weather in your chosen location, enter the following URL in your web browser, but insert your location and API key in the right places:

https://api.weatherapi.com/v1/current.json?q=YOUR_LOCATION+&key=YOUR_API_KEY'

For example, in my case:

https://api.weatherapi.com/v1/current.json?q=Oporto+&key=d1578a064b07453c917164350240106'

Copy your URL and paste it into your browser, and the API will return information corresponding to your local weather. For example:

{
"location": {
"name": "Oporto",
"region": "Porto",
"country": "Portugal",
"lat": 41.15,
"lon": -8.62,
"tz_id": "Europe/Lisbon",
"localtime_epoch": 1719843562,
"localtime": "2024-07-01 15:19"
},
"current": {
"last_updated_epoch": 1719843300,
"last_updated": "2024-07-01 15:15",
"temp_c": 22.3,
"temp_f": 72.1,
"is_day": 1,
"condition": {
"text": "Sunny",
"icon": "//cdn.weatherapi.com/weather/64x64/day/113.png",
"code": 1000
},
"wind_mph": 10.5,
"wind_kph": 16.9,
"wind_degree": 310,
"wind_dir": "NW",
"pressure_mb": 1021,
"pressure_in": 30.15,
"precip_mm": 0,
"precip_in": 0,
"humidity": 69,
"cloud": 0,
"feelslike_c": 24.7,
"feelslike_f": 76.4,
"windchill_c": 21.9,
"windchill_f": 71.5,
"heatindex_c": 24.6,
"heatindex_f": 76.2,
"dewpoint_c": 15,
"dewpoint_f": 58.9,
"vis_km": 10,
"vis_miles": 6,
"uv": 6,
"gust_mph": 15.4,
"gust_kph": 24.7
}
}

From this JSON, we can easily get the temperature for your location, either in Celsius or Fahrenheit: temp_c and temp_f.

Installing Libraries

For this example, you need to install the ArduinoJSON library by bblanchon.

Install ArduinoJSON library Arduino IDE

Code – TM1637 Temperature Display

You can upload the following code to your board. You need to:

  • insert your SSID and password;
  • insert your WeatherAPI API key;
  • insert the city where you want to get the temperature for.
/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <TM1637Display.h>

// Wi-Fi credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const char* api_key = "REPLACE_WITH_YOUR_WeatherAPI_API_Key";
const char* location = "Oporto";  // "q" Parameter documentation for location: https://www.weatherapi.com/docs/#intro-request

// Request URL
String url = "https://api.weatherapi.com/v1/current.json?q=" + String(location) + "&key=" + String(api_key);

// TM1637 pins
#define CLK 19
#define DIO 18

TM1637Display display(CLK, DIO);

// Create the °C Symbol
const uint8_t Celsius[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // Circle
  SEG_A | SEG_D | SEG_E | SEG_F   // C
};

// Create the °F Symbol
const uint8_t Fahrenheit[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // Circle
  SEG_F | SEG_E | SEG_A | SEG_G   // F
};

// Global variables for temperatures and timers
float currentTempC = 9999;  // Initial error value
float currentTempF = 9999;  // Initial error value
unsigned long lastFetchTime = 0;
const unsigned long fetchInterval = 3600000UL;  // 1 hour in milliseconds

// Init Wifi
void initWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connection successful");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

bool updateTemperatures() {
  HTTPClient http;
  http.begin(url);

  int httpCode = http.GET();

  if (httpCode == HTTP_CODE_OK) {  // Check for 200 specifically
    String payload = http.getString();
    Serial.print(payload);

    // Parse JSON
    StaticJsonDocument<1024> doc; // Adjust size if needed based on response
    DeserializationError error = deserializeJson(doc, payload);

    if (error) {
      Serial.print("JSON parsing failed: ");
      Serial.println(error.c_str());
      http.end();
      return false;
    }

    // Get both temperatures
    currentTempC = doc["current"]["temp_c"];
    currentTempF = doc["current"]["temp_f"];
    http.end();
    return true;
  } else {
    Serial.print("Error during request: ");
    Serial.println(httpCode);
    http.end();
    return false;
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000); // Give time for Serial to initialize

  // Connect to Wi-Fi
  initWiFi();

  display.setBrightness(7);  // Set the display brightness (0-7)

  // Initial fetch
  if (updateTemperatures()) {
    lastFetchTime = millis();
  }
}

void loop() {
  // Check if it's time to fetch new data
  if (millis() - lastFetchTime >= fetchInterval) {
    if (updateTemperatures()) {
      lastFetchTime = millis();
    } else {
      // If failed, try again next loop 
      Serial.println("Fetch failed, keeping old values.");
    }
  }

  // Show Celsius
  Serial.print("Temperature in Celsius: ");
  Serial.println(currentTempC, 2);
  
  int roundedTempC = round(currentTempC);
  display.showNumberDec(roundedTempC, false, 2, 0);
  display.setSegments(Celsius, 2, 2);

  delay(5000);

  // Show Fahrenheit
  Serial.print("Temperature in Fahrenheit: ");
  Serial.println(currentTempF, 2);

  int roundedTempF = round(currentTempF);
  display.showNumberDec(roundedTempF, false, 2, 0);
  display.setSegments(Fahrenheit, 2, 2);

  delay(5000);
}

View raw code

How Does the Code Work?

Let’s take a quick look at the relevant parts of the code for this tutorial.

Including Libraries

We start by including the required libraries.

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <TM1637Display.h>

Network Credentials

Insert your network credentials in the following lines.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Weather API

Insert your WeatherAPI key and the location you want to get data for.

const char* api_key = "REPLACE_WITH_YOUR_API_KEY";
const char* location = "REPLACE_WITH_YOUR_LOCATION";

This is the request URL that will return the weather data.

String url = "https://api.weatherapi.com/v1/current.json?q=" + String(location) + "&key=" + String(api_key);

TM1637 Display

Set the pins that are controlling the display and initialize an instance of the display called display.

// TM1637 pins
#define CLK 19
#define DIO 18

TM1637Display display(CLK, DIO);

Create an array with the required segments to create the ºC and ºF symbols.

// Create the °C Symbol
const uint8_t Celsius[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // Circle
  SEG_A | SEG_D | SEG_E | SEG_F   // C
};

// Create the °F Symbol
const uint8_t Fahrenheit[] = {
  SEG_A | SEG_B | SEG_F | SEG_G,  // Circle
  SEG_F | SEG_E | SEG_A | SEG_G   // F
};

The SEG_A, SEG_B, and so on are references to their specific bytes (these are defined in the library .h file).

Global variables

Create global variables to store the temperature in Celsius and Fahrenheit.

float currentTempC = 9999;  // Initial error value
float currentTempF = 9999;  // Initial error value

And auxiliar variables to count the time to make a request to the API every hour.

unsigned long lastFetchTime = 0;
const unsigned long fetchInterval = 3600000UL;  // 1 hour in milliseconds

Initialize Wi-Fi

The initWiFi() function will initialize Wi-Fi and connect to your network using the inserted credentials.

// Init Wifi
void initWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connection successful");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

Get/Update the Temperatures

The updateTemperatures() function makes a request to the WeatherAPI request URL.

The request returns a bunch of weather data as we’ve seen previously. We print all data to the Serial Monitor.

bool updateTemperatures() {
HTTPClient http;
http.begin(url);

int httpCode = http.GET();

if (httpCode == HTTP_CODE_OK) {  // Check for 200 specifically
  String payload = http.getString();
  Serial.print(payload);

Then, we only save the data we’re interested in. In this case, the temperature in Celsius and Fahrenheit. We save them in the currentTempC and currentTempF variables.

currentTempC = doc["current"]["temp_c"];
currentTempF = doc["current"]["temp_f"];

If everything goes well with the request, the function returns true. Otherwise, it returns false.

setup()

In the setup(), we initialize the Serial Monitor, connect to Wi-Fi, and set the display brightness.

void setup() {
  Serial.begin(115200);
  delay(1000); // Give time for Serial to initialize

  // Connect to Wi-Fi
  initWiFi();

  display.setBrightness(7);  // Set the display brightness (0-7)

Then, we make our first request to the API to get the current temperatures when the code first runs. From that time on, we also start counting the time to check later in the loop() if it’s time to make another request.

// Initial fetch
if (updateTemperatures()) {
  lastFetchTime = millis();
}

loop()

In the loop(), we’re constantly checking when it’s time to get new values.

// Check if it's time to fetch new data
if (millis() - lastFetchTime >= fetchInterval) {
  if (updateTemperatures()) {
    lastFetchTime = millis();
  } else {
    // If failed, try again next loop 
    Serial.println("Fetch failed, keeping old values.");
  }
}

Then, in the display, we’re alternating between showing the temperature in Celsius and in Fahrenheit every five seconds.

// Show Celsius
Serial.print("Temperature in Celsius: ");
Serial.println(currentTempC, 2);
  
int roundedTempC = round(currentTempC);
display.showNumberDec(roundedTempC, false, 2, 0);
display.setSegments(Celsius, 2, 2);

delay(5000);

// Show Fahrenheit
Serial.print("Temperature in Fahrenheit: ");
Serial.println(currentTempF, 2);

int roundedTempF = round(currentTempF);
display.showNumberDec(roundedTempF, false, 2, 0);
display.setSegments(Fahrenheit, 2, 2);

delay(5000);

Since the temperature values come as float variables, we need to convert them to integers. To do that, we use the round() function to round the number. For example:

int roundedTempC = round(currentTempC);

Then, we simply call the showNumberDec() function to display the values.

display.showNumberDec(roundedTempC, false, 2, 0);

Then, call the setSegments() function to display the ºC and ºF Units.

display.setSegments(Celsius, 2, 2);

Demonstration

Upload the code to your ESP32 board. Don’t forget to insert your SSID and password in the code, as well as the API key, and your location.

You should get a successful message on the Serial Monitor.

Get Temperature from API - ESP32 - Serial Monitor

And the temperature in Celsius and Fahrenheit degrees will show up alternating on the display.

Wrapping Up

This was a comprehensive guide on how to interface the TM1637 4-digit 7-segment display with the ESP32. It can be quite useful to display temperature, the time, or other information.

The specific format of display we have, with a colon in the middle, might be especially useful to create a digital clock or to display a timer.

We hope you’ve found this guide useful. We have guides for other displays that might be helpful:

To learn more about the ESP32, make sure to check out our resources:



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.