I purchased one of these 4 digit 7 segment displays using a TM1637.
I installed the TM1637 display library from the libraries manager and included it:
(#include <TM1637Display.h>)
.
I am trying to display the time, and I would like, preferably, to display 3 digit times with a colon, but without the leading zero.
I found this great reference online for using the library., and saw the usage for numbers with colons:
showNumberDecEx(number, dots, leading_zeros, length, position)
according to the guide, to have the colon in the center, you would pass 0b01000000
as the dots
parameter.
And I figured that if I then want to display, for example, the time 1:36
, then my number
parameter would be 136, my leading_zeros
parameter would be 0
(false), my length would be 3
for a 3 digit number, and my position would by 1
to start the number in the zero-indexed second position:
display.showNumberDecEx(136, 0b01000000, false, 3, 1); //displays 5136
But this displayed 5136
with no colon.
I tried a number of other things, including:
display.showNumberDecEx(136, 0b01000000, true, 3, 0); //displays 13:66
display.showNumberDecEx(136, 0b01000000, false, 3, 0); //displays 13:6A
I finally found code from this site, which works to display the time (albeit with a leading zero), but I don't fully understand it:
display.showNumberDecEx(1*100+36, 0x80 >> 1, 1, 4, 0);
I get that 1*100+36 represents number of hours plus minutes, but I don't get the 0x80>> 1 bit. I'm assuming the rest of it is just saying make it a 4 digit number and add a leading zero.
Can anyone possibly: * help me understand the above working code * tell me an easier way to construct a time so that I can ideally just pass a 3 or 4 digit number and have it automatically render out a clock time with separating colon * tell me why my previous attempts were incorrect
2 Answers 2
I tested your first code line and it outputs a right aligned 136 without colon at my display. (Said I have only a colon at the middle and no decimal points)
The 5 at the fist digit (and also the A at your third code line) must have been set somewhere beforehand. The function does not change the unused digit, so it will stay whatever you set it to beforehand (Even from before the last reset of the Arduino. The display doesn't reset with the Arduino). You can set the segments for that digit to zero (or set all segments to zero, to clear the complete display) before you show the decimal number.
About the colon: Here it is important on which position you start the printing of the number. The colon/decimal point bitmask, that you provide the function with, is seen from the starting position, that you provide. The middle colon of a 4 digit display is wired to the second digit. When providing 1
as the starting position, you start with the second digit. Thus the colon bitmask must set the most significant ("first") bit, to enable the middle colon, since it belongs to the first digit, that is processed by the function. Meaning:
position = 0 and bitmask = 0b10000000 --> colon/decimal point at first digit on
position = 0 and bitmask = 0b01000000 --> colon/decimal point at second digit on
position = 0 and bitmask = 0b00100000 --> colon/decimal point at third digit on
position = 1 and bitmask = 0b10000000 --> colon/decimal point at second digit on
position = 1 and bitmask = 0b01000000 --> colon/decimal point at third digit on
position = 2 and bitmask = 0b10000000 --> colon/decimal point at third digit on
position = 2 and bitmask = 0b01000000 --> colon/decimal point at fourth digit on
The 0x80 >> 1
is just a different representation of your binary number. 0x80
is the hexadecimal form of the binary 0b10000000
. The >>
operator shifts the byte to the right, here by one digit. Thus:
0x80 >> 1 = 0b10000000 >> 1 = 0x40 = 0b01000000
So the code, that you found, enables the colon/decimal point at the second digit.
tell me an easier way to construct a time
Easier it relative. I used such a display in a project to display a time and used two showNumberDecEx()
calls; one for the minutes and one for the seconds:
display.showNumberDecEx(seconds, 0x00, true, 2, 2);
display.showNumberDecEx(minutes, 0x40, true, 2, 0);
Having directly minutes and seconds may make it easier for you. About the no-leading-zeros: Since the library always prints left to right, you need to handle that by yourself. But that is rather easy. One if statement to check, if the minutes are greater than 9 or not. Depending on that you set the position to 0 or 1.
display.showNumberDecEx(seconds, 0x00, true, 2, 2);
if(minutes > 9){
display.showNumberDecEx(minutes, 0x40, false, 2, 0);
} else {
display.showNumberDecEx(minutes, 0x80, false, 1, 1);
}
You could put that into a function, so that you don't have to write this code multiple times.
Note: For my last code snippet to work, you should first clear the display (or optionally only the first digit), so that no number from before will be displayed there.
-
In your last code snippet, the case
minutes
≤ 9 won't work as expected since, as you put it yourself, "the function does not change the unused digit, so it will stay whatever you set it to beforehand".Edgar Bonet– Edgar Bonet2020年02月18日 09:24:23 +00:00Commented Feb 18, 2020 at 9:24 -
That's true. I assumed implicitly, that the display is cleared beforehand. I will add a note for that.chrisl– chrisl2020年02月18日 09:28:08 +00:00Commented Feb 18, 2020 at 9:28
Always start by reading the docs. The README of the TM1637 display
library gives a short summary of the available functions, then states
"Please refer to TM1637Display.h for more information." It would thus
seem the authoritative documentation is the header file itself, which is
indeed rich ins structured comments. According to it, the
signature of showNumberDecEx()
is
void showNumberDecEx(int num,
uint8_t dots = 0,
bool leading_zero = false,
uint8_t length = 4,
uint8_t pos = 0);
where the parameters have the following meanings (emphasis mine):
num
: the number to be showndots
: dot/colon enable [...]leading_zero
: when true, leading zeros are displayed, otherwise unnecessary digits are blanklength
: the number of digits to setpos
: the position of the most significant digit (0 - leftmost, 3 - rightmost)
The length
and pos
parameters control which digits are set. It is
important to note that any digits that are not set are left as is.
Note also that, if you are setting more digits than needed to display
the number, the leftmost digits are either zeros or blank, depending
on the value of leading_zero
. And that is exactly what you want: you
want the leftmost digit to be blank.
Here are some examples of what various calls display:
display.showNumberDecEx(136, 0x40, true, 3, 1) → "X1:36"
display.showNumberDecEx(136, 0x40, false, 3, 1) → "X1:36"
display.showNumberDecEx(136, 0x40, true, 3, 0) → "13:6X"
display.showNumberDecEx(136, 0x40, false, 3, 0) → "13:6X"
display.showNumberDecEx(136, 0x40, true, 4, 0) → "01:36"
display.showNumberDecEx(136, 0x40, false, 4, 0) → " 1:36"
In the examples above, "X" means "whatever was previously left there", as the corresponding digit is not updated by the call. The last example is the one you want. Incidentally, the last three parameters of this example have their default values. You can thus achieve this simply with:
display.showNumberDecEx(136, 0x40);
You can also follow chrisl's advice and display the hours and minutes separately:
int hours = 1;
int minutes = 36;
display.showNumberDecEx(hours, 0x40, false, 2, 0);
display.showNumberDecEx(minutes, 0, true, 2, 2);
No need to separately handle the case where hours
is larger than 9.