Multiple 8x8 LED Matrix Control with MAX7219
Duane Degn
Posts: 10,588
Another thread to document my latest hacking.
A while back erco once again forced to purchase stuff off ebay I didn't really need. First it was some little 8x8 red LED arrays and then he posted a link to the arrays which included a MAX7219 and a small PCB to attach everything to.
Below is a picture of one of these PCBs and array (cost less than $3 shipped).
I hadn't used a MAX7219 before but I have driven LEDs arrays with shift registers.
It was a lot of fun figuring these MAX7219 chips out. The datasheet actually made sense as I read through it. The people who write datasheets must have gotten better at it. Five years ago when I first started my journey into hobby electronics the datasheets were all very confusing. Well I guess practice makes perfect and the guys writing datasheets have finally had enough practice.
I've cleaned up the program a bit from the version I posted in erco's thread. I moved the MAX7219 control portion into its own object. The SPI driver is all Spin but it's fast enough to scroll text.
Here's a demo video (same one as in the other thread).
I plan to add some sort of feature to use these as robot eyes (as Dickel on LMR has done).
I'll probably wait until I add a few more features before adding this to the OBEX. I looked around for a Propeller project which uses a MAX7219 to control an 8x8 array but I could only find 7-segment examples.
If any of you use this object, I hope you let me know. It's always fun to learn when someone else is using code I wrote.
I'll add some details on how to use the program in the following posts.
Let me reserve the first six posts of this thread so I can add updates and other information in an easy to find location.
If there isn't code similar to what is attached here on my on GitHub, send me a message and I'll make and check for any improved versions of the code.
Edit (July 19, 2016): The code attached to this post is not very good. I believe the arrays are ordered incorrectly. Use a later version of the code.
A while back erco once again forced to purchase stuff off ebay I didn't really need. First it was some little 8x8 red LED arrays and then he posted a link to the arrays which included a MAX7219 and a small PCB to attach everything to.
Below is a picture of one of these PCBs and array (cost less than $3 shipped).
I hadn't used a MAX7219 before but I have driven LEDs arrays with shift registers.
It was a lot of fun figuring these MAX7219 chips out. The datasheet actually made sense as I read through it. The people who write datasheets must have gotten better at it. Five years ago when I first started my journey into hobby electronics the datasheets were all very confusing. Well I guess practice makes perfect and the guys writing datasheets have finally had enough practice.
I've cleaned up the program a bit from the version I posted in erco's thread. I moved the MAX7219 control portion into its own object. The SPI driver is all Spin but it's fast enough to scroll text.
Here's a demo video (same one as in the other thread).
I plan to add some sort of feature to use these as robot eyes (as Dickel on LMR has done).
I'll probably wait until I add a few more features before adding this to the OBEX. I looked around for a Propeller project which uses a MAX7219 to control an 8x8 array but I could only find 7-segment examples.
If any of you use this object, I hope you let me know. It's always fun to learn when someone else is using code I wrote.
I'll add some details on how to use the program in the following posts.
Let me reserve the first six posts of this thread so I can add updates and other information in an easy to find location.
If there isn't code similar to what is attached here on my on GitHub, send me a message and I'll make and check for any improved versions of the code.
Edit (July 19, 2016): The code attached to this post is not very good. I believe the arrays are ordered incorrectly. Use a later version of the code.
Comments
Scrolling Text on Four ICStation Arrays
The software used in the above video is available in post #3. (This is the same video as the one used in post #9.)
Here's a new version of the code.
Notes about version 140116e (uploaded January 14, 2014):
This will scroll the text sideways instead of just vertically.
A video of the software in use is currently uploading to YouTube.
This software is not finished. It can scroll text but not much else.
See post #9 for more information.
Notes about version 140128d (uploaded January 28, 2014)
I added methods to make it easier to plot points and draw lines.
Lots of changes to the child object.
Still no "eyes" support. I hope to use these arrays to display eyes on robots.
All graphics methods only use displays one array deep.
See post #32 for more information.
The MAX7219 requires 16 clock pulses to update 8 bits. For applications where you'd want to use PWM on the various channels, a normal '595 would provide better resolution than the MAX7219.
I can tell from my limited exposure to the '7219 chip, I wouldn't want to use it my RGB LED array project.
The MAX7219 certainly has its advantages and I'm very glad I've learned how to use it but it's another tool to add to the tool kit not one that will be making other tools obsolete.
Edit: The MAX7219 particularly has the advantage over '595 chips if you didn't want to have to continuously refresh the LED array. The MAX7219 doesn't require one to dedicate a cog to continuously updating a multiplexed LED array.
Thanks for posting your code and videos.
- Ron
Here's the video showing the new code in action.
This latest version allows the text to be scrolled horizontally. The original arrays from ebay could only be set side by side if the text were scroll vertically (which looked horizontal when the group was rotated). It turns out it's a lot easier to scroll thing vertically with these arrays. Adding coded to get it to scroll horizontally was harder than writing the vertical scrolling code.
The new column to be added is held in a byte but that byte needs to distributed among eight other bytes.
I don't think I'm clear on which bits in the buffer correspond to which position on the array. I should add some code to be able to control the individual bits so I can make sure I know which bit corresponds with which location. As it is, it seems like I had to scroll the individual characters opposite to the way I was expecting. The text scrolls correctly, but I don't have a clear understanding of why.
One thing that has become clear as I've tried these various displays it I don't think I have a clear understanding of how the pixels relate to the bits that get clocked in the MAX7219 chip.
I don't think my code is currently safe to trust for any important applications.
While the code might not be "safe", it's still fun. I should have a video of the small arrays soon.
I got the five MAX7219 boards I ordered (the ones with the DIP chip) and soldered them all up.
Ordered them on Dec 27 and got them today.
I used your Max7219Demo131226c.spin code to test each board and they all worked.
However, sometimes when I power up the propeller, all the LEDs are lit and stay lit. If I hit the prop' s reset button as I power up, it usually works properly but not always.
I am using 3.3V to power the array (from my Propeller Demo board). Do you have any idea why I am getting this strange behavior?
Are feeding 5V to the arrays or 3.3V?
Thanks,
Ron
P.S. I tried your Max7219Demo140116e.spin code with two arrays cascaded and it works fine...
This kept happening to me also. I think the test register gets set. It needs to be set to zero. The latest version of the driver I'm currently working on includes a command to set the test register to zero.
In the "Init" method of the child object is the following code:
If you add the code below, the arrays should flash on and off (more than one array will cause an alternating flash).
I'm powering the arrays with 5V. The arrays can pull a lot of current in test mode. The small arrays (0.8" x 0.8") use about 700mA each in test mode. The MAX7219 gets hot fast when using a lot of current.
I'm convinced my attempt at having the chip on the same side of the board as the arrays with my 0.8" x 0.8" PCBs was a bad idea. The 16 array PCB will have the MAX7219 on the back side of the board like the ICStation boards.
I can cascade three arrays but it won't work with four or five. I am using your code from 01/16/14.
I thought it might be the voltage regulator I was using so I switched to a DC-DC Step Down converter that should handle it - no luck...
I am using Parallax cables for CS,CLK and Data but use a breadboard for the power and ground to each board.
There's a constant in the child object that also needs to be changed:
I don't see a reason why I used it. I'll remove it from future code.
I think I originally planned to have the buffer in the child object but instead included a pointer as part of the Init method.
You can set "MAX_ARRAY_ALLOWED" so some very large number without causing trouble.
My arrays have not all worked flawlessly. For a while I couldn't only get two of my ICStation arrays to work and then they all started working again.
I do keep find things I had been doing wrong so hopefully I'll eventually get this code reliable.
I changed the video to "unlisted".
Changing the MAX_ARRAY_ALLOWED didn't seem to help either. Maybe I've got some loose connections or cable noise/interference.
I'll keep experimenting.
Thanks for your help.
P.S. If I leave the code set for 4 arrays and just remove the left array, it displays the text properly like it was set for three...
Not a code issue it seems
Shouldn't the code to initialize the MAX7219 registers be shifted to every MAX7219 in use or do I misunderstand?
EDIT: I read your comments in the ShiftOut routine and think I better understand how data is cascaded thru the arrays!
Would this code update the registers in all the ICs?
Thanks,
Ron
As you can see when the test pattern is shifted out, whenever you shift data to one array, the previous data gets shifted to the next array in line.
The code is far from finalized but there are several different methods for sending data to the arrays. ShiftOut will send data to the closes array to the Prop but each new ShiftOut call causes the previous data sent using ShiftOut to be sent to the next array in line. You see after all the ShiftOut calls with real data are ShiftOut calls to register zero. ShiftOut calls to reg 0 forces the previous data to make its way through the chain of arrays.
To send data to multiple arrays at once the method "ClockOut" is used in conjunction with controlling the latch (CS) line.
As I mentioned, the ShiftOut method only sends data to the nearest array (with the previous data being sent on to the next in line). There also a method "ShiftOutSingle" which allows data to be sent to an individual array. "ShiftOutSingle" uses ClockOut together with Reg 0 to get the data to the desired array.
This was one aspect of the MAX72019 that took me a bit to come to grips with. The way data gets propagated through the line of arrays has a lot to do when the CS line gets toggled. If the CS line is toggled after a single register packet, then that packet will make its way down the chain as each new packet is received.
You'll notice at the end of the setup section, I use:
This forces the last data to be shifted out to propagate down the line of arrays.
You probably noticed the propagation as the test command gets shifted out. As the new command to turn off the test register is sent the command to turn on the test register moves on to the next array in the line. If you added a pause after "ShiftOut(0, 0)" you'd see the test pattern (all on) slowly propagate down the line instead of suddenly turning off.
Sorry the code is such a mess. The newer code (not yet posted) is even worse but it includes more features. I think I'm finally understanding which bit in which register corresponds to which LED on the displays.
I'll try to get my more recent code cleaned up enough to post later today.
I know there are various sources of info on the MAX7219 (luckily) - I can 't imagine trying to control this IC strictly by using the datasheet!
Thanks again!
P.S. Still trying to figure out why I can't get a fourth and fifth array to work... What a puzzler
One thing I'd suggest is just set the test register to zero. Multiple arrays turned all the way on (when test register is set to one) seems to cause communication problems. I think the high current causes brownouts in either the Prop or the MAX7219 chips.
Have you tried changing the order of the arrays?
Even with the number arrays set to one, you should see output on additional arrays as the data gets pushed from one array to the next.
Yes, I added the code you mentioned earlier to toggle the test register (you can see it in my video).
I wrote numbers on the back of the PCBs and swapped them around to see if any were defective. It works with any three boards.
When I add a fourth board the results are erratic. I tried a different propeller board too - no change.
I have powered the LED arrays with a separate LM2940 voltage regulator which should handle 1 amp.
I also tried a DC-DC converter (with a 7.5AH 12V gell cell) which should handle over 2 amps.
Setting ARRAYS_IN_USE to 1 works with 3 arrays but not with four.
Maybe I should make cables like you did rather than the breadboard.
- Ron
My recent suggestion was not to toggle the test register but to just set it to zero so all the LEDs on multiple arrays wouldn't be on at the same time.
One of the arrays I was using used 700mA while the test register was on. I still think this is the source of your trouble.
A couple of arrays with the test register set on can easily pull more than 1 amp. I'm surprised your 2 amp supply didn't let you add an array or two.
Unless you have bad contacts on the breadboard, I don't see why it should be a problem.
When you change the code to set the test register to zero, you might want to connect each array one at a time to the Propeller (and reset the Prop with each new array) to make sure all the test registers are cleared. If multiple test registers are set, they might interfere enough to keep the Prop from clearing the test registers.
Made no difference unfortunately. I'm going to pull it apart and rewire the array connections.
Here are pic showing the connections Parallax cables are used for CS, CLK and Data (white,red,black) and the breadboard power wires are VCC (red) and GND (orange). The green wire is the common ground between the propeller and the breadboard.
Removing the far left array and just connecting a Parallax cable to the top (output) side of the third array makes it fail.
Remove the extraneous cable and it works. (Doesn't make any difference if the wire ties are removed)
A capacitance issue with the Parallax cables?!?
I suggest just using the long Parallax cables on the data line and move the clock and CS lines to the breadboard (with short wires).
The data line gets driven from each chip but the clock and CS lines are only driven by the Propeller. It doesn't matter which end of the board the clock and CS lines are connected and they only need to be connected to one end. Using shorter wires to connect the clock and CS lines might solve the problem.
If shorter wires doesn't fix the issue, you might want to try a level shifter to drive the clock and CS lines at 5V.
Solved!
I used individual wires for the DATA IN/OUT connections between the modules rather than the Parallax ribbon cables - not really much shorter.
Maybe the wires in the ribbon cable are too close together and caused interference.
Thanks Duane!!!
That's great! You're very welcome.
It's cool to see five arrays in a row like that.
The problem wit the long data lines has got me a bit worried about the 16 array PCBs I just ordered.
I think there may be several of us attempting to make arrays with 8 of the small arrays across. I hope the data lines leading from the end of one row to the beginning of the next row don't cause a problem.
I wonder if ICStation was on to something when they turned every other row of arrays upside down in order to keep the data lines short?
I hope the long data lines don't cause too much trouble because it would make the software side of things harder if the arrays alternated between right side up and upside down.
I've seen threads where someone has made it easier to use the ROM font on small displays. It would be nice to have the font automatically scale based on the number of pixels available.
Do you have a preference between the two fonts in the current program? I think I'm partial to the "Free Design" font I found on the internet. I think it's a bit easier to read than the SimplyTronics font when the text is scrolling quickly. The SimplyTronics font (borrowed from their RGB 8x8 array) uses less current than the Free Design font and I also think the SimplyTronics font looks more formal than the other font.
There sure are a lot of things to consider when you design your own boards and if you screw-up it's money down the drain. I hope your boards aren't problematic.
I wonder if using small shielded cable (like thin microphone wire) would be helpful when connecting individual boards...
I actually like the thinner font (guess that is the SimplyTronics one). It could be fun to tweak them - maybe italics. Kinda limited with 8x8 pixels though.
My arrays sometimes act funcky after running a while - I need to make up some better/shorter cables.
I'm sure you spent a lot of time on the spin code - I need to study it carefully. It's been a while since I've used spin...
You could obviously use relays to connect/disconnect the DOUT to DIN pins between modules while having each DIN pin hooked to a different propeller pin.
It would be nice if you could do it without relays though...
Do you want individual control to overcome the problems caused by the long data line?
One way to do this is to use multiple instances of the child object. Nope, that would require separate clock and CS lines too.
Most (two) of the other MAX7219 controlled arrays I'm aware of, have the data in line right next to the other module's data out line so the long data lines are much of a problem (except when moving from row to row). If the row to row data lines are a problem, I'll probably use ICStation's suggestion of turning the odd rows of arrays upside down.
Would you want to arrays to behave the same as they do now but with separate data lines?
I don't think it would be too hard to use separate data lines. I'll take a look at the program to see what would need to be changed.
After looking at the program a bit, I think there are two different approaches that would work.
One way would be to clock the data out to each array one at a time. Only one array would receive useful data at a time and the other arrays would receive data to the zero registers (since the low data line would cause all zeros to be shifted out to the arrays). This approach would be the easiest to implement and the data would be send just a little slower than with the arrays all linked together.
The other way to do this would be to send data on all the data lines at the same time. I've used this approach with some of my '595 LED projects. The programming on this is more involved but it would likely results in the arrays being updated faster than the conventional method. I'll probably give this approach a try later in the day.
Here's the beginnings of the new method to send data to multiple lines at once. So far the only thing I've changed are the parameters used when calling the method. These parameters might give you an idea of what I have in mind.
My thinking was to control the leds in a graphics sort of fashion rather than displaying ascii characters so that what displays in one array can be independent from the others but then if you want to switch back to cascading text, you could do it programmatically without changing the wiring.