Centre colon on TM1637 4-digit 7-segment LED display?

Hi all.

Using a bunch of 4-digit 7-segment column displays (TM1637). Love the retro tech look.

All good, except the centre colon. I read some advice here (Thanks, @LarryD !), so I tried:

  display4.showNumberDecEx(hour, 0b01000000, true, 2, 0);
  display4.showNumberDec(minute, true, 2, 2);

I also tried a similar solution given in the data sheet.

Both have the same problem: when the colon displays, a "0" right before the colon is flashed briefly, before it is displaced by the actual time.

I must be doing something stupid. Not sure what, though!

EDIT: Yes, I am stupid.. some old code still in there (see below). I am guessing that's the case - will try tonight..


Which library are you using? There are several, and they differ in how the colon is addressed.

My code has

const uint8_t colonMask = 0b01000000;
display.showNumberDecEx(hourFormat12(timeinfo.tm_hour), colonMask, false, 2, upperDigits); 

Which appears to boil down to the same thing you posted, so yours should work.
Therefore, it is likely that there is some other mistake in your code that is doing it...

1 Like

Doubt we will discover the problem, given we do not have the actual code! :face_with_raised_eyebrow:

What's a "column display"?

I guess you haven't spent much time on AliExpress... :slight_smile: A lot of vendors use the phrase.

Yeah my bad: I meant 4-column 7-segment display...

It's a little long (the sketch does all sorts of things), and I am debating how best to post the display bits... but here is the whole sketch (unfinished: after this I do the time setting etc):

New Sketch with LED displays
And GY68 air pressure/temp meter plus dht11 temp/humidity meter and time
Code by Michael Willems
version 1.0

// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
#include <Wire.h>                 // for I2C communication
#include <DS3231.h>               // for real-time clock
#include <Adafruit_BMP085.h>      // for air pressure/temp meter
Adafruit_BMP085 bmp;
int temperature;
int barometer;
int oldtemperature = 0;
int oldbarometer = 0;

#include <dht11.h>  //for temp sensor:
dht11 DHT11;
#define DHT11PIN 8
int temp2;
int humidity;
int oldtemp2 = 0;
int oldhumidity = 0;

/* Code for TM1637 4 digit 7 segment display with Arduino. More info: www.makerguides.com */
#include <TM1637Display.h>
#define CLK 2  // Define the connections pins for display 1
#define DIO 3
#define CLK2 4 // Define the connections pins for display 2
#define DIO2 5
#define CLK3 6 // Define the connections pins for display 3
#define DIO3 7
#define CLK4 9 // Define the connections pins for display 3
#define DIO4 10
// Create two display objects of type TM1637Display:
TM1637Display display = TM1637Display(CLK, DIO);
TM1637Display display2 = TM1637Display(CLK2, DIO2);
TM1637Display display3 = TM1637Display(CLK3, DIO3);
TM1637Display display4 = TM1637Display(CLK4, DIO4);
// Create array that turns all segments on:
const uint8_t data[] = {0xff, 0xff, 0xff, 0xff};
// Create array that turns all segments off:
const uint8_t blank[] = {0x00, 0x00, 0x00, 0x00};
// You can set the individual segments per digit to spell words or create other symbols:
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
const uint8_t hPA[] = {
  0x00,                                            // 
  SEG_C | SEG_E | SEG_F | SEG_G,                   // h
  SEG_A | SEG_B | SEG_E | SEG_F | SEG_G,           // P
  SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G    // A
const uint8_t rh[] = {
  0x00,                                            // 
  0x00,                                            // 
  SEG_E | SEG_G,                                   // r
  SEG_C | SEG_E | SEG_F | SEG_G                    // h
const uint8_t dC[] = {
  0x00,                                            // 
  0x00,                                            // 
  SEG_A | SEG_B | SEG_F | SEG_G,                   // [deg]
  SEG_A | SEG_D | SEG_E | SEG_F                    // C

unsigned long counter;            // for flashing on-board LED 13 with 1s frequency
unsigned long cyclecounter = 0;   // to see how often the loop does its thing
unsigned count;
int onboardled = 13;              // for heartbeat LED 13

//clock stuff:
DS3231 Clock;
boolean Century=false;
boolean h12;
boolean PM;
byte ADay, AHour, AMinute, ASecond, ABits;
boolean ADy, A12h, Apm;
char *dayString[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
int second,minute,hour,date,month,year,val,dow,temp3; 

// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
void setup() {
  // put your setup code here, to run once:
  pinMode(onboardled, OUTPUT);
  Wire.begin(); // Initiate the Wire library
  counter = millis();
  cyclecounter = 0;  //for testing loops/second
  // set up, and start, the air pressure detector:
  if (!bmp.begin()) {
	  Serial.println("Could not find a valid BMP085 sensor, check wiring!");
	  while (1) {}
  // Set the brightness:
  // All segments on:


// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
void loop() {
  // Let's see if it's time to update the screen/flash LED/etc:  
  if ((millis() - counter) > 1000) {   //yes, it's time to do the once-a-second stuff!
    counter = millis();
    digitalWrite (onboardled,!(digitalRead(onboardled)));   //the on-board heartbeat LED
    count = (millis()/1000);
    temperature = ((bmp.readTemperature())-1);   //read temp from the chip & adjust
    barometer = ((bmp.readPressure()/100)+5);    //read pressure from the chip & adjust
    temp2 = (DHT11.temperature);     //read temp from DHT & adjust (not used)
    humidity = (DHT11.humidity+5);   //read humidity from DHT & adjust
    // now display the values:
    if (temperature != oldtemperature) {
      display.showNumberDec (temperature, false, 4, 0);
      oldtemperature = temperature;
    if (barometer != oldbarometer) {
      display2.showNumberDec (barometer, false, 4, 0);
      oldbarometer = barometer;
    if (humidity != oldhumidity) {
      display3.showNumberDec (humidity, false, 4, 0);
      oldhumidity = humidity;
    uint8_t segto;
    int value = 1244;
    segto = 0x80 | display4.encodeDigit((value / 100)%10); display4.setSegments(&segto, 1, 1);
    cyclecounter = 0;

  // now, any code that has to continously run (not just once a second):

  cyclecounter = cyclecounter +1;  //to facilitate counting the cycles/second
} //end of loop

// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------

// read and display time:
void ReadDS3231() {
  int second,minute,hour,date,month,year,pm;
  display4.showNumberDec(minute, true, 2, 2);
  display4.showNumberDecEx(hour, 0b01000000, true, 2, 0);

  //------print line 1:----------------------------  
  Serial.print ("20");
  Serial.print (year);
  if (month<10){
    Serial.print("0");           // leading zero
  Serial.print(month,DEC);       // month
   if (date<10){
     Serial.print("0");          // leading zero
  Serial.print(date,DEC);        // date
  Serial.print(" ");
  Serial.print(dayString[dow]);  // day of week
  Serial.println(" ");

  //-------print line 2:---------------------------
  if (hour<10) {
   if (minute<10){

  Serial.print (temperature);
  Serial.print (" - ");
  Serial.print (temp2);
  Serial.print (" - ");
  Serial.print (temp3);
  Serial.println (" <<< ");  


What is this magic number?

    segto = 0x80 | display4.encodeDigit((value / 100)%10); display4.setSegments(&segto, 1, 1);

You should never put multiple statements on one line. It hides code.

1 Like

Oh boy, you've probably just found my mistake.

That bit of code should have been removed! It is the code suggested by the display's datasheet (exactly as suggested by that data sheet). And I agree about the multiple statements. My code is usually pretty easy to read (when a sketch is finished I document it well before sharing - usually :slight_smile: )

I have a test sketch on my website which I use to test my bezels, if that helps.
Check the downloads tab...

1 Like

Yes, TM1637. The ones you sell, they have an I2C interface?

Hello, might that be your problem?
As far as I know - most of the TM1637 clock modules do NOT use I2C. They have CLK and DIO pins. BUT - that does not make them I2C :slight_smile:
I see in your sketch that you include wire.h which you will need for the DS3231.
However, you might be mixing up your digital pins with I2C pins?
If it were me, I would start with a basic arduino, and only one display. Load the necessary library (i.e. TM1637Display.h) and no other libraries and test only that.
Then add wire.h and the ds3231 with it's library. Then the temperature sensor and so on... At some point it will stop working and you will have a better diagnostic.

But to answer the specific question. No, I think these displays are all "standard" digital not I2C.

My bad! I meant to say, CLK and DIO. All good.

Now I notice the bezels are about 1cm larger than the board, altogether. I'll have to see if I can fit four (yes, four) on the case front. :slight_smile:

Oh, the board is all working, no worries. It's just the construction.

I have learned really that although that they are a nice display (and under-rated), they are actually not that popular. We sell some bezels at a ratio of 40:1 over the TM1637 clock displays. In reality they are great for clocks as intended (FYI there is a non-clock version of that display).
Hence, although I greatly appreciate your interest in our bezels, we only have 2 available.

However, it would not take much to make more, but there will be a 4-5 day lead time.

Regarding the dimensions, I agree that the bezel is a bit larger than the display. All of our bezels are bigger in order to hide whatever cut-out is made in the project box (usually quite messy!).
But also for this display we also wanted to centre the display in the bezel. So, we had to make other dimensions bigger to make that work. Hence the somewhat larger bezel.

We do make custom bezels, and we could I suppose make one to accommodate 4 displays. This would be a one-off as we'd never sell another. So there is a design fee, sorry to say. Contact us via our website if you want to discuss.

In any event, I am glad you have it working and frankly I think it looks like a really neat project!

1 Like

None of them do. Entirely different protocol and no individual addressing.

Looks nice. :+1:

Were the pin headers fitted to the displays when you received them? The better way to fit them is underneath the board and pointing inward, so the "Dupont" sleeve is neatly hidden and does not poke out from the side.

Did you check that they did not have the wrong capacitors fitted? If they are or 10 nF or more, they need to be removed or you will have erratic operation.

They were fitted. And thanks, I'll check the caps. Didn't know there was an issue. (They're working fine so far)


The beauty of the TM1637 is that, unlike some other popular display IC's, they will work directly on 3.3V and so can interface without voltage translators to 3.3V MCU's. I've noticed that the availability and diversity of modules that use it, is increasing.

But also on 5V, right? I usually use 5V for everything and then use 3.3V and a logic level translator for the odd one that runs only on 3.3V.

Yes, the TM1636, TM1637 and TM1638 can run on either 5V or 3.3V

1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.