Ever wanted to make a twitter sign? Of course you have. I do too, so I made one! My goal was to have minimal hardware so that the sign can easily be mounted anywhere, so I used a Linksprite WiFi DiamondBack Arduino to connect wirelessly to the Internet and control the sign.
But first, how to get the Arduino talking to the sign? The sign communicates with a standard serial cable (DE-9 RS232) which the Arduino SoftwareSerial library can talk to pretty easily. What data does it need, though? Sending straight ASCII characters to it didn’t do anything, so some digging was necessary.
Fortunately, it comes with a Windows application for programming the sign, and HeatSync Labs has a Logic Analyzer. So, I loaded up the program on a laptop with a serial port and carefully stripped the serial cable’s wires bare without breaking them. I also installed Salae Logic on the computer and hooked the analyzer’s leads up to the bare wires. Finally, I programmed the sign to display a sample message.
Turns out, this sign definitely doesn’t read plain ASCII text! The logic analyzer didn’t find anything readable aside from the first few characters of the message (likely the message’s “title”, i.e. part of its advanced programming and not the actual message itself.) I finally parsed all the raw sniffed binary into CSV and a LibreOffice spreadsheet, and colored each cell, to visualize the binary content of my test messages. I was pretty cross-eyed by this point and heading nowhere fast.
But wait, even though the first few images are illegible, I kept sending test messages and eventually landed upon a single period (4×4 dot) and then two periods (two 4×4 dots separated by a 2×2 space). The last two columns in this image show an inverted dot, and then finally a message containing an inverted dot followed by a positive dot. Finally! It looks like the dots are being written to the screen in binary, with a lot of header information. Looking at the info closely, it seems that the binary is laid out horizontally; a whole row is written out, then the second row, etc. This is why it’s illegible for all but the most basic of messages.
So we figured out what it’s doing, but we’ve still got to send stuff via Arduino and figure out how to generate our own messages on the fly.
First step, I copied the sniffed binary in hex form to an Arduino SoftwareSerial program, and used Logic to compare the Arduino outputs and sign replies to the stuff I’d sniffed earlier. Looked good, with a few tweaks! I just wired the Arduino pins 2, 3, and GND straight into the end of the serial cable.
Here came the tough part. Any time I made the slightest change to the code, I’d receive different responses from the sign (presumably error messages.) There must be some error checking routine, because I could change the ORDER of certain bytes in the message data, but I couldn’t change their content (value.) It took a lot of trial and error, but I finally realized there had to be a checksum, and while exasperatedly explaining it to people on IRC it hit me: 0x2 is “packet start”, 0x3 is “packet end”, 0x0 is null or padding, and the byte right before the “packet end” is the checksum. It should’ve hit me earlier, but I ignored the amazing coincidence that the difference between the checksums and the sum of all the bytes in the packet (except start, end, and checksum) was always divisible by 32 and 64…
Anyway, turns out the sign’s checksum is calculated by an 8-bit accumulator, or mathematically it’s the result of the sum of all the data bytes in the packet, modulo 256.
With this knowledge, I’m able to construct a data packet for the sign in the Arduino. Every packet is 0x2, 0x0, [data], 0x0, [checksum], 0x3. Everything else is simply a matter of getting the message to send and outputting the appropriate dot pattern in binary. I used a webserver to connect to twitter and prepare the message, along with a binary 8×8 dot matrix font on the Arduino, but this is all secondary to establishing communication.
Arduino sketch files for this specific sign are available on Github.