Home Arduino Projects Nokia 5110 Arduino Project From Start to Hero

Nokia 5110 Arduino Project From Start to Hero

by Tutorial45

The Philips PCD8544 driver chip is connected to a recycled screen from the very popular Nokia 5110 phone. Because the screens are second hand there are often small scratches/blemishes on the glass cover. They are rehoused in a metal box on a PCB with 8 connections. You need to solder on the supplied pins. The screen is a Liquid Crystal Display, LCD.

Nokia 5110 unboxing

You can obtain a copy of the documentation for the driver chip from here and here.

AZ Delivery supply a free, 9-page pdf guide to using the device. 

If we look more closely at the board, we find that the 8 connection pins are labeled on the bottom surface and there appear to be 4 resistors, near each of the LEDs, which illuminate the screen from the sides.

The two sets of pads are interconnected so you can use either set. (Other suppliers of similar boards do not include resistors, which need to be added to the input line by the user. With these boards, you can control the brightness with a PWM pin supplying power to the LEDs. The connections on such boards may be in a different order – beware!)

There appear to be jumper pads (JP), linking something to GND, but there is no information in the documentation.

Important! This is a 3.3V device and will be damaged if connected directly to 5V.

Nokia 5110
Pin: Description Additional information
1 RST (Reset )Input 
2 CE (Chip Enable)Input 
3 DC (Data/Control)Input 
4 DIN (Data in)Input 
5 CLK (Clock)Input 
6 VCC Power supply – max. 3.3V! 
7 LIGHTLED active when connected to GND 
8 GND (Ground)Ground

The AZ Delivery documentation gives a Fritzing circuit showing the connections to an Arduino UNO using voltage shifters to protect the display.

This involves a great deal of wiring and extra expense for the voltage shifters.

A more compact and cheaper arrangement is to connect the data lines with 10K Ohm protection resistors as shown below. Make sure that VCC goes to the 3.3V outlet on the Arduino UNO.

schematic Nokia 5110 Arduino Project

The simplest solution would be to use a 3.3V Arduino microcontroller with direct connection.

Display Pin Comment UNO Pin
1 RST (Reset ) Input 3
2 CE (Chip Enable)Input 4
3 DC (Data/Control) Input 5
4 DIN (Data in)Input 6
5 CLK (Clock)Input 7
6 VCC Max. 3.3V!3.3V
7 LIGHT To GND on breadboard GND 
8 GND (Ground) GroundGND 

With the black link between pins 7 & 8 the LEDs are always on.

The documentation gives an example sketch to write pixels directly to the display using commands to the PCD8544. This is a pretty advanced method of driving the display and very a tedious method of creating images. You have to count pixels on graph paper and calculate the values of bytes.

// Control Nokia 5110 LCD Display
// AZDelivery Example script
#define CLK 7  // More convenient pins
#define DIN 6
#define DC 5
#define CE 4
#define RST 3
static const byte LOGOTBL[] = { //AZ Delivery Bitmap Logo
0x0F,0x5,0x5,0x0F,0x90,0xD0,0xB0,0x90,0x00,0x00,0x08,0x08,0x08,0x08,0x00,
0x00,0xFF,0x81,0x81,0x81,0x81,0x7E,0x00,
0xFF,0x89,0x89,0x81,0x81,0x81,0x00,0xFF,0x80,0x80,0x80,0x80,0x80,0x00,
0xFF,0x00,0x07,0x38,0xC0,0xC0,0x38,0x07,
0x00,0xFF,0x89,0x89,0x81,0x81,0x81,0x00,0xFF,0x09,0x19,0x29,0x49,0x86,
0x00,0xF,0x90,0x90,0x90,0x90,0xF7
};
// Functions
void LcdWriteCmd(byte order) { // Send command to display
  digitalWrite(DC, LOW); // DC Pin is LOW for commands to the display
  shiftOut(DIN, CLK, MSBFIRST, order); // Transmit data byte serially
  // with MSB (most significant byte) first
 }
void LcdWriteData(byte data) { // Send data to display
  digitalWrite(DC, HIGH); // DC Pin is HIGH for data to the display
  shiftOut(DIN, CLK, MSBFIRST, data); // Transmit data byte serial
  // with MSB (most significant byte) first
 }

void LcdWriteLogo() {
  digitalWrite(CE, LOW); // Chip Enable Pin is LOW,
  // data transfer is activated
  LcdWriteCmd(0x80); // Jump to row 0 column 0, Jump Column
  LcdWriteCmd(0x40); // Skip row

  // Clear screen completely
  for(int i=0; i < 504; i++) { 
  LcdWriteData(0x00); // Delete complete display
 }

  // Output AZ logo
  for(int i=0; i < 66; i++) {
  LcdWriteData(LOGOTBL[i]); // Write logo data into display
 }

  digitalWrite(CE, HIGH); // Chip Enable Pin is HIGH,
  // data transfer is deactivated
}

void setup() {
  pinMode(CLK, OUTPUT); // Switch pin to output
  pinMode(DIN, OUTPUT); // Switch pin to output
  pinMode(DC, OUTPUT); // Switch pin to output
  pinMode(CE, OUTPUT); // Switch pin to output
  pinMode(RST, OUTPUT); // Switch pin to output
  digitalWrite(RST, HIGH); // Reset signal to Nokia display
  delay(100);

  // forward
  digitalWrite(RST, LOW);
  delay(100);
  digitalWrite(RST, HIGH);
  delay(100);

  // Initialization of the display according to data sheet
  digitalWrite(CE, LOW); // Chip Enable Pin is LOW,
  // data transfer is activated
  LcdWriteCmd(0x21); // Extended command set LCD
  LcdWriteCmd(0x90); // set LCD Vop
  LcdWriteCmd(0x20); // Normal command LCD
  LcdWriteCmd(0x0C); // LCD Normal Mode
  digitalWrite(CE, HIGH); // Chip Enable Pin is HIGH,
  // data transfer is deactivated
}

void loop() {
  LcdWriteLogo();
  delay(20000);
}

On executing the script, I was pretty disappointed at this point as nothing appeared on the screen.

I looked in the datasheet and found that it was possible to change Vop (operational voltage?) and Bias.

I replaced

LcdWriteCmd(0x90); // set LCD Vop

With these 3 lines and ran the script again.

LcdWriteCmd(0xBF); // set LCD Vop
LcdWriteCmd(0x04); // Set Temp coefficient
LcdWriteCmd(0x13); // Bias mode 1:40

The expected display appeared.

Nokia 5110 Arduino Project first test

The method works but we need to find an easier method of obtaining the bytes for a screen image. I decided to use Paint.net, to create the image, and LCDAssistant to convert a bitmap file to a list of bytes.

Starting with Paint.net (This could also be done using MS paint)

image to convert

I defined a drawing area of 84 pixels wide and 48 pixels high. I disabled Antialiasing, added a star shape and some text to make a test piece. I saved the image as a bitmap with automatic depth.

I then loaded the saved image into LCDAssistant and used these settings.

creating images

I saved this to create another file called T45Test, which I then opened in Notepad.

COnverting images to code

I replaced the data block in the original script, and adjusted this loop to cope with the extra data and name change.

// Output Image
for(int i=0; i < 504; i++) { 
  LcdWriteData(T45Test[i]); // Write logo data into display
 }

This quickly produced the expected display.

image on the Nokia 5110

What we need to be able to do now is write words, graphic elements and numbers to the screen in real-time under program control.  Luckily there is an Adafruit library for this device to provide the necessary help.

Nokia 5110 Arduino Project From Start to Hero

This library is used with the Adafruit GFX library installed earlier on my computer for another project. Install any dependencies indicated as well. Try the long example script that comes with the library. It may well lack contrast initially.

The library handles contrast (Vop) and Bias slightly differently so I wrote a short script to allow investigation of the best settings to overcome the poor contrast.

// Set up screen visibility PCD8544 & Nokia 5110 screen
// Tony Goodhew 9th July 2020
// Tutorial45.com
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

//   PINS                                   CLK, DIN, DC, CE, RST
Adafruit_PCD8544 display = Adafruit_PCD8544(7,   6,   5,  4,  3);

void setup()   {
  Serial.begin(9600);
  display.begin(); // Initialise display
  int con = 56; // Change up or down by 1 to get
  int bias = 4; // the best settings for your display
  display.setBias(bias);
  display.setContrast(con);
  display.clearDisplay();  
  display.setCursor(0,5);  // INCLUDE ABOVE AT START OF YOUR OWN SCRIPTS
  display.println("Tutorial45.com");
  display.setCursor(0,15);
  display.print("Contrast: ");
  display.println(con);
  display.setCursor(0,25);
  display.print("Bias: ");  
  display.println(display.getBias());
  display.fillCircle(68, 36, 11, BLACK);
  display.fillCircle(68, 36, 6, WHITE);
  display.display();      // Essential instruction to update visible display
}
void loop() {}

Settings of con = 56 and bias = 4 gave the best contrast without activating the background (white) pixels on my display. Just try running the script with single unit changes to the values of con and bias until you get good visibility.

Nokia 5110 Arduino Project printing letters

Now that the contrast has been fixed, we can see that the display has a slight aspect ratio ‘feature’ and circles appear as ellipses. The lower pixel count means that there is less space to write and draw when compared to other LCD displays – especially when compared with the SSD1306 128×64 display. However, the screen size and pixels are larger aiding visibility from a greater distance.

SSD1306 128×64 = 8192 pixels
SSD1306 128×32 = 4086 pixels
Nokia 86×48 = 4032 pixels

We are now ready to check how quickly the screen updates in a useful application. I added a 10K Ohm potentiometer on A0 to provide an input to the script. (You will need 2 potentiometers for a later script.)

schematic arduino project with potentiometers
// Volt Meter on Nokia 5110
// Tony Goodhew 9th July 2020
// Turorial45.com
// 10K Ohm potentiometer on A0
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

//   PINS                                   CLK, DIN, DC, CE, RST
Adafruit_PCD8544 display = Adafruit_PCD8544(7,   6,   5,  4,  3);

int sensorPin = A0;   // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup()   {
  Serial.begin(9600);
  display.begin();      // Initialise display
  int con = 56;         // Change up or down by 1 to get
  int bias = 4;         // the best settings for your display
  display.setBias(bias);
  display.setContrast(con);
  display.clearDisplay();
  display.setCursor(0,5);
  display.println("Tutorial45.com");
  display.setCursor(0,15);
  display.print("Volt Meter");
  display.setCursor(17,40);
  display.print("Volts:");
  display.display();  // Static parts of screen written at this point
}

int bar(int v, float vv) {  // Bar graph
  display.drawLine(0,28,0,40, BLACK);  
  display.fillRect(1,30,80,8,WHITE);   // Rub out old bar graph
  display.fillRect(0,30,v,8,BLACK);    // Write new bar graph
  display.fillRect(55,40,26,10,WHITE); // Rub out old text
  display.setCursor(55,40);
  display.print(vv);                   // Write new text
  display.display();                   // Update display
}
// ++++++++++++Main Loop ++++++++++++++
void loop() {
  // Read pot and display values
  sensorValue = analogRead(sensorPin); // Read the value from the sensor
  float volts = (sensorValue * 5.0 / 1023.0);  // Calculate voltage
  int x = float(sensorValue * 80.0/1023);     // Calculate percentage
  bar(x,volts);  // Redraw bar graph
  delay(100);      // Delay to reduce jitter 
}
Nokia 5110 Arduino Project printing tutorial45.com

Twisting the knob of the potentiometer changes the length of the bar and updates the voltage value. Notice the slight scratch marks on the bottom left corner of the bar graph.

Nokia 5110 Arduino Project with the AZ-Delivery with PCD8544 84×48 Pixel LCD Display

This project illustrates how the display can be changed under the control of a couple of 10K Ohm potentiometers. The potentiometers control the left/right and up/down position of a circular sight in which the player moves to cover the target, indicated by a small cross. As soon as the centers are identical the ‘target’ is destroyed and another target appears at a random position. There are 5 targets in a game. The search time is recorded and displayed at the end of the game.

// Game on Nokia 5110 – Search and Destroy
// Tony Goodhew 12th July 2020
// Turorial45.com
// 10K Ohm potentiometers on A0 and A1
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

//   PINS                                   CLK, DIN, DC, CE, RST
Adafruit_PCD8544 display = Adafruit_PCD8544(7,   6,   5,  4,  3);

int xPin = A0;   // x potentiometer
int yPin = A1;   // y potentiometer
int ox = 0;      // Old sight position - ring
int oy = 0;
int nx = 20;     // New sight position
int ny = 20;
int tx = 15;     // Target position
int ty = 15;
int count = 0;   // Targets destroyed
float t1 = 0;    // Time increment – for a single target
unsigned long t0;// millis() value when target appears
float total = 0; // Total time spent searching

void setup()   {
  Serial.begin(9600);      // Ready for debugging
  display.begin();         // Initialise display
  int con = 56;            // Change up or down by 1 at a time to get
  int bias = 4;            // the best settings for your display
  display.setBias(bias);
  display.setContrast(con);
  display.clearDisplay();
  display.setTextSize(2);  // Large text for Title screen
  display.setCursor(0, 0);
  display.print("Search");
  display.setCursor(0, 16);
  display.print("and");
  display.setCursor(0, 32);
  display.print("Destroy");
  display.display();
  delay(3000);
  display.setTextSize(1);  // Normal size text for game play
  display.clearDisplay();
}
int target(int x, int y, int c){   // Show target cross
  display.drawLine(x-2,y,x+2,y,c);
  display.drawLine(x,y-2,x,y+2,c);
}
int finish(){                  // Final screen to display total time
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(5,5);
  display.print("You took:");
  display.setTextSize(2);
  display.setCursor(20,18);
  display.print(total);
  display.setTextSize(1);
  display.setCursor(0,40);
  display.print(count);
  display.setCursor(8,40);
  display.print(" Targets hit");
  display.display();
  while(1){}                     // Wait for ever - HALT
}
int ring(int x, int y, int c) {  // Draw a ring - sight
  display.drawCircle(x,y,3,c);   // Radius is 3 pixels
}
int blob(int x, int y, int c){   // Fill a ring - target destroyed
  display.fillCircle(x,y,3,c);
}
int flash(int x,int y){          // Flash location of destroyed target
  t1 = ((millis() - t0)/1000.0); // Incremental search time in seconds
  total = total + t1;            // Update total searching time
  randomSeed(int(t1*100.0));     // Improve randomness
  display.clearDisplay();
  display.display();
  display.setCursor(0,0);
  display.print(total);
  count = count + 1;             // Update targets destroyed
  display.setCursor(78,0);       // Show count - top right
  display.print(count);
  display.display();
  for (int i = 0; i<3; i++){     // Flash the blob - A hit!
    blob(x,y,1);
    display.display();
    delay(300);
    blob(x,y,0);
    display.display();
    delay(300);
  }
  t0 = millis();                 // Reset incremental timer
  if (count == 5){finish();}     // Enough targets destroyed?  
}
// ++++++++++++Main Loop ++++++++++++++
void loop() {
  target(tx,ty,1);                     // Show target
  nx = 3 + int(analogRead(xPin) /14);  // Get x position of sight
  ny = 43 - int(analogRead(yPin) /31); // Get y position of sight
  ring(ox,oy,0);                       // Blank old sight
  ring(nx,ny,1);                       // Show new sight
  ox = nx;                             // New position becomes old position
  oy = ny;
  display.display();
  if ((ox == tx) & (oy == ty)){ // Is it a hit?
    flash(tx,ty);               // Yes – Explode! Update time and targets hit
    tx = random(76) + 3;        // Get new random target position
    ty = random(33) + 10;
  }
}
Nokia 5110 Arduino Project search and destroy
Nokia 5110 Arduino Project addition
Nokia 5110 Arduino Project printing digits and letters

Conclusion

This display is a 3.3-volt device and requires additional wiring and protection with either voltage shifters or 10K resistors when used with 5-volt boards like the UNO. After initial disappointments with the documentation and the poor contrast of the display I now quite like this device. It may be rather low in pixel count, supporting just 6 short lines of text, but it has a bigger display diagonal than the SSD1306 128×64, making it easier to read from a distance. It uses 5 data lines rather than the 2 used with I2C devices. It is quick enough for simple games and real-time feedback.

Additional things to try:

  • Exchange the simple potentiometer for an analog potentiometer joystick and see if this brings down your overall time with the game.
  • Use Paint.net and LCDAssistant to create a series of images to display one after another in a slide show.
  • Connect a distance sensor such as an HC-SR04 Ultrasonic or VL53L0X Time of Flight sensor and display the distance as you move your hand back and forth in front of the sensor.
  • Add an accelerometer and build a 2-dimensional ‘bubble-level’.

Hint

If your instructions are not appearing on the screen just check that you have ended the sequence with 

display.display();

This is the essential instruction to force your changes to the screen and it is so easy to forget it.

Related Posts

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

Privacy & Cookies Policy