TM1638 display library

Attached is a new "library" for the 7-segment/LED displays based on the TM1638 controller.
These displays can be had for cheap on eBay etc.

The attachment is not a "library" in the usual sense. To make it work you'll have to edit the TM1638.h header file and configure which pins to use in that file. No run-time pin configuration is available to keep the library compact and fast.

The library uses direct port access to dramatically speed up the display/button access and to keep the compiled size small. It also uses a font stored in PROGMEM to keep SRAM usage down.

There is an existing library for the TM16xx based displays, that is easier to use, available here:

Then why use the attached library?

Take this very simple program, counting up to 65534 and reading the button states, as an example:

void setup()
{
    TM1638 disp(2, 1, 0);  
    for (uint16_t  j = 0; j != 0xffff; ++j)
    {
        disp.setDisplayToDecNumber(j, 0);
        disp.setLEDs(disp.getButtons());
    }
}

void loop() {}

Using the TM16xx library for code.google.com, the compiled binary has the following size (note the 88 bytes of SRAM used as well):

text    data     bss     dec     hex filename
2814      88       9    2911     b5f obj/tm1638_org.elf

With the new, attached library, the binary size is:

text    data     bss     dec     hex filename
1178       0       0    1178     49a obj/tm1638.elf

Running on a Digispark (ATTiny85), the program takes this long to count from 0-65534 while checking the buttons and setting the LEDs accordingly:

"Old" library:
5min, 40s or 340s.

"New" library:
39s (!!!!)

So the old library allows about 120 refreshes per second while the new one achieves >1600.
And that's on an ATTiny85...

While you rarely want/need 1600 updates per second, speeding up the screen updates and button checks frees up your controller to do other things.

TM1638_v1.00.zip (6.03 KB)

Thanks for sharing,

A quick look at the lib showed some well engineered code but also some /= 10 (3x) and %10 (2x) which are both quite expensive operations

you might check the divmod10 discussion to speed up the lib even further - divmod10() : a fast replacement for /10 and %10 (unsigned) - Libraries - Arduino Forum -
Should speed up your lib too. Esp when using the highly optimized asm version - divmod10() : a fast replacement for /10 and %10 (unsigned) - #54 by pjrc - Libraries - Arduino Forum -
Could you please check what numbers you get as I do not have such device?

alternatively

    while (number && offset != 0xFF)
    {
        setDigit(offset--, number % 10);
        number /= 10;
    }

could also be made quite faster by using one additional var

    while (number && offset != 0xFF)
    {
        uint16_t x = number / 10;
        setDigit(offset--, number - x*10);
        number = x;
    }

(this code snippet appears twice)

  1. Please add some example sketches to the library to show how to use it. This might include your performance test.

robtillaart:
A quick look at the lib showed some well engineered code but also some /= 10 (3x) and %10 (2x) which are both quite expensive operations

you might check the divmod10 discussion to speed up the lib even further - divmod10() : a fast replacement for /10 and %10 (unsigned) - Libraries - Arduino Forum

Thanks for the tips!
I did incorporate divmod10_asm() and it indeed made quite a difference.
While I was performance tweaking, I un-rolled the send loop and did some other tweaks - hopefully without compromising the code readability too much.

As it stands now, it can count to 65534 while checking all the buttons and setting the LEDs in <27s! Over 2400 screen updates per second!

The code has increased in size a bit with the example program now clocking in at 1944 bytes. Still acceptable in my book....

TM1638_v1.01.zip (6.28 KB)

The code has increased in size a bit with the example program now clocking in at 1944 bytes. Still acceptable in my book....

you should make it conditional, something like

in .h file
#define TM1638_HIGHSPEED

in .cpp file
#ifdef TM1638_HIGHSPEED
divmod10(x,y,z);
#elseif
x = y/10;
z = y%10;
#endif

Hi,
Thanks for your very good work.

As you know those 7 segments modules can be put in daisy chain to have up to 6 displays driven by 6 different Strobo pins.
Your fast library is very important due to the bigger data throughput it can provide without so much latence and delay. It is more important to be fast as the displays are more.

I'm absolutely not familiar with CPP, so I'm messing around a way to have separates instances of the same library being referred from the main c by adding the strobe pin value, so to drive those 6 displays with no hassle.

Can you help providing a modified library where the strobe pin can be provided for each TM1638 command routine?

Thanks so much

Gigislab

can explain me a simple code to use this fast-tm1638 library with arduino code ?

-->>> code sample <<<--
#include <TM1638.h>
#include <TM1638Font.h>

void setup()
{
TM1638 disp();
for (uint16_t j = 0; j != 0xffff; ++j)
{
disp.setDisplayToDecNumber(j, 0);
disp.setLEDs(disp.getButtons());
}
}

void loop() {}

-->>> errors <<<--
sketch_jul09a.ino: In function 'void setup()':
sketch_jul09a:9: error: request for member 'setDisplayToDecNumber' in 'disp', which is of non-class type 'TM1638 ()()'
sketch_jul09a:10: error: request for member 'setLEDs' in 'disp', which is of non-class type 'TM1638 ()()'
sketch_jul09a:10: error: request for member 'getButtons' in 'disp', which is of non-class type 'TM1638 ()()'

thanks for any advance

Something like this (can't test it right now):

#include <TM1638.h>

void setup()
{
    TM1638 disp;
    for (uint16_t j = 0; j != 0xFFFF; ++j)
    {
        disp.setNumber(j);
        disp.setLEDs(disp.getButtons(), 0);
        delay(100);
    }
}

void loop()
{
}

this work, thanks.
i have modified in TM1638.cpp from uint16_t number to uint32_t number the three sub-routine of setNumber (line 185, 197 and 209)
and added in TM1683.h this lines
// PORTC
// PC0 A0
// PC1 A1
// PC2 A2
// PC3 A3
// PC4 A4
// PC5 A5
//
// PORTD
// PD0 D0/RX
// PD1 D1/TX
// PD2 D2
// PD3 D3
// PD4 D4
// PD5 D5
// PD6 D6
// PD7 D7
//
// PORTB
// PB0 D8
// PB1 D9
// PB2 D10
// PB3 D11/MOSI
// PB4 D12/MISO
// PB5 D13/SCK
//
#define PB4 4 //D12/MISO
#define PB3 3 //D11/MOSI
#define PB2 2 //D10
//

attached modified library with display connected in D3 (STB0),D4 (CLK), D5 (DIO).

TM1638_v1.02.zip (6.39 KB)

It's been a while, but the "library" is now available on GitHub:

Also added a simple example to demonstrate the usage.

you might add meta info to the header file like

//
//    FILE: tm1638.h
//  AUTHOR: int2str
// VERSION: 0.1.02
// PURPOSE: lib for 7 seg display
//     URL: https://github.com/int2str/TM1638
//

Hello to everyone, I would like to know how to modify the library TM1638 v 1.02 for driver 2 modules TM1638.
Thanks in advance and greetings

topik need to be deleted. the library is now changed

Has anybody had trouble with these EBay Tm1638 Modules ?

  • I ordered (3) of them - and none seemed to work.
    All that works is the Left Power LED.
    I am connecting with an Arduino Mini Pro.

I followed the Pinout:
VCC – 5v from Arduino
Gnd – GND from Arduino
STB – strobe pin -> D6
CLK – clock pin -> D7
DIO – data pin -> D8

TM1638 module(8, 7, 6);

I also tried:
TM1638 module(8, 9, 10);

I tried assortment of examples from the github Lib :

Also tried this example, still does not work :

#include <TM1638.h>

// /// define a module on : DIO data pin 8 , CLK clock pin 9 , STB strobe pin 10
// TM1638 module(8, 9, 10);
/// DIO data, CLK clock , STB strobe connected to pins 8, 7, 6
TM1638 module(8, 7, 6);

unsigned long a = 1;

byte keys;

void setup()
{
 Serial.begin(9600);
 Serial.println("Starting...");
}

void loop()
{
 for (a=1; a<=100; a++)
 {
   Serial.println(a);
   module.setDisplayToDecNumber(a,0,false);
   //module.setLEDs(0xE007);
   module.setLEDs(a);
   delay(100);
 }
 
 module.setDisplayToString("Complete");
 delay(300);

 for(a=1; a<=20; a++)
 {
   keys = module.getButtons();
   if(keys != 0  &&  keys != 255)
     Serial.println(keys);

   // light the first 4 red LEDs and the last 4 green LEDs as the buttons are pressed
   module.setLEDs(((keys & 0xF0) << 8 ) | (keys & 0xF));

   delay(100);
 }
}

Serial just returns :

  • "Starting..."
  • counting from 1 to 100
  • 255 for the keys - pressed or not

None of the Tutorials seem to specify Resistors or Pullups needed.

Does the Mini Pro have enough power to drive the Tm1638 ?

Does this Library / Tm1638 work on the Arduino Mini Pro ??

I found out that the Tm1638 Lib/Code works on the UNO.

Tried on a second Arduino mini Pro.
Works on this one.

  • Must be a Bad Arduino Mini Pro Brd.
    Programs, Blink works, but Tm1638 does not work - not with Pins 7,8,9 nor Pins 10,11,12.
  • Some of the Arduino Outputs must be damaged.