maxint-rd / TM16xx

Arduino TM16xx library for LED & KEY and LED Matrix modules based on TM1638, TM1637, TM1640 and similar chips. Simply use print() on 7-segment and use Adafruit GFX on matrix.
176 stars 35 forks source link

TM1650 Arduino library for 2 x 7 led display #35

Closed StealthRT closed 1 year ago

StealthRT commented 1 year ago

Hey all I am using a 2 digit 7 segment TM1650 and I cant seem to find the setting for that? I can only find TM1650_DISPMODE_4x8 and TM1650_DISPMODE_4x7. No 2x7.

Digit animation

If someone could let me know how to go about modifying the code in order to allow me to use just 2 digitals instead of 4 then that would be great!

The current arduino nano code I am using:

#include <TM1650.h>
#include <TM16xxDisplay.h>
//              [data Pin]
//              |  [clock Pin]
//              |  |  [num Digits]
//              |  |  |  [activate Display]
//              |  |  |  |     [intensity]
//              |  |  |  |     |  [display mode]
//              ↓  ↓  ↓  ↓     ↓  ↓
TM1650 display1(2, 3, 2, true, 7   );

void setup()
{
}

void loop()
{
   int n;

   for (n = 0; n < 10; n++)
   {
      //                             [nNumber]
      //                             |  [byte bDots]
      //                             ↓  ↓
      display1.setDisplayToDecNumber(n, 0b0000);
      delay(250);                               
   }
}
StealthRT commented 1 year ago

Looking at the pcb tracks on the back of my unit the power, gnd, data and clock tracks seem to be the only things going to the correct places? Does that look correct to you compared the the datasheet?

image

maxint-rd commented 1 year ago

Hello @StealthRT,

Thank you for submitting this question and illustrating it with an animation and annotated photo.

As you can see in the last table on page 4 of the TM1650 datassheet, the chip has only two display modes: 8 or 7 segments. For compatibility with the other chips I named the mode constants the way you stated.

To use only two digits out of the maximum of four, setting the numDigits to 2 should be sufficient, assuming that those digits are connected to pins 1 (dig1) and 5 (dig2) of the chip. Judging from the picture that seems to be the case (segment dig3 on pin 6 seems to be only connected for reading button presses). So even if the mode is named TM1650_DISPMODE_4x8, by setting numDigits to 2 it will use those digits.

For completeness, this is the default constructor:

TM1650(byte dataPin, byte clockPin, byte numDigits=4, boolean activateDisplay=true, byte intensity=7, byte displaymode = TM1650_DISPMODE_4x8);

Your example seems to use the proper constructor initialization and your animation shows the first digit is being set to the number of the loop. However; it seems that the segments are in non-standard order. The traces lead to different segments than specified on page 2 of the datasheet. This results in wrong segments lighting up than what should be to properly display the number.

In the future I intend to add a method to map the segments to alternative pins and I have done so for some specific chip-classes, but not yet for the base class. The easiest way for you to have the library show numbers with your segment layout is to use a modified number font. Can you handle that?

BTW. If you don't need to use the convenient print() method provided by TM16xxDisplay.h, you can skip that include and use the setDisplayToDecNumber() method to display numbers 0-99.

StealthRT commented 1 year ago

Thanks for getting back to me @maxint-rd .

Someone has made this work for their unit but it looks like mine is a little different from theirs: https://github.com/jingsno/intex-swg-iot/blob/master/main/IntexSWG.h

Can any of that code be used with your library? It kind of looks the same as the TM1650.cpp and some things not.

Also, is there an example of reading what's on the LED segments? I'm only finding buttons that are read.

Using your example of TM16xx_setSegments.ino and also TM16xxButtons_clicks.ino and debugged it and found the results to be: image

maxint-rd commented 1 year ago

Hello @StealthRT, nice picture! I'm sure it is helpful in giving your pool-module some second life. The led numbers you show represent the various segment-bit-positions of the LEDs.

Almost all chips in the TM16xx family have write-only display memory. Some support reading buttons, but not all. The TM1650 also only supports writing to display memory and reading of button state.

The six buttons on your module all use the DIG3 line, connecting the switches via resistors to Kxx pins. See datasheet page 8 for details. From your tracing picture its hard to see to which Kxx pin the lock/unlock switch is connected, but be aware of the resistor in between.

With regards to the other code: I looked at those TM1650.h and TM1650.cpp files and recognized my code! I see all my own comments and no significant modifications. Good to see my work has inspired others, but I'm a bit disappointed to see Antonio Flores removed the credits from the top of the file...

Having said that, I do encourage people to reuse my work, as I also wouldn't be able to do what I do without others. (Just give credit where credit is due...) So feel free you use my code to make your own version to fit your specific needs. As I don't have your module in my collection, I will not be able to provide any module-specific support. To make my library work better for your module, I already suggested to change the number-font file according the wiring of your module. Have fun experimenting!

StealthRT commented 1 year ago

Hey again @maxint-rd .

I see there is a receive() function. Is this where it can read what's on the led segment/led lights? I'm looking around in your examples and I'm not seeing an example of the tm1650/tm16xx using it. Would you mind adding an example of the receive() to your repository?

This is how the display looked while debugging from my previous post just as a visual: https://i.postimg.cc/9MNCqm02/ezgif-com-optimize.gif

As far as the Tony's code I seem to have found something that works:

#include <TM1650.h>
TM1650 module(2, 3);  // SDA/DIO, SCL/SCK

// Segment-bit: E D G F B A DP C
#define DISP_BLANK  0b00000000
#define DISP_0      0b11011101
#define DISP_1      0b00001001
#define DISP_2      0b11101100
#define DISP_3      0b01101101
#define DISP_4      0b00111001
#define DISP_5      0b01110101
#define DISP_6      0b11110101
#define DISP_7      0b00001101
#define DISP_8      0b11111101
#define DISP_9      0b01111101
#define DISP_DP     0b00000010
#define DISP_A      0b10111101
#define DISP_P      0b10111100
#define DISP_1_CLEAN_06P 0b11110111
#define DISP_1_CLEAN_10P 0b11011111
#define DISP_1_CLEAN_14P 0b00111011

#define LED_OZONE           0   // 0b00000001
#define LED_SLEEP           1   // 0b00000010
#define LED_BOOST           2   // 0b00000100
#define LED_POWER           3   // 0b00001000
#define LED_PUMP_LOW_FLOW   4   // 0b00010000 12???
#define LED_LOW_SALT        5   // 0b00100000
#define LED_HIGH_SALT       6   // 0b01000000
#define LED_SERVICE         7   // 0b10000000

#define LEFT_DIGIT  1
#define RIGHT_DIGIT 0
#define STATUS_LEDS 2

#define POWER_STATUS_OFF        0
#define POWER_STATUS_STANDBY    1
#define POWER_STATUS_ON         2
#define POWER_STATUS_BOOTING    3
#define POWER_STATUS_BUS_ERROR  4

#define DIGIT1              0x68
#define DIGIT2              0x6A
#define DIGIT3              0x6C

#define BUTTON_BOOST        0x44
#define BUTTON_TIMER        0x46
#define BUTTON_POWER        0x4C
#define BUTTON_LOCK         0x4E
#define BUTTON_SELF_CLEAN   0x74

char getDisplayDigitFromCode(uint8_t code) {
  switch (code) {
    case DISP_BLANK: return 0;
    case DISP_0: return '0';
    case DISP_1: return '1';
    case DISP_2: return '2';
    case DISP_3: return '3';
    case DISP_4: return '4';
    case DISP_5: return '5';
    case DISP_6: return '6';
    case DISP_7: return '7';
    case DISP_8: return '8';
    case DISP_9: return '9';
    case DISP_DP: return '.';
    case DISP_1_CLEAN_06P: return '6';
    case DISP_1_CLEAN_10P: return '0';
    case DISP_1_CLEAN_14P: return '4';
    default: return 0;
  }
}

uint8_t getCodeFromDisplayDigit(char displayDigit) {
  switch (displayDigit) {
    case 0: return DISP_BLANK;
    case '0': return DISP_0;
    case '1': return DISP_1;
    case '2': return DISP_2;
    case '3': return DISP_3;
    case '4': return DISP_4;
    case '5': return DISP_5;
    case '6': return DISP_6;
    case '7': return DISP_7;
    case '8': return DISP_8;
    case '9': return DISP_9;
    case '.': return DISP_DP;
    default: return DISP_BLANK;
  }
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (byte i = 0; i < 100; i++) {
    module.setSegments(getCodeFromDisplayDigit(i / 10 + '0'), 1);
    module.setSegments(getCodeFromDisplayDigit(i % 10 + '0'), 0);
    delay(200);
  }
}

It counts up from 0 to 99 and then repeats. https://i.postimg.cc/3N50zQ5g/Full-Size-Render.gif

However, the module.setDisplayToString("HA"); does not seem to work. image

I'm guessing that is caused by my module being mapped differently than the datasheet says that it should be?

maxint-rd commented 1 year ago

Is this where it can read what's on the led segment/led lights?

No, you cannot read what's displayed on the led lights. As stated before, the display memory is write only. You can only read the button state. Please refer to the datasheet for more information. The receive() function is an internal protected method used by the public method getButtons(). Feel free to examine the implementation yourself.

This is how the display looked while debugging from my previous post just as a visual

Nice gif. It's a good demonstration of how the module doesn't follow the segment pin-out as shown in the datasheet. I already saw that behavior in the first animated gif and it was confirmed by the tracing photo.

As far as the Tony's code I seem to have found something that works

Good. You could use that information to make your own version of a number font file and use that file in my library.

However, the module.setDisplayToString("HA"); does not seem to work.

To get that working you also need to map the alphabetic characters. In my library characters A-F are also in the number font file (for hexadecimal numbers) and in the alpha-numeric font file which contains all supported characters. When calling setDisplayToString() the alpha-numeric font is used.

StealthRT commented 1 year ago

Just want to thank you for taking the time to help me out @maxint-rd!