Since price is such an important consideration, more time is put into reducing costs than if only one unit was to be made for fun. The smallest, cheapest CPU that can do the job is used, and as much of the work is done in software as is possible. The circuit is designed to run the desired number of LEDs with as few pins of CPU I/O as possible.
The generally accepted method of controlling as many LEDs as possible with a fixed number of output pins is called "Charlieplexing" (because it was invented by a fellow named Charlie). It relies on the fact that LEDs only work if power is applied in one direction across them, combined with the fact that if you flash lights very fast, your eye thinks they're on constantly. It also uses the fact that microcontrollers can put their output pins into THREE different states - on, off, and disconnected.
A downside to Charlieplexing is that the software to drive it is a lot more complicated than simpler solutions that use more wires.
I've used Charlieplexing in the past, but for this particular blinkie I didn't need to drive that many LEDs, 9 to 12 was all I really wanted. This also greatly reduces the complexity of the software. What I used is basically the same thing but I've left out some of the more complex cases that are normally used to get a few more LEDs running.
Here's the circuit that I used for this blinkie:
Before I go further, I should point out that I am well aware that this circuit SHOULD have resistors in series with all the LEDs. However, I am taking advantage of the fact that not only can the CR2032 battery not source more than about 120ma and the CPU can't sink more than that much anyway, the LEDs are only on at maximum about 1/4 of the time, so on average the maximum current rating of the LEDs is not exceeded.
This circuit should NOT be taken as an indication that you can just hook LEDs up straight to power without limiting the current to them in some way. You will fry LEDs if you hook them up to a power source that can deliver more than their maximum current.
You can see that the nine LEDs are set up in three groups of three. The top LED in each group I refer to as bank 0, the others banks 1 and 2. To drive bank 0 (LEDs 0, 1 and 2), pin 7 (PB2) on the chip is set to low (ground), and pins 5 (PB0), 6 (PB1) and 3 (PB4) are set high for each LED that is to be lit.
After a bit of time, pin 7 (PB2 again) is changed to high (+voltage), and the other pins are now set LOW for each LED that is to be lit - note that for instance D3 is hooked up exactly like D0 but backwards.
After some more time, pin 7 is set to floating (it's not either ground or +), and instead pin 2 (PB3) is set to low and one more bank of 3 is driven in the same way. A fourth bank could also be driven on PB3 but nine LEDs is all we want for this circuit.
In order to test a circuit out, it's assembled on a solderless breadboard. In this case two circuits are built. The one on the right in the photo is the circuit above, the one on the left is just the wiring for the USB programmer that is used to flash the software into the chip. The bare circuit board in the front with the cable, and the one on the breadboard that the cable goes to is the USBASP programmer. The large green block is a programming socket, the chip is moved all the way to the left to program and to the right to test. The battery and switch are at the far right.
After the circuit is proven to work, I will lay out a circuit board for it. There are several pieces of software that will do this, I currently use KiCAD which is free and open source, and works about as well as the previous software I used, EagleCAD, but without the limitations of EagleCAD.
After completing the design, I sent it off to a place that specializes in making small run prototype boards called OSHPark. They produced a mock-up of what the board will look like by processing the production files I sent them. This is the image they sent.
While one way to control the brightness of an LED is to control the amount of current passing through it, that is complex and usually wasteful (the energy that does NOT go to the LED is usually burned as heat). Instead, almost all LED brightness control is done by turning the LED on for only a very short period of time. I will get into describing the LED driver software in the next post.