Nokia 5110 DIsplay (Graphic LCD 84x48 from Nokia 3310) [SOLVED]

I have plenty of them around - but i’m not sure how to get them working on my spark.
http://mikrocontroller-praxis.de/de/Display-Optoelektronik/LCD-Grafik-Monochrom/NOKIA-5110-LCD-84x48.html

I tried the ported LiquidDisplay Library without success, i’m still having problems understanding the connectors of the 5110… ( http://mikrocontroller-praxis.de/media/images/popup/NOKIA-5110-LCDe.JPG )

Is it somehow possible to get this to work without using additional chipsets?

I can whip up something over the weekend. The LiquidDisplay library won’t help the 5110 as it uses SPI with an additional command/data pin.

2 Likes

Here’s hoping this little bump will find that someone has this little screen working with the spark core.

all of my attempts to-date have always been a cascade of required libraries and it’s just too involved for me.

I’ll port my MSP430 library over for you tonight. :clock430:

2 Likes

timb, how goes on the library?

Anyone else? I have my sketch working on an Arduino with two adafruit libraries but with the Core I’ve added tab after tab of .h files and now even though I’ve added sfr_defs.h in a tab it still calls a compile error about it being missing (included from io.h).

james, if you post you code on github I can port it for you. :smile:

1 Like

Hej peekay, thanks for that. My code is 100% based off of the Adafruit tutorial here: https://learn.adafruit.com/nokia-5110-3310-monochrome-lcd?view=all

If those libraries worked I think it would be a great display combination for the Core, especially given the low-ish power used by this display and the 3.3v.

this works

#define PIN_RESET D4 //0Pin 4 no LCD

#define PIN_SCE   D3 //Pin 3 no LCD

#define PIN_DC    D2 //Pin 5 no LCD

#define PIN_SDIN  D1 //Pin 6 no LCD

#define PIN_SCLK  D0 //Pin 7 on LCD


//The DC pin tells the LCD if we are sending a command or data

#define LCD_COMMAND 0 

#define LCD_DATA  1


//You may find a different size screen, but this one is 84 by 48 pixels

#define LCD_X     84

#define LCD_Y     48


//This table contains the hex values that represent pixels

//for a font that is 5 pixels wide and 8 pixels high

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 ~

  ,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f DEL

};


//This is awesome in bitmap form

char awesome[] = {

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x30, 0x18, 0x1C,

  0x0C, 0x0C, 0x06, 0x06, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,

  0x07, 0x07, 0x0E, 0x06, 0x1C, 0x1C, 0x38, 0x70, 0x70, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0x3C, 0xCE, 0x67, 0x33, 0x18, 0x08,

  0x08, 0xC8, 0xF8, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,

  0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x01, 0x07,

  0x0F, 0x3C, 0xF8, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x0F, 0x00, 0x0C, 0x7F,

  0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x63,

  0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF,

  0xF0, 0x00, 0x00, 0x00, 0x08, 0x08, 0xFC, 0x8C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,

  0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,

  0x0C, 0x0C, 0x0C, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x3C, 0x70, 0xE0, 0x80, 0x00, 0x07, 0x0C, 0x38, 0x60, 0xC0,

  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0,

  0xF0, 0xE0, 0xC0, 0x80, 0xC0, 0x30, 0x18, 0x0F, 0x00, 0x00, 0x80, 0xC0, 0x70, 0x3C, 0x1F, 0x07,

  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06,

  0x0E, 0x1C, 0x18, 0x38, 0x31, 0x73, 0x62, 0x66, 0x64, 0xC7, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,

  0xC7, 0xC7, 0xC7, 0x67, 0x63, 0x63, 0x71, 0x30, 0x38, 0x18, 0x1C, 0x0C, 0x06, 0x03, 0x03, 0x01,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  

};
int pos=0;
int incomingByte = 0;
void setup(void) {
  Serial.begin(9600);
  LCDInit(); //Init the LCD
 

}


void loop()

{

LCDClear();

LCDBitmap(awesome);

delay(200);
  
LCDClear();

delay(200);


LCDClear();

LCDString("Sparkcore!");

delay(1000);

}


void gotoXY(int x, int y) {

  LCDWrite(0, 0x80 | x);  // Column.

  LCDWrite(0, 0x40 | y);  // Row.  ?

}


//This takes a large array of bits and sends them to the LCD

void LCDBitmap(char my_array[]){

  for (int index = 0 ; index < (LCD_X * LCD_Y / 8) ; index++)

    LCDWrite(LCD_DATA, my_array[index]);

}


//This function takes in a character, looks it up in the font table/array

//And writes it to the screen

//Each character is 8 bits tall and 5 bits wide. We pad one blank column of

//pixels on each side of the character for readability.

void LCDCharacter(char character) {

  LCDWrite(LCD_DATA, 0x00); //Blank vertical line padding


  for (int index = 0 ; index < 5 ; index++)

    LCDWrite(LCD_DATA, ASCII[character - 0x20][index]);

    //0x20 is the ASCII character for Space (' '). The font table starts with this character


  LCDWrite(LCD_DATA, 0x00); //Blank vertical line padding

}


//Given a string of characters, one by one is passed to the LCD

void LCDString(char *characters) {

  while (*characters)

    LCDCharacter(*characters++);

}


//Clears the LCD by writing zeros to the entire screen

void LCDClear(void) {

  for (int index = 0 ; index < (LCD_X * LCD_Y / 8) ; index++)

    LCDWrite(LCD_DATA, 0x00);


  gotoXY(0, 0); //After we clear the display, return to the home position

}


//This sends the magical commands to the PCD8544

void LCDInit(void) {


  //Configure control pins

  pinMode(PIN_SCE, OUTPUT);

  pinMode(PIN_RESET, OUTPUT);

  pinMode(PIN_DC, OUTPUT);

  pinMode(PIN_SDIN, OUTPUT);

  pinMode(PIN_SCLK, OUTPUT);


  //Reset the LCD to a known state

  digitalWrite(PIN_RESET, LOW);

  digitalWrite(PIN_RESET, HIGH);


  LCDWrite(LCD_COMMAND, 0x21); //Tell LCD that extended commands follow

  LCDWrite(LCD_COMMAND, 0xB0); //Set LCD Vop (Contrast): Try 0xB1(good @ 3.3V) or 0xBF if your display is too dark

  LCDWrite(LCD_COMMAND, 0x04); //Set Temp coefficent

  LCDWrite(LCD_COMMAND, 0x14); //LCD bias mode 1:48: Try 0x13 or 0x14


  LCDWrite(LCD_COMMAND, 0x20); //We must send 0x20 before modifying the display control mode

  LCDWrite(LCD_COMMAND, 0x0C); //Set display control, normal mode. 0x0D for inverse

}


//There are two memory banks in the LCD, data/RAM and commands. This 

//function sets the DC pin high or low depending, and then sends

//the data byte

void LCDWrite(byte data_or_command, byte data) {

  digitalWrite(PIN_DC, data_or_command); //Tell the LCD that we are writing either to data or a command


  //Send the data

  digitalWrite(PIN_SCE, LOW);

  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);

  digitalWrite(PIN_SCE, HIGH);

}
2 Likes

James, I have posted the adapted library on my github. I modified it to use hardware SPI plus a fast software SPI depending on how you create your display object. I modified the demo program to use hardware SPI so it goes fast but I had to set the SPI clock to 2.25MHz since the maximum for the 5110 is 4MHz. The top of the demo program shows the pin configuration for both the software and hardware SPI modes.

I don’t have a Nokia 5110 display so you will have to do the testing. If all works well with hardware SPI, we could try and up the SPI clock to 4.5MHz to see if it works. Let me know how it goes! :smile:

3 Likes

hey rasmussen!
does not run here - I’m connecting D0 till D4 as seen in the code (D1 with MOSI connected), but it wont show anything… I’m really stuck here, code compiles great, though…

vanderbreye, did you try the library I posted on github?

yeah, seen it yesterday, but was too tired to try it. I will give it a try this afternoon. thanks in advance!

I’m happy to confirm that @peekay123 's libraries work as intended with this display.

Thank you so much!

1 Like

works great. my compliments. thank you!

1 Like

Super glad to hear that! :smile:

Nice work @peekay123! Thanks for picking up the slack, I’ve been so swamped lately this sort of stuff keeps slipping my mind! :smile:

Anytime timb! And anything to help get that battery shield out faster :wink:

Ok, i just tried to talk to two or more displays- but it seems, as if there a troubles with the SPI while initiating the second display.

i use the SW SPI, init goes as following:

Adafruit_PCD8544 display = Adafruit_PCD8544(A3, A5, D2, A1, D3);
Adafruit_PCD8544 display2 = Adafruit_PCD8544(A3, A5, D2, A2, D3);

(HW SPI wont work, there seems to be no real CS?!)

First, i had to set both CS pins to HIGH in order to talk to the displays - which works nice during setup.
I was not able to switch displays after init (PCS8544:begin())…
BUT
i could manually remove ONE of the 5110 and place it instead of the second one…
magically HERE it works as well; Now, i got 1 display which works in this setup, displaying different information on each pins…WTF?
The other displays will show up the splash-buffer-screen while setup, but stay empty during the loop - am i missing something with the CS?
confused…

vanderbreye, can you tell me more about the display configuration? [quote=“vanderbreye, post:19, topic:2863”]
(HW SPI wont work, there seems to be no real CS?!)
[/quote]

What do you mean by no real CS? To use more than one display, they must have CS lines or the display will not “disconnect” from the SPI lines which will interfere with the other display. Can you tell me which display model you are using?