Main Site Documentation

LED 32x32 matrix design


#1

Hi,

im thinking of building my own led matrix display either 32x32 or 16x32 it will depend, can someone comment, if this is the right path, or is there a better way?

I was thinking of using a 12V input, switch the voltage to 3.3V so that each led can be powered independently and use shift registers to control them. LED’s will be 5mm, so the display will be big. There are some driver IC’s for such stuff but never used one?

Also if I was to store 0’s and 1’s in a 16x32 array would that work? and how well would that work with the G120’s internal EEPROM using this:
https://www.ghielectronics.com/community/codeshare/entry/756

Lastly if anyone had done that what are the power considerations that I need to be aware of, id want it reasonably efficient as it will be powered by a 12V battery.


#2

Google “Charlieplexing”

For efficiency, drive with a PWM signal will lowest usable duty cycle


#3

@ Darko - Well, I’ve tried sofar to start it with just a CerbuinoBee (168MHz) and the result is somewhat, well there is room for improvement.

My next try is to let the LED Matrix be controlled by the Arduino with just 16 MHz. I’ve seen it working with a Teensy, RPi, Arduino, even an STM32F401 but all with compiled code.

So I recon RLP has to be called to the resque, ehm, dunno, never done before …

The code is pretty simple, maybe to … any performance tips are more than welcome …

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace conPortTest1
{
    public class Program
    {
        // Define port easy readers
        // Data
        static OutputPort Red1 = new OutputPort(LedMatrix.Data.RedOne, false);
        static OutputPort Red2 = new OutputPort(LedMatrix.Data.RedTwo, false);
        static OutputPort Green1 = new OutputPort(LedMatrix.Data.GreenOne, false);
        static OutputPort Green2 = new OutputPort(LedMatrix.Data.GreenTwo, false);
        static OutputPort Blue1 = new OutputPort(LedMatrix.Data.BlueOne, false);
        static OutputPort Blue2 = new OutputPort(LedMatrix.Data.BlueTwo, false);
        // Row selectors
        static OutputPort Row1 = new OutputPort(LedMatrix.Rows.First, false);
        static OutputPort Row2 = new OutputPort(LedMatrix.Rows.Second, false);
        static OutputPort Row3 = new OutputPort(LedMatrix.Rows.Third, false);
        static OutputPort Row4 = new OutputPort(LedMatrix.Rows.Fourth, false);
        // Controls
        static OutputPort CLK = new OutputPort(LedMatrix.Control.Clock, false);
        static OutputPort LAT = new OutputPort(LedMatrix.Control.Latch, false);
        static OutputPort OE = new OutputPort(LedMatrix.Control.OutputEnable, false);

        // Arrays to put the RGB info into 
        static Int32[] RedBuffer = new Int32[32];
        static Int32[] GreenBuffer = new Int32[32];
        static Int32[] BlueBuffer = new Int32[32];

        // Working vars
        static Int32 _Data1;
        static Int32 _Data2;
        static Int32 _Data3;
        static Int32 _Data4;
        static Int32 _Data5;
        static Int32 _Data6;

        // Some test data to display
        #region TestData
        static Int32[] DemoDataRed = new Int32[32]
            {
                0x00000000,
                0x00000000,
                0x22FBE8BE,
                0x22808DA0,
                0x00000000,
                0x2AE088B8,
                0x268088A0,
                0x00000000,
                0x22F888A0,
                0x00000000,
                0x00000000,
                0x00000000,
                0x02113810,
                0x15114454,
                0x0E114038,
                0x3B9138EE,
                0x0E110438,
                0x150A4454,
                0x02043810,
                0x00000000,
                0x00000000,
                0x00000000,
                0x0E000000,
                0x11000000,
                0x01000000,
                0x02000000,
                0x04000000,
                0x08000000,
                0x1F000000,
                0x00000000,
                0x00000000,
                0x00000000
            };

        static Int32[] DemoDataGreen = new Int32[32]
            {
                0x00000000,
                0x00000000,
                0x00000000,
                0x22808DA0,
                0x00000000,
                0x00000000,
                0x268088A0,
                0x00000000,
                0x00000000,
                0x00000000,
                0x00000000,
                0x00000000,
                0x02000010,
                0x15000054,
                0x0E000038,
                0x3B8000EE,
                0x0E000038,
                0x15000054,
                0x02000010,
                0x00000000,
                0x00000000,
                0x00000000,
                0x001C1000,
                0x00223000,
                0x00225000,
                0x00221000,
                0x00221000,
                0x00221000,
                0x001C7C00,
                0x00000000,
                0x00000000,
                0x00000000
            };

        static Int32[] DemoDataBlue = new Int32[32]
            {
                0x00000000,
                0x00000000,
                0x00000000,
                0x22808DA0,
                0x32808AA0,
                0x00000000,
                0x268088A0,
                0x228088A0,
                0x00000000,
                0x00000000,
                0x00000000,
                0x00000000,
                0x00113800,
                0x00114400,
                0x00114000,
                0x00113800,
                0x00110400,
                0x000A4400,
                0x00043800,
                0x00000000,
                0x00000000,
                0x00000000,
                0x000000FC,
                0x00000080,
                0x00000080,
                0x000000F8,
                0x00000004,
                0x00000084,
                0x00000078,
                0x00000000,
                0x00000000,
                0x00000000
            };
        #endregion

        public static void Main()
        {
            Debug.Print(Resources.GetString(Resources.StringResources.String1));

            // Fill the buffers
            for (int i = 0; i < RedBuffer.Length; i++)
            {
                RedBuffer[i] = DemoDataRed[i];
                GreenBuffer[i] = DemoDataGreen[i];
                BlueBuffer[i] = DemoDataBlue[i];
            }

            // Copy the data from the buufer to the matrix
            //while (true != false)
            //{
            loop:
                // For all rows
                for (int idy = 0; idy < 16; idy++)
                {
                    // Copy the the first and the 16th row to  
                    // the one and two data channels per color
                    _Data1 = RedBuffer[idy];
                    _Data2 = RedBuffer[idy + 16];
                    _Data3 = GreenBuffer[idy];
                    _Data4 = GreenBuffer[idy + 16];
                    _Data5 = BlueBuffer[idy];
                    _Data6 = BlueBuffer[idy + 16];
                    // Now shift the bits into the data channels last bit first
                    // Get bit 31 down to bit 0
                    int q = 0;
                    int tmp = 0;
                    for (int idx = 0; idx < 32; idx++)
                    {
                        q = 1;
                        q = q << (31 - idx);
                        tmp = RedBuffer[idy] & q;
                        Red1.Write((_Data1 & q) != 0 ? true : false);
                        Red2.Write((_Data2 & q) != 0 ? true : false);
                        Green1.Write((_Data3 & q) != 0 ? true : false);
                        Green2.Write((_Data4 & q) != 0 ? true : false);
                        Blue1.Write((_Data5 & q) != 0 ? true : false);
                        Blue2.Write((_Data6 & q) != 0 ? true : false);

                        // Force a falling edge
                        CLK.Write(true);
                        CLK.Write(false);
                    }
                    // Set the appropriate row active
                    Row1.Write((idy & 0x01) != 0 ? true : false);
                    Row2.Write((idy & 0x02) != 0 ? true : false);
                    Row3.Write((idy & 0x04) != 0 ? true : false);
                    Row4.Write((idy & 0x08) != 0 ? true : false);

                    // Latch the info through
                    LAT.Write(true);
                    LAT.Write(false);

                    // Wait for a bit and do an output enable cycle
                    OE.Write(false);
                    Thread.Sleep(1);
                    OE.Write(true);
                }
            goto loop;
            //}
        }
    }
}

#4

If you wanted to get fancy, you could also try using something like this chip. It would almost certainly require a custom PCB, though.

http://www.digikey.com/product-detail/en/LT3746EUHH%23PBF/LT3746EUHH%23PBF-ND/2621411


#5

That’s going to be your main issue as they tend to draw a lot of power depending on the number of LED’s that at on at any one time. I’ve just ordered a 63 x 32 RGB display from Adafruit to play around with and it draws 4A at 5V when fully lit up.

LED’s and efficiency really don’t go together so not sure how long you want it to run on a 12V battery and what size your battery is?


#6

It would be nice to have some sort of tristate mosfet or something.


#7

Shoot … now I have to get native (RLP) it can’t be that a simple Arduino Uno on 16 MHz is beating a 168 MHz Cortex-M4 in performance … those interpreters, it’s always the same, they can’t do things fast enough … one has always to ask help from the native side …

Well, I’ve got some spare time … wish me luck …

Oh, BTW the clock is now at .1 us/div so at about 300 ns with 20% duty cycle …

Edit: It is so stable I could even take a picture instead of making a liitle video …


#8

Umm.

“If a single LED fails, by becoming either open-circuit, short-circuit, or leaky (developing a parasitic parallel resistance, which allows current in both directions), the impact will be catastrophic for the display as a whole, and furthermore the actual problematic LED may be notoriously difficult to identify”

“one or two burned-out LEDs, whatever the mode of failure, will almost certainly cause a catastrophic cascade of unintended lightings of the LEDs that still work, very likely rendering the entire device completely and immediately unusable”

ill pass on this, and figure something out


#9

@ Darko - first time I have heard about paranoid electronics


#10

that’s what it says here:


#11

@ Darko - catastrophic is a bit strong for a failed electronic component like a led display. Unless you led display is used for guiding airplanes coming in for a landing, a failure is just a failure.


#12

A simplistic explanation … hope it helps


#13

ok, that explains it a bit better, now I just have to figure it out, ill post when I have updates.


#14

If you haven’t checked them out, the little panel “backpacks” made by “Nootropic” and sold by adafruit (link below) are great for those 16x32 and 32x32 panels. They use a small dedicated arduino to drive them…but it is simple to wire up the chip to a gadgeteer u socket to the RX/TX pins, add a little serial based command set to the arduino code of the backpack, and you have a versatile 16x32 or 32x32 gadgeteer panel module (with the gadgeteer board freed up from having to refresh the thing)

I made such a panel module for a netduino last year. I let my 7 year old script shapes and misc graphics to it from .net …it would be just as easy for a spider/cerberus/hydra


#15

Im actually more interested in how the 16x32 panel is made, I wouldn’t need RGB LEDs but White coloured 5mm ones, with PWM ability. I though about using 74HC595, but no PWM control then.


#16

Instead of software PWM, you could try Binary Coded Modulation:

or

or

but it all comes down to one site:

http://www.batsocks.co.uk/readme/art_bcm_1.htm