P2 brightness FAQ

From Evil Mad Scientist Wiki
Jump to: navigation, search

This article is adapted from an FAQ on our old, archived forums.

Peggy 2 and its derivatives are hackable open-source LED "pegboard" matrix displays capable of displaying fast animation on up to 625 LEDs. We've seen some remarkable things made out of these-- signs in car windows, multiple Peggy boards connected and used as a giant scrolling message display, live video streaming from a webcam, LED end tables, a marriage proposal, giant RGB LED matrices, and hundreds of LEDs on long skinny wires going every which way.

Some popular questions come up about Peggy 2:

  • Why do some LEDs flash super-bright during programming?
  • How can you get higher brightness?
  • Why is Peggy hard to photograph?

These are connected questions, and so it's helpful to address them together. To do so, it's necessary to understand how the Peggy 2 works, what design choices were made, and why.

The Peggy 2 is a low-power multiplexed display. That means that fundamentally (and while you can't tell by looking), only one row of LEDs is lit at any instant in time. In the normal mode of operation, the microcontroller sends out four bytes of data to the LED driver chips, to set which LEDs in the first row will be lit. The demultiplexer chips are used to activate the transistor that turns on power to the first row of LEDs, so that the selected LEDs in that row are lit up. Then the next row's worth of data is sent out and the next row is lit. And so on, to light the full display. This process can happen very fast-- usually redrawing the full screen more than 1000 times per second. To the eye, it appears that every LED is lit at the same time.

A multiplexed display has definite advantages and disadvantages with respect to other types of LED displays. The obvious alternative-- a "non-multiplexed display"-- would use 25 pairs of LED driver chips-- one pair for each row. That's an overestimate, because you actually only need 40 LED drivers (40*16 bits = 640 bits). But compared to that, how does multiplexing stack up?

Advantages of multiplexing:

  • Compact. Four driver chips + 25 transistors + 25 resistors takes up much less circuit board real estate than 40 LED driver chips.
  • Easier to assemble. Four driver chips + 25 transistors + 25 resistors => 4*24 + 25*3 + 25*2 = 221 pins to solder. 40 LED driver chips => 40*24 = 960 pins to solder. (Each chip also has a resistor and capacitor, so perhaps 1120 pins would be a better estimate.) All in all, this would mean that there are more things to solder outside the LED matrix than in it.
  • Low power. Driving one row of LEDs at a time takes about 20 mA*25 LEDs = 500 mA. That makes it possible to run off of a low-cost 1 A power supply or even off of batteries. Driving 625 LEDs at a time takes about 20 mA * 625 LEDs = 12.5 A of current. That requires a desktop PC class power supply. Not cheap or compact or even quiet, usually. It requires special connectors or terminals that can handle the current as well.
  • Low heat. If you deliver 60 W of power to the Peggy, it's mostly dissipated as heat at the LEDs and the LED drivers. While the LEDs can handle it, we might well need to go to an aluminum clad PCB and/or cooling fans and/or a much larger circuit board to deal with the driver chips. The multiplexed display, in contrast, only gets hot on the driver chips, and it's not usually necessary to provide special considerations for cooling.
  • Low cost. The Peggy 2 kit would likely cost 3-4 times as much without multiplexing. This is due to (1) component costs (2) printed circuit board costs (size, complexity -- i.e. number of layers, number of holes, copper weight, thermal issues all increase dramatically) and (3) power supply. As this begins to approach commercial LED video displays in terms of cost and component count, it is debatable how much merit there would be in actually pursuing a kit design like that.
  • Fast and Flexible. The Peggy 2 uses fast LED driver chips and software multiplexing, which leads to a remarkable degree of flexibility in how the display is used. Certain types of data can be displayed to the screen with refresh rates measured in the tens of kilohertz. By scanning the full matrix quickly, many times with different data, you can make a 60 Hz display with 16 levels of gray. By turning off the full screen redraw, you can light up an individual point or a few with intensity well in excess of what you can get through standard multiplexing. It's just software: you can change between all these models (and many more) on the fly.

Disadvantages of multiplexing:

  • More complex to control. Rather than just sending out a long stream of data, multiplexing requires addressing each row separately, sequentially. This is particularly true versus a non-multiplexed display with PWM ( "gray scale" ) LED driver chips, that can display many shades without sequential refresh. This is a tradeoff versus the higher speed of addressing individual locations in a multiplexed display; PWM chips are particularly slow in that regard.
  • Low power. As only one row is lit at a time, the total power available to drive the LEDs is much lower, and the brightness is correspondingly lower as well. A multiplexed display like the Peggy 2 is generally not suitable for outdoor display applications, except at night. (Usual caveats about weatherproofing apply as well.) One compensating factor is that it's possible to get much more brightness out of today's ultrabright LEDs than those just a few years ago.
  • Dead time between rows. When switching between rows, the matrix turns off for a small but finite time. This introduces a small loss of brightness, which may be larger or smaller depending on the mode of refreshing the display.

Why is Peggy hard to photograph?

A camera shutter (or just exposure time on a digital sensor) is open for a certain interval of time to make its exposure for a photograph or frame of video. So long as this duration does not evenly line up with the amount of time required to scan through all of the rows -- and it won't -- you won't get even exposure. The solution is to use a fairly slow shutter speed, so that several scans through the whole display are recorded for each shot.

A separate problem is that LEDs are just hard to photograph in general. This is because the dynamic range of most camera sensors is very far below that of the human eye. Humans can experience very bright colors as, well, very bright and intense colors. A camera on the other hand, will only see extremely bright colors as being very bright -- it's common to find that sufficiently bright red, green, or blue all look white. If you want to photograph LEDs and capture their color, you'll need to use a very low exposure value, that makes it look as though the LEDs are very dim. Tough tradeoff.

About those flashes during programming:

When the Peggy 2 first turns on, or during programming, the LED matrix is not scanned, and so usually will be one or two rows that are basically on *all the time* -- dumping the full power of the matrix into one or two rows. It's very bright, and you might naturally think, "how can I turn up all the LEDs that bright?" But you can't-- and the reasons should be pretty clear once you understand how the Peggy works. (So tantalizingly out of reach, isn't it?)

Brightness considerations

A. Hardware.

The LED drivers on the Peggy 2 are constant-current drivers, which deliver to each *lit* LED a constant amount of current, pre-set to be 20 mA, or lower if the trimpots are adjusted lower. The current limit for the left half of the board (columns 0-15) is set by the series sum resistance of RA1 and VR1 (or just RA1 for older Peggy 2 models), and for the right half of the board by the series sum resistance of RA2 and VR2 (or just RA2 for older Peggy 2 models).

On versions with the trimpots, the total resistance range (in each half) is 1 k to 6 k, which gives a current setpoint range of 20 mA to 5 mA (or so). These are provided to allow lower current use for longer battery life. For highest brightness, you may want to solder a wire across the three pins of the trimpots to short circuit them, guaranteeing that the resistance is pegged to 1 k.

The relationship between the resistor value and the current setpoint is given in the LED driver chip datasheet. Lower resistance values will result in higher current, up to a maximum of 90 mA or so, depending on the exact chip variety. The 20 mA setpoint that you get with the 1k resistor is suitable and safe for nearly any commercially available LED variety, and it's chosen for that reason. Most LEDs are capable of tolerating 25 or 30 mA continuously. If you know that all of your LEDs are rated for 25 mA or 30 mA, you can certainly go right ahead and replace those two 1 k resistors with 780 ohms or 650 ohms to set the current limit to one of those values, respectively. Adding 30% more current is an easy way to get (roughly) 30% more brightness in most cases.

What if you want to go higher? Setting a current limit beyond 30 mA is not an "officially supported" modification-- for reasons that we'll clarify in a moment --but is worth mentioning since Peggy is designed to be hackable, after all.

Most low-power LEDs, i.e., those rated for 20-30 mA of continuous forward current, also have a "pulse current" rating. Typically, that's something like "100 mA, 10% duty, 0.1 ms max" -- in other words, that the LEDs can handle 100 mA, but only for 100 microseconds at a time, and only if they are turned off for 90% of the time when they're doing this-- But, that's just the kind of operating conditions that a multiplexed LED array produces! In other words, LEDs are usually are designed, tested, and specified for use in a multiplexed LED display. So the LEDs can usually handle it even if you turn up the LED driver setpoint to 90 mA. That gives you (potentially) more than four times the brightness. BUT, there is still a problem: that bright row when you turn on or during programming. That is to say, there are times when the matrix can stop scanning-- either due to those factors or due to your programming --when it could dump more current into the LEDs than they are rated for. (Also note: the 2STX2220 transistors are rated for 1.5 A continuous. If you drive 90 mA into 25 LEDs that's 2.25 A, but it's generally safe so long as you keep scanning-- they have a similar ability to handle peak currents up to 3 A. Also note: You'll need a beefy power supply that can source up to 2.5 A continuously if you want to do this. Also note: Your LED driver chips will get hot. You may need to use a cooling fan on them.)

So: turning up the current to a level where it's no longer safe if the matrix stops scanning is possible, but do so at your own risk. There are creative ways to reduce the risk, e.g., putting the current limit resistors on switches, or removing the chip before programming (on a separate board), or programming the chip through the ISP connector and removing the bootloader to avoid the 2 second delay before operation. However, these methods are still fundamentally risky.

B. Software.

As we've mentioned, the multiplexed architecture leads to tremendous flexibility. The standard Peggy2 Arduino library implements only one of many, many possible ways to drive the matrix. The method implemented is a straightforward general purpose monochrome full-screen refresh. It's something of a lowest common denominator: Easy and useful for most applications, but probably optimal for no application at all. There are instead significant performance gains to be had in a number of different directions. What you should learn from what follows here are some of the factors to consider when designing a program for the Peggy 2.

The simplest examples tend to implement a scheme like the following (in pseudocode):


While technically correct (and usually very easy), this is actually suboptimal in a number of ways. One of the big ones is that there is significant dead time. During the computation stage, the LEDs are simply *off.* If no computation is needed, or if there are ever *delays* in the computation stage, that's simply wasted time that could have been used to produce light instead. Slightly more subtle is this: There's dead time in redrawing the same thing on the screen ten times. Rather than displaying every row of the display ten times, it would be better to display each row of the screen once, but for ten times longer-- that would save a significant amount of dead time, while still probably being fast enough for any given application. The standard refresh takes an amount of time of order 1 ms (give or take)-- drawing at 1/10 that speed still gives 100 Hz refresh; pretty good for most applications, and you can squeeze a few more drops of brightness out in the process.

A better, but more involved way to approach this would be to do something like:


Such a scheme can be implemented through raw scheduling (like this) or through an interrupt routine. Either can be implemented even from within the Arduino environment, and there are a number of example programs and alternative libraries that use these sorts of schemes to get higher brightness and more uniform refresh. One worth calling out by name is the RGB Peggy example sketch. (A number of other example codes exist, and we can provide additional help in the forums as well.)

The big win here is from having the LEDs *on* while doing computation, rather than *off*. A second, smaller win can be had by optimizing the refresh rate to be as slow as possible while still acceptably fast (acceptably non-blinky), so as to minimize the row-switching dead time.

In certain circumstances, a big win in brightness can be obtained by reducing the degree of multiplexing. Suppose, for example, that you want to draw a bouncing ball that's 10 pixels in diameter. Obviously, there will never be a case where more than ten rows are lit at a time. In a case like that, it does not make sense to refresh the entire 25 rows. Rather, you should just refresh the ten rows that are active-- giving you an automatic factor of 2.5 increase in brightness.

Any application where it's known that fewer than 25 rows will be used at a time can benefit from this type of trick. Taking it to an extreme, if you have an application that only uses LEDs in one row at a time, you can turn off scanning entirely, and dump the full power into that row. A neat demo app based on this is one that just turns on one random LED, somewhere on the board, for 50 ms each-- but with full brightness.