I love LEDs. They are the best invention since sliced bread. I mean think about it - you have this tiny little device that costs pennies, consumes next to no current and can display 8 bit color. Naturally, I have always been envious of NYC’s giant color display. Last winter break, I had the idea of a panel which would be a small LED display. The interesting thing about this display is that you would be able to connect multiple together into a larger, arbitrarily sized and shaped display matrix. At the time, I was on a Perlin noise kick, so the coolest thing I could think of to do with them was to display 3D perlin noise, and possible add snake and pong. After 4 months of working on this project, I have refined it a bit. I’m not exactly sure how this post will go - it won’t really be a good judge of my other posts because the goal of this will be catching you up to my current status. Hopefully you will be able to see my thought process as I went about designing this. I will try to point out various issues I ran into along the way, as well as things that I’ve learned through this. (For posterity sake, my original post about this project is on the AMP Lab website - https://sites.google.com/a/vt.edu/amp_lab/current-projects/modular-led-panel)
I went into this project confident that I could finish it (or at least get something working by the end of the semester), but with very few firm ideas of how to proceed and knowing that I would be learning quite a bit. My first go at a task list is as follows:
Research and decide upon LED driver setup
There are a few options: usePWM directly from a microcontroller, use separate LEDs and driver chips, or use LEDs withPWM drivers inside.
- My inclination is that PWM directly from the microcontroller is not feasible because I am planning on driving something on the order of 64 LEDs on each unit.
Separate LEDs/driver chips
- Possible chips: WS2811, TLC5952
Integrated LEDs/drivers
- Possible chips: WS2812
Decided upon size of unit, and SMD/through hole LEDs
Research and decide upon a microcontroller
- Must determine the overhead of the LED driving, and how much of the computation for the display must be done on chip as opposed to sending data from an external computer.
Research and decide upon communication standard between themicrocontrollers
- Currently I am thinking about either UART or SPI, though I need to research both of these more fully.
Design PCB board
Build/iterate through the design
Design a nice enclosure for the units
This has actually been quite accurate. I am currently in the build/iterate stage - with my third revision headed off to the PCB manufaturer soon. The only changes I have made were some decisions that I either left out or globbed into other steps (into the generizied research steps).
Jumping In
I went into this project with a few ideas in mind: I did not want to multiplex the display (mostly because I thought that this would adversly effect the brightness levels), I wanted each module to have a decent number of LEDs on it (greater than 32, but not exactly sure how many), and I wanted the display to be decently dense. I realize this is pretty subjective, but as I went through the design process I firmed up ideas and made educated decisions based on my initial opinions.
The first decision I made was that I would have 64 LEDs per module. This was arbitrary, and decided because 8 is a nice number with electronics. Also, many LED drivers are meant to drive some multiple of either 4 or 8. Next, I began googling for LED drivers. There were one or two that I knew about - including the chips used in Adafruit’s NeoPixels (WS2812 is the chip I believe). I found a handful of possibilities - mostly made by TI. The list included: TLC59711, TLC5971, TLC5947, TLC5951, TLC5952, and the WS2812.
I elemenated the TLC5952 fairly quickly, as it does not support PWM (a simple, though potentially disastrous oversight in my research). The WS2812 was elemenated because of the somewhat complicated communication protocol as well as the 5V logic levels - I had in mind a few 3.3V devices to look into, and choosing an LED/driver which limited me to 5 volts or a voltage level shifter was not an acceptable option. The TLC5971 and TLC59711 were basically the same chip (I still can not figure out the difference between them), so this left me with 3 chips to choose from. Between the 47 and the 51, the 47 was less versatile (does not have dot correction or brightness control, limits data input to 15MHz, and only operates in 12-bit mode) so I dropped the 47.
The 5971⁄59711 is a nicer chip - one main difference is it operates with 16-bit color, and it uses a slightly differnt PWM scheme. The PWM scheme is called ES-PWM, and I am curious to try it out to see if it actually makes a difference. I am willing to see, but am unconvenced as of yet. I will most likely use this in one of my upcoming projects. However, I decided against using this chip for this project becuase the extended color depth increased the amount of data that I would be sending across the display (of course I could have sent less data, but then what is really the point of using a 16-bit chip if you don’t use the entire range). Also, it doubled the number of chips that I would have needed.
So this left me with the TLC5951. There are two packages available for this chip - a 40-QFN and a 38-TSSOP. I had originially wanted to go with the QFN, but when I was looking to order the chips, there were non in stock at any distributor. So I went with the TSSOP.
Alphabet Soup (AKA Communication Protocols)
If you want the whole scoup about this, there is a fairly in depth discussion on the original page. What follows is basically a TL;DR of that 2000+ word discourse. And no, I’m not exagerating.
While I was researching this, I would take breaks to think about the communication protocol. My original thought was that I would use either SPI or UART and basically cascade the devices. I however wanted to look into other protocols and methods. The protocols that I have run into are I2C, CAN, SPI, and UART. I actually developed an interesting methodology to use CAN for this, however ended up trashing it because CAN limits the speed too much. Each panel that I add needs 192 bytes of data to completely describe that panels entire color, plus a few bytes for control. Lets be generous and round up to a maximum message size of 200. Given this size, the speeds at which CAN can run, the amount of overhead per message for CAN, and the maximum message size, the largest number of panels which I could have connected and be able to update at 60Hz is 5. That is not acceptable - I wanted to be able to connect hundreds of these modules together, and if not hundreds then at least tens. So I tried the same thing with I2C, and a similar problem arose. Both of these protocols were out, and I was back again to SPI and UART. Both SPI and UART can run at speeds which were acceptable to me, however it was recommended to me to use SPI because UART becomes unreliable at high speeds. So SPI it was.
Microcontrollers
With both of those decisions out of the way, I decided it was time to tackle the next big decision. Which microcontroller do I use?
I had experience with Arduinos (basically AVRs with some goodies attached to them), and with PICs. I don’t really like Arduinos - they work, but are a pain if you want to do anything remotely complicated. Don’t get me wrong, they are great for what they do. However I didn’t want their software interfaces getting in my way. And if you aren’t using the Arduino software, then what’s the point of using an Arduino? Also, as a side note, the Arduino IDE (if it can even be called an IDE) is one of the worst IDEs I have ever used. I honestly prefer a text editor to that. As for PICs, my only main issue is that the documentation and support suck. The IDE is pretty bad as well, but they have improved since MPLAB 8.
The basic requirements for the microcontroller were: it needed at least 5 hardware SPI (this turned out to elemenate nearly all of the microcontrollers out there), and it had to be able to run the SPI interfaces fast enough (once again, arbitrary subjective measurement eventually backed up by math and objectiveness), and the lower the pin count, the better. A little more explination about these requirements is in order I guess. So the 5 hardware SPI comes from 4 to go between each of the possible connected boards, and one to talk with the LED driver chip. Fast enough means that the communication speeds would not meaningfully limit the size of the display. Given the number I mentioned previously (200 byte maximum message size), a speed of 50MHz would limit the display to ~500 modules, and 25MHz to ~250 modules with an update frequency of 60Hz. These were acceptable limits to me (this made the limiting factor power distribution), and so I looked for microcontrollers which could operate their SPI in this frequency range. The only one which I found with the required number of hardware interfaces was the PIC32MZ line - microchips new line of 32 bit PICs. They were complete overkill for the project, however at the time they were the only ones I thought would actually work. The smallest package they came in that I have the ability to soler is a 100-QFP.
This chip did not end up working out though - once again because of supply issues. (I think that I had to reselect nearly every single part for this project because of lack of supply). So I went back to the drawing board. At this point, someone suggested looking into the MSP430 line of microcontrollers. At first I was not sure if these would work. They have two different types of communication modules - TI calls them Universal serial communication interfaces type a and b. There were some which had 3 and 4 of both types of modules, but it took a while before I found anything mentioning using both types simultaneously. Also, the highest speed you can run these at is 25MHz. After searching around, I ended up choosing the MSP430F5438A - once again complete overkill for my project. It has 8 SPI (these can also act as other things, but SPI is all I really cared about for my purposes), runs at 25MHz, has nearly 90 GPIO (some of which are multiplexed with other functionality). And most importantly, it was in stock. To program this, you either need to buy a fairly expensive programmer (on the order of 100 dollars), or buy the F5 launchpad (~13 dollars) and a cheap connector cable and you are set. Needless to say, I went the launchpad route. I also decided to use a cool cable from tag-connect which reduced the programmer footprint by quite a bit - though the cables are fairly pricey.
Making Some Arbitrary Decisions…
I went into this project wanting to directly drive every single LED. The reason for this was that I was afraid that multiplexing would reduce the brightness to unacceptable levels. However, one huge issue with direct drive is the current required can be quite large. In my case, each LED runs at a maximum of 20mA (and because there are basically three LEDs in an RGB led package, this means 60mA per “pixel”). 64 * 60mA = ~3.5A per panel, which is a lot. Think staring into the sun brightness levels. One option would have been to reduce the current levels which I was going to pass through the LEDs, however I did not want to do this - reducing the current going through the LEDs also limited me in other ways. Another option was to switch to multiplexing. In addition to reducing current consumption per panel, it also reduced the number of LED drivers which I needed. I have already mentioned the supply chain issues I had run into. Given those, I decided that the slight increase in complexity was worth the benefits that multiplexing brought.
I couldn’t decide on a final size until I had actually drawn up the schematic and starting laying out components, but I wanted to have an idea or a goal in mind before starting. To this end I drew up some layouts and sizes on a white board. After spending a bit of time looking at sizes and drawings, I decided that somewhere in the 3 to 4 inch range worked well for me. It was large enough that I thought I would have room to route everything, but still small enough that the LEDs weren’t absurdly spread out. I knew that I would be SMD LEDs, but didn’t really know what size until I looked through digikey and picked out a specific LED.
At this point in the project, I also had the idea for a controller board. The purpose would be to allow connection of external controllers or external connections. It would basically convert between different types of protocols (my original idea was Ethernet -> SPI so that you could connect it to a network, but it would work for anything sufficiently fast). This idea is still not fully flushed out as it has been put on the back burner until I am able to get enough boards ordered that I could actually play with this.
And Some Not So Arbitrary Ones
I actually learned a lot about bypass capacitors through this project. I guess boiling it down to the essentials it went like this: The purpose of bypass caps is to reduce noise which arises in power lines or planes. In order to be effective at this, they must be positioned as close to the power pins as possible. When you are using mutiple values and sizes of caps, the smaller packages and values should be closer to the power pins than the larger ones. Capacitor value really depends on the types of noise that they will have to handle. In general, larger valued capacitors handle lower frequencies and smaller valued capacitors handle higher frequencies. The package contributes to the capacitors ESL and ESR - different sizes have different effects. I ended up choosing to go with a 10uF capacitor in a 0603 package, and a .1uF capacitor in an 0402 package. I then hated myself as I assmebled the PCB, but that’s a different issue.
At this point, I had made most of the major design decisions (at least in regards to or affecting component choices). After finishing choosing the components, the next thing to do was to draw up the schematic and lay out the PCB. To choose the rest of the components, I asked people for recommendations on what they knew worked well and searched through digikey for components meeting my requirements. Here is what I came up with:
- LED Driver Chip: TLC5951
- Microcontroller: MSP430F5438A
- LED: CLV1A
- MOSFET: SI2316DB
- MOSFET Driver: TC4452
- Voltage Regulator: LP2989
The next thing to do was go through the datasheets and draw up the schematic. This is when I settled on capacitor and resistor values. I am still not happy with my connector solution, they are extremely expensive compared with the rest of the board. I feel like there is a better solution out there, but haven’t found it yet.
Wrap up
So far, I made quite a few of the major decisions about the board. I have decided upon most of the major components, determined the inter panel communication protocol, have an idea of a control board, and have an idea of a physical size to aim for. This is all that will be in this part of the series. Next post will be about the schematic and PCB layout.