Almost every micro-based project that I have designed in the past 25 years has had a flashing LED, originally as a “health” indicator, but the feature has expanded to use as a status indicator where the number and length of the flash can impart more information. This technique is very common in providing diagnostic information on low end products where there is only a single LED to provide communication. Devices like furnace controllers spring to mind.
click for larger image
Figure 1: An LED matrix controlled by an ICM 7218 LED Display Driver. I wasn't expected to provide any flashing with these LEDs. I just wanted to reinforce the point that you should be using a lookup table to map the physical outputs to the logical output. And yes, you have seen this photo before. I have used it in at least two other blogs! (Source: Author)
Figure 2: A controller for a standby diesel driven pump. Each pair of LEDs was connected in parallel for redundancy (a leftover requirement from incandescent lamps). It followed the normal annunciator format of flashing when an alarm was detected and continuously on when acknowledged - so no fancy flashing codes. (Source: Author)
On some occasions I have designed products with quite a few LEDs. Figures 1 and 2 show an early ones, but in a recent product (Figure 3) the customer wanted a simple multi LED display (instead of an alphanumeric LCD), and with it, the ability to flash them at different rates and codes. Fortunately only one was bi-colour and I treated it as two separate LEDs.
Figure 3. First protoype of a burner controller. There are 15 LEDs in total, down the right hand side. The STOP/RESET and START buttons along with the LEDs will be designed on to a membrane keypad and no doubt the resulting allocation of LEDs to the connector will not match the outputs that I selected initially. As it is, the customer has moved the relative physical locations of the LEDs twice since this photo was taken. (Source: Author)
The device shown in Figure 3 is a prototype with the intention of using a membrane keypad to implement the system in the future. For those of you who have never worked on a real live system, let me tell you a secret. Whatever pinout you select to drive the LEDs, it will change at least once over the life of the project. In this case above, the LEDs are driven from individual ports on the micro, but they could just have been driven from an LED controller as shown in Figure 1. The approach is to write a driver that includes a lookup table so that the logical outputs can be mapped to the physical outputs and subsequently shuffled around with the changes being made in only one place. If that’s all you take from this blog I would be satisfied, but there’s more advice.
Where I have only used one LED to convey information, I have never really been consistent and often re-wrote software from scratch as the presented information differed. The code would consist of separate blocks to flash the LED under normal circumstances and then some code to vary timing and number of flashes. I never figured out a simple approach until now. Quite obviously I am slow on the uptake and maybe this is a well-known approach and I re-invented the wheel (not for the first time). Perhaps there is an even simpler approach - but here goes.
I created an array of 15 32-bit variables. Each element of the array corresponds to a particular LED (there being 15 of them). I chose an update timer of 100ms which seemed to me optimal for the eye to detect and register especially when trying to count flashes. At each timer “tick” the processor looked at each bit of the element of the array in turn. If the bit was set, the LED was turned on, and conversely if the bit was cleared the LED was turned off. (Please note that this is done via the aforementioned lookup table). This would give me a cycle time of 3.2 seconds (32 * 0.1). If the LED was to be continuously illuminated, the concomitant variable would be set to 0xffffffff. Three short flashes could be 0xa8000000, and one long and 2 short could be 0xf0a00000. In my case the processor would have to analyse all 15 variables at each timer tick.
I think I can even turn this into re-usable code! Who’d a thunk you could write a whole blog on the blinky LED?