Pages: [1]   Go Down
Author Topic: TM1638 display library  (Read 1802 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Sr. Member
****
Karma: 9
Posts: 272
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
http://code.google.com/p/tm1638-library/

Then why use the attached library?

Take this very simple program, counting up to 65534 and reading the button states, as an example:
Code:
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):
Code:
text    data     bss     dec     hex filename
2814      88       9    2911     b5f obj/tm1638_org.elf

With the new, attached library, the binary size is:
Code:
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 - downloaded 44 times.)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 - http://forum.arduino.cc/index.php?topic=167414.0 -
Should speed up your lib too. Esp when using the highly optimized asm version - http://forum.arduino.cc/index.php?topic=167414.msg1291081#msg1291081 -
Could you please check what numbers you get as I do not have such device?

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

could also be made quite faster by using one additional var

Code:
    while (number && offset != 0xFF)
    {
        uint16_t x = number / 10;
        setDigit(offset--, number - x*10);
        number = x;
    }
(this code snippet appears twice)

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

« Last Edit: September 28, 2013, 10:11:15 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Sr. Member
****
Karma: 9
Posts: 272
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 - http://forum.arduino.cc/index.php?topic=167414.0

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 - downloaded 30 times.)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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
« Last Edit: September 30, 2013, 06:24:00 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

Offline Offline
Sr. Member
****
Karma: 9
Posts: 272
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
#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()
{
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
//
Logged

Pages: [1]   Go Up
Jump to: