Go Down

Topic: 8x16 Segment display driver with limited input (Read 865 times) previous topic - next topic

PaulRB

#15
Apr 21, 2019, 07:13 am Last Edit: Apr 21, 2019, 07:14 am by PaulRB
Why are you reading the data sheet for tms1651? Your chip is tms1629. The table you show should have been this one, I think:

JordanSmith

#16
Apr 21, 2019, 07:16 am Last Edit: Apr 21, 2019, 07:21 am by JordanSmith
Yes, I understand the difference. I just picked out a smaller table that seems to reflect the same information. I don't know what it represents though, does that help me at all?

I think this thread is better suited to the programming topic. When I first posted this, I didn't know how the microprocessor operated. But now I don't know how to program it.

PaulRB

Don't just pick out parts of the wrong data sheet. You risk confusing us, or at least making us think you are so confused that its hopeless trying to help you.

The table seems to show the memory registers inside the chip which control the segments of the display. I don't know why the data sheet author makes it seem so complex with all the "00HU" designations, they don't help to make things clearer, in my opinion. Basically there are 8 x 16-bit registers to control up to 8 digits with up to 16 segments per digit. However, the data is read/written in bytes, so each 16-bit register has two consecutive addresses.

How you write to them must be explained elsewhere in the data sheet. There must be some way for the microcontroller to send an address, then send the data to be written to that address.

OneTransistor

The problem here is that manufacturers wire the display to TM1629 (and similar) controllers the way they want.

From datasheet:

"The storage of this register is transferred from external component to TM1629 through serial
port, with an address of 16 bytes unit in total from 00H-ODH, corresponding to the LED lamps
connected to the chip's SGE and GRID pin respectively. "

Display RAM is 16 bytes only. 16x8 = 128 bits. Make an empty buffer of 16 bytes and send it to TM1629 using its interface. Then take each byte in a loop and set each of its bits in another loop. Send the buffer to TM1629. Print what byte and bit you are setting on Arduino serial monitor and add a sufficient delay.

Take a pen and paper and draw the segments of your display. When they light up (one at a time), write the byte and bit next to each of them. You will soon notice a pattern.

Maybe every byte holds the bits for the same segment of each digit. Or maybe every byte's bits control a single digit. It's likely that not all buffer data is used.

It's not as hard as it seems to do it and this is the only way. This is how I wrote the libraries for TM1628, SC75823 and HT16515 (https://github.com/onetransistor/arduino-libraries/tree/master/Display_Segment). There's no other way when you can't find a schematic of the module and display.

JordanSmith

#19
Apr 21, 2019, 04:52 pm Last Edit: Apr 23, 2019, 10:02 am by JordanSmith
Thank you so much for the reply, I really appreciate that! I'm so close to being able to control 100% of the display now!

I went through your library and a few similar ones from other publishers. I really struggle to understand them. This is the first microprocessor I have attempted to repurpose. I thought that being a simple display I wouldn't have too much trouble with it. I was wrong.

I assume you read this, but for reference, I'll leave it here.
Code: [Select]

I determined the anode connections include(segments from right to left of the display):
GRID1 - Second segment
GRID2 - First segment
GRID3 - third segment
GRID4 - fourth segment
GRID5 - Utility
GRID6,7,8 - N/C

and the cathode connections:

Seg 11    o---Seg10---o       Seg 9
             |                         |
             |                         |       Seg 8
             |                         |
Seg 2      o---Seg4---o       Seg 16
             |                         |
Seg 1    |                         |       Seg 15
             |                         |
Seg12     o---Seg3---o       Seg 14

The top left segment is connected to grid5, strange.


Take a pen and paper and draw the segments of your display. When they light up (one at a time), write the byte and bit next to each of them. You will soon notice a pattern.
Okay, I have done this. I am building off your TM1628ts and I've been using disp.putDigitAt(). I have edited the block of information in your .h file to:
Code: [Select]
const unsigned char tm_digit[32] = {0x00, // All off
                                    0x04, 0x08, 0x10, 0x20, 0x40, // one segment 0,1,2,3,4,5
                                    0x44, 0x48, 0x50, 0x60, 0x24, 0x28, 0x30, 0x14, 0x18, 0x0C,// two segments
                                    0x4C, 0x54, 0x64, 0x68, 0x70, 0x34, 0x38, 0x1C, 0x58, 0x2C, // three segmenents
                                    0x78, 0x74, 0x6C, 0x5C, 0x3C, // 4 segments
                                    0x7C // all on
                                   };

 byte tm_buffer[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

I realized what you had been doing in the block. Knowing this I applied it. Being 8x16 system I must be trying to write with a single byte to specify the desired grid pin (might be obvs for u soz :P). With trial and error, I was able to discover the important bits to store (01111100 the '1's in the byte correspond to grids 1-5 so 01111100 would light the chosen segment of all 5 grids). and I changed the buffer to 16 as you said. This drastically improved the ability to display segments for me!

So I have the Grid pins, sorted but I'm stuck with the segment pins. Your library was initially written for 7 segments but I have access to 16. My issue is that I can only go up to segment 7. Something in your code is locking me out from going any higher than 7, no error message, just a blank output. I feel a solution to this should be as simple as changing a 7 to a 16 somewhere.

I tried editing the function to fix this, with no prevail:
Code: [Select]
void TM1628ts::putDigitAt(byte digit, int pos) {
for (int i = 0; i < 7; i++)
bitWrite(tm_buffer[i * 2], pos, bitRead(tm_digit[digit], 6 - i));
}

For further clarification, I have access to the first 8 (0-7) segments but I am clearly missing 8 segments (8-16). This is an image of all LEDS I can illuminate at this point. Focusing on the first digit you see the top left, top middle, top right, right, lower right, bottom right, bottom middle and bottom left are uncontrollable. I have 8 segments missing.

This is the full program which displayed that image:
Code: [Select]
  const unsigned char tm_digit[32] = {0x00, // All off 0
                                      0x04, 0x08, 0x10, 0x20, 0x40, // one segment 1-5
                                      0x44, 0x48, 0x50, 0x60, 0x24, 0x28, 0x30, 0x14, 0x18, 0x0C,// two segments 6-15
                                      0x4C, 0x54, 0x64, 0x68, 0x70, 0x34, 0x38, 0x1C, 0x58, 0x2C, // three segmenents 16-25
                                      0x78, 0x74, 0x6C, 0x5C, 0x3C, // 4 segments 26-30
                                      0x7C // all on 31
                                     };

  byte tm_buffer[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
int tm_dio = 9;
int tm_clk = 8;
int tm_stb = 7;

void setup() {
  Serial.begin(9600);
  init(2);
  // put your setup code here, to run once:
}

void loop() {
  clearBuffer(-1);
  writeBuffer();
  for (int i = 0; i < 16; i++){
    putDigitAt(31, i);
  }
  writeBuffer();
  delay(100000);
  }


void init(int intensity)
{
  pinMode(tm_dio, OUTPUT);
  pinMode(tm_clk, OUTPUT);
  pinMode(tm_stb, OUTPUT);

  digitalWrite(tm_stb, HIGH);
  digitalWrite(tm_clk, HIGH);

  delay(200);

  tm_sendCommand(0x40); // command 2

  digitalWrite(tm_stb, LOW);
  tm_sendByte(0xc0); // command 3
  for (int i = 0; i < 16; i++)
    tm_sendByte(0x00); // clear RAM
  digitalWrite(tm_stb, HIGH);

  tm_sendCommand(0x03); // command 1

  setIntensity(intensity);
}

void setIntensity(int intensity)
{
  if (intensity < 0)
    {
      tm_sendCommand(0x80); // command 4
      return;
    }

  tm_sendCommand(0x88 | (intensity % 8)); // command 4
}

void putDigitAt(byte digit, int pos)
{
  //if ((pos < 0) || (pos > 7))
    //return;

  for (int i = 0; i < 7; i++)
    bitWrite(tm_buffer[i * 2], pos, bitRead(tm_digit[digit], 6 - i));
}

void clearBuffer(int pos) {
  if (pos == -1)
    {
      for (int i = 0; i < 16; i++)
        tm_buffer[i] = 0x00;
      return;
    }

  if (pos >= 8)
    return;

  for (int i = 0; i <  8; i++)
    bitWrite(tm_buffer[i * 2], pos, 0);
}

void writeBuffer()
{
  tm_sendCommand(0x40); // command 2
  digitalWrite(tm_stb, LOW);
  tm_sendByte(0xc0); // command 3
  for (int i = 0; i < 16; i++){
    tm_sendByte(tm_buffer[i]); // set RAM
  Serial.println(tm_buffer[i]);
  }
  digitalWrite(tm_stb, HIGH);
}

void tm_sendCommand(byte data)
{
  digitalWrite(tm_stb, LOW);
  tm_sendByte(data);
  digitalWrite(tm_stb, HIGH);
}

void tm_sendByte(byte data)
{
  for (int i = 0; i < 8; i++)
    {
      digitalWrite(tm_clk, LOW);
      digitalWrite(tm_dio, data & 1 ? HIGH : LOW);
      data >>= 1;
      digitalWrite(tm_clk, HIGH);
  }
}


@OneTransistor, you're my best hope at figuring this out! Any insight?

OneTransistor

If you fill the entire buffer with 0xFF and write it to controller what happens? All segments should be on.

disp.putDigitAt() must be completely rewritten so don't count on it. For the moment just play with various bits of the buffer, write it to display and see what happens.


JordanSmith

If you fill the entire buffer with 0xFF and write it to controller what happens? All segments should be on.
tysm! In the end, I only needed 10 bytes in the buffer because I needed two bytes to display one digit, and there are only 5 used grids.

Anyways, thanks for all the help!

Go Up