Controlling Your Festive Lights with the .NET Micro Framework


Author: Rob Miles:
Download: Download
Software: Visual Studio 2008 Express Edition or better,
.NET Micro Framework 3.0
Hardware: Digi Connect-ME
GHI Electronics Embedded Master
Devices Solutions Tahoe II
Time Required: 3 hours
Cost: 30 dollars for lights plus the .NET Micro Framework device

The Micro Framework is one of the newest kids on the .NET block, but it does something really rather wonderful. It brings embedded development within the reach of any C# programmer. If you know C# and love Visual Studio, you can now get started building hardware and controlling it with your software. Moreover, it lets developers achieve one of their most cherished dreams, to control their festive lights using programs that they have written. This project shows you how to do just that and adds an extra magical feature, in that you can make all your festive lights flash red whenever I, Rob Miles, make a new post on that most famous of blogs,

Actually, you can modify the code so that you can make your lights do most anything in response to an event that happens on the web. You could signal home that you are running late, send the weather forecast to your Christmas tree or explore any number of communication options. You might decide that this is so useful that you leave your decorations up all year round.

If you just want to play with the .NET Micro Framework and get a feel for how easy it is to create software for tiny devices you don't actually need to use any extra hardware at all. The project comes with a complete emulation of the lights display so that you can run the whole thing on your computer and learn how hardware and software can be made to work together without burning your fingers with a soldering iron.

However building the hardware will give you an understanding of how some simple electronic components can be controlled from C# and even how serial and parallel data transfer works. It is also great fun.

To get started you will need some hardware and some software. Let's take each in turn.


Processor Hardware

The .NET Micro Framework lets you run C# programs on tiny embedded devices. There are a number of these available today, and they are getting progressively cheaper. You can base this project on any.NET Micro Framework device that has a network port and three or more output ports. The ones I'd recommend are:

I built the project for Digi Connect board but the code can be customised for any of the above platforms. The beauty of the .NET Micro Framework is that you hardly need to change your program even if the underlying hardware is completely replaced. The only thing you will have to do is adjust the code to target different output pins. I'll flag this part of the program up when we get to it.

The project as supplied runs on a special emulator that runs on the PC and behaves like a .NET Micro Framework device with lights connected, so you can get started exploring the code right away.


I'm keeping things deliberately low voltage for this project. This means that kids of all ages can have a go at building the hardware without messing around with mains. The lights that I used were supplied as lines of twenty leds wired up as four strands of five leds each. All the leds in each strand were the same colour. The lights were fitted with a little battery box which held three AA batteries and a tiny controller. To get my display I simply removed the battery box and connected the strands to my hardware.

Figure 1: My Battery Powered Lights

You can do the same with any low power lighting kit that you wish to use. The drivers that I'm using can handle around 500 milliamps of continuous current and so you can connect a fair number of lights to each strand.

Buying the Lights

The lights I used can be bought in the UK from Lights4Fun: and are called "C-LED-4.5-M 20 Multi Coloured Battery Operated LED Fairy Lights". They are supplied with a battery box and controller that you can remove to connect to the Darlington drivers. I used an old 5 volt mobile phone charger to power the lights. If you search eBay for "led christmas lights battery" you should find plenty of suppliers.

Driver Hardware

We can't connect a .NET Micro Framework device directly to our lights. There are two reasons for this:

  1. The Micro Framework device will not be able to switch the amount of current that we need to drive the lights themselves.
  2. The Micro Framework device will not have enough outputs to control all the lights that we want to use.

This means that we need to make some hardware that goes between the processor and our lights. I actually don't see this as a problem. Making hardware is great fun, seeing something that you've built spring into life is very nice. The hardware we are going to use will provide a means by which we can control many hundreds of lights from a single Micro Framework board if we wish. It also has the ability to switch reasonable amounts of current, so you can use quite large numbers of lights if you wish. We are going to use two semiconductor components, a CD4094 Shift Register/Latch and a ULN2803 Octal Darlington Driver. A pair of these chips will allow us to control 8 outputs. If you want to control more outputs you simply get more chips and chain them together. For my version of the project I just used one of each chip, you can use as many as you like.The shift registers and Darlington amplifiers can be obtained in the UK from Maplin: The chip numbers and part numbers as are as follows: QW54J 4094 Shift Register, QY79L ULN2803A Darlington Driver. In the US you can obtain the components and breadboard from Digi-Key:

Serial and Parallel Data

You might be wondering how we can use just three output lines to control lots of lights. We are going to do this by using the three output lines to provide a serial data stream which is converted by our hardware into parallel data that can be used to control our lights. This is a fundamental principle of digital electronics and is how, amongst many other things, computer networks transfer data.

We are going to use three signals which are called clock, data and latch. Each of these can be set high (a voltage is present) or low (no voltage is present) by the .NET Micro Framework device under the control of our software. The signals are connected to the clock, data and latch inputs of our CD4094 shift register so that the program can talk to it.

The clock line triggers the shift register to do two things:

  1. Shift all the bits along to make room.
  2. Sample the value of the data input and store this value in the space that was created.

To get a feel for how this works, take a look at Figure 2 below. It shows a shift register with a pattern of bits in it. The pattern is 01100001. Note that although this represents a number; it can also be regarded as a pattern of 0s and 1s in the shift register itself. The value 0 means 0 volts and the value 1 means some volts. These are the signals that will be used to control our lights. I'm going to call them 0 and 1 from now on. The Shift Register has Clock, Data and Latch signals connected and they are all set to 1. We can ignore the latch part of the chip for now.


Figure 2: A shift register and latch with some data in it

When the clock signal changes from 1 to 0 this causes the shift register to perform the two steps described above. First the data is shifted along to the right. Note that this means that there is an "empty" location at the start of the register, and that the right most bit in the register "falls off" the register and disappears. Figure 3 shows how this works.


Figure 3: Shifting along the values in the shift register

Once the shift has finished the shift register can copy the data signal into the empty bit at the left as shown in Figure 4 below.

Figure 4: Storing the new data bit

By repeating this process 8 times a program can load a new pattern of 8 bits into the shift register. Then it is time to latch the new value to control the lights. This is the point at which the lights will appear to change. When the latch value is changed from 0 to 1 this causes the chip to copy the value in the Shift Register into the latch, as shown in Figure 5 below.


Figure 5: Copying the shift register pattern into the latch.

The latch is required so that the lights will not flicker as the new patterns are shifted into position. Each of the bits in the latch is connected to an output pin on the CD4094 which is used to switch a particular light colour on or off.

We need to create some C# that will provide the appropriate sequence of signals. It turns out that using the .NET Micro Framework to achieve this is actually very easy. The displayByte method below sends an 8 bit value into a shift register and then latches it into the output. If you read through the code you can see how the clock, data and latch values are all set to true (high) or false (low) to first clock the data out and then trigger the latch to display the pattern on the lights. The input is an 8 bit byte value and the program uses a mask to pick out the value of each bit in turn and set the data output accordingly.

private static void displayByte(byte value)

    byte mask = 1;

    for (int i = 0; i < 8; i++)
        if ((value & mask) > 0)
        mask <<= 1;

The dataPort, clockPort and latchPort variables are instances of the .NET Micro Framework class OutputPort, which provides a method called Write which can be used to control the state of the output signal. We will consider how these are created a little later in the article.

The sample code for this project comes with a software emulator of the CD4094 which shows how it works. Figure 6 below shows that a new pattern is in the process of being shifted into the shift register, while the lights retain the previous one in the latch. The Clock and Data signals are high and the next statement will drop the Clock signal to add the next bit into the new pattern.


Figure 6: The light emulator

This figure also shows that I have two bits in the pattern controlling a strand of each colour. You can single step through the displayByte method above and watch it perform this output.

You can use this technique every time you want to control a large number of outputs using a small number of output pins. The CD4094 has "daisy chain" inputs and outputs so that the devices can be connected in sequence. If I used two devices I could control 16 bits, with three I could control 24 and so on. This would require only minimal changes to the software.

Output Driver

The CD4094 device will produce a signal output, but it is not really powerful enough to drive things like lights. To do this we need an amplifier and the ULN2803 Octal Darlington Driver is perfect for this. It is packaged as a single chip which contains 8 pairs of transistors. Each transistor pair is wired in a "Darlington" configuration and can be used as a switch which is controlled by on output from the CD4094. When the transistors are turned on they allow current to pass through them and this will cause the lamps to light. The lights that I bought used a "pull down" arrangement to make them light up. All of the light emitting diode (LED) lamps had one end wired to a common line that was connected to the positive supply. To make the a chain of LEDs light the other end that controls that chain needed to be pulled down to the ground level. This is a common arrangement with lights like these. The ULN2803 driver has the transistors wired in an arrangement that allows it to pull signals low in this way. Figure 7 shows how this arrangement works. The resistor shown is actually wired into each LED in the set of lights that I used.

Figure 7: Lighting the LEDs

Complete Circuit

The complete circuit shown in Figure 8 simply links each output of the CD4094 shift register to an input on the ULN2803 Darlington Driver. Note that there is no reason to link any particular bit with any other, the diagram shown is one which will translate most easily to a prototype "breadboard".

Figure 8: The Complete Circuit

The diagram just shows four lights connected to OUT1 from pin 18 of the ULN2803, the other 7 channels are connected in exactly the same way. Some of the pins can be left unconnected. Pins 9 and 10 of the CD4094 are only required if you are connecting multiple shift registers together and the common connection on pin 10 of the ULN2803 is not required. The Latch, Data and Clock signals on the CD4094 are connected to the output signals from the Micro Framework device.

Figure 9 shows the completed circuit built up on a prototype breadboard. The chip on the left is the CD4094 and the one on the right is the ULN2803.

Figure 9: The Completed Circuit

The red wires carry the positive voltage from the power supply, which is connected to the top left of the circuit. The green wires are ground. Other coloured wires are used for signals. The Clock, Latch and Data signals are brought out to a connector which will fit a Digi-ME prototyping board.

Selecting Lights

Each bit in the value sent to the displayByte method and then into the shift register will be mapped to a particular chain of lights. The mapping of these is not particularly important, since you can use program constants to represent particular values. I wired the red signals to output pins 4 and 8. To light up just the red lights I used the value 0x88 which is the appropriate bit pattern. I then set up constants for all the other colors:

const byte GREEN = 0x11;
const byte BLUE = 0x22;
const byte YELLOW = 0x44;
const byte RED = 0x88;

Setting Up the Hardware

The .NET Micro Framework provides a set of classes that can be used to represent the hardware in a system. The program uses instances of the OutputPort class to represent the output pins. These are created in the method that sets up the hardware:

const Cpu.Pin clockPin = Cpu.Pin.GPIO_Pin0;
const Cpu.Pin dataPin = Cpu.Pin.GPIO_Pin1;
const Cpu.Pin latchPin = Cpu.Pin.GPIO_Pin2;

static OutputPort clockPort;
static OutputPort dataPort;
static OutputPort latchPort;

private static void setupOutputs()
    clockPort = new OutputPort(clockPin, false);
    dataPort = new OutputPort(dataPin, false);
    latchPort = new OutputPort(latchPin, false);

In this version of the hardware I have connected pin 0 of the processor to the clock, pin 1 to the data and pin 2 to the latch. If you use different pins you can change the settings above.


Now that we have working hardware we can consider how the software is to work. Note that this version of the program works correctly but lacks exception handlers that would make it truly robust. I've left these out to simplify the explanation. To make sense of this description you will need to have a copy of the program itself available for reference.

You can develop the code using Visual Studio 2008 Express edition, which you can download from

The software is written for the .NET Micro Framework 3.0 which you can download from

Reading the Blog

The program reads the RSS feed from a blog and looks for the <pubDate> value. This contains the date when the feed was last updated. Whenever this date changes the lights must flash red for a few seconds before resuming a random display. Users of the full .NET Framework can use the HTTPRequest class to build a GET command to be sent to a server. Unfortunately the .NET Micro Framework does not support this, so we have to access the web feed using socket based communication. This part of the program is heavily based on the SocketClient example supplied with the .NET Micro Framework.

// This method requests a page from the specified server.
private static String GetWebPage(String server, string webPage)
    const Int32 c_httpPort = 80;
    const Int32 c_microsecondsPerSecond = 1000000;

    // Create a socket connection to the specified server and port.
    using (Socket serverSocket = ConnectSocket(server, c_httpPort))
        // Send request to the server.
        String request = "GET "+ webPage + 
             " HTTP/1.1\r\nHost: " + server + 
             "\r\nConnection: Close\r\n\r\n";
        Byte[] bytesToSend = Encoding.UTF8.GetBytes(request);
        serverSocket.Send(bytesToSend, bytesToSend.Length, 0);

        // Allocate a buffer to receive HTML chunks
        Byte[] buffer = new Byte[1024];

        // 'page' refers to the HTML data as it is built up.
        String page = String.Empty; 

        // Wait up to 30 seconds for initial data 
        // Will throw exception if connection closed
        DateTime timeoutAt = DateTime.Now.AddSeconds(30);
        while (serverSocket.Available == 0 && 
               DateTime.Now < timeoutAt)

        // Poll for data until 30 second time out
        // Returns true for data and connection closed
        while (serverSocket.Poll(30 * c_microsecondsPerSecond,
            // Zero all bytes in the re-usable buffer
            Array.Clear(buffer, 0, buffer.Length);

            // Read a buffer-sized HTML chunk
            Int32 bytesRead = serverSocket.Receive(buffer);

            // If 0 bytes in buffer, then connection is closed, 
            // or we have timed out
            if (bytesRead == 0)

            // Append the chunk to the string
            page += new String(Encoding.UTF8.GetChars(buffer));

        return page;   // Return the complete string

This method is called to fetch the journal RSS feed from my blog:

string address = "";
string name = "/journal/rss.xml";

string html = GetWebPage(address, name);

You can use it to download from any RSS feed or page on the web. It will throw an exception if the page cannot be read. This version of my program does not perform exception handling however.

Getting the Published Date

The date is held in the form:

<pubDate>Wed, 05 Nov 2008 22:38:52 +0000</pubDate>

It would be enough just to record this content and check for changes in the text, but I decided that I might want to use the date information in a later version of the program and so I created some small helper methods to read numbers from the input string and a larger method to read the publish date itself:

private static DateTime getRecentPubDate(string html, string startTag)
    int index = html.IndexOf(startTag) ;

    if (index < 0) 
        throw new Exception("Missing tag " + startTag);

    index += startTag.Length;

    // spin past the name of the day
    while (index < html.Length && html[index] != ',') index++;
    if (index == html.Length) 
        throw new Exception("Short publish date");

    int dayValue = getInt(html, ref index, ' ');

    string monthName = getString(html, ref index, ' ');
    int monthValue = getMonth(monthName);

    int yearValue = getInt(html, ref index, ' ');
    int hourValue = getInt(html, ref index, ':');
    int minuteValue = getInt(html, ref index, ':');
    int secondValue = getInt(html, ref index, ' ');

    return new DateTime(yearValue, monthValue, dayValue, 
                        hourValue, minuteValue, secondValue);

The main body of the program uses this method to extract the date out of the RSS feed. When a new date is found it is time to update the lights.

Lights and Threads

My first version of the program flashed the lights for a while and then checked to see if a new blog post had been made. This worked OK, but the process of loading the RSS feed from the server and checking the dates can take a few seconds, which meant that the flashing lights would freeze every now and then. This did not look very good, and so I decided to use two threads instead. One is in charge of flashing the lights in a random pattern and the other loads the RSS feed from my blog and checks the date of the most recent publication.

Note that the threading I am using is exactly the same as threading in the full .NET Framework.

Thread Communication

The two threads communicate by means of a single boolean variable which is set to true when the blog alert is to take place. The display thread reads this flag and flashes the lights red if it is time to alert.

public static bool alert = false;

public static void flasher()

    while (true)
        randomDisplay(400, 10);
        if (alert)
            alert = false;
            flashRed(600, 20);

The methods randomDisplay and flashRed do exactly what you would expect. Each of them gets two numbers to control the lights. The first number gives the delay in milliseconds between flashes (a few hundred milliseconds giving best results). The second gives the number of times that the lights should be flashed before the method finishes. RandomDisplay displays random colors, whereas flashRed is simply flashes the red lights. The alert flag is cleared before the red lights are flashed so that the system will resume normal display after the alert.

The second thread in the system performs the blog download and date test behaviour. This all happens inside the Main method:

public static void Main()
    flashThread = new System.Threading.Thread(flasher);


    string address = "";
    string name = "/journal/rss.xml";

    String html = GetWebPage(address, name);

    DateTime lastUpdate = getRecentPubDate(html, "<pubDate>");

    Debug.Print("Initial Update Value : " + lastUpdate.ToString());

    while (true)

        html = GetWebPage(address, name);

        DateTime blogUpdate = getRecentPubDate(html, "<pubDate>");

        if (!blogUpdate.Equals(lastUpdate))
            Debug.Print("Updated at : " + blogUpdate.ToString());
            lastUpdate = blogUpdate;
            alert = true;

To reduce the load on the network the system only checks the blog feed every 10 seconds.

Future Work

The program itself works fine, but the error handling is not wonderful. Although some of the methods used throw exceptions these are not caught anywhere, causing the blog reading thread to terminate. This does not stop the lights flashing, but it does mean that there will be no more alerts. However, it is not too hard to create a version which contains proper error handling and even flashes the lights different colors to indicate the alarm conditions. I have created a version that flashes the lights yellow every now and then if the network connection fails. There is also considerable scope for reading other web based sources and changing the output accordingly. Feel free to do all these things and make sure that you have fun.


Thanks go to Ian Mitchell of Ormston Technology ( for doing such a great job of hardware design and build.

The Discussion

  • User profile image
    Code Monkey Labs

    Pick of the Week: Controlling Your Festive Lights with the .NET Micro Framework General New and Improved CLR 4 Thread Pool Engine : Daniel Moth writes about upcoming enhancements to the thread pool. xUnit.NET 1.1 Released : Brad Wilson announces a new

  • User profile image
    Dave Baker's WebLog

    Rob Miles has come up with a new spin on seasonal project by making his festive lights flash red whenever

  • User profile image
    ASP.NET on Channel9

    This Week on Channel 9, Brian and Dan discuss: - Oxite : The open source ASP.NET MVC Content Management

  • User profile image

    you don't need two chips for this.  Allegro and Toshiba both make combination shift register and constant current driver chips made for driving LEDs (and the constant current drive ensures equal brightness even if the LEDs are mismatched).

    for example

  • User profile image

    I ran across your site by accident I think I may be glad I did, if you can help I would love it, nobody so far has.  I want to take the tiny light like shown on your site and connect it to outdoor low voltage lights.  It would be easier to explain like this.  I have the outdoor malibu lights like you buy at home depot, the low voltage wire is ran around the garden with the low voltage lights connected to the main line, which is connected to the transformer, these light  are 7 watt others are 11 are still to bright.  I would like to connect the tiny lights to this line how do I do this? I want to add bits of interest in bushes here and there. Kind of like maybe fireflies that do not blink.  Individual ones.

  • User profile image
    Code Monkey Labs

    Pick of the Week: Controlling Your Festive Lights with the .NET Micro Framework General New and Improved CLR 4 Thread Pool Engine : Daniel Moth writes about upcoming enhancements to the thread pool. xUnit.NET 1.1 Released : Brad Wilson announces a new

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.