TM1638 display Common Anode 8 LED with 16 buttons

I bought a module from ebay, it has 8 LED digits and 16 buttons. The display is common anode so the standard TM1638 library wouldn’t work properly without some extra coding. Basically the digit are driven by what is normally the segment outputs and the segments are driven by what is normally the digit outputs. Also the buttons require more bits because there are 16 of them.

Link to ebay for similar item:

To get the buttons to work I needed to add a function to the library (need to add a line to the header file also), the library should be under the Arduino folder in a library folder in the file system.

Here is what I came up with to test the module:

The library I used:

Add the following code to the TM1638.cpp library file (needed to read buttons)

uint16_t TM1638::getButtons16()
{
    byte keys[4] = {0,0,0,0};
    uint16_t valueButtons;
    digitalWrite(strobePin, LOW);
    send(0x42);
    for (int i = 0; i < 4; i++) {
        keys[i] = receive();
        keys[i] = keys[i] >> 1; // pack key value into lower nibble
        if (keys[i] > 2) {
            keys[i] = keys[i] >> 2;
        }
    }
    digitalWrite(strobePin, HIGH);

    valueButtons = (keys[3] << 12) | (keys[2] << 8) | (keys[1] << 4) | keys[0];  // Pack nibbles into return integer
    return valueButtons;
}

Add the following line to TM1638.h under the public section (needed to read buttons)

virtual uint16_t getButtons16();

// Arduino code to test the 8 LED common anode module with 16 keys

/*
Example for TM1638 with an 8 digit common anode display.
The module also contains 16 buttons
The button value is returned in an unsigned integer with each bit representing a button
The keys are in a 4x4 grid (returned value):
   2     8   32    128
 512  2048 8192  32768
   1     4   16     64
 256  1024 4096  16384
*/

#include <TM1638.h>

// define a module on data pin 8, clock pin 9 and strobe pin 7
TM1638 module(8, 9, 7);

// declare variables / constants
  const byte segmentEncode[10] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111}; // for digits from 0 to 9
  uint16_t keys;  // to hold key value - each key is 1 bit in this unsigned int
 
void setup() {
// set up serial monitor
  Serial.begin(9600);
}

// Function to format and send digits to the display module, fixed to send to 8 digit display currently
void outputDisplay(byte dDigits[8], byte dDecimal) {
  byte values[8];
  byte vout[8];
// set values array to the segments required for each displayed digit into values array, only for decimal 0-9 (could extend for HEX)
  for (int i=0; i < 8; i++) {
    values[i] = segmentEncode[dDigits[i]];
  }

// fill output array - need to pack for common anode display - brute force method, this is for 8 digits
// digit order on display from left to right is 4,3,2,1,8,7,6,5  
  vout[0] = (values[3] & 1) | ((values[2] & 1) << 1) | ((values[1] & 1) << 2) | ((values[0] & 1) << 3) | ((values[7] & 1) << 4) | ((values[6] & 1) << 5) | ((values[5] & 1) << 6) | ((values[4] & 1) << 7);
  vout[1] = ((values[3] & 2) >> 1) | ((values[2] & 2)) | ((values[1] & 2) << 1) | ((values[0] & 2) << 2) | ((values[7] & 2) << 3) | ((values[6] & 2) << 4) | ((values[5] & 2) << 5) | ((values[4] & 2) << 6);
  vout[2] = ((values[3] & 4) >> 2) | ((values[2] & 4) >> 1) | ((values[1] & 4)) | ((values[0] & 4) << 1) | ((values[7] & 4) << 2) | ((values[6] & 4) << 3) | ((values[5] & 4) << 4) | ((values[4] & 4) << 5);
  vout[3] = ((values[3] & 8) >> 3) | ((values[2] & 8) >> 2) | ((values[1] & 8) >> 1) | ((values[0] & 8)) | ((values[7] & 8) << 1) | ((values[6] & 8) << 2) | ((values[5] & 8) << 3) | ((values[4] & 8) << 4);
  vout[4] = ((values[3] & 16) >> 4) | ((values[2] & 16) >> 3) | ((values[1] & 16) >> 2) | ((values[0] & 16) >> 1) | ((values[7] & 16)) | ((values[6] & 16) << 1) | ((values[5] & 16) << 2) | ((values[4] & 16) << 3);
  vout[5] = ((values[3] & 32) >> 5) | ((values[2] & 32) >> 4) | ((values[1] & 32) >> 3) | ((values[0] & 32) >> 2) | ((values[7] & 32) >> 1) | ((values[6] & 32)) | ((values[5] & 32) << 1) | ((values[4] & 32) << 2);
  vout[6] = ((values[3] & 64) >> 6) | ((values[2] & 64) >> 5) | ((values[1] & 64) >> 4) | ((values[0] & 64) >> 3) | ((values[7] & 64) >> 2) | ((values[6] & 64) >> 1) | ((values[5] & 64)) | ((values[4] & 64) << 1);

// To display a decimal point to the right of a digit set the value of vout[7] to
// 8, 4, 2, 1, 128, 64, 32, 16 (for digits from left to right), can set more than 1 decimal by adding the numbers
  vout[7] = dDecimal;
  
  module.setDisplay(vout);  // send to display module
}  // end outputDisplay
void loop() {
  keys = module.getButtons16(); // get a key (button)
// output key value to serial monitor
  if (keys) {
  Serial.println(keys); 
  }
  
// Digits to output on 8 display digits
  byte displayDigits[8] = {0, 1, 2, 3, 4, 5, 6, 7};
// The second parameter is the decimal point - set 1 bit for each decimal displayed
  outputDisplay(displayDigits, 8);

  delay(200); // delay .2 seconds then loop
}

Hi Brian

Your code works out of the box! Thanks x 1000 for sharing!
I had nearly given up on this module but your post rescued the project :slight_smile:

I just bought this module, and start to test it, thanks so much!

Hello, I followed how do you explain to the change in the library, but in time to compile the program appears error. I do not think I made the change correctly.
You can send me the library have changed, or show me how?
Still trying to make changes in the libraries, but I'm new in this part.
My email jymmy29@bol.com.br, thank you very much.

OK, solved, I modified library and now it works well.

Hi there..

I did all modification to the library and buttons work well but there is a problem with display.

The code example from first post displays digits
45670123 - should be 01234567

OK, this can be fixed in vout definition..
Unfortunately there is still problem with display, if I try to display text

module.setDisplayToString("01234567", 0);

all i got is just rubbish.

The library works very well with 8key/8led module, but i need more keys, do not need leds.
On the display need to show more than digits only.

Hi!

I'm the author of the TM1638 lib in "GitHub - rjbatista/tm1638-library: Automatically exported from code.google.com/p/tm1638-library".

rajdarge01 wrote a comment on the library talking about these common anode modules and I sent for one myself.

Got it this week and managed to find a few hours and added support in the library for it (v2.2.0). I've also added an example interacting with the new module.

My free time is REALLY tight these days so I haven't really tested it thoroughly.

Anyway, as I was updating the google code site with the new version and replying to rajdarge01's comment I saw this thread and decided to drop a line if anyone is interested in trying the library out.

Hope it helps.

Is it possible to make a digital clock using TM1637 or 1638 + DS1307 clock generator without Arduino ?

No.

Hi,

I'm new here.

At my Arduino is connected: an LCD2x16 and a TM1638-based-pcb with 8xLed/8x7Segments/8x buttons.

Writing AND reading working fine ( single DIO-line )

Now connected a TM1638-based-pcb with 8x7segments/16x buttons.

Reading the buttons goes ok. The 'scan' goes ok and the number of the pushed button is showed on the LCD2x16. OK!

Unfortonately, displaying numbers on the 7-segments goes wrong.
First it looked liked a total rubbish but after some re-coding/testing it shows some patern etc.

( more about this and details, soon )

Well, I'm coding in mikroPascal but I can understand some C-code.

Can anyone tell me what is the major difference between the 8-button-pcb and the 16-button-pcb?

Thnaks in advance! Marcel.

Hi
I have designed my own tm1638 board with 10 digit seven segment . I have used the application circuit schematic which is presented by the dataseet for common anode 7-segments . But what I see is that the segment number 9 and segment number 10 do not display anything . in other words seg9 and seg10 pins of the Ic are not active .
can anyone kindly help me how to use these two segments too please ?
best regards

syavash_kasraeee:
Hi
I have designed my own tm1638 board with 10 digit seven segment .

The library seems to be hardcoded for 8 digits.

For a quite hacky hardware test you can try to change

sendData(i << 1, val);

to

sendData((i << 1)+1, val);

in TM1638QYF.cpp line 43

Rintin:

sendData(i << 1, val);

to

sendData((i << 1)+1, val);

Thanks so much for the help .I just tested and It worked for the last 2 digits (segment9 and segment10 ) nothing is displayed in the first 8 digits

syavash_kasraeee:
It worked for the last 2 digits (segment9 and segment10 ) nothing is displayed in the first 8 digits

You found the hacky part. So I guess your hardware is working.

Now the next step is to add 10 digit support to the library.

When you are lucky you just need to replace the hardcoded 8 in the constructor with a 10 and rewrite TM1638QYF::setDisplay() to match your hardware wirering.

In the datasheet of the tm16538 you find the memory mapping in chart 2.