Netduino Controlled LED Cube

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Commercial LED cubes have been around for a while now and can be quite large and capable of some http://www.seekway.com.cn/e/3d/h32/detail.htm interesting displays . This project is on a smaller scale and goes through the steps required to build a Netduino Mini-controlled 512 LED cube (8 x 8 x 8). Clearly, the Mini does not have 512 pins and so we use http://en.wikipedia.org/wiki/Persistence_of_vision Persistence of Vision to control the LEDs in the cube. The result is that seven pins on the Netduino Mini can control 512 LEDs. At the end of this article you should be able to create a cube capable of the following: <object width="425" height="355 <param name="movie" value="http://www.youtube.com/v/FdpeC0GSRkM&hl=en </param><param name="wmode" value="transparent </param><embed src="http://www.youtube.com/v/FdpeC0GSRkM&hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355 </embed></object> <h3>Bill of Materials</h3><table class="MsoTableLightShadingAccent1" border="1" cellspacing="0" cellpadding="0 <tbody><tr><td valign="top" width="308 <p class="MsoNormal <span>Description </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>Quantity </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>LEDs (I chose blue) </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>512 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>74HC595 Shift Registers </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>8 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>74HC238 3 to 8 line decoder </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>1 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>Netduino Mini </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>1 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>16 Pin DIL Socket (0.3") </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>9 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>24 Pin DIL Socket (0.6") </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>1 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>TIP122 NPN Transistor </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>8 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>100nF Ceramic Capacitor </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>10 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>2.2K Resistor </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>8 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>68 Ohm 0.25W Resistor (you may need to change these depending upon the LED you choose) </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>64 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>8 Way Single Row Socket </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>9 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>36 Way Header Strip (Straight) </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>3 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>2 Way Single Row Socket </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>2 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>2 Way PCB Mount Terminal Connector </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>1 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>8 Way Cable (ribbon or alarm) </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>2.5m </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>Wire </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>Miscellaneous </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>Pad board 160 x 115 Hole </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>1 </td></tr><tr><td valign="top" width="308 <p class="MsoNormal <span>Hex PCB spacer and screw (M3 threaded) </td><td valign="top" width="143 <p class="MsoNormal" align="center <span>4 </td></tr></tbody></table> The following items are also required: 5V Power capable of delivering 2A Solder (I used about 15 metres over the life of this project). One 30cm x 30cm piece of wood Drill and wood drill bits (4mm – 5mm) Some cardboard and tape A fair amount of patience Good attention to detail You may need to shop around for the LEDs. I went to my preferred supplier and was quoted 18.5 pence each. By going on eBay I managed to negotiate the price down to 2.5 pence each including delivery. You are buying in bulk so don’t be afraid to ask for a good bulk price. Also, buy a few more than you need in case you have a faulty part or break a few. <h3>Building the Cube</h3> This is probably the most time consuming part of the project requiring a lot of patience and testing. The aim of the project is to convert these 512 blue LEDs: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B2%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb.png" alt="image" width="602" height="449" border="0 Into this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B5%5D-3.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B1%5D-1.png" alt="image" width="602" height="615" border="0 <h4>Shaping the LEDs</h4> The exact dimensions of the cube depend upon the length of the legs on the LEDs. The legs are soldered together with the cathodes of the LEDs forming a horizontal plane and the anodes vertically connecting the layers. Each of the layers are configured into a common cathode display. Take one of the LEDs and bend the cathode at a point as close to the body of the LED as possible. The cathode should be at 90 degrees to the anode and parallel to the flat base of the LED. This allows the horizontal legs to be soldered together to form the common cathode. Shaping the anode is a little more difficult. The anodes connect the horizontal layers and so need to be shaped to ensure that each LED in the layer is directly above the corresponding LED in the layer below. Otherwise, each layer will be slightly offset from the one beneath it. To achieve this, bend the anode in the opposite direction as described for the cathode. Then, still working with the anode, start about 2mm along the leg. Finally, bend the top 2-3mm through and fashion an angle at 90 degrees pointing back to the LED body. The end result should look like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B8%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B2%5D-3.png" alt="image" width="624" height="526" border="0 The horizontal leg is the cathode and the vertical leg is the anode. When these are connected it should look like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B11%5D-1.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B3%5D-4.png" alt="image" width="520" height="864" border="0 http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B14%5D-1.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B4%5D-1.png" alt="image" width="248" height="864" border="0 Notice how the shaped anode allows the LEDs to be placed above each other. Now repeat this process for the remaining 511 LEDs. <h4>Building a Layer</h4> Our next task is to connect the LEDs together. This is best achieved by using a template for the individual layers. Use a piece of wood with a grid of holes drilled into it as the template. Measure the distance from the center of the now horizontal cathode to the end of the leg and subtract about 2mm. This will tell you how far apart the LEDs are in the horizontal plane. The 2mm will be used to overlap with the neighboring LED and will connect the cathodes. Now drill an 8 x 8grid of holes, each of which are distance of your choosing apart. Here they are 20mm apart. http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B17%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B5%5D.png" alt="image" width="381" height="380" border="0 The holes need to be large enough to hold the LEDs securely but should not be so small that the LEDs are wedged into the hole and difficult to remove. Take eight of the LEDs and place them along the top row with the cathodes all pointing to either the right or the left. If all are pointing to the right, the cathodes of seven LEDs will overlap slightly with the next LED to the right. The rightmost cathode will go off into space. Solder the cathodes together. http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B20%5D-1.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B6%5D-2.png" alt="image" width="624" height="84" border="0 Now let’s add the remaining LEDs in the layer. I started on the left because I hold the soldering iron in my right hand. Take another seven LEDs and place these under the top row and down the far left column. The cathode of each first LED should overlap the cathode of the LED in the top layer. Solder these together. http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B23%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B7%5D-1.png" alt="image" width="624" height="394" border="0 Repeat with the remaining columns. At this point, you should have a horizontal row of LEDs connected together with eight strings of seven LEDs hanging from it. Eventually you should have something looking like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B26%5D-1.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B8%5D-4.png" alt="image" width="624" height="468" border="0 Now test the layer using a power supply and current limiting resistor. A 5V supply and a 68 Ohm resistor are adequate. Ground the cathode of the LED pointing off into space. Now touch each leg of the LEDs in turn with the positive output of the supply (through the current limiting resistor, of course). Each LED should light up and as you touch the anode. One final bit of soldering is needed to add a stiffening wire to the layer. Cut and strip a piece of wire. The wire should be long enough to cross the entire layer. Place the stripped wire on the cathodes of the LEDs at the bottom of the string and solder it on to each. At this point you will have one complete layer. Remove the layer from the template. This should be done carefully so that you do not put too much stress on the joints. Gently lifting it up with a screwdriver should help. Don’t hurry. Put this layer to one side and repeat another seven times. <h4>Connecting the Layers - The Cube Appears</h4> Now that all of the layers are built, test them again. This repeated test may save you future pain. Just imagine how difficult it will be to fix a bad joint in the middle of the cube. Check that the LEDs are still connected and none of the joints were broken when layers were removed from the template. Now drop one of the layers back into the template. What we now need to do is to place a second layer on top of the first so that the anodes of the layer in the template touch the anodes of the LEDs in the upper layer. Once in place, we need to solder the anodes together, and so need a way of supporting the top layer whilst connecting the LEDs. A strip of cardboard can accomplish this. Cut the cardboard into strips (making sure the cardboard is the height needed to support the layer) and bind the strips together with tape. Two of these strips should be enough to support the layer. Here’s how it looked when several layers had already been connected: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B29%5D-1.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B9%5D.png" alt="image" width="624" height="631" border="0 Now that you have the layer supported, solder the anode of each LED in the top layer to the anode of the corresponding LED in the layer directly beneath it. Once this has been done, test each LED. Connect the cathode of the bottom layer to ground and touch each of the legs on the top layer in turn with the positive supply (going through the current limiting resistor). The LED on the bottom layer should light up. Repeat for each LED in the layer. Move the cathode to the top layer and repeat the test—this time the LED on the top layer should light. Again, repeat for each LED in the layer. Now add the remaining layers. Just for safety, test every layer in the cube as it is built up. This repeated testing sounds like a big pain, but trust me its worth it. At this point you will have a cube of LEDs looking something like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B32%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B10%5D-3.png" alt="image" width="624" height="650" border="0 Now trim the cathodes that are still flying off into space. <h3>Building the Controller Board</h3> The controller board will allow any of the 512 LEDs in the cube to be turned on by a Netduino Mini using only seven pins. <h4>Persistence of Vision</h4> Connecting the anode to a positive supply while grounding the layer in which the LED is located can turn on any LED. You can also do this with more than one LED in a layer, and so within a layer can turn on 0 to 64 LEDs. To light the entire cube, we need to switch on each layer in turn while doing so fast enough to give the impression of static image. This is where the principle of http://en.wikipedia.org/wiki/Persistence_of_vision Persistence of Vision comes into play. The basic algorithm is as follows: Layer = 0 Repeat Connect the anodes of the desired LEDs in Layer to positive supply Connect Layer to ground (this turns the layer on) Move to next Layer If we do this fast enough, the human eye will see a single image as when watching TV or a movie. Our basic building blocks for the controller are as follows: Microcontroller (a Netduino Mini) to run the whole show Hardware to select the layer to be turned on (74HC238 and TIP122 transistors) Hardware to turn on the LEDs (Shift registers) <h4>Shift Registers</h4> The shift registers determine which LEDs are turned on. The board has a series of eight cascaded 74HC595 registers. This allows us to control 64 LEDs (8 chips x 8 outputs). The following schematic shows how two of these registers should be wired together: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B38%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B12%5D-2.png" alt="image" width="624" height="498" border="0 The above should be repeated until you have eight shift registers cascaded. The output from the register is 5V and will give more than enough power to burn out an LED, so we need to put a http://en.wikipedia.org/wiki/LED_circuit current limiting resistor in the circuit. A 68 Ohm resistor is required for the LEDs in this project—make sure you verify the value you choose against the LEDs used. Putting this together gives the following layout: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B41%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B13%5D.png" alt="image" width="624" height="373" border="0 Each socket holds a 74HC595 shift register. The connections are identical for each register with the data cascaded into the next register. So if we look at the bottom left socket you will see the following: Below the socket there is a connector that allows the output to be connected to the LEDs in the cube. Above the connector are the resistors that limit the current flowing through the LEDs. The socket above that will hold the 74HC595 shift register. To the left of the socket is a 100nF capacitor. This smooths out the power supplied to the shift register and is connected between the power input and ground and placed as close to the IC as possible. The following colors have been used: Red = Power Blue = SPI and cascaded data Yellow = RCK White = SPI clock Note that the connectors and current limiting resistor are slightly offset as output 0 is on pin 15 and this is routed on the underside of the board. The remaining connections are a direct one to one path from the pin to the resistor/connector. The microcontroller uses the http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus Serial Peripheral Interface (SPI) bus to tell the shift registers which LED to turn on. The data from the registers is cascaded and so we can store 64 bits of information (1 bit for each LED in a layer). With logic 1 turning a particular LED on and 0 turns the LED off. <h4>Layer Switching</h4> The layer switching logic allows the controller to connect any one of the layers to ground (using a common cathode). Coupling this with the LED selection logic above allows us to turn on any one of the LEDs in the cube. This is achieved by using a transistor as a switch. The TIP122 was selected because it is capable of sinking 2A. This may seem like a lot considering the 25mA for each LED, but remember that we potentially have 64 LEDs being turned on at once. This means we may be drawing 1.6A of current. If you use a different LED, you will need to verify that the shift registers, power supply, and the transistor are capable of dealing with the amount of power you will be drawing. The schematic for the layer switching looks like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B44%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B14%5D-2.png" alt="image" width="624" height="468" border="0 The 74HC238 has three input signals. These represent a binary number 0-7. The chip converts this number into eight output lines. 0 turns on line 0, 1 turns on line 1 etc. The output from each line (0 through 7) is then fed in the base of a TIP122 transistor. This turns on the appropriate layer by connecting the layer through to ground. One line for the Netduino Mini controls enable line on the 72HC238 chip. This allows us to turn all of the outputs off whilst a new value is being loaded into the chip. This line is used to make sure that the transitions between the states are “invisible.” Without this there is the chance that the viewer may see a flickering effect when new values are loaded into both the 74HC595s and the 74HC238. <h4>The Completed Controller Board</h4> The completed controller board looks something like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B47%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B15%5D.png" alt="image" width="624" height="491" border="0 Note that there are a pair of connectors to the top right and bottom left of the Netduino Mini. The pair at the top right breakout the COM1 port. The two at the bottom left allow grounding of an FTDI lead (connected to the controller board) and also one socket that is not connected. This allows the 5V lead on the FTDI connector to have a place to live and not be in danger of touching something it shouldn’t. And on the underside: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B50%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B16%5D.png" alt="image" width="624" height="444" border="0 <h4>Connecting the Cube and Controller</h4> The final task (from a hardware point of view) is to connect the cube to the controller board. I tried both ribbon cable and alarm cable. The alarm cable was a little more difficult to connect but was flexible. The ribbon cable was easier to work with but was not as flexible. The principle is the same whichever you chose. Place the cube on a flat surface (the anodes touching the surface) with one face of the cube facing you. The connections should be made so that the lower back left corner is co-ordinate (0, 0, 0). The co-ordinates increase moving to the right, towards you and up. So looking at the controller board above, shift register 0 connects to the LEDs farthest away from you with output 0 from the register connecting to the LED to the far left. Cut and make the 8 cables according to this pattern varying the lengths to suit the location of the controller board with respect to the cube. Each cable will need a single eight-way socket on one end with the other end connected to the appropriate LED. The layer selection logic should be connected using a similar cable. Each layer should be connected to a TIP122 with layer 0 being the bottom layer. The cube will then look like this: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B53%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B17%5D-1.png" alt="image" width="624" height="587" border="0 Connecting it up to the controller: http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B56%5D.png <img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B18%5D.png" alt="image" width="624" height="346" border="0 I found it easier to be consistent and wire each plug and LED identically, and so all of the connections above have a black wire to the right of the connector. It helps with connecting things up later. If we have everything connected then we only need one more thing... <h3>Software</h3> The software running the cube needs to perform two main tasks: Work out which LEDs are turned on Run the display (cube) These two tasks need to be performed at the same time (or so fast that they appear to run at the same time). Luckily the .NET Micro Framework has a built in mechanism to allow us to do this—threading. Threading allows us to do this by running two tasks interleaved. So task 1 will run for a while, the system will then switch and run task 2 for a while, then back to task 1 and so on. To do this, the software is split into two parts, the main program that decides what to display and a separate class that runs the display. <h4>LEDCube Class</h4> This class has only one purpose in life, to output data to the controller board and so “run” the display. It is a relatively simple class containing the following methods: Constructor Buffer update method Display Buffer method The constructor sets everything up by instantiating an instance of the SPI class and setting the buffer (which contains the data to be displayed) to be empty, effectively clearing the cube: <pre class="brush: csharp public LEDCube()
{
config = new SPI.Configuration(SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_PIN_20,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: true,
Clock_Edge: true,
Clock_RateKHz: 100); spi = new SPI(config);
buffer = new byte[64];
for (int index = 0; index < buffer.Length; index++)
{
buffer[index] = 0;
}
}[/code] The buffer is 64 bytes of data, 8 rows of 8 bytes. Each byte corresponds to a vertical layer in the cube. The UpdateBuffer method allows the calling program to change what is displayed in the cube. A little control is needed here to ensure that the pattern displayed in the cube is consistent, and so locking is used to ensure that the buffer cannot be updated part way through a display cycle: <pre class="brush: csharp public void UpdateBuffer(byte[] newValues)
{
lock (buffer)
{
for (int index = 0; index < buffer.Length; index++)
{
buffer[index] = newValues[index];
}
}
} [/code] The final method in this class is the method spawned off into it’s own thread: <pre class="brush: csharp public void DisplayBuffer()
{
while (true)
{
lock (buffer)
{
byte[] displayData = new byte[8]; for (int row = 0; row < 8; row++)
{
int offset = row * 8; for (int index = 0; index < 8; index++)
{
displayData[index] = buffer[offset + index];
} enable.Write(true);
bit0.Write((row & 1) != 0);
bit1.Write((row & 2) != 0);
bit2.Write((row & 4) != 0);
spi.Write(displayData);
enable.Write(false);
}
}
}
}[/code] This method again uses the lock statement to lock the buffer. This means we cannot update the buffer until a full cube of data has been displayed. The method takes a block of eight bytes representing a layer and then writes this to the shift registers using SPI. Note that the spi.Write is embedded in the write to the enable line. This ensures that all of the layers are turned off whilst we are updating the shift registers. Wrapping all of this in the LEDCube class means that we now have a very simple class where we can spawn the DislpayBuffer method into its own thread. <h4>Main Program</h4> The main program sets the cube up and then controls what is actually shown in the cube. The first thing we need to do is to set up a buffer to store the cube display and then spawn off the DisplayBuffer into its own thread. <pre class="brush: csharp private static LEDCube cube = new LEDCube();
private static byte[] newFrame = new byte[64];
ClearCube();
Cube.UpdateBuffer(newFrame);
Thread display = new Thread(new ThreadStart(cube.DisplayBuffer));
display.Start(); [/code] The ClearCube method is trivial and simply sets all of the bytes in newFrame to zero. At this point we have a cube with a whole lot of nothing going on. The next thing we need to do is to add some effects. <h4>Making it Rain</h4> Now that we have the mechanism to control the cube, we simply need to work out what we want to display. The rain effect in the opening video illustrates the majority of the techniques used to control the cube. The rain algorithm is as follows: Set up the cube with a number of rain drops Repeat Count the drops in the bottom layer Move drops down one layer Add the number of drops that have disappeared back into the top layer To do this we will create two methods: AddDrops Rain <pre class="brush: csharp private static void AddDrops(int count, int plane = -1)
{
for (int drops = 0; drops < count; drops++)
{
bool findingSpace = true;
while (findingSpace)
{
int x = rand.Next() % 8;
int y = rand.Next() % 8;
int z; if (plane == -1)
{
z = rand.Next() % 8;
}
else
{
z = plane;
} int position = (z * 8) + y;
byte value = (byte) ((1 << x) & 0xff);
if ((newFrame[position] & value) == 0)
{
newFrame[position] |= value;
findingSpace = false;
}
}
}
}[/code] AddDrops simply adds a specified number of rain drops to the buffer. It also makes sure that if asked for 10 it will always add 10 by checking to see if one exists in the location it wanted to use (check out the findingSpace variable): <pre class="brush: csharp private static void Rain(int noDrops, int cycles)
{
ClearCube();
AddDrops(noDrops);
cube.UpdateBuffer(newFrame);
for (int currentCycle = 0; currentCycle < cycles; currentCycle++)
{
int bitCount = 0;
for (int plane = 0; plane < 8; plane++)
{
byte value = 1;
for (int bit = 0; bit < 8; bit++)
{
if ((newFrame[56 + plane] & value) > 0)
{
bitCount++;
}
value <<= 1;
}
}
for (int plane = 7; plane > 0; plane--)
{
for (int currentByte = 0; currentByte < 8; currentByte++)
{
newFrame[(plane * 8) + currentByte] = newFrame[((plane - 1) * 8) + currentByte];
}
}
for (int b = 0; b < 8; b++)
{
newFrame = 0;
}
AddDrops(bitCount, 0);
cube.UpdateBuffer(newFrame);
Thread.Sleep(75);
}
}[/code] Rain adds the specified number of drops to the newFrame, shows the drops, and then moves them all down by one horizontal plane. Before doing this, it counts how many drops are going to fall out of the cube (the number in the bottom horizontal plane). After all the drops have moved down one plane it adds the drops which have disappeared out of the bottom of the cube back in at the top in random positions. We can display this by adding the following to the main program: <pre class="brush: csharp while (true)
{
Rain(10, 60000);
} [/code] Full source code at http://netduinoledcontrol.codeplex.com/ http://netduinoledcontrol.codeplex.com/ . If you add your own effects, remember to consider the rating of the equipment and parts used. Turning on a full horizontal layer consumes 1.6A for the LEDs alone. Things can get warm/hot if every LED in the cube is turned on at the same time so avoid such effects. <h3>Conclusion</h3> When I started out on this project I was not sure how fast the Netduino Mini could control the cube. It has proven that it is up to the task of keeping the display running whilst also being able to work on the upcoming “frame.” If you have gone this far and built a cube then how about expanding it: Add some filters and a microphone and make the display respond to its environment Connect the cube to a PC using Bluetooth Add an MP3 player module and write software to synchronise the display to the music Where will you take it? <h3>About The Author</h3> Mark Stevens is a software engineer and self-confessed technology addict. Mark started in the computer industry in the 1980s and at the age of 16 wrote a disk operating system for a then state of the art 8-bit microprocessor (despite the fact the machine already had one). He did it for fun and has been hooked on IT ever since then. Mark currently writes line of business applications for Win32, ASP.NET, and Silverlight platforms. He has recently taken up microelectronics as a hobby and has since discovered that his wife does not like the smell of solder. Marks’ current exploits, thoughts, and contact information can be found on his http://blog.mark-stevens.co.uk/ blog . <p class="MsoNormal <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Feeds/RSS&WT.dl=0&WT.entryid=Entry:RSSView:a6740467db934541858d9f9101670ead

View the full article
 
Back
Top