Scrolling Text with an Arduino and Nokia 5110 screen

A while ago I purchased a nice little Nokia 5110 screen from MindKits.co.nz (or Sparkfun). It comes complete with a little PCB and a built-in PCD8544 controller.  It took  me a while looking at some different demos on the web to get it working – but once you’ve got it worked out, it is very easy.

It has 8 pins, connect these as follows (or adjust the code below for the correct arduino pins):

  1. VCC (3v arduino output)
  2. GND – Not needed, but if you do some sites say to connect via a small capacitor
  3. SCE – Pin 7
  4. RST – Pin 6
  5. D/C – Pin 5
  6. DN – Pin 4
  7. SCLK – Pin 3
  8. LED (backlight) – No needed, but if you do, remember to use a current limiting resistor!

I took one of the example pieces of code, and improved it with a scroll routine.  Call the ‘scroll(“Message”)’ function in the main loop, and each time the loop repeats, it will scroll the message on one more character, and when needed, it starts looping again.

Here is a video of it working, and below that is the code:

/*
Scrolling text example code
Modified from: http://www.arduino.cc/playground/Code/PCD8544
*/

// The pins to use on the arduino
#define PIN_SCE   7
#define PIN_RESET 6
#define PIN_DC    5
#define PIN_SDIN  4
#define PIN_SCLK  3

// COnfiguration for the LCD
#define LCD_C     LOW
#define LCD_D     HIGH
#define LCD_CMD   0

// Size of the LCD
#define LCD_X     84
#define LCD_Y     48

int scrollPosition = -10;

static const byte ASCII[][5] =
{
 {0x00, 0x00, 0x00, 0x00, 0x00} // 20
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ←
,{0x00, 0x06, 0x09, 0x09, 0x06} // 7f →
};

void LcdCharacter(char character)
{
  LcdWrite(LCD_D, 0x00);
  for (int index = 0; index < 5; index++)
  {
    LcdWrite(LCD_D, ASCII[character - 0x20][index]);
  }
  LcdWrite(LCD_D, 0x00);
}

void LcdClear(void)
{
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(LCD_D, 0x00);
  }
}

void LcdInitialise(void)
{
  pinMode(PIN_SCE,   OUTPUT);
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC,    OUTPUT);
  pinMode(PIN_SDIN,  OUTPUT);
  pinMode(PIN_SCLK,  OUTPUT);

  digitalWrite(PIN_RESET, LOW);
  digitalWrite(PIN_RESET, HIGH);

  LcdWrite(LCD_CMD, 0x21);  // LCD Extended Commands.
  LcdWrite(LCD_CMD, 0xBf);  // Set LCD Vop (Contrast). //B1
  LcdWrite(LCD_CMD, 0x04);  // Set Temp coefficent. //0x04
  LcdWrite(LCD_CMD, 0x14);  // LCD bias mode 1:48. //0x13
  LcdWrite(LCD_CMD, 0x0C);  // LCD in normal mode. 0x0d for inverse
  LcdWrite(LCD_C, 0x20);
  LcdWrite(LCD_C, 0x0C);
}

void LcdString(char *characters)
{
  while (*characters)
  {
    LcdCharacter(*characters++);
  }
}

void LcdWrite(byte dc, byte data)
{
  digitalWrite(PIN_DC, dc);
  digitalWrite(PIN_SCE, LOW);
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
  digitalWrite(PIN_SCE, HIGH);
}

/**
 * gotoXY routine to position cursor
 * x - range: 0 to 84
 * y - range: 0 to 5
 */
void gotoXY(int x, int y)
{
  LcdWrite( 0, 0x80 | x);  // Column.
  LcdWrite( 0, 0x40 | y);  // Row.
}

void drawBox(void)
{
  int j;
  for(j = 0; j < 84; j++) // top
  {
    gotoXY(j, 0);
    LcdWrite(1, 0x01);
  }

  for(j = 0; j < 84; j++) //Bottom
  {
    gotoXY(j, 5);
    LcdWrite(1, 0x80);
  }

  for(j = 0; j < 6; j++) // Right
  {
    gotoXY(83, j);
    LcdWrite(1, 0xff);
  }

  for(j = 0; j < 6; j++) // Left
  {
    gotoXY(0, j);
    LcdWrite(1, 0xff);
  }
}

void Scroll(String message)
{
  for (int i = scrollPosition; i < scrollPosition + 11; i++)
  {
    if ((i >= message.length()) || (i < 0))
    {
      LcdCharacter(' ');
    }
    else
    {
      LcdCharacter(message.charAt(i));
    }
  }
  scrollPosition++;
  if ((scrollPosition >= message.length()) && (scrollPosition > 0))
  {
    scrollPosition = -10;
  }
}

void setup(void)
{
  LcdInitialise();
  LcdClear();
  drawBox();

  gotoXY(7,1);
  LcdString("Nokia 5110");
  gotoXY(4,2);
  LcdString("Scroll Demo");
}

void loop(void)
{
  gotoXY(4,4);
  Scroll("Scrolling Message from MindKits.co.nz / blog.stuartlewis.com");
  delay(200);
}
Posted on February 12, 2011 at 2:34 pm by Stuart · Permalink
In: Uncategorized · Tagged with: 

14 Responses

Subscribe to comments via RSS

  1. Written by Leonardo
    on July 7, 2011 at 1:15 pm
    Permalink

    Hi, this code doesn’t work for me, screen remain off.could you post also your schematics?

  2. Written by Stuart
    on July 7, 2011 at 1:21 pm
    Permalink

    Sorry – I don’t have a schematic, but the post lists the pins to connect.

  3. Written by Leonardo
    on July 7, 2011 at 10:39 pm
    Permalink

    I’ve tried with an Arduino Uno but nothing.. display stay off

  4. Written by transfinite
    on July 10, 2011 at 4:24 pm
    Permalink

    It works for me on a duemilanove clone. I did connect pin 2 to ground. Thanks posting it!

    -transfinite

  5. Written by Alex
    on August 25, 2011 at 12:34 pm
    Permalink

    Hey, don’t you want 3.3V on those input pins, too?

  6. Written by Todd Freeman
    on October 24, 2011 at 5:00 am
    Permalink

    Hi, Stuart. Thanks for the write up. For the first time since buying this nokia 5110 LCD several months ago, I have text being displayed!

    I wanted to comment, not only to thank you for the article, but also say that the ground is required. I am using an arduino Uno, if that matters to you. I tried tying the ground in through a small capacitor as the display had a slight flicker, but no txt. When I removed the capacitor and went straight to ground with pin 2 from the LCD your text came right up.

  7. Written by crunchy
    on October 28, 2011 at 10:04 pm
    Permalink

    Thank you a lot for your work! Its works for me. with a lot of try on other site, I begin to think that my device was “kapout”.
    Do you think to use 5V level on a 3.3V is dangerous ?
    Sorry for my english

  8. Written by mcnewton's notes » Blog Archive » Nokia screen on Arduino
    on November 12, 2011 at 3:11 pm
    Permalink

    [...] just to wire it all up, then test. I found a great scrolling message example by Stuart Lewis with wiring instructions and code, although he wired his screen directly with 5v. It looks [...]

  9. Written by steve
    on December 2, 2011 at 5:54 pm
    Permalink

    Stuart,

    How would I display non-scroling text on this LCD? Just jump over the scrolling function straight to LcdCharacter?

    Based on the code, I am assuming that the max text lines is 5?

    Also, do pins 1, 3, 4, 5, 6, 7 all need to be at 3.3V (pin 2 at ground, pin 8 on 3.3 w/ resistor)?

    This requires a 6 channel logic leveler?

    Thank You.

  10. Written by Troy Dixon
    on February 3, 2012 at 7:25 pm
    Permalink

    I found that with the UNO, I had to put a trim pot in place from pin 2 to ground so i could adjust the contrast, if i go straight to ground from display pin 2 gives me a black screen, but if i go through a 10K trim pot (variable resistor – etc.) I can adjust the contrast and get an absolutely beautiful display with the scrolling text. no streaking whatsoever.!! Thanks for the code sample. – Troy Dixon

  11. Written by Paul
    on February 4, 2012 at 10:45 pm
    Permalink

    Nice work Stuart….. Thanks heaps, I’m building an alarm and using this in RFID wall plate….

  12. Written by JIndra
    on February 27, 2012 at 1:42 am
    Permalink

    Hello, I did not get it with pin 2: you do need ground as common reference for all other pins, right? What do you mean by “Not needed, but if you do some sites say to connect via a small capacitor”? Ground means ground, hard ground, zero, right?
    So why should it work without it (because on my Arduino 2009 the screen remains blank)? Small capacitor – to where?
    I am puzzled. To me all of this makes no sense at all :(
    – Jindra

  13. Written by Jindra
    on February 27, 2012 at 4:18 am
    Permalink

    Sorry, I connected all data pins in reverse order, obviously :-)

    It works perfectly. I put LED pin directly on 3.3 V from Arduino, works fine (no regulation at all)

  14. Written by Ajax Jones
    on May 9, 2012 at 4:28 pm
    Permalink

    HI
    Great example. I connected the ground though and using an Arduino UNO so using 10K resistors in line with the data pins. Also set the value “Set LCD Vop” to B1 and got a much better contrast that way.

Subscribe to comments via RSS

Leave a Reply