There comes a time you just want to test your code. For example if you write some control for a watering system you want to drive some pumps and or toggle valves.

For that you drive an ULN2803 or an MOSFET. But it is too cumbersome to test and debug everything on the real hardware.

For that purpose there is a board you need - the LED&KEY TM 1638 Board. It's easy to use, and you can really do a lot of stuff with it. But bear in mind, toggling a led is not that easy like an digitalWrite.

I wrote an small Documentation about this Module in my newly created Docs-Section. You can read about it here:

Turais Docs.

How to connect?

TM1638(byte dataPin, byte clockPin, byte strobePin, boolean activateDisplay = true, byte intensity = 7); 

This is the definition of the TM1638 constructor. I used an WEMOS D1 Mini with an ESP8266. You initiate your TM1638 module like so:

TM1638 module(D5, D6, D7); 

So I'm using D5 as the dataPin, D6 the clockPin and D7 as the strobePin.

Connection of the WEMOS D1 Mini (ESP8266) with the LED&KEY Module

What library to use

You can use the TM1638 Library from Ricardo Batista. https://github.com/rjbatista/tm1638-library

You have to change the min-function used in this library if you want to use this library with an ESP8266 or an ESP32. Or use my fork.

Library Download

Here is my diff:

44c44 <   sendCommand(0x80 | (activateDisplay ? 8 : 0) | _min(7, intensity)); --- >   sendCommand(0x80 | (activateDisplay ? 8 : 0) | min(7, intensity)); 56c56 <   sendCommand(0x80 | (active ? 8 : 0) | _min(7, intensity)); --- >   sendCommand(0x80 | (active ? 8 : 0) | min(7, intensity)); 179a180 > 

I changed min to _min.

As the owner is not accepting pending pull-requests you can use my fork instead: https://github.com/turais/tm1638-library

How do I power an LED?

Basically you write an byte to an address. Like so:

ledkey_module.setLEDs(led_state); 

Every bit in this byte represents one of those LEDs. For example:

| Bit# |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  | +------+-----+-----+-----+-----+-----+-----+-----+-----+
|      | 2^8 | 2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 
| VAL: | 0   | 0   | 0   | 0   | 0   | 1   | 1   | 0   | +------+-----+-----+-----+-----+-----+-----+-----+-----+ 

this would be the value: 0x06. To calculate easily you could create an enum:

enum {
  LED1 = 0u,
  LED2 = 1u,
  LED3 = 2u,
  LED4 = 4u,
  LED5 = 8u,
  LED6 = 16u,
  LED7 = 32u,
  LED8 = 64u
};

If you defined this enum you can easily use that in your setLEDs.

ledkey_module.setLEDs(LED1 | LED5 | LED7);

For setting an specific LED, without destroying the state from already lighted LEDs, I'm using this handy macro I wrote:

#define SET_BIT(A, i, val) \
        do{ A &= ~(1u << i); A |= (val << i); } while(false)

this macro sets bit number i to val in the byte: A. I use an global variable: static word led_state = 0x00; where I 'save' the current state for the LEDs.

Then I wrote myself a nice little function I use for writing to an pin.

static void pin_write(int pin, int val) {
  //#ifdef LOG_TO_APP
  //Blynk.virtualWrite(pin, val);
  //#endif
  pin = pin_mapping[pin];

  word _val = (val == 0) ? 1 : 0;
  
  //debug_print("pin_write(%i, %u) \n", pin, _val);
  SET_BIT(led_state, pin, _val);
  ledkey_module.setLEDs(led_state);
    
}

Then you can wrap this in an if-else macro and define an DEBUG variable, so that only this function gets called if you're debugging.  If you are using the LED&KEY Module only for debugging, and want to flash the real hardware: you just delete the debug define and you're good to go.

My "production" pin_write-would look like this:

#ifndef NDEBUG

#define SET_BIT(A, i, val) \
        do{ A &= ~(1u << i); A |= (val << i); } while(false)

enum {
  LED1 = 0u,
  LED2 = 1u,
  LED3 = 2u,
  LED4 = 4u,
  LED5 = 8u,
  LED6 = 16u,
  LED7 = 32u,
  LED8 = 64u
};

static word led_state = 0x00;

static void pin_write(int pin, int val) {
  #ifdef LOG_TO_APP
  Blynk.virtualWrite(pin, val);
  #endif
  pin = pin_mapping[pin];

  word _val = (val == 0) ? 1 : 0;
  
  debug_print("pin_write(%i, %u) \n", pin, _val);
  SET_BIT(led_state, pin, _val);
  ledkey_module.setLEDs(led_state);
    
}
#else
static void pin_write(int pin, int val) {
  #ifdef LOG_TO_APP
    Blynk.virtualWrite(pin, val);
  #endif
  debug_print("pin_write(%i, %u) \n", pin, val);
  digitalWrite(pin, val);
}
#endif

I use an define LOG_TO_APP if I want to write some data to my Blynk-App, otherwise, the code above is self explanatory. If you have some questions, please write in the comments below. (Really I mean it don't hesitate)

And of course I have the TM1638-Module defined above. Like so:

#ifndef NDEBUG
TM1638 ledkey_module(D5, D6, D7);
#endif

I used D5, D6 and D7 on an WEMOS D1 Mini to connect the board.

Reading Key Presses

Look below for the working example below, for how to poll the key presses. I poll them every 50ms.

Writing something to the Display

It's easy:

String str = "0123ABCD"; 
module.setDisplayToString(str); 

ESP8266 NTP Clock and Date with LED&KEY Display

Check out my repository. It's an simple LED&KEY example which displays the date or the time. You can change the display by pressing Button 2.

To read a button press with the LED&KEY Module, you can use the library function: getButtons(). This call gives you a byte, and in this byte every bit is representing the button from left to right.

So for example if your byte looks like this: 0x01 , Button 1 is pressed. 0x02 for Button 2. Combinations out of more than one button press give you for example: 0x22. If you look at this in binary everything is clear:  0010 0010b reading from right to left. So the LSB gives you the state of button 1.

In the case of 0x22 Button 2 and Button 6 is pressed. To read those conveniently I used an ENUM:

typedef enum {
  BTN1 = 1,
  BTN2 = 2u,
  BTN3 = 4u,
  BTN4 = 8u,
  BTN5 = 16u,
  BTN6 = 32u,
  BTN7 = 64u,
  BTN8 = 128u  
} BTN;

To get only the state from one button you could do something like this:

void get_pressed(const byte &state, const BTN check, bool &pressed) {
    byte btn_state = (state & check);
    pressed = btn_state / check;
}

If you have questions, please post a comment below :)

Not so easy to get the light right with those shining bright 7-segment displays - Clock: (16:31:09) 
The LED&KEY with the current Date: 02/08/2020 (DAY/MONTH/YEAR)