Friday, 15 August 2014

Sending Bender over the air to a Nokia 5110 screen via IR infrared

Last night's BuildBrighton was an illuminating affair - not least of all thanks to Steve's impressive "Arcadie Pong Clock" demo. It used a cheap Nokia 5110 screen as the display (most pong clocks use two 8x8 LED matrices) which got us interested in using the screens in future projects.
The screens use a simple SPI interface to push 1-bit bitmap data to the screen. That sounds easy enough - write a simple routine to query the black-or-white status of a bunch of 8-pixels in a bitmap, and send it out as a byte value to the screen.

After a few tries, we could see that we were on the right lines, but not quite there - the screen was operating in "horizontal mode" which meant that the way the groups of pixels were handled was different to how we were sending them.

The screen is 84 x 48 pixels. But these are handled as 6 "banks" of 8-bits in the y-axis.
So each byte of data is effectively drawing a "column" of pixels.

Since the most significant bit is at the "bottom of the stack" we're having to read our bitmap data from the 8th pixel from the top, then read upwards 8 bits, to create our byte value.


Once we'd finally worked out the correct way to parse the initial bitmap image, getting an image  onto the screen was actually quite easy!


Steve christened our routine the Bender Render.
Messing about with pushing serial data into the screen was fun enough - but what we really wanted was to send Bender "over the air". The challenge was to send the serial data into one device, and have it send the data, using an IR LED, to another - and have the other device display the image on the Nokia screen.

Our bitmap image is 48 * 84 / 8 = 504 bytes in size. That's actually a lot of data to be sending over IR (which is usually confined to just a few command bytes and a checksum for things like TV remote controls). Undaunted, we stuck a 38khz IR sensor on one device and an IR LED on the other.

There are many different types, makes and sensitivities of IR sensor. Out of four or five we had available, only one actually gave consistent results. It may be that some sensors work only at exactly 38khz, and - perhaps due to timing/rounding errors, or interrupt latency or something like that - our sending IR LED isn't quite sending at the right frequency. Or perhaps we've just got loads of stray IR from the fluorescent bulbs at the hackspace, but for whatever reason, only one gave the results we were expecting.



In the video, the bitmap data is actually being sent to the device on the right, nearest to the laptop, and passed via IR to the device on the left, where the image appears

The refresh rate is much slower than sending serial data directly to the screen - we're running the IR straight into the hardware serial module, at about 2400bps. Normally we'd push the data at not less than 9600 and the screen redraws much more quickly. But, as a proof of concept, this worked pretty well.

We were even able to create some (pretty low-res, ultra-slow, slightly rubbish) animations, by redrawing one image over the top of another.


At the end of the project, we learned a few things about both the screens and sending data over IR.
Firstly, the Nokia screens, although simple to interface with, have a quirky graphics format - or, at least, if you're used to parsing binary data by reading a bit, setting the LSB and then bit-shifting from right-to-left (i.e. sending the data MSB first) then the pixel layout seems a bit quirky. This could probably be fixed more easily by changing the order we sent the binary data, but what we had - although a bit "hacky" - did actually work.

The other thing of note was how poor the IR data transmission was. In one of the videos, you can see a small tube, connecting the IR LED on the sending device to the IR receiver on the other. This was to shield the IR from stray, extraneous IR light. Without the tube, the range that we were getting consistent results was only a few inches!

Secondly, we're also aware that pushing more than 500 bytes through an IR based system, in just a couple of seconds, is probably a bit adventurous. We're drawing each byte straight to the screen as it's arrived, and because there's no buffering, there's no real way of handling errors - there's no point receiving a garbage byte and rejecting it (as you might with packets of data and ask for a resend) because the next byte coming in is the next sequence of pixels in the image; as the data comes in, it needs to be drawn to the screen - garbage or not!

It was also interesting to note how different IR sensors performed differently.
There's an assumption that one 38khz IR sensor should perform just as well as another; we're speculating, but perhaps some sensors are a little more tolerant of a carrier wave just outside the 38khz band. It may be that the sensor we used could allow for something like 37khz-39khz, whereas others work only with 38khz and nothing else.

We've no real proof of this, of course, only speculation after observing our own results. But, then again, given that there's no real-world application for a Bender Render Sender, the whole point of the project was to build something and speculate over the results. And for that reason, we're calling last night's efforts a resounding success!