Similar to other teams, our robot this year we used the Sparkfun addressable RGBs (uses WS2812 LED drivers internally to the strip).
https://www.sparkfun.com/products/12026
You only have to plug in 5V, GND and the 1-wire interface which we drove using an Arduino and the Adafruit WS2812 libraries (details in the Sparkfun hookup guide). The power was supplied by a 5V/10A regulator very similar to the one supplied for the router (no 5V source on the robot is capable of supplying this much current). Additionally, we used an LED diffuser film to spread out the light source. This helped us give the effect that the arms were filled with light, where there was only a strip of RGB LEDs running through the top side of each arm.
https://www.inventables.com/technolo...diffuser-films
The Arduino allowed us to program light patterns that were triggered by the cRIO's digital outputs when the robot performed various actions (e.g. feeding, shooting, cocking the catapult). For instance, when the feeder motor was running, the robot would pull a zero on a cRIO digital output which fed into a digital input on the Arduino. Every 10ms, the Arduino firmware checked the digital inputs for changes and would modify the light pattern accordingly.
This may get a bit detailed for those not familiar with embedded programming, but the key to making these animations work fluidly and seamlessly (and respond to asynchronous input) was to program the Arduino an interrupt-driven model. The simplest way to get patterns to display is to shift in the colors to each LED (24 in our case) and then to delay() for the number of milliseconds until the next color pattern needed to be shifted. In Arduino speak, these delay() statements literally force the processor to sit and wait for a number of milliseconds and not do anything (this is an eternity for a processor).
In the interrupt-driven model, these delay() statements are replaced by conditional checks on variables (sometimes called flags) which are set by interrupts based on events (in our case, a 10ms timer interrupt since there weren't enough IRQ-capable pins). Every 10ms, the timer would interrupt the processor, check all of the inputs for any updates from the cRIO and it would increment a timer variable that counted the number of 10ms interrupts that passed. This variable could be checked by the main program to determine how many seconds had elapsed and whether or not it was time for the next pattern to be pushed to the LEDs.
In our reveal video, we hadn't yet finished coding all of the patterns, but you can see what the diffuser material looks like up close:
http://www.youtube.com/watch?v=tEhQnKbRz-0
You can see the patterns when we drive/load/shoot pretty well in this video:
http://www.youtube.com/watch?v=iOK7eQOLqag#t=300