Wondering what we did with our web server on a business card project from last week? It’s powering a giant LED graffiti wall. Animations can be user-submitted using the online designer. You can watch a live feed of user animations as well. The online interface runs on the Google App Engine for maximum scalability and resilience.
In today’s How-to we cover all the ins and outs of building your own networked graffiti wall.
Large, low resolution displays
Our graffiti display is a 1 meter square, 5×5 matrix of LEDs. It’s inspired by the Daft Punk coffee table sold by Habitat a few years ago. The Daft Punk table spawned many DIY replicas, including this excellent Instructable on building a Daft Punk table. Over time, the trend morphed into several permutations, such as our “Daft Punk table” wall-hanging. Given the range of big, blinking furniture, we sought a better term than “Daft Punk table”. We came up with “large, low resolution display” or LLRD for short (pronounced ‘lard’).
The original Daft Punk table flashed randomly, or in time to music. [Mathieu Roncheau]‘s replica table stored animation sequences in an EEPROM. Our first design took this a step further by storing the animation files on a FAT formatted SD card. Now, we’ve put the designer online so that we can fetch user-submitted animation sequences over the internet.
- Click the boxes to toggle the LEDs shown in each frame of your animation.
- Use the arrow buttons to navigate between frames.
- The backup and restore tools provide an easy way to save your sequence locally in a text file.
“Add text frames” inserts character frames using a bitmaped font. If you hate the default font, just create a new one:
- Click the ‘edit font’ button to load the existing font.
- Make your modifications.
- Click ‘update font’ to replace the default font with the new frames.
When you’ve completed an animation, enter your name in the author box and press submit. The sequence code will be generated and sent to the server.
The script will work for any arbitrary matrix, just change the dptRows and dptCols variables to the dimensions of your LLRD.
The live viewer uses asynchronous HTTP (AJAX-ish) requests to show a streaming feed of user-submitted graffiti animations. It will try to set a cookie so that it can start with fresh sequences each time the page loads. If you don’t allow the cookie, it ‘ll just start over at 0 on your next visit.
Sequence bitmap format
The sequence builder outputs each column as an ASCII formatted bitmap. The bitmap for each column is separated by a space, and each full frame is terminated with a line feed (nr). This format was defined by [Mathieu Roncheau]‘s PC sequencer program, we kept it to maintain backwards compatibility.
Bitmap data is zeroed on the upper left hand corner of the frame. The top cells of each column are bit 0, and the bottom cells are bit 4. It seems more logical to follow standard mathematical notation and use the bottom left cell as the origin, but we didn’t design the specification.
The value for each column is found by treating lit LEDs as 1 in a binary number, and converting to decimal. For example, the first column above is 10000 binary, or 1 decimal. The last column is 11111 binary, or decimal 31. You can verify our conversions using an online binary-decimal calculator.
Note that the column bitmaps are represented by ASCII equivalents of the actual decimal values. Numeric digits are encoded according to the ASCII standard, which is the actual value plus 0x30h. Further, multi-digit numbers are stored as individual characters; 24 in the example is stored as 0x32h,0x34h.
The backend is a simple piece of software that accepts animation sequences, does some validation, and saves them to a database. Stored sequences are accessible from the datafeed API.
We wrote two versions of the backend; both are in the project archive. The first is a simple PHP/MYSQL backend for low volume online LLRDs, the other is a Google App Engine/Python version that should be able to handle a bunch of Hack a Day readers.
It’s really easy to write a backend for your favorite platform. Change the graffiti designer’s submit form action to point at your backend; both versions currently POST to backend.php. Now, catch the ‘author’ and ‘seq’ variables on your server and save them to a database.
Our backend performs a bit of validation to prevent attacks on the system. We implemented checks in phases so they don’t waste too many resources. First, the overall size of the submission is checked to make sure its within reason. Next, the sequence is split into individual frames and each is checked for form. If it passes validation, it’s saved to the database.
Sequences are accessible through a simple datafeed API. The API has two variables:
- max – the maximum number of sequences to send.
- last – the last sequence read, only newer data is sent.
The datafeed begins each animation sequence with the character ‘#’, followed by an ID number and line feed. ‘#’ is an invalid bitmap value that alerts clients to the beginning of a new sequence. Clients can use the ID number with last variable of the API to get fresh sequences on each pull.
Mini web server
We used our PIC24F mini web server as a TCP enabled client for this project. Read our previous articles to learn how to build the web server.
Daft punk table
[mrgalleta] has a great construction tutorial for the actual table part of a Daft Punk table replica. An LLRD can take many forms, though, such as our wall-hanging.
Most of Daft Punk table replica designs are controlled by a 74HCT595 (pdf) output expander and ULN2803A (pdf) transistor array. The driver board from this Instructable combines both into an easy-to-etch, through-hole PCB. Each driver board has two 74HTC595s, or 16 outputs; we needed two driver boards for our 25 cell LLRD.
The 74HCT595 is a serial output expander that’s controlled by an SPI-like interface. An update is initiated by dropping the latch line. The state of each LED (on or off) is put on the data line, followed by a pulse of the clock. Bits are put on the output pins once the latch signal returns to high. Data cascades from the data-output pin of one 595, to the data-input of the next. Read this 74xx595 tutorial for a detailed look at interfacing this device.
It’s important to note that we used the 74HCT595, and not the 74HC595. The “HCT” part works over a wide range of voltages, including the operating voltage of the mini web server: 3.3volts.
The 74HCT595 sources current, meaning we could probably run a single LED directly from each output at 3.3volts. Since most LLRDs have 2-8 LEDs per cell, operating between 5 and 24volts, we employ a ULN2803A transistor array to switch the larger load. The ULN2803A sinks current, rather than sourcing it; it switches the ground connection of the LEDs, rather than the power.
Our LLRD has two LEDs per cell, running at 20mA with a 5 volt supply and 56ohm resistor. We soldered the LEDs around a piece of cardboard, rather than etching 25 tiny circuit boards.
A 5 wire connection between the mini web server and the driver boards controls the LLRD.
|V+||Vsys||3.3volt supply for the 595s.|
|GND||GND||Shared ground connection.|
|RA0||Data in||Data signal.|
|—||Vled||LED power supply.|
Our firmware is written in C using MPLAB and the Microchip C30 demo compiler. Learn more about programming and working with the PIC24F in our introductory tutorial. Two firmware versions are included in the project archive. The first just reads all *.seq sequence files from the SD card, the second version adds the Microchip TCP/IP stack for internet connectivity. Learn more about the Microchip SD card and TCP/IP libraries in our mini web server tutorial.
All graphics functions, including the TCP client, can be found in graffitigfx.c. The TCP client is based on the generic TCP client example that’s included with the TCP/IP stack. We followed Microchip’s cooperative multitasking approach and broke our code into small segments that share CPU time with the rest of the TCP/IP stack.
The client periodically connects to the datafeed and requests new sequences. New sequences are parsed for ID numbers, and appended to a temporary file on the SD card. The last ID detected is written to the very end of the temporary data file, and is appended to the last variable of the URL on subsequent datafeed requests. We record the ID at the end of the file to avoid repeated writes to the same sector on the SD card. Hopefully wear leveling inside a 1GB SD card is sufficient to avoid problems for the first few decades of use. If no network connection is available, the device plays any *.seq files in the root directory of the SD card.
A parser function decodes frames and sends them to the LLRD. The parser is fairly robust to errors. Bad data that makes it past the backend validation routine will be rejected at the device level without ill effect. If a few corrupt frames do manage to display, it’ll hardly be noticed amongst the other abstract patterns playing on the wall.
#define GFX_USE_TCP_CLIENT //include the TCP client #define GFX_TCP_ONLY //only do TCP and read temp file, don't read other files on the SD card. #define GFX_CLEAR_TEMP_ON_RESET //optionally delete the temp file on reset. good for Google App Engine...
Three defines at the beginning of graffitigfx.c control which features are included at compile time. GFX_USE_TCP_CLIENT compiles the firmware with the TCP client enabled, comment this definition for a SD card only version of the firmware. GFX_TCP_ONLY ignores any .seq files on the SD card, and only plays sequences downloaded from the web. The GFX_CLEAR_TEMP_ON_RESET option will delete the temporary sequence file on each reset; this is helpful for databases that have non-sequential record IDs, like Google’s datastore. In the future, these definitions could be changed to variables that are set by a configuration file on the SD card.
Taking it further
Our simple firmware is a stable starting point for an online graffiti wall. While we were working on this project we came up with a ton of additional features that didn’t make it into the prototype.
- Display IP address on startup.
- A configuration file on the SD card that sets the datafeed url, refresh frequency, and other variables.
- A telnet or web interface for remote configuration.
- A TCP server for direct access to the display; push animation frames from a remote PC.
- A mail client that reports errors and status information.
- Progress messages during startup and sequence downloads. SD card not present/full errors.
- Scrolling Twitter feeds.
- Your thoughts?
Don’t just read about this project, contribute some frames to the graffiti wall.
Next time we’ll introduce our final PIC24F project, an ethernet backpack for the tiny $20 color Nokia LCD knock-off from SparkFun Electronics.