Nokia 3310 LCD board for Raspberry Pi

I recently ordered a Nokia 3310 LCD shield from Texy. The beauty is it comes pre-assembled with 5 micro switches and the 84x48 LCD so no soldering required. The price was pretty superb too at £14 + £4 postage. I looked up the list price of just the LCD and it is about £10 hence 8 pounds extra for a fully assembled board delivered to my door is a bargain.

I have some interesting plans a-foot for this little board.

To get it up and running I needed to install WiringPi from Gordons Projects to work with Texy’s sample code. Be sure to install WiringPi for Python though else you’ll sit there confused like I did wondering what went wrong ;)

Texy_Nokia3310LCD

Something that is most interesting with the 3310 LCD is that it has no internal font set. Consequently you have to define all characters in hex up-front. Luckily (and VERY thoughtfully) Texy provides sample Python code to introduce the functionality of the board which includes a default fairly small font. Calling:

text(‘Hello world’)

will display the text string on-screen. One of the first things I did was to port a pretty good large font to Python from C, the latter courtesy of Petras Sadulkis. The large font takes up three rows per character meaning I had to get it to loop through each row of the array which takes me into my favourite world of multi-dimensional arrays :) (ask me sometime why I love multidimensional arrays so much...) You can see the board outputting the current time (HH-MM, SS.ms) using this larger font.

Here’s some code to get large text working for you for numbers and a few characters (add this into Texy’s sample code), and I apologise in advance for the gratuitous hex:

def display_largechar(char, character_position, display_on_row, font=LARGEFONT):
  try:
    gotorc(0 + display_on_row, character_position)
    for value in font[char][0]:
      lcd_data(value)
    gotorc(1 + display_on_row, character_position)
    for value in font[char][1]:
      lcd_data(value)
    gotorc(2 + display_on_row, character_position)
    for value in font[char][2]:
      lcd_data(value)
    lcd_data(0) # Space inbetween characters.
  except KeyError:
    pass # Ignore undefined characters.


def largetext(string, display_on_row, font=LARGEFONT):
  character_position = 0
  for char in string:
    display_largechar(char, character_position, display_on_row, font)
    character_position += 2

# Based on http://mbed.org/users/snatch59/code/N3310LCD/
LARGEFONT = {
  '0': [
    [0x00,0x00,0xc0,0xe0,0x70,0x30,0x30,0x30,0x70,0xe0,0xc0,0x00,0x00,0x00,0x00,0x00],
    [0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00],
    [0x00,0x07,0x1f,0x38,0x70,0x60,0x60,0x60,0x70,0x38,0x1f,0x07,0x00,0x00,0x00,0x00],
  ],
  '1': [
    [0x00,0x00,0x00,0xc0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x60,0x60,0x60,0x7f,0x7f,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00]
  ],
  '2': [
    [0x00,0xe0,0x60,0x70,0x30,0x30,0x30,0x30,0x60,0xe0,0x80,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xc0,0xf0,0x3f,0x1f,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x70,0x78,0x7c,0x6e,0x67,0x63,0x61,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00],
  ],
  '3': [
    [0x00,0xe0,0x60,0x70,0x30,0x30,0x30,0x30,0x30,0x60,0xe0,0xc0,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x3c,0x7c,0xe7,0xc3,0x00,0x00,0x00,0x00],
    [0x00,0x38,0x30,0x70,0x60,0x60,0x60,0x60,0x70,0x38,0x1f,0x0f,0x00,0x00,0x00,0x00],
  ],
  '4': [
    [0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xc0,0x60,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00],
    [0x00,0xe0,0xf0,0xdc,0xce,0xc7,0xc1,0xc0,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x7f,0x00,0x00,0x00,0x00,0x00],
  ],
  '5': [
    [0x00,0x00,0xf0,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x1f,0x1f,0x18,0x18,0x18,0x18,0x30,0xf0,0xc0,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x30,0x70,0x60,0x60,0x60,0x60,0x70,0x38,0x1f,0x0f,0x00,0x00,0x00,0x00,0x00],
  ],
  '6': [
    [0x00,0x00,0x80,0xc0,0xe0,0x60,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,0x00],
    [0x00,0xfc,0xff,0x33,0x18,0x18,0x18,0x18,0x18,0x30,0xf0,0xc0,0x00,0x00,0x00,0x00],
    [0x00,0x07,0x1f,0x38,0x70,0x60,0x60,0x60,0x60,0x30,0x1f,0x0f,0x00,0x00,0x00,0x00],
  ],
  '7': [
    [0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xb0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x00,0xc0,0xf0,0x78,0x1e,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x60,0x78,0x3e,0x0f,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
  ],
  '8': [
    [0x00,0x80,0xe0,0x60,0x30,0x30,0x30,0x30,0x30,0x60,0xe0,0xc0,0x00,0x00,0x00,0x00],
    [0x00,0x87,0xe7,0x6c,0x18,0x18,0x30,0x30,0x38,0x6c,0xc7,0x83,0x00,0x00,0x00,0x00],
    [0x00,0x0f,0x3f,0x38,0x70,0x60,0x60,0x60,0x60,0x30,0x1f,0x0f,0x00,0x00,0x00,0x00],
  ],
  '9': [
    [0x00,0x80,0xc0,0x60,0x30,0x30,0x30,0x30,0x70,0xe0,0xc0,0x00,0x00,0x00,0x00,0x00],
    [0x00,0x0f,0x3f,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0xff,0xff,0x00,0x00,0x00,0x00],
    [0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x70,0x38,0x1e,0x0f,0x03,0x00,0x00,0x00,0x00],
  ],
  ':': [
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,00,56,56,56,56,56,56,56,56,56,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  ],
  '+': [
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,64,64,64,64,64,254,254,64,64,64,64,64,0,0],
        [0,0,0,0,0,0,0,15,15,0,0,0,0,0,0,0]
  ],
  '-': [
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,64,64,64,64,64,64,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  ],  
}

from datetime import datetime

# clear the screen then display the time HH:MM on one row and SS:ms on another
cls()
now = datetime.now()
largetext(now.strftime("%H:%M"),0)
largetext(now.strftime("%S.%f")[:5],3)

With the large font in place and the time display working I can move on to adding a stop watch, along with some configuration menus for brightness, contrast and a few other parameters. Once this is done the fun begins as I’ll be using it to remotely control my two Nikon cameras using the time and stop watch functionality to control when the Pi triggers the cameras to take a photo.

This is a great board to experiment with. It brings out the hex in all of us;) Luckily there are tools online to help out with generating hex images in case you need them:

http://www.quinapalus.com/hd44780udg.html (online character generator - this is pretty nifty)
http://en.radzio.dxp.pl/bitmap_converter/ (LCD Assistant: windows tool for converting monochromatic bitmaps to hex data arrays)

As you can probably tell I’m very pleased with this shield. If I was being picky I would say, as Texy notes, it “almost” fits within the credit-card form factor of the Pi, with the red board under the LCD just poking out a little. I’m hoping this can be sorted as it means the board won’t fit inside tight-fitting cases designed for the Pi. But apart from that, this shield gets a thumbs up from me.
Comments