Miniature LED beacon for LEGO

The aim is to make a revolving police light style beacon as small as I can so that it could be used with LEGO (contained in a clear brick). Ideally I’d like to be able to animate the LEDs using PWM to simulate a real revolving light source including inertia during power up and maybe some additional flashing effects.

Here’s a what I’m working on, 8 1206 SMD LEDs charlieplexed on a 10mm disc.
(Blue LEDs on top, Red on Bottom)

Ok, first problem. I’ve got no LEGO here in Spain… It’s all at my parents place in the UK.
So I can’t do any measuring or trial fitting of bits and bobs.
Never mind, for the moment I won’t bother trying to make it to fit specifically for LEGO, I’ll just try and make something as small as I can. Once I have a good prototype up and working I can get some bricks and have a go at fitting it all in.

I’ve got a whole bunch of surface mount LEDs around the house as I seem to keep buying them whenever I go on eBay. I can’t help myself, they’re bright and shiney!
If I couple them with a bit of clever wiring I should be able to drive quite a few LEDs with just 4 pins, this means that I could use one of the tiny 6 pin PIC10f series or maybe an 8pin PIC12f if I need a bit more memory as the 10f are pretty limited, typically having 1/2kb of program memory and just 24 bytes of RAM.

I started out thinking that I could tie 4 LEDs together with a common cathode and use 4 pins to drive them, but then I started to think that I wanted more LEDs to allow me more colours but that would require more pins so I decided to use a technique called Charlieplexing.

Charliplexing is a clever way of using the tri-state outputs of the PIC (or other uC) to drive large amounts of LEDs from a small amount of output pins. You connect all your chosen output pins so that each pin is connected to every other pin with two LEDs, one in each polarity.

The formula is LEDs = PINS * (PINS -1)
2 Pins = 2 LEDs : 2 x (2 - 1)
3 Pins = 6 LEDs : 3 x (3 - 1)
4 Pins = 12 LEDs : 4 x (4 - 1)
5 Pins = 20 LEDs : 5 x (5 - 1)
6 Pins = 30 LEDs : 6 x (6 - 1)
8 Pins = 56 LEDs : 8 x (8 - 1)

So with just 8 pins and a lot of wire you could drive 56 LEDs!

It uses that fact that PIC outputs can be either high, low or high impedance (input) combined with LED’s minimum working forward voltage to allow you to light any one LED at a time. With a suitably fast update rate we can make it appear that many or all LEDs are lit just like traditional multiplexing but with less wires. Any way rather than re-explaining the wheel, you can find out more in this article, How to control multiple LEDs.

To reduce the amount of LED packages and to make the wiring easier I wanted to try and find some dual colour SMD LEDs. They’re dead easy to find in standard 5mm leaded package but not at all easy to find in SMD. I also wanted Red/Blue colour mix which made things even harder again. I could find some references to suitable parts online but not anywhere that actually sell the things. So for now I’ll stick with single color LEDs.

I also thought that it would be a good idea if I could mount the LEDs vertically rather than horizontally to save space.

Here’s my first attempt on a bit of spare prototype board.


Not so good. It’s bloody hard to solder tiny 1206 components “freehand” without a proper PCB to mount them. So It’s time to break out Eagle and knock up a quick circuit layout.

At this stage the idea is just to create a prototype to test the idea and to develop the software.

Here’s my prototype circuit with just 8 LED’s and a connector to keep things small and simple. I’ll add some 150R resistors at the PIC end of the circuit, 150R being a trade off between what the red LEDs want and what the blue ones would prefer. Either way, I’ll be charlieplexing the LEDs so they’ll only be lit for 1/8th of the time.


Here’s the layout for a small (1cm dia) double sided PCB.


The layout is the same on the bottom, Red LEDs on top, Blue LEDs on the bottom joined together by a 4 pin .1″ pitch connector.

I arranged the print out as 2 rows (one for each side of the board) of four layouts separated by a couple of centimeters with a line printed down the center line as a guide to fold by. Printing out 4 at a time makes it easier to handle the paper and also happened to fit quite well on a bit of copper board I had handy.

I made the board using my normal toner transfer technique the difference was that being a double sided board you have to be careful to get both sides aligned as closely as possible. This is made easier by having the both sides of the board on a single sheet of paper (folded) as it give a solid reference point to work with, assuming you fold it accurately in the first place.

Printout and copper board with toner transferred after etching. Strip of board is approx 2cm x 6cm. Note only a single group of four layouts shown in this test print.
Close-up after cleaning and drilling with a 0.6mm bit. This is the back
side of the board so you can see my alignment isn’t too bad really.
Actually one end of the board was better aligned that the other so I’ll
pick the best layout and work with that.
Cut out and rounded off with a needle file.
Soldering the red LEDs, held down on my board with a couple of pins.
LEDs are normal 1206 flush mount packages, but I’m mounting them
sideways so that light will be emitted out the edge of the disc.
Soldering the blue LEDs on the other side. You can just see the green dots
that indicate the cathode of the blue LEDs and the Anode of the Red ones.
LEDs are arranged back to back so that red LEDs run in one polarity and
blue ones in the opposite direction.
Finished device with 4 pin connector acting as a
via to connect both sides, 2cm x 1 cm overall size.

Now that the hardware is made its time to connect it up to my development board and write a simple routine to get the thing flashing.


My development board. PIC18f2525 at 20Mhz. It’s overkill for this project, but I had it handy and it’s nice to write for a big fast easy target early on before trying to optimize things.

Software approach;
As usual I’m coding using the microchip C18 student edition. I’m also using the tinyBld bootloader to speed up development.

The tri-stated-ness of a port pin is managed by two port registers, TRIS and PORT, eg. TRISB PORTB for manipulating PortB. TRIS sets the pin to be either an high impedence input (when TRIS=1) or an output when TRIS=0, PORT sets the output to be either high or low (vcc or gnd) when TRIS is set as output. (TRIS = 0). This gives us our three states, Hi (vcc), Lo (gnd) and Nada (High impedance).

I have 4 output pins and I need to store both output state and tri-state condition (PORT & TRIS) for each LED which is 4 bits of information for each. Luckily this can be packed quite nicely into a single byte for each LED. So I’m using an array of 8 x chars (one 8bit char for each LED) with the 4 high bits representing the PORT and the 4 low bits representing the TRIS. This keeps things small and neat and means that I’m already thinking of only having 1/2Kb to work with even though on this chip I have loads of room.

I created a simple function called ledOn() to “un-pack” this data by shifting and OR’ing it with the current port status so as not to effect the 4 pins I’m not using (RB0-3). It uses the array to look up the TRIS and PORT states for the LED number you require. I set TRIS to all inputs before modifying any values to ensure that all LEDs are dark whilst the changes happen. Then just before exiting the function sets the relevant TRIS bits to light up the required LED.

void ledOn (unsigned char ledNum){
   unsigned char tmp;
   //reset all charlie pins to high impedance (input) no LEDs lit now.
   //calc output status : use masking to retain b3-0
   tmp = (PORTB & 0b00001111) | (charlieBits[ledNum] & 0b11110000);
   //set output status : No LEDs lit cos TRIS is set all high impedance
   PORTB = tmp;
   //calculate tris : Use mask to retain b3-0
   tmp = (TRISB & 0b00001111) | ((charlieBits[ledNum] << 4) & 0b11110000);
   //set tris : LEDs should now light.
   TRISB = tmp;

(WordPress seems to mangle any code I try to post by removing all spaces from a <code> block… Arse!)

Back to the circuit.

The prototype circuit is pretty simple if you ignore all the basic stuff that is part of the development board like the 232 converter and reset circuitry etc.

I have a button connected to RA5 that controls spin or no spin, and a plain ole LED attached to RA0 to act as a heartbeat to let me know the program is running.

I also have TX and RX (RC6 & RC7) connected back out to my PC for a bit of debugging.

The charlieplex LED thingy is connected to portB pins RB4-7 with 150R resistors inline on each pin. This gives each LED a series resistance of 300R (150 on each end) which is a trade off between the correct value for the Blue LED and the Red LEDs which work at different forward voltages. However, it works ok and the even when static the current is only around 10ma, so nothing to worry about. The only thing that may need to be solved is the relative brightness between the red and blue LEDs. From my previous LED Clock experience I now know that blue LEDs appear so much brighter than red ones even if you drop their current to a fraction of the reds. I might be able to sort this in software though by using a longer PWM period for the blue leds to reduce their on time in regards to the red.

You can download my code from here if you are interested. It compiles to around a 15 Kb HEX which is in great part due to libraries I’ve included for ease of development rather than any useful code. Stdio.h alone is huge with all it’s fancy string formatting that makes debugging so easy. Having a nice big overspec’d PIC like the 2525 makes this all nice and simple. I’m sure writing for a 10f would be a completely different game!It’s not the best C code you’ll ever see, in fact if any one has any tips for me I’d love to hear them as I’m still finding C a bit of a mystery, especially the whole organization of header files and incs…

Finally. What does it do right now you might ask…

Here’s a short video.

The next stage is to write some decent code;

Things to do

  • Move LED driving code into interrupt routine to maintain consistency and avoid glitching.
  • Use PWM to control brightness and to balance red/blue intensity.
  • Create a “spin up” “spin down” effects to simulate inertia of a real revolving reflector.
  • Create additional effects such as bright flashes and counter rotating red/blue lights.
  • Actually build the thing to run on a tiny PIC such as 10f or 12f
  • Find someone who will sell me some 1206 SMD bi-colour red/blue LEDs

Not much eh!
Until later…

As always, leave a comment if you found this interesting, let me know you are out there.

Update : I’ve got some Lego now!

9 thoughts on “Miniature LED beacon for LEGO

  1. Pingback: Little flashing lights « Catmacey’s stuff

  2. Hello,
    I found your project very interesting. I was looking at your code and 1 thing I was amazed about is that you do not have any goto statement as stated in tinybld website. I am still looking for how to translate the
    ORG 0x0000
    goto main
    into C18 statements.

    Well anyways keep up the good work.

  3. Hi Nandish,

    When I first started with tinyBld I was worried about having to set a goto too. Every other bootloader seemed to need some modification or another. But I found that it worked perfectly with the hex file from c18 without having to make any TinyBld specific changes.
    I have tinyBld v1.9.5, you can download the .asm and .hex that I’m using here for the bootloader for pic18f2525 : 20Mhz : 115200rx

  4. Pingback: Mini LED Lighthouse | only hacks

  5. Nice police light. Does anyone know how i can get a PIC18F4520 working with tinybld? or a ready built asm file? please…


  6. hello
    i like your lighthouse project , i do it on test board , but i using instead single leds rgb leds with 4 legs .(cathode common)
    the effects are very nice , like a firefly .
    try it your self
    i have a question >for what is button ?what can i do with the button ?
    thank you

    • Hi Puiu,
      Glad you like the circuit. I’ve used the button as a start/stop for the beacon. Rather than just cutting the power pressing/releasing the button causes the circuit to spin down/spin up as if it had momentum like a real rotating beacon. But you could use it for anything really. I thought about making it switch modes between different flashing patterns or directions but never got around to writing that code.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s