jasonacox / TM1637TinyDisplay

Arduino library to display numbers and text on a 4 and 6 digit 7-segment TM1637 display modules.
GNU Lesser General Public License v3.0
72 stars 19 forks source link

bug in flipdisplay with colon : #18

Open stef-ladefense opened 2 years ago

stef-ladefense commented 2 years ago

hi,

i use this for write time

void ShowTime(uint8_t _mins, uint8_t _secs, bool _Colon, bool _zns) { display.showNumberDec(_mins, 0b01000000 * _Colon, _zns, 2, 0); display.showNumber(_secs, true, 2, 2); }

but with display.flipDisplay(true) not colon write ...

jasonacox commented 2 years ago

HI @stef-ladefense - thanks for opening this issue!

The Problem

The challenge we have with flipping the display is that the "colon" is hardwired to be set by the 2nd digit in "non-flip" orientation. The same happens for "decimal" displays where the digit to the left of the decimal is what sets that dot. For example:

Non-Flip Display

        1. (index for digit) [0] [1:] [2] [3] - The colon is set by the "1" (index 1) - which would be your _mins setting.

Flip Display Over

        1. (flip index) [3] [2] [:1] [0] - The colon is still set by the "1" (index 2) - which would now be your _secs setting in this orientation.

The flip code in the library knows that the colon moves and shifts the setting, but it can only set values in the range of digits you give it (for minutes, you are telling it to limit the change to only length=2 spaces - digits index 0 and 1). If we go outside the length value, we would need to know the value in index 2 (my example = "1") to be able to toggle the colon bit.

The Fix?

The function that drives the setting of the segments and dots is TM1637TinyDisplay::setSegments() - If you have any suggestions on how we could adjust it to handle this situation, I would love help.

For your particular use case, I would recommend making a slight change to your function that would work in both orientations, something like this:

void ShowTime(uint8_t _mins, uint8_t _secs, bool _Colon, bool _zns) {
    int output = _secs + (100 * _mins);
    display.showNumberDec(output, 0b01000000 * _Colon, _zns);
}

Alternatively, since there is only one "colon" the the display, you could cheat and force a colon set for all digits:

void ShowTime(uint8_t _mins, uint8_t _secs, bool _Colon, bool _zns) {
    display.showNumberDec(_mins, 0b11110000 * _Colon, _zns, 2, 0);
    display.showNumberDec(_secs, 0b11110000 * _Colon, true, 2, 2);
}
stef-ladefense commented 2 years ago

thank the 1st dont work, colon work but zns dont, for 0mn et 5s : __:_5 the 2th not colon with flip

I need to think about how to send it I will need time to dissect the setSegments routine and see how the points are transmitted and how to make the distinction with colon

jasonacox commented 2 years ago

Ah, yes, you are correct! Sorry about that.

Here is a possible workaround, not elegant but works:

void ShowTime3(uint8_t _mins, uint8_t _secs, bool _Colon, bool _zns) {
  char output[MAXDIGITS+1];
  if(_zns) sprintf(output, "%02d%02d", _mins, _secs);
  else sprintf(output, "%2d%02d", _mins, _secs);
  display.showString(output, 4, 0, 0b01000000 * _Colon);
}

I'll see if there is something more we can do to setSegments() to make this more intuitive.

jasonacox commented 2 years ago

The challenge is really caused by the approach of using direct address writes (position and length) to the display. If we were to use a intermediate memory buffer (e.g. digits[]) for manipulation of the display so that showNumber(), etc., calls just update the buffer and then always write the full buffer to the display, we would be able to control the decimal/colon flip. It is a bit of a rewrite but could be worth it. I doubt it would introduce much latency and could likely reduce some code. I'll run some tests.

jasonacox commented 2 years ago

Hi @stef-ladefense - I created a test class (TM1637TinyDisplayB) using my buffer idea. It seems to work well but I plan to run more tests. It works with your original ShowTime() function. I would love your thoughts on this.

#include <TM1637TinyDisplayB.h>
TM1637TinyDisplayB display(CLK, DIO);

void setup() {
  display.setBrightness(BRIGHT_HIGH);
  display.clear();
}

void ShowTime(uint8_t _mins, uint8_t _secs, bool _Colon, bool _zns) {
  display.showNumberDec(_mins, 0b01000000 * _Colon, _zns, 2, 0);
  display.showNumber(_secs, true, 2, 2);
}

void loop() {
  display.flipDisplay(false);
  display.showNumber(1234);
  delay(5000);
  display.flipDisplay(true);  // with flip will render w/o redraw
  delay(5000);

  ShowTime(0, 5, true, false);
  delay(5000);

  ShowTime(0, 5, true, true);
  delay(5000);
}
stef-ladefense commented 2 years ago

i test your B it's work with flip for me! like this new approach !

stef-ladefense commented 2 years ago

question how to mix a string to display a text (showString) with a patern on a specific character?

jasonacox commented 2 years ago

Thanks @stef-ladefense ! The tests all look good for me too so I'm going to fold it into TM1637TinyDisplay and TM1637TinyDisplay6 and release it to Arduino, along with your brightness update.

For the string question, are you talking about sending a specific pattern not in the string dictionary? If so, you would use setSegments() for the new pattern:

uint8_t data[] = { 0x03, 0x18, 0x0c, 0x21 };
display.setSegments(data)

If you wanted a mix, you can use the position and length and position parameters:

  uint8_t data[] = { 0x2a, 0x00, 0x00, 0x00 };
  display.showString("YES ");
  display.setSegments(data, 1, 3);

You can use this tool to get the codes for the pattern: https://jasonacox.github.io/TM1637TinyDisplay/examples/7-segment-animator.html

image
stef-ladefense commented 2 years ago

yes I know that, but what bothers me is having to declare a data[] variable of 4 bytes to be able to use setSegments. so I made a other definition of setSegments as follows:

in .h
void setSegments(const uint8_t A, uint8_t pos = 0);

in .cpp
void TM1637TinyDisplayB::setSegments( uint8_t A, uint8_t pos) {
digitsbuf[pos] = A;  
writeBuffer();
}

which allows me to write a byte of segments wherever I want

jasonacox commented 2 years ago

Great suggestion! I'll add it.