Looking for a library for driving an odd-to-me MBI5026GNS based LED matrix.

Backstory on this LED matrix:
Work bought a, in my opinion, very overpriced monochrome sign about 14 years ago. Couple months ago it quit working. Finally got time to look into it last week. Three of the four 50amp/5v PSU units "died" and were only outputting 3.3v. After replacing those the LEDs would light up when the system was first powered but be blank after that or flicker randomly. Finally just gutted the thing after getting tired of working in the heat, brought it all inside the building and out of the heat so i could think while I worked on it. I deduced the main control board was/is dead or at least dead enough it might as well be entirely dead. Looking at the LED panels themselves I thought hey these got some nicely labeled pins that make me think that I could probably drive the LED display with an Arduino.

So this is where I am now. The LED sign consists of 12 led panels arranged in a 6x2 grid and each panel is a 16x16 grid of LEDs. Thus the entirety of the LED sign is 96x32 pixels. Pretty straight forward until I started trying to drive the thing. Each LED is driven by a MBI5026GNS (shift register chip for LED with a latch and enable pins) and a MC74HC244A. The only purpose of the MC74HC244A seems to be making sure the input pins to the LED chips are never floating. I say that because the enable pins for the MC74HC244A are hardwired to the enabled state effectively making it a pass-through chip, confirmed by testing and except for one gotcha this chip doesn't "exist".

I've managed to bit-bang my way to success after reading over the MBI5026GNS datasheet plus some continuity testing but then things got weird on me. That gotcha I mentioned at the end of the backstory? That MC74HC244A chips splits each panel into a top half and bottom half. So what I'm really doing is driving 4 independent 96 wide by 8 tall pixel displays that only share a common VCC and GND. So in order to drive one section of LED requires 4 pins; CLK, Data, Latch and OutputEnable. To drive each of the 4 "lanes" independently would require 16 pins in total. To drive the entire display using the minimum number of pins would require 7 pins. 4 pins for each of the Data lines plus 3 more if I grouped the individual CLK, Latch and OutputEnable into single pins.

Every library I find expects either NeoPixel-style RGB strips or monolithic monochrome shift-register display (opposed to the 4 part monochrome shift-register display I'm working with).

Here is a crappy forum table of how the bits move about on a 16x16 panel. I only did three of the columns. Bits shift in starting with the top-right most pixel of their half of the 16x16 panel. Moving down until they reach the bottom of their half before moving to the top of the next column to the left. What would you call that? Top-to-bottom then right-to-left bit-shift order?

A17 A9 A1
A18 A10 A2
A19 A11 A3
A20 A12 A4
A21 A13 A5
A22 A14 A6
A23 A15 A7
A24 A16 A8
B17 B9 B1
B18 B10 B2
B19 B11 B3
B20 B12 B4
B21 B13 B5
B22 B14 B6
B23 B15 B7
B24 B16 B8

Anyone know of library that can handle a display such as this or am I stuck trying to write it myself? I can provide more information if needed tomorrow including pictures if desired.

Hi and welcome to the forum.

I guess you don't have a schematic for each 16x16 panel? If not, how many of each type of chip are there?

You mention only two types of chip, so I'm wondering if there are 16 of the shift registers per panel, and multiplexing is not used. That's unusual because it would make the panels expensive to manufacture, but it would make them maximum brightness for outdoor use. The other chip you mentioned is just used as a buffer to prevent problems caused by "fan-out" where many inputs are connected to a single output, I suspect.

All the libraries I have seen for similar displays have been for multiplexed displays, so won't work unaltered with your panels. The AdaFruit libraries for the panels they sell are well supported, so I might consider modifying those. But such projects are for advanced Arduino users and far beyond the abilities of most Arduino beginners. Do you have any relevant experience in electronics and coding?

I didn't really understand your comments around "monolithic monochrome" and "4 part monochrome" panels. Or your table, which has 16 rows but only 3 columns?

PaulRB:
I didn't really understand your comments around "monolithic monochrome" and "4 part monochrome" panels. Or your table, which has 16 rows but only 3 columns?

The table isn't the full display but just enough to show the pattern of how shifting the bits appear on the display. It repeats the whole way across. I brought pictures with me today so hopefully they make more sense. My Photoshop skills are crap so work with me on that.


2MB total attachment limit got me so I had to break them up across two posts.

Here are two more pictures...and now the 5 minute wait time between posts has me.

[edit]
Guess it helps if I explain these two pictures.

Panel-ShiftOrder shows how the bits move about the screen. The two colors are to show how the top half and bottom half are independent of each other.

Panel-WireDiag is the poor photoshop I mentioned for how everything is wired up.

[edit2]
I'm currently in the process of writing my own extremely basic library for this display which will barely be able to make text appear but it will see the entire display as 4 smaller displays since that is how the physical wiring works.

Really hoping to find an already premade lib that will make the sign appear as a single larger display or at least a library close enough I can modify.

Thanks, mods!

@credomane, I get it.

4 smaller displays

each 96 x 8? You could wire them together, so 384 x 8. Then you can drive the whole display using the Arduino's hardware SPI interface. Much faster than bit-banging.

Or keep them as 4 separate displays, share the Arduino's MOSI, SCK across the 4 but have 4 separate Arduino pins for the 4 LATCH lines.

So each shift register/current driver controls 16 LEDs, so two bytes.
You have 8 shift registers per half, so each half needs 16 bytes.
24 panels, 384 bytes per ‘frame’ if you will.

Are all the shift registers connected? Or just in each panel?
If just by panel, then just 24 slave selects, 1 for each panel top & bottom half.

I would use SPI.transfer() and send the data out from an array holding the contents.
Would be pretty straightforward. Say all are daisychained

digitalWrite (outputEnablePin, LOW)
digitalWrite (latchPin, LOW);
for (x = 0; x < 25; x=x+1){ // cycle thru the panels
  for (y = 0; y < 16; y = y+1){ cycle thru each panel
  SPI.transfer (dataArray[(x*25) +y]); // bytes 0 to 15, then 16-31, 32-47, etc
  }
}
digitalWrite (latchPin, HIGH);
digitalWrite (outputEnablePin, HIGH);

Use fastest SPI clock that works reliably.
Change the digitalWrites to direct Port Manipulation to save some time.

Keep the inner y loop and use the outer x loop for driving individual latchPins and outputEnablePins if that’s what you have.

As usual, the hardest part will be coming up with content to show.

PaulRB:
each 96 x 8? You could wire them together, so 384 x 8. Then you can drive the whole display using the Arduino’s hardware SPI interface. Much faster than bit-banging.

You know that’s a very interesting thought and quite feasible to do/try too.

CrossRoads:
I would use SPI.transfer() and send the data out from an array holding the contents.
Would be pretty straightforward. Say all are daisychained

digitalWrite (outputEnablePin, LOW)

digitalWrite (latchPin, LOW);
for (x = 0; x < 25; x=x+1){ // cycle thru the panels
 for (y = 0; y < 16; y = y+1){ cycle thru each panel
 SPI.transfer (dataArray[(x*25) +y]); // bytes 0 to 15, then 16-31, 32-47, etc
 }
}
digitalWrite (latchPin, HIGH);
digitalWrite (outputEnablePin, HIGH);



Use fastest SPI clock that works reliably.
Change the digitalWrites to direct Port Manipulation to save some time.

Keep the inner y loop and use the outer x loop for driving individual latchPins and outputEnablePins if that's what you have.

As usual, the hardest part will be coming up with content to show.

Damn…That’s brilliant. That isn’t how things are wired up in the “stock” configuration but couple jumpers wires can make it wired that way easy.

As for content to show. That isn’t too hard to come by. Always getting told to put this or that out on the sign. Already missing it but don’t want to budget anything to get a new one.

Hardware engineer doncha-know. Never learned how to do libraries. Can barely write a function. Prefer the simple approach to software.

If the display were mine, inevitably I would have to run Conway’s Game of Life on it. John died recently, you know. He was a genius mathematician and invented all kinds of stuff, but everyone remembers Game of Life. I have code that I have adapted to several displays, like this for example.

Made my LED "driver" for that sign. I ended up using CrossRoads' idea for the wiring.

I can Use either hardware SPI or software SPI mode (shiftOut).
Hardware uses the SCLK and MOSI pins for the Clock and Data pins
Software uses Digital pins 11 (Data) and 12 (Clock).
Both hardware and software SPI needs digital pin 10 for the Output Enable 6-9 for the 4 latches.

I do need to learn how to use PROGMEM properly. Currently wasting 75% of a nano's ram just for the font. Originally I shoved it into the PROGMEM but my understanding how to pull it back out is totally wrong.

I uploaded the sign.ino and font.h to a github gist for your viewing pleasure or as nightmare fuel. :stuck_out_tongue:
I didn't embed them in code blocks because who wants to scroll through a view hundred lines of code on a forum thread?

100% positive there is a far better way to store the font efficiently. Along with a host of other things that could be done better. My knowledge as far as cpp goes is pushed to the limit already with this project.

I saw Adafruit has some monochrome display drivers. I looked over them and while none of them would work for this sign. It does look like it shouldn't be too much of a nightmare to write my own Adafruit GFX LED driver for this work sign. Would make some things wonderfully easy...I think.

Anyways. once the sign finishes the setup() and enters the loop() phase. I just listen to the serial line for commands. "L1Blah Blah" will put "Blah Blah" on the top 1/4 of the screen. L2 L3 and L4 do the same for their quarter of the screen. "B#" is for sending in raw bytes so I can do "fancy" things like drawing pictures but I haven't worked on that any. "C#" is for clearing that section of the screen. My serial code is slow and there is a noticeable 1 second long pause after I hit enter and the sign updates.

Here is a picture of the nano setup and another pic for what the "boot" screen looks like on the sign.
So....how do I embed the pictures? Do I have to post, edit post and insert picture with attachment url?
[edit]
Well That's what I did. Editted the post and stuck the attachment url into the img tag. If that is the wrong way @mods please fix.


NanoWires.png

NanoWires.png

img tags is how it's done. I modify posts with those all the time.
Wiring didn't turn out to be too complex it looks like.
Sending out a screen's worth of data goes pretty quick?
I had a project where I refreshed 45 shift registers at a 20 KHz rate (from SRAM) using 8 MHz SPI and direct port manipulation for slave select pin, so SPI can be pretty darn quick.

I've also used EEPROM to store font data and messages to be displayed (and got myself really confused for a while when I put in more than 1K of message data and it wrapped around).

Moving letters at more than a 50mS rate across a screen made it hard to read.

The spec sheet for the chips claims 25mhz is the max frequency, assuming I understood it correctly. I highly doubt these unshielded straight tiny gauge wires are gonna handle that kind of frequency. The 4000000 I have the SPI set to now works great. Whatever frequency that works out as (4mhz?). The 40-60ms range is where the letters start to blur and become unreadable to the naked eye. Considering the sign text is normally updated every 3-10 seconds as the "slide" changes my setup is already more than good enough. Doesn't mean I'm satisfied with it though. I wanna push it until it breaks then back it off a bit. lol

I want to implement overall screen brightness soon but that can be a lazy pulse to the output enable pin. At night full brightness can be intense when a lot of the screen is lit up. Eventually down the road I want to be able to draw pictures, maybe even with greyscale. That will be a lot of screen updates per second and require a in-memory pixel buffer instead of the send-n-forget approach I did.

Wiring it stupid simple after following your suggestion; So much better than the 16 pins I was doing before. Once I finalize the wiring diagram, 70% there, I'm going to solder up one of those "dev" single-side PCB boards with the sign wire connectors connectors I heatgunned off the dead sign brain. I feel bad stealing the connectors but the $1500 brain is dead and replaced with a brain so cheap it is "free" by comparison.

[edit]
Just updated the gist to the version that uses eeprom storage for the font. That saved a lot of ram just like I was hoping.