LED Bandwidth Monitor
After discovering how cool RGB LED strips are, I decided to make a bandwidth monitor for the Internet connection at our place. Since there are many users active on the same connection there's bound to be conflicts where someone is gaming and another is downloading, causing the ping to fluctuate (even with QoS HTB-init set up).
One meter of LED strip has 32 LEDs, where each section is 2.5 inch (6.35 cm) and consists of one shift-register IC, controlling two LEDS. There is also a bypass capacitor for the IC and current-limiting resistors for the LEDs. Each RGB LED has 6 pins, grouped in pairs for each of the 3 primary colors, this allows resistors to be connected fore or aft. One reel is 5 meters and comes with end-connectors already soldered on.
The strip is housed in a rubber casing and when the ends are sealed can be made semi-waterproof.
Pin-out for Arduino UNO:
- SI - pin 8 (set static high in code)
- DI - pin 11 (SPI data)
- CI - pin 13 (SPI clock)
- LI - pin 10 (latch pin toggled in code)
The control IC is a HL1606 with two channels (A and B) each controlling one RGB LED, fading capability, driven by 5V, and has a SPI-like protocol.
The kind people over at Adafruit has updated/published two Arduino libraries, one plain primary only colors and one using PWM to create a huge color spectrum. The latter allows dimming of the three primary colors to display 3, 4, or 5-bit colors per LED.
- Adafruit HL1606 LED Strip (local mirror Nov 2009) - Arduino lib
- Adafruit HL1606 LED Strip PWM (local mirror Nov 2009) - Arduino lib
Shift-register updates are pushed down the strip in serial form (one clock cycle, one bit). A single update consists of 16-bit, where the first 8-bit is channel A and the least 8-bit channel B.
The data format for the 8-bit channels (datasheet):
________________________________________________________________________ | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | ------------------------------------------------------------------------ LED1 CMD LED2 CMD LED3 CMD 2X LatchOK
Each LED has 2-bit control, where 00 is off and 01 is on, the last two combinations are for fading (not used in PWM lib). The 2X fading-bit is not used here either. LatchOK, when pulled high, puts the content of the shift-register into the 'live' output buffers to control the LED.
To drive 128 LEDs without flickering due to low update frequency or spaz out due too slow shift-register reaction time (slew rate), the strip object is using:
- 3-bit PWM per LED, results in 2^3=8 color resolution per LED (dimming single color)
- For the full RGB LED (3 LEDs), this gives a total of 8^2=512 available colors
- SPI clock is FCPU/32 -> 16MHz/32=500kHz
Processing time for one LED strip update: (128 LEDs * 8-bit per LED * 32 SPI-divider * 1000 ms) / 16 MHz = 2.048 ms. This means the update frequency is 1000/2.048 = 488 Hz. Which is pleny to avoid flickering and low enough for the HL1606 to keep up.
There is a lot of details on the HL1606 in the Arduino-lib examples by Adafruit.
The data used to change the active display is feed from the network gateway using the bwbar utility for Linux. It runs as a daemon and outputs two text files every other second containing the current bandwidth utilization on the inbound and outbound interface. This text file is picked up by a shell script (sh), parsed, percentage of the maximum speed (9500kbit/s) is calculated and put in two variables. Last, the values are then passed over the network to an Arduino with an ethernet-shield using the wget utility.
bwbar -k -t 1 -d bwbar/ -f inbound.txt -p inbound.png --output eth1 1000 bwbar -k -t 1 -d bwbar/ -f outbound.txt -p outbound.png --output eth0 1000 wget -O resp.txt http://192.168.233.177/?up=6&dn=30
A simple GET-http request containing the values as parameters, e.g. http://192.168.233.177/?up=6&dn=30, is sent to a basic webserver listening on the first Arduino. Once the values are received by the microcontroller, they're parsed to integers and transferred over a I2C/TWI-bus to the second LED-driving Arduino.
The second Arduino is the LED-driver and is responsible for updating and driving the strip. It had to be on a separate device because the ethernet-shield requires SPI, as does the LED strip, and there's only one hardware SPI-interface. It might be possible to put everything on one device and address ethernet/strip when needed, but I decided it was too time consuming to look into at the moment. The update rate of the LED strip could also suffer (as the 3-bit colors are controlled by PWM and require processor cycles).
strip.setLEDcolorPWM(i, 0, 255*bright, 0); // parameters: LED-index, R, G, B color
Download the shell script:
- Download Linux monitor update script - Requires bwbar, screen, wget, and the usual Unix essentials
Download the Arduino source code:
- Download Arduino Ethernet Web Server Interface - 2012-01-01 rev3
- Download Arduino LED Driver - 2012-01-01 rev3 - Requires the HL1606-LED-Strip-PWM LED-Strip-PWM library to be installed (put in library folder)
A 5V 2.5A powersupply is powering the LEDs and the Arduinos. The maximum driving current for one 2.5-inch section is unknown, but the Adafruit product page states 120mA for 2 LEDs including the HL1606 (which seem a bit high to me).
I have yet to measure the actual current draw.
I wanted to make the monitor bars to be huge and as long as possible to get satisfactory resolution. To fit the space on the wall, I ended on the final dimension of 2 meters long and 15 cm height. That's 2x64 LEDs for download and upload monitor bar, 100/64 = 1.6 LED per percentage-point.
To mount the LED strips, I first made a 2 meter long baseplate out of 10 pieces of 15x20 cm plexiglass plates glued together using regular CA-glue. Drilled holes for each 20 cm section, pulled fishing string through the holes, put double sided adhesive padding on the strip, and tighned the string to get a firm fit. Remember, the LED strips is hang vertically and gravity will pull the strips down over time so adhesive only will fail.
Using 4 hooks and double feed of fishing string, the entire plate with the two Arduino devices and LED strips was lifted into place. The assembly is hanging 8.5 cm away from the wall to give a cool effect.
The only wires connected to the assembly is 5V power and an ethernet cable connected to a network-switch.
Shows the bandwidth meter in action. Shoot on a Nikon D5000, soundtrack "Caribou - Sun Altrice's 'Only What You Gave Me' Remix".
- Use UDP instead of initializing a HTTP connection every time to update
- One Arduino instead of two
- One cable, power-over-ethernet, might need to cut traces on ethernet-shield