Project: Words vs Numbers “Art” with an Arduino & HD44780 LCD

I’m definitely no artist – I don’t normally go on “artistic” endeavours, but I try to do practical things as any engineer would. But it’s been a while since I’ve had the time or inclination to build something … and things rarely ever go to plan. After a little building of something else, I somehow ended up building something just for the sake of it. Call it “art”.

The Inspiration Frustration Process

It was an afternoon, I had pulled out an Arduino Leonardo and an LCD Keypad Shield. I wanted to build something Wi-Fi connected, so I grabbed an ESP8266 Wi-Fi Shield as well and thought I’d be on my way. Even if the AT-command set mode wasn’t great, I was only looking to build something simple.

Getting a little ahead of myself, I had no stackable pin headers, so I decided to stuff the Wi-Fi Shield behind the LCD Keypad Shield and just solder it to the slightly-long headers it already had. That went just fine and so I tried snapping it onto the Leonardo – aside from a slight port-clearance issue, it sat “well enough”.

This was when I ran into trouble. The shield acted dead – give it all the AT+RST‘s you want, this thing was not talking no matter what baud. It wasn’t a software vs hardware UART selection switch issue either – the module just didn’t work.

But now I had a problem on my hands – getting the unit out was a nightmare.

Desperate not to “bin” the whole lot and just start fresh, I tried to desolder the shield with very little success – so many plated through-holes wicked solder to inaccessible regions where no wick or bulb could reach. The board was so big it was not practical to hot-air the whole assembly, so I resorted to snipping pins as short as possible and trying to lever the bits apart.

After tearing a few (useless) pads off the board and still resorting to a heat-gun, I managed to separate the two but not without some casualties – the LCD had taken a good dose of heat resulting in some noticeable discolouration, so I don’t know if that was still good or not.

Going into salvage mode, I was still convinced the ESP8266 Wi-Fi Shield would be of use, so I decided to try programming it directly using the ESP8266 Arduino Core and an FTDI cable. I could get a response – I could program the chip to blink an LED, but absolutely anything Wi-Fi related was not working at all. I checked the WiFi Mode was being set correctly, and even tried scripts to disable and re-enable it to no avail. My AP was also telling me that it never even saw a connection attempt.

By now, I was really majorly frustrated, so I decided to try recovering the shield as it had nice level shifters and voltage regulators on it – I loaded a Wi-Fi scan program onto it and it said no network. Suspecting something happened to the antenna connection, I checked for continuity – there was no issue. I suspected a crack in the ceramic capacitor connected to the antenna – desoldered it and shorted it out to no avail.

Now I suspected a bad ESP8266 – so I got the hot air gun out and desoldered the IC and reworked another ESP8266 from another board on. With the fine pitch and complex pad pattern, it was a big stretch but worth a try. Still no dice.

Now suspecting either an EEPROM data problem or a crystal oscillator out of tolerance, I moved both from the other “donor” module to the shield. I thought this would be a sure win – but no. Only blinks, no Wi-Fi.

By now, I was fed up. It was only a few dollars … I was prepared to let it go. Weekend project postponed until later … when the parts arrive.

But What About the LCD?

I still had a really beaten up LCD shield module that had been through many ordeals and seemed to be bin material. But then, I thought I might as well give it a go – by desoldering as much of the broken pins out and replacing just the pins necessary, I decided to give it a shot.

In order to do this, I had to write a program to write some data to the screen. I could have stuck with “Hello World”, but where’s the fun in that? It wouldn’t test the character generator much …

So I decided to embark on a project to fill the LCD with random characters as quickly as possible and continually do this.

The LCD was still alive, but with a slight bright spot on the top row. That’s quite amazing. But then, I thought it would be nice to make something less “random and confusing” – why not make something aesthetically eye-catching.

The New “Art” Project

Keeping myself occupied for the afternoon, I decided that I would take the random-character-sketch and instead do something a little less random and a little more artistic. That’s when I came up with the idea of illustrating “Words vs Numbers” on an LCD. As I had an old Arduino Mega 2560 that had a bunch of blown I/O pins due to an accident with some scrap wire and an even larger 20×4 LCD that was doing absolutely nothing for the past six years, I decided it would be nice to just cobble it together for some fun.

The new project would:

  • Put numbers in random positions on the display on a regular basis, rather than doing random characters sequentially as my LCD test did. This would create a sparkling that would look like “noise” on a background of numbers that might be somewhat reminiscent of The Matrix.
  • Write random words to random positions on the display on a regular basis. This would be taken from a list of common English words – fitting as many in as possible to increase variety.
  • Be fleeting but still readable – illustrating a battle between the two by having the random numbers “erode” the words over time, whereas words would spring up suddenly at intervals. This is sort of entropic in a way, showing the words “decaying” into the field of numbers.
  • Be powered via USB, which is no trouble for Arduinos.

All in all, nothing hard, but at least something I could get my hands on.

The Result

With some white coloured hook-up wire (as that was what I had left), a half-damaged Arduino Mega 2560 clone board, a 10kohm precision trimpot, an old LCD display and a lot of hot glue … we have this monstrosity.

What does it do? Simply, this …

An abridged version of the code is as follows:

#include <LiquidCrystal.h>

#define INT_CHAR_DEL 45
#define CHARSET_HIGH 57
#define CHARSET_LOW 48
#define ROWS 2
#define COLS 16
#define INJECTINT 24

LiquidCrystal lcd(8,9,4,5,6,7);
const char string_0[] PROGMEM = "a";
const char string_1[] PROGMEM = "abandon";
const char* const string_table[] PROGMEM = {string_0, string_1};
char buf[17];
int cyclecount=0;

void setup() {
  lcd.begin(COLS, ROWS);

void loop() {
  if (cyclecount>INJECTINT) {
    strcpy_P(buf, (char*)pgm_read_word(&(string_table[random(0,2350)])));
    for(cyclecount=0;cyclecount<strlen(buf);cyclecount++) {

This code was kept as simple as possible and was something I ended up writing within half an hour. The idea is to use LiquidCrystal library for parallel LCD interfacing, using random() to generate the necessary random values seeded by an analogRead() value from an unconnected pin. The loop sets the cursor to a random position within the LCD and writes a random character within the range (defined as numbers) to that position. It delays a fixed amount of time, and counts every loop. After a fixed number of loops, we turn on the “blink” feature so the block cursor shows (to make the word printing more obvious) and pull a random string from the string table in PROGMEM. This is written to a random position on the screen character by character (ensuring it fits into the screen), followed by a five-times-length delay to give the eye some time to identify and read the word before it is “destroyed” by further random writes. The blink feature is turned off when returning back into the random number writing loop.

Due to the difference in memory, the number of words that can be accommodated depends on the microcontroller in question and how it accesses memory. In the case of 32kB microcontrollers (e.g. 32U4, 328P), the amount of space is somewhere around 28kB-30kB depending on which particular microcontroller is used. The Leonardo, for example, has less because some of this space is necessary for the bootloader’s USB emulation. As a result, I made a “smaller” version with 2350 words from EF Australia that just fits into those.

For larger microcontrollers, such as the ATMEGA1280/256o used in the Mega boards, they have 128/256kB of memory minus some for the bootloader. Unfortunately, there is a problem with using all of this memory as pointers are 16-bit in the Arduino code, resulting in a hard 64kB limit in pointers. Exceeding this results in code that doesn’t execute properly through to assembler errors. The solution for this is to apparently use far-pointers, which don’t seem nicely supported, so I’ve capped the number of words to 6500 words instead from Google’s corpus to fit within this space limit.

The full code for both an Arduino Leonardo (or other 32kB microcontrollers) and Arduino Mega 1280/2560 (or 64kB+ microcontrollers) can be downloaded:

Porting to other microcontrollers might allow for even more words to be accommodated due to the difference in capacity and way memory accesses are handled.


It’s not something really amazing or perhaps even unique, but more a result of a lot of frustration. Borne out of some code I wrote to just test an LCD which I had tortured, I decided to extend it with the help of a few online corpuses to print random words over a sea of random numbers. But now that I’ve built it, I do like it – it seems rather visually interesting at times to just pick a word out from the “sea” of numbers before it disappears.

About lui_gough

I'm a bit of a nut for electronics, computing, photography, radio, satellite and other technical hobbies. Click for more about me!
This entry was posted in Electronics and tagged , , , . Bookmark the permalink.

2 Responses to Project: Words vs Numbers “Art” with an Arduino & HD44780 LCD

  1. I rather like the look of the end product! Would be fun to have the columns always raining down like the matrix, and occasionally aligning to form a word, persist for a moment, then continue to decay.

  2. sparcie says:

    This reminds me of similar programs I wrote back in the day in BASIC just to try out some of the features. I had colour and sound to play with as well.

Error: Comment is Missing!