LED matrix display - MD_Parola, MD_MAX72xx and MD_MAXPanel

Cool. I just tried my authentic 7219's (I have four). By moving them around I could get a string of Parola 16 modules working perfectly. It's almost as these are acting as signal conditioners for the not so stellar crowd. On the scope they don't look any different though.

Now, if we could MAXX to sell us the authentic chips for $2.... :smiley:

Mel

Mel - What was the pattern for using the genuine chips? Every other one?

I decided to look at the initialization code some more.
(I'm still not convinced that there is a chip issue yet)
I did this because I was noticing some garbage pixels during the initialization
that show up briefly and then go away as the scrolling demo starts up.
I would see this after pushing the reset button on the Arduino.
Not every time but occasionally.
This shouldn't happen.
I figured there was an issue so I slowed down the SPI clock to as slow as it would
go in attempt to increase the probability. It worked. It would happen more often.

In looking at the actual code I found an issue that can and does send
garbage commands to the chips.
Down in MD_MAX72XX::begin(void)

there is this sequence.

  if (_hardwareSPI)
  {
	// Set direction register for SCK and MOSI pin.
	// MISO pin automatically overrides to INPUT.
	// SS pin is still used and needs to be made HIGH
	pinMode(SS, OUTPUT);
	digitalWrite(SS, HIGH);

The issue with this is that the pinMode will force the pin to be driven low.
Then the digitalWrite will drive the pin high.
If the csPIn is the same pin as SS (which it normally is when using SPI),
that just clocked in whatever is in the shift registers.
If it is a clean startup, it should be zeros, which is NOPs
but if it was a reset during operation from either pushing the reset button
or from an autoreset when uploading the sketch, then there is a possibility
that the shift registers are not all zeros.
There is also the possibility that if the clock and data lines glitch
during the reset process, that the 7219 might actually clock in data since
it clocks data regardless of the state of LOAD/CS.

One thing that I did to ensure that the LOAD/CS is never driven low prior
to driving it high by swapping the initialization order to:

	digitalWrite(SS, HIGH);
	pinMode(SS, OUTPUT);

I also inserted additional debug code to be able control and pause every pin
initialization and control() call.
Strange things happened and you could watch the "garbage" pixels turn and off
from the TEST and SHUTDOWN control() calls.
Certain pixels would go away and then re-appear.
It was very strange.

The good news is that after
the SS initialization order change, I no longer saw the garbage pixels after many resets.

I'm assuming that this worked because the 7219 CS pin is biased high if it is floating and so if the AVR pin
is made an input with the pullup turned on,
which is what happens if setting the pin high before you set it to be an output,
then the CS pin would never see the low which avoids the low to high transition.

One thing that is interesting is if you look at the 72xx register table you can see
that registers 0xD and 0xE don't exist.
It is undefined what would happen if you write to them.
If sending garbage bits, it is possible that these end up being written to
and that strange things then happen.
It is also possible that different versions of the chips react differently to this
invalid condition and maybe some don't ever recover.

Another thing that is interesting about this is that the powerdown that mel is doing
would force the shift registers to be zeroed out whereas a normal reset will just
interrupt the SPI operation leaving garbage in the shift registers.

I'd be curious if the issues you guys are seeing go away if you modify
the SS initialization code.

-- bill

Yep. I put them at the odd number positions. Worked the best that way. I tried spacing them out more but about 4 modules apart things started to regress...

Mel

bperrybap:
I decided to look at the initialization code some more.
(I'm still not convinced that there is a chip issue yet)

One thing that I did to ensure that the LOAD/CS is never driven low prior
to driving it high by swapping the initialization order to:

	digitalWrite(SS, HIGH);
pinMode(SS, OUTPUT);



I'd be curious if the issues you guys are seeing go away if you modify
the SS initialization code.

-- bill

Bill, I finally got some times to try out your suggestion. I modified the MD7219xx library as per your instructions. I'm using an official UNO, 24 Parola modules.

With the unmodified library, the 11th module would get exactly the same artifacts every time from a cold boot. A warm boot would not make the artifacts go away once they show up.

With the modified library, the 11th module showed the exact same problem. No difference what so ever.

Interestingly, I could swap out the 11th module with ANY other module in the chain, and the 11th module would still exhibit the problem using either the modified library or unmodified one.

I attached the scope shots from the CLK and LD lines at the 1st and 24th module.

clk_1st.png

clk_24th.png

LD_1st.png

LD_24th.png

My findings, running the eyes demo (which has always had the most 'artefacts' with my setup) and 22 Parola modules:

  • With no changes artefacts happened every time I cold booted and then get worse with warm boot. Multiple displays affected every time
  • Putting the NODECODE in the initialisation immediately cleaned it up and the artefacts. Cold boot, warm boot made no difference, they just don't appear.
  • Changing the order for the SS pin high made no difference without the DECODE.

Looking up the didtalWrite() manual reference:

If you do not set the pinMode() to OUTPUT, and connect an LED to a pin, when calling digitalWrite(HIGH), the LED may appear dim. Without explicitly setting pinMode(), digitalWrite() will have enabled the internal pull-up resistor, which acts like a large current-limiting resistor.

So I am guessing that this code

digitalWrite(SS, HIGH);
pinMode(SS, OUTPUT);

is not doing anything but setting the input resistor rather than setting the pin HIGH.
Update: I also found this, which answers my question

a pin that is configured to have pullup resistors turned on when the pin is an INPUT, will have the pin configured as HIGH if the pin is then switched to an OUTPUT with pinMode().

If only there was a way to 'reset' the 7219 chips without cycling power, I think we would have no problem...

marco_c:
So I am guessing that this code

digitalWrite(SS, HIGH);

pinMode(SS, OUTPUT);



is not doing anything but setting the input resistor rather than setting the pin HIGH.

Correct. It turns on the pullup which is very important in this situation.
The existing order causes the AVR pin to go from
floating to driven low to driven high.
The swapped order causes the AVR pin to go from
floating to pulled high to driven high.
It must be done in this order to ensure that the AVR does not clock the CS line on the 72xx
by first driving it low then high.

If you slow down the code, you can visually see garbage being clocked into the chips
on warm-starts as I would have expected without this change.
(In my case, when decode register is updated the garbage is cleaned up)

Setting the NODECODE fix ensures that the 72xx decode register is properly
set if it gets clobbered for some reason like the garbage writes that happen
when the SS line accidentally strobes by accidentally setting it low first.

Both of these fixes should be in the code.
The NODECODE being the more important one as it should initialize
the decode register to a known state which should correct
the issue created by the incorrect SS initialization order.
However, if the chip freaks out when register 0xD or oxE is written to,
then all bets are off if there is some other h/w glitch going
on that does this.

But at least by correcting the SS initialization order, it can ensure
that garbage somewhat random registers writes are not happening as
part of the initialization sequence.

wabbitguy,
I'm not understanding your scope diagrams.
I can't tell what the voltages are and where ground is.
If the clock signal is really undershooting ground, that looks like
ringing or a ground bounce problem.
i.e. are we seeing ground floating up, or are we seeing undershoot?

--- bill

bperrybap:
I'm not understanding your scope diagrams.
I can't tell what the voltages are and where ground is.
If the clock signal is really undershooting ground, that looks like
ringing or a ground bounce problem.
i.e. are we seeing ground floating up, or are we seeing undershoot?

I had all the measurement data turned off since I was looking at the raw signal coming out of the UNO, then comparing that against the signal at the end of the 24th module. Thus I moved the waveforms around on the scope (the clk was all in the top right quadrant on the scope so bottom of the trace is 0v). If you see a ground ringing problem in the clk_1st, then it's coming directly out of the UNO, and it is powered by a bench supply.

Mel

Ok, so still not believing there is any sort of chip problem,
I decided to dig a bit deeper into the s/w to see if there were any other s/w issues
since even though my displays seemed to no longer have initialization issues,
there were some funky pixel issues I had earlier seen during the initialization when I
had slowed things down that I never resolved.
So I REALLY slowed down everything and starting seeing the funky pixel changes again during
initialization after pressing RESET on the Arduino.
It all eventually seem to recover to work ok, but there shouldn't be any odd pixels.
It was REALLY odd, momentarily some pixels changed, some displays had pixels with different
intensities. Lots of funky stuff.
It was very repeatable. This was good!

So then I went back to pausing after each control() message and
noticed the funky pixel stuff had happened by the time the first
control message was done.
control(TEST, OFF);
(my pauses were after each control function call)
So now thinking there must be some sort of reset issue potentially
related to the led pin13 blinking (which is the clock line)
I hooked up the logic analyzer to see what the signals
going to the modules looked like to see what was going on.

First thing I noticed was WAY more messages being sent to the displays
than I expected.
(I'll get back to that later).

So after spending quit a bit time going down MANY rat holes,
I noticed that for the TEST/OFF command,
the commands being sent were the wrong ones!
I was seeing a string of DIGIT0, 0 commands (0x1, 0x0)
instead of TEST/OFF (0xf, 0x0)
Now we are getting somewhere!
Looking closer at the commands,
I had 7 displays but I noticed that there were 49 command being sent to set the test mode
on the 7 displays.
Seven bursts of 7 commands.
The command looked like:
six (d0/0) one (TEST/0)
five (d0/0) two (TEST/0)
four (d0/0) three (TEST/0)
....
seven (TEST/0)

It eventually turned out to be something really simple:
This code:

void MD_MAX72XX::spiClearBuffer(void)
// Clear out the spi data array
{
  memset(_spiData, SPI_DATA_SIZE, OP_NOOP);
}

Here is the prototype for memset:

void *memset(void *s, int c, size_t n);

So the code should be:

void MD_MAX72XX::spiClearBuffer(void)
// Clear out the spi data array
{
  memset(_spiData, OP_NOOP, SPI_DATA_SIZE);
}

The error caused the _spiData arrary to not be filled in with
the needed NOOPs.
So whatever was there was being used and since it is malloc'd
it can vary depending on the actual code.

After this fix, no more funky pixel stuff.

One thing that would be nice is if the code could be a little smarter and
send the commands to all the displays at the same time vs sending the
command to each display separately which requires sending NOOPs to all
the other displays.
This would reduce the number of commands sent from NxN to just N.

I'd be curious if others still see issues after all four s/w updates are incorporated.

  • the decode register
  • the SS init order change
  • the _csPin init order change
  • the memset() parameter order fix.

marco,
I am curious on one thing. The SPI code.
Any reason not to use the SPI library that comes with the IDE so that the code could work
on the non AVR platforms? Like chipkit or Teensy 3?
Anyway just wondering.

--- bill

After this fix, no more funky pixel stuff

I am staggered that the library worked at all reliably given that this clear function is called for EVERY comms cycle. Well done finding that! Thanks. Having fixed the problems with memset, DECODE does not seem to be needed any more.

This would reduce the number of commands sent from NxN to just N

Yes it would. The library is like that for historical reasons and it is time to address this inefficiency. Commands are rare compared to the number of other messages, so it was left alone at the time when there was a lot of other stuff to sort out and never came back to it. I have fixed this now.

Any reason not to use the SPI library that comes with the IDE

Nothing specific (I assume you are referring to the SPI.h library). I originally used the library but decided it would be neater (header files, better control) if the specific code was just included in my lib. The defines for SS, MOSI, SCK are from the Arduino header files.

Repo has been updated with revised library code.

Sure glad this works for you guys....because doesn't look one iota different here. Same artifacts as always. Maybe it just doesn't like having 24 modules online. To make sure my UNO wasn't haywire, I also tried 3 other Arduino UNO's I have.

Artifacts on 3, 11, 22. Changed the module order. Artifacts stayed in the same positions.

I'm going to test with less modules running when I get some time later today, see if there's a magic break point. And I'm going to throw a MEGA at it as well to see how that fairs.

Mel

Have you taken the latest from the source code section?

Memset was definitely wrong ...

marco_c:
Have you taken the latest from the source code section?

Memset was definitely wrong ...

No, I didn't. I assumed, incorrectly, that it was the usual download (the March date should have been the tip off but it was late; that's my excuse and I'm sticking to it). So I just now redownloaded from the source code and colour me elated!

All of my 24 modules work perfectly, as well as the 4 UNO's I've been testing with. Way to go Bill!

Good thing I can repurpose these power boards for other projects... XD

Mel

That's good news that it works for you as well.

The source code download will always be the latest working copy as I develop a new release, before the official release. The zip file releases include updated documentation. This applies for Parola as well. You can look at the history of the source code to see my check-in comments as to what has changed.

latest code works for me.
I clone the repo directly into my libraries directory so I can just pull in the latest code
and merge it into any local changes that I've made.

I'm currently playing with using some 8x8 fonts from my openGLCD library.
There are some slight issues that crop up when the font spacing is zero pixels.
But I've got the fonts up and working.

On the down side while playing with this, one time, I did run into some displays
that got stuck pixel rows just like what I was seeing before.
This happened after a download of some new code.
reseting or downloading new code would not fix it.
I had to power down everything to clear it. Not sure what is going there
as I would have thought the new initialization code should clear it up even
if some thing strange happened.
I can't seem to re-produce it.

--- bill

Marco I just saw all the new effects that you have added to your library and wanted to congratulate you on the great job you do with your library and the continual improvements you incorporate. I also see that you have Bill and a few of the other guys all enthused and hard at work too. Great job guys 8)

Dear sir, Can i expand this matrix vertically. If yes pls. provide demo video of the vertical expansion of displays in actions.

All I can Say is Thank You both Bill and Marco... I have 8 of the original and 20 of the square Ebay modules with the SMD 7219's (Leave it to CN to Phuck things up)... I had been using a digistump USB power switch [Really Handy] to clear my original modules... BTW I had the artwork reworked to triple the bus width for the common signals, CLK... and no joy... I'm not too sure I made a wise decision in buying 20 of the Ebay modules (the SMD ones)... But so far it really looks like a slight mistake in the initialization order... with the original Parola code... I haven't done much with the MD_72XX code yet. I have a 40 year history with H'ware but pointers are just becoming clear enough to read and understand... Not yet too sure about using them... I have to say that this has been a Very interesting project, Very educational in Many aspects...
Again Thank You BOTH for your hard work.. I own a Saleae Logic... Funny thing but it never occurred to monitor each I and O Vs the clock.. The scope pictures really look like capacitive loading is the issue... A lower value pull-up or some Fast buffering might fix that. However Sharp leading edge generally means an HP filter (faster rise time, sharp trailing edges generally mean a LP filter.. I use a Buono for testing as it has a switcher for the 5V output and a 7.5V wall wart or a 5A PSU adj to 7V out. THe USB switch seems to clear things up But it might take two or three attempts and I have noticed that as the modules are handled the artifacting will re-appear and is cleared by cycling the PSU via the power switch... I've been too busy to build a wooden box to hold two rails (90 Deg angle brackets 10" long) which will with some smoke acrylic for front and rear house both a Pro-Mini and the GPS for the time data... Etc. More latter.. Off to get the latest code.. and try it out. Sure beats an HT1632 though..

Doc

Can i expand this matrix vertically

You need to explain what you want to do. You can stack the displays on top of each other - that is just a physical layout.

If you want your software to operate as if it was a big screen, then you will need to handle the operations between the 'lines' of display. The ability to define zones has made this much easier - just define a zone for each line.

Built 8 modules from ICstation yesterday, and tried out an example sketche of the library. Works great. Thanks for the fantastic library :slight_smile: