Skip to content

Commit 10ab4b2

Browse files
committed
0.3.0 TM1637_RT
1 parent 77e0a22 commit 10ab4b2

File tree

12 files changed

+444
-25
lines changed

12 files changed

+444
-25
lines changed
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
compile:
2-
# Choosing to run compilation tests on different Arduino platforms
2+
# Choosing to run compilation tests on 2 different Arduino platforms
33
platforms:
44
- uno
5-
- leonardo
6-
- due
7-
- zero
5+
# - due
6+
# - zero
7+
# - leonardo
8+
- m4
9+
- esp32
10+
# - esp8266
11+
# - mega2560

libraries/TM1637_RT/.github/workflows/arduino_test_runner.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ name: Arduino CI
44
on: [push, pull_request]
55

66
jobs:
7-
arduino_ci:
7+
runTest:
88
runs-on: ubuntu-latest
99

1010
steps:
1111
- uses: actions/checkout@v2
12-
- uses: Arduino-CI/action@v0.1.0
12+
- uses: ruby/setup-ruby@v1
13+
with:
14+
ruby-version: 2.6
15+
- run: |
16+
gem install arduino_ci
17+
arduino_ci.rb

libraries/TM1637_RT/LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 Rob Tillaart
3+
Copyright (c) 2019-2021 Rob Tillaart
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

libraries/TM1637_RT/README.md

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,18 @@
77

88
# TM1637
99

10-
Library for TM1637 driven displays.
10+
Library for TM1637 driven displays and keyscans.
1111

1212

1313
## Description
1414

15-
The TM1637 drives 7 segment displays
15+
The TM1637 drives 7 segment displays and can also scan a 16 key keyboard
1616

1717
Library is tested with Arduino UNO and a 6 digits display.
1818

1919
ESP32 is supported since 0.2.0 see https://github.com/RobTillaart/TM1637_RT/pull/5
2020

2121

22-
TO ELABORATE
23-
24-
2522
## Interface
2623

2724
- **TM1637()** constructor
@@ -34,6 +31,18 @@ As the display is only tested with a 6 digit display, this is used as the defaul
3431
- **void displayClear()** writes spaces to all positions, effectively clearing the display.
3532
- **void setBrightness(uint8_t b)** brightness = 0 .. 7 default = 3.
3633
- **uint8_t getBrightness()** returns value set.
34+
- **uint8_t keyscan(void)** scans the keyboard once and return result. The keyscan() function cannot detect multiple keys.
35+
36+
37+
**displayRaw()** can display multiple decimal points, by setting the high bit (0x80) in each character for which you wish to have a decimal lit. Or you can use the pointPos argument to light just one decimal at that position.
38+
39+
**displayRaw()** can display some of the alphabet as follows:
40+
- space (blank) is 0x10
41+
- - (blank) is 0x11
42+
- a-f are coded as 0x0a-0x0f
43+
- g-z are coded as 0x12-0x25
44+
45+
So "hello " is coded as 0x13, 0x0e, 0x17, 0x17, 0x1a, 0x10
3746

3847

3948
### Tuning function
@@ -44,13 +53,78 @@ To tune the timing of writing bytes.
4453
- **uint8_t getBitDelay()**
4554

4655

47-
### Tuning minimum pule length
56+
### Tuning minimum pulse length
4857

4958
The class has a conditional code part in writeSync to guarantee the length of pulses
5059
when the library is used with an ESP32. The function called there **nanoDelay(n)**
5160
needs manual adjustment depending upon processor frequency and time needed for a digitalWrite.
5261
Feel free to file an issue to get your processor supported.
5362

63+
### Keyboard Scanner usage and notes
64+
65+
66+
Calling keyscan() returns a uint8_t, whose value is 0xff if no keys are being pressed at the time. The TM1637 can only see one key press at a time, and there is no "rollover". If a key is pressed, then the values are as follows:
67+
68+
<CENTER>
69+
<TABLE>
70+
<TR>
71+
<TD colspan = 10 align="center">
72+
keyscan results are reversed left for right from the data sheet.
73+
</TD>
74+
</TR>
75+
<TR>
76+
<TH>pin</TH><TD>&nbsp</TD><TD>2</TD><TD>3</TD><TD>4</TD><TD>5</TD><TD>6</TD><TD>7</TD><TD>8</TD><TD>9</TD>
77+
</TR>
78+
<TR>
79+
</TD><TD>&nbsp;</TD><TH>name</TH><TD>sg1</TD><TD>sg2</TD><TD>sg3</TD><TD>sg4</TD><TD>sg5</TD><TD>sg6</TD><TD>sg7</TD><TD>sg8</TD>
80+
</TR>
81+
<TR>
82+
</TD><TD>19</TD><TD>k1</TD><TD>0xf7</TD><TD>0xf6</TD><TD>0xf5</TD><TD>0xf4</TD><TD>0xf3</TD><TD>0xf2</TD><TD>0xf1</TD><TD>0xf0</TD>
83+
</TR>
84+
<TR>
85+
</TD><TD>20</TD><TD>k2</TD><TD>0xef</TD><TD>0xee</TD><TD>0xed</TD><TD>0xec</TD><TD>0xeb</TD><TD>0xea</TD><TD>0xe9</TD><TD>0xe8</TD>
86+
</TR>
87+
</TABLE>
88+
</CENTER>
89+
<P>
90+
To modify a "generic" TM1637 board for use with a keyboard, you must add connections to either or both of pins 19 and 20 (these are the "row" selects) and then to as many of pins 2 through 9 (the "columns") as needed. It is easiest to connect to the "column pins" (2-9) by picking them up where they connect to the LED displays (see second photo). Generic keyboards that are a 4x4 matrix won't work; the TM1637 can only scan a 2x8 matrix. Of course, fewer keys are acceptable; I use a 1x4 keyboard in my projects.
91+
</P>
92+
<P>
93+
Further, the TM1637 chip needs a fairly hefty pull-up on the DIO pin for the keyscan() routine to work. There is no pull-up in the TM1637 itself, and the clone boards don't seem to have one either, despite the data sheet calling for 10K ohms pull-ups on DIO and CLOCK. 10K is too weak anyway. The slow rise-time of the DIO signal means that the "true/high" value isn't reached fast enough and reliably enough for the processor to read it correctly. The new pull-up reduces the rise time of the signal, so that true/high values are achieved in a few microseconds. I find that a 1K (1000) ohm resistor from DIO to 3.3 v works well. This is perfect with a 3.3 volt processor like the ESP8266 or ESP32, and a 5V Atmega 328 ("Arduino UNO") family processor is happy with that as well.
94+
</P>
95+
<P>
96+
The TM1637 boards want to be run off of 5 volts, regardless of what the processor voltage is. Their logic levels are compatible with 3.3 volt processors, and they need 5 volts to make sure the LEDs light up.
97+
</P>
98+
The unmodified generic TM1637 board (front and back).</br>
99+
<IMG src="images/unmodified.jpg">
100+
</br>
101+
The modified generic TM1637 board with connector for 1x4 keyboard. The blue wire is bringing out pin 19 (k1). Four segments/columns are picked up from the LEDs.</br>
102+
<IMG src="images/modified.jpg">
103+
</br>
104+
The 4 button keyboard plugged into the TM1637 board.</br>
105+
<IMG src="images/disp_plus_kbd.jpg"></br>
106+
</br>
107+
Scope photo showing slow rise time of DIO pin (upper trace) on the unmodified TM1637. The lower trace is the CLK. The 8 fast CLK pulses on the left represent the 0x42 command to read keyboard being sent to the TM1637.</br>
108+
<IMG src="images/slow_rise.jpg"></br>
109+
</br>
110+
Scope photo showing faster rise time of DIO pin (upper trace) with 1000 ohm pull-up on DIO. In both scope photos, the F5 key is pressed; the bits are least significant bit (LSB) first, so read as 10101111 left to right.</br>
111+
<IMG src="images/fast_rise.jpg"></br>
112+
113+
The scope photos were taken using the TM1637_keyscan_raw example, with the scope trigger hooked to the TRIGGER pin, and the two channel probes hooked to DIO and CLK. Vertical sensitivity is 2v/division, horizontal timebase is 20usec/division.
114+
115+
## Keyscan
116+
117+
Implemented in version 0.3.0 Please read the datasheet to understand the limitations.
118+
119+
```
120+
// NOTE:
121+
// on the TM1637 boards tested by @wfdudley, keyscan() works well
122+
// if you add a 910 ohm or 1 Kohm pull-up resistor from DIO to 3.3v
123+
// This reduces the rise time of the DIO signal when reading the key info.
124+
// If one only uses the pull-up inside the microcontroller,
125+
// the rise time is too long for the data to be read reliably.
126+
```
127+
54128

55129
## Operation
56130

libraries/TM1637_RT/TM1637.cpp

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// FILE: TM1637.cpp
33
// AUTHOR: Rob Tillaart
44
// DATE: 2019-10-28
5-
// VERSION: 0.2.0
5+
// VERSION: 0.3.0
66
// PURPOSE: TM1637 library for Arduino
77
// URL: https://github.com/RobTillaart/TM1637_RT
88
//
@@ -11,14 +11,26 @@
1111
// 0.1.1 2021-02-15 first release + examples.
1212
// 0.1.2 2021-04-16 update readme, fix default values.
1313
// 0.2.0 2021-09-26 add ESP32 support - kudos to alexthomazo
14+
// 2021-10-07 add support for letters g-z; added keyscan()
15+
// tested on ESP8266
16+
// 0.3.0 2021-10-27 improved keyscan + documentation - kudos to wfdudley
17+
1418

1519
// tested on 6 digits display only for now.
1620

1721

22+
// NOTE: on the inexpensive TM1637 boards @wfdudley has used, keyscan
23+
// works if you add a 1000 ohm pullup resistor from DIO to 3.3v
24+
// This reduces the rise time of the DIO signal when reading the key info.
25+
// If one only uses the pull-up inside the microcontroller,
26+
// the rise time is too long for the data to be read reliably.
27+
28+
1829
#include "TM1637.h"
1930

2031

2132
#define TM1637_ADDR_AUTO 0x40
33+
#define TM1637_READ_KEYSCAN 0x42
2234
#define TM1637_ADDR_FIXED 0x44
2335

2436
#define TM1637_CMD_SET_DATA 0x40
@@ -50,6 +62,14 @@ static uint8_t seg[] =
5062
0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00, 0x40 // A - F, ' ', '-'
5163
};
5264

65+
static uint8_t alpha_seg[] =
66+
{
67+
0x00, 0x74, 0x10, 0x00, // g, h, i, j,
68+
0x00, 0x38, 0x00, 0x54, // k, l, m, n,
69+
0x5c, 0x00, 0x00, 0x50, // o, p, q, r,
70+
0x00, 0x31, 0x1c, 0x1c, // s, t, u, v,
71+
0x00, 0x00, 0x00, 0x00 // w, x, y, z
72+
};
5373

5474
TM1637::TM1637()
5575
{
@@ -160,7 +180,7 @@ void TM1637::setBrightness(uint8_t b)
160180

161181
void TM1637::displayRaw(uint8_t * data, uint8_t pointPos)
162182
{
163-
uint8_t b;
183+
uint8_t b, dp;
164184
start();
165185
writeByte(TM1637_ADDR_AUTO);
166186
stop();
@@ -169,14 +189,28 @@ void TM1637::displayRaw(uint8_t * data, uint8_t pointPos)
169189
writeByte(TM1637_CMD_SET_ADDR);
170190
for (uint8_t i = 3; i < 6 ; i++)
171191
{
172-
b = seg[data[i]];
173-
if (i == pointPos) b |= 0x80;
192+
dp = data[i] & 0x80;
193+
data[i] &= 0x7f;
194+
if(data[i] <= 17) {
195+
b = seg[data[i]];
196+
}
197+
else if(data[i] <= 37) {
198+
b = alpha_seg[data[i]-18];
199+
}
200+
if (i == pointPos || dp) b |= 0x80;
174201
writeByte(b);
175202
}
176203
for (uint8_t i = 0; i < 3 ; i++)
177204
{
178-
b = seg[data[i]];
179-
if (i == pointPos) b |= 0x80;
205+
dp = data[i] & 0x80;
206+
data[i] &= 0x7f;
207+
if(data[i] <= 17) {
208+
b = seg[data[i]];
209+
}
210+
else if(data[i] <= 37) {
211+
b = alpha_seg[data[i]-18];
212+
}
213+
if (i == pointPos || dp) b |= 0x80;
180214
writeByte(b);
181215
}
182216
stop();
@@ -244,6 +278,47 @@ void TM1637::writeSync(uint8_t pin, uint8_t val)
244278
}
245279

246280

281+
// keyscan results are reversed left for right from the data sheet.
282+
// here are the values returned by keyscan():
283+
// pin 2 3 4 5 6 7 8 9
284+
// sg1 sg2 sg3 sg4 sg5 sg6 sg7 sg8
285+
// 19 k1 0xf7 0xf6 0xf5 0xf4 0xf3 0xf2 0xf1 0xf0
286+
// 20 k2 0xef 0xee 0xed 0xec 0xeb 0xea 0xe9 0xe8
287+
288+
uint8_t TM1637::keyscan(void)
289+
{
290+
uint8_t halfDelay = _bitDelay >> 1;
291+
uint8_t key;
292+
start();
293+
key = 0;
294+
writeByte(TM1637_READ_KEYSCAN);// includes the ACK, leaves DATA low
295+
pinMode(_data, INPUT_PULLUP);
296+
297+
for (uint8_t i = 0; i <= 7; i++) {
298+
writeSync(_clock, LOW);
299+
delayMicroseconds(halfDelay);
300+
writeSync(_clock, HIGH);
301+
delayMicroseconds(halfDelay);
302+
key >>= 1;
303+
key |= (digitalRead(_data)) ? 0x80 : 0x00 ;
304+
}
305+
306+
writeSync(_clock, LOW);
307+
delayMicroseconds(halfDelay);
308+
writeSync(_clock, HIGH);
309+
310+
// wait for ACK
311+
delayMicroseconds(halfDelay);
312+
313+
// FORCE OUTPUT LOW
314+
pinMode(_data, OUTPUT);
315+
digitalWrite(_data, LOW);
316+
delayMicroseconds(halfDelay);
317+
stop();
318+
return key;
319+
}
320+
321+
247322
// nanoDelay() makes it possible to go into the sub micron delays.
248323
// It is used to lengthen pulses to be minimal 400 ns but not much longer. See datasheet.
249324
void TM1637::nanoDelay(uint16_t n)

libraries/TM1637_RT/TM1637.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// FILE: TM1637.h
44
// AUTHOR: Rob Tillaart
55
// DATE: 2019-10-28
6-
// VERSION: 0.2.0
6+
// VERSION: 0.3.0
77
// PUPROSE: TM1637 library for Arduino
88
// URL: https://github.com/RobTillaart/TM1637_RT
99

@@ -13,7 +13,7 @@
1313

1414
#include "Arduino.h"
1515

16-
#define TM1637_LIB_VERSION (F(0.2.0))
16+
#define TM1637_LIB_VERSION (F(0.3.0))
1717

1818

1919
class TM1637
@@ -35,6 +35,7 @@ class TM1637
3535
// tune the timing of writing bytes.
3636
void setBitDelay(uint8_t bitDelay = 10) { _bitDelay = bitDelay; };
3737
uint8_t getBitDelay() { return _bitDelay; };
38+
uint8_t keyscan(void);
3839

3940
private:
4041
uint8_t _clock = -1;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// FILE: TM1637_alpha.ino
3+
// AUTHOR: William F. Dudley Jr.
4+
// VERSION: 0.1.0
5+
// PURPOSE: demo TM1637 library
6+
// DATE: 2021-10-12
7+
// URL: https://github.com/RobTillaart/TM1637
8+
9+
10+
#include "TM1637.h"
11+
12+
TM1637 TM;
13+
14+
void setup()
15+
{
16+
Serial.begin(115200);
17+
Serial.println(__FILE__);
18+
19+
TM.init(2, 3);
20+
TM.setBrightness(2);
21+
}
22+
23+
void ascii_to_7segment(char *buff, uint8_t *data) {
24+
for(int8_t i = 0, j=5 ; j > -1 && i < 12 && buff[i] ; i++) {
25+
if(isalpha(buff[i])) { buff[i] = tolower(buff[i]); }
26+
if(buff[i] >= '0' && buff[i] <= '9') {
27+
data[j--] = buff[i] - '0';
28+
}
29+
else if(buff[i] >= 'a' && buff[i] <= 'f') {
30+
data[j--] = buff[i] - 'a' + 10;
31+
}
32+
else if(buff[i] >= 'g' && buff[i] <= 'z') {
33+
data[j--] = buff[i] - 'g' + 18;
34+
}
35+
else if(buff[i] == '.') {
36+
data[j+1] |= 0x80; // decimal point on previous digit
37+
}
38+
else {
39+
data[j--] = 0x10; // blank
40+
}
41+
}
42+
}
43+
44+
void loop()
45+
{
46+
char buff[20];
47+
uint8_t data[10];
48+
strcpy(buff, "hello ");
49+
Serial.println("hello");
50+
ascii_to_7segment(buff, data);
51+
TM.displayRaw(data, -1);
52+
delay(1000);
53+
TM.displayClear();
54+
delay(1000);
55+
}
56+
57+
// -- END OF FILE --

0 commit comments

Comments
 (0)