Driving the Nokia 5110 Display with Arduino (No external library)

The Nokia 5110 Display is one of the well-loved display modules out there to use with your prototyping activities/exercises/experiments. As the datasheet says it, the module should be powered with 3.3V and not with 5V (I am a bit naughty, so I powered my modules via the 5V power supply, and they still work fine – but we stick with powering the module with 3.3V, and place current-limiting resistors for the pins).

The focus of this tutorial is to drive the display via an Arduino board. Our goal is to output some string to the display, using only the instructions from its datasheet.

COMPONENTS REQUIRED

  1. Nokia 5110 Display
  2. Arduino Nano (or any Arduino-compatible board)
  3. Four (4) 10k-ohm resistors
  4. One (1) 1k-ohm resistor
  5. Eight (8) jumper wires
  6. Breadboard

PINOUT
To start with, let us study the pinout of this module. You might have different versions of this module, but the pins should be the same. Some modules have labels 1 and 8 on them. These labels only show the order of the numbering as they appear in the module (1 = RST, 2 = CE, 3 = DC … 8 = GND):

1 - RST - Reset
2 - CE  - Chip Enable
3 - DC  - Data / Command Selection
4 - DIN - Data Input
5 - CLK - Clock
6 - VCC - Power, usually 3.3V, although 5V still worked for my modules
7 - BL  - Backllight
8 - GND - Ground

CONNECTION TO ARDUINO BOARD

NOKIA 5110 WordPress_bb

  1. Connect the RST pin of the module to Pin 6 of the Arduino board via a 10k-ohm resistor.
  2. Connect the CE pin of the module to Pin 7 of the Arduino board via a 1k-ohm resistor.
  3. Connect the DC pin of the module to Pin 5 of the Arduino board via a 10k-ohm resistor.
  4. Connect the DIN pin of the module to Pin 4 of the Arduino board via a 10k-ohm resistor.
  5. Connect the CLK pin of the module to Pin 3 of the Arduino board via a 10k-ohm resistor.
  6. Connect the VCC pin of the module to 3V3 Pin of the Arduino board.
  7. Connect the BL pin of the module to 3V3 Pin of the Arduino board.
  8. Connect the GND pin of the module to GND Pin of the Arduino board.

After having connected the Nokia 5110 Display to the Arduino using the schematics above, the setup should look like the one below:

Now, this module is driven by the PCD8544 driver, and I think the first thing we should be studying is the datasheet itself. I got interested with reading the datasheet when I saw one of Julian Ilett’s set of videos about the Nokia 5110 Display. From the datasheet, let’s study the command set needed for the module:

COMMAND SETS
Nokia 5110 Commands

COMMAND SETS PARAMETER DETAILS
Nokia 5110 Command Parameters.png

To initialize the Nokia 5110 Display, we need the following instructions from the COMMAND SETS table above (ignoring those reserved ones):

  1. Function Set (DC = 0, Instruction =  0 0 1 0 0 PD V H where PD, V and H are explained under the COMMAND SET PARAMETERS DETAILS above)
  2. Display Control (DC = 0, Instruction = 0 0 0 0 1 D 0 E where D and E are explained under the COMMAND SET PARAMETERS DETAILS above)
  3. Temperature Control (DC = 0, Instruction = 0 0 0 0 0 0 1 TC1 TC0 where TC1 and TC0 are explained the COMMAND SET PARAMETERS DETAILS above)
  4. Bias System (DC = 0,  Instruction = 0 0 0 1 0 BS2 BS1 BS0 where BS2, BS1, and BS0 are explained the COMMAND SET PARAMETERS DETAILS above)
  5. Set Vop (DC = 0, Instruction = 1 Vop6 Vop5 Vop4 Vop3 Vop2 Vop1 Vop0 where the whole instruction ranges from 10000000 to 11111111).

EXAMPLE INSTRUCTIONS FROM THE DATASHEET
In the datasheet, there is a programming example (page 22 of this datasheet) that demonstrates a set of commands to output something to the display. We will go through each step (in actual programming, you should do a A RES pulse must be applied (page 15 of the datasheet, under section 8.1 — we will demonstrate this later in the code):

STEP 1. Set SCE/CE to LOW before each command, the set it to HIGH, after sending it)
STEP 2. Send Function Set command: PD = 0, V = 0, H = 1 (DC = 0, Instruction = 00100001)
STEP 3. Send Contrast Command: (DC = 0, Instruction = 10010000)
STEP 4. Send Function Set command: PD = 0, V = 0, H = 0 (DC = 0, Instruction = 00100000)
STEP 5. Send Display Control command: D = 1, E = 0 (DC = 0, Instruction = 00001100)
STEP 6 – 12. Write the following bytes to the display (DC = 1, Bytes to write: 00011111, 00000101, 00000111, 00000000,  00011111,  00000100, 100011111).

The output for the instructions above (most significant bit first), is shown below:

This output actually is consistent with that of the datasheet on page 23, step 12:
sample output from the datasheet

You may proceed with the rest steps and thye output should be the same with that of the datasheet on page 23, step 15 (the last step for the example):


img_0758

This is the output as seen from the datasheet on page 23, step 15:
sample output from the datasheet 2.png

When sending a byte of data, the following pins are set:

  1. SCE or CE
  2. DC or D/C
  3. SCLK or CLK
  4. SDIN or DIN

This setting of the pin can be seen from  the datasheet on page 12, Figure 10:
One byte transmission

I included the Figure above because this will be used in the Arduino sketch we will be creating later. From the image above, it demonstrates that when sending a  byte, the SCE should be set to LOW. When a command to the module is to be sent, D/C should be set to LOW, and when data is to be sent to the module, D/C should be sent to HIGH. So to demonstrate, let’s write a pseudo-code for this.

Sending a command:

Set scePin = LOW
Set dcPin = LOW
Set dcByteData = 00100001 // LCD Extended Command
Transmit(dcByte to dcPin, rightmost bit first, toggling sclkPin)
Set scePin to HIGH // End of transmission

Writing data:

Set scePin = LOW
Set dcPin = HIGH
Set dcByteData = 00100111 // data to be written/sent to the module
Transmit(dcByte to dcPin, rightmost bit first, toggling sclkPin)
Set scePin to HIGH // End of transmission

Before sending any command or data, 8.1 of the datasheet says:

8.1 Initialization
Immediately following power-on, the contents of all internal
registers and of the RAM are undefined. A RES pulse
must be applied. Attention should be paid to the
possibility that the device may be damaged if not properly
reset.

We will also demonstrate the resetting of the module how this is done in the sketch later.

I think we are now ready writing our first sketch, using the Programming example as shown in the datasheet on page 22-23, Steps 1 – 15. To begin with, let us define what pins in the Arduino board are to be connected with the pins in the Nokia 5110 Display:

Arduino Pin Definition

 #define   CE    7
 #define   RST   6
 #define   DC    5
 #define   DIN   4
 #define   CLK   3

We create a method to send command / data

 void sendLCDCommand(byte dc, byte data)
 {
    digitalWrite(DC, dc);
    digitalWrite(CE, LOW);
    shiftOut(DIN, CLK, MSBFIRST, data);
    digitalWrite(CE, HIGH)
}

Arduino Pin Initialization inside the setup() method

 pinMode(CE,  OUTPUT);
 pinMode(RST, OUTPUT);
 pinMode(DC,  OUTPUT);
 pinMode(DIN, OUTPUT);
 pinMode(CLK, OUTPUT);

 // Refer to Section 8.1 of the datasheet:
 digitalWrite(RST, LOW);
 digitalWrite(RST, HIGH);

Initialize the Nokia 5110 Module inside the setup() method

 // Refer to Tables 1 and 2 of the datasheet on page 14
 // This is the same as the COMMAND SETS and 
 // COMMAND SETS PARAMETER DETAILS discussed above.

 sendLCDCommand(0, B00100001 ); // LCD Extended Commands.
 sendLCDCommand(0, B10110000 ); // Set LCD Vop (Contrast).
 sendLCDCommand(0, B00000100 ); // Set Temp coefficent.
 sendLCDCommand(0, B00010100 ); // LCD bias mode 1:48.
 sendLCDCommand(0, B00100000 ); // LCD Basic Commands.
 sendLCDCommand(0, B00001100 ); // LCD in normal mode.

In the Programming Example as demonstrated in the datasheet on page 22-23, we will begin from STEP 6 to STEP 15 since STEPS 1-5 are already done in the code above. Take note that the first parameter is DC, and the second parameter is DATA to be sent. To review, when DC = 0, it is expected that a command is to be sent, if DC = 1 then data is expected to be sent (to the module). For this exercise, we only need to have this shown once, so these instructions will be inside the setup() method after the reset command:

 sendLCDCommand(1, B00011111); // STEP 6
 sendLCDCommand(1, B00000101); // STEP 7
 sendLCDCommand(1, B00000111); // STEP 8
 sendLCDCommand(1, B00000000); // STEP 9
 sendLCDCommand(1, B00011111); // STEP 10
 sendLCDCommand(1, B00000100); // STEP 11
 sendLCDCommand(1, B00011111); // STEP 12
 sendLCDCommand(0, B00001101); // STEP 13
 sendLCDCommand(0, B10000000); // STEP 14
 sendLCDCommand(1, B00000000); // STEP 15

COMPLETE SKETCH LISTING
I think we’re done. The complete sketch is shown below:

#define  CE   7
#define  RST  6
#define  DC   5
#define  DIN  4
#define  CLK  3

void sendLCDCommand(byte dc, byte data)
{
 digitalWrite(DC, dc);
 digitalWrite(CE, LOW);
 shiftOut(DIN, CLK, MSBFIRST, data);
 digitalWrite(CE, HIGH);
}

void setup() {
 pinMode(CE,  OUTPUT);
 pinMode(RST, OUTPUT);
 pinMode(DC,  OUTPUT);
 pinMode(DIN, OUTPUT);
 pinMode(CLK, OUTPUT);

 digitalWrite(RST, LOW);
 digitalWrite(RST, HIGH);

 sendLCDCommand(0, B00100001 ); // LCD Extended Commands. You can use 0x21
 sendLCDCommand(0, B10110000 ); // Set LCD Vop (Contrast). You can use 0xB0
 sendLCDCommand(0, B00000100 ); // Set Temp coefficent. You can use 0x04
 sendLCDCommand(0, B00010100 ); // LCD bias mode 1:48. You can use 0x14
 sendLCDCommand(0, B00100000 ); // LCD Basic Commands. You can use 0x20
 sendLCDCommand(0, B00001100 ); // LCD in normal mode. You can use 0x0C
 sendLCDCommand(1, B00011111); // STEP 6
 sendLCDCommand(1, B00000101); // STEP 7
 sendLCDCommand(1, B00000111); // STEP 8
 sendLCDCommand(1, B00000000); // STEP 9
 sendLCDCommand(1, B00011111); // STEP 10
 sendLCDCommand(1, B00000100); // STEP 11
 sendLCDCommand(1, B00011111); // STEP 12
 sendLCDCommand(0, B00001101); // STEP 13
 sendLCDCommand(0, B10000000); // STEP 14
 sendLCDCommand(1, B00000000); // STEP 15 
}

void loop() {
}

Compile the code above to your Arduino board (I am using an Arduino Nano for this exercise. You may also use UNO for this. The output of the code to your module should be similar to this:
img_0757

MY OWN EXPERIMENT
Just for the fun of it, I created my own code and displayed the letters E L D R I C to the module. Here is the complete listing of my code:

#define CE 7
#define RST 6
#define DC 5
#define DIN 4
#define CLK 3

void sendLCDCommand(byte dc, byte data)
{
 digitalWrite(DC, dc);
 digitalWrite(CE, LOW);
 shiftOut(DIN, CLK, MSBFIRST, data);
 digitalWrite(CE, HIGH);
}

void setup() {
 pinMode(CE, OUTPUT);
 pinMode(RST, OUTPUT);
 pinMode(DC, OUTPUT);
 pinMode(DIN, OUTPUT);
 pinMode(CLK, OUTPUT);
 digitalWrite(RST, LOW);
 digitalWrite(RST, HIGH);

 sendLCDCommand(0, B00100001 ); // LCD Extended Commands.
 sendLCDCommand(0, B10110000 ); // Set LCD Vop (Contrast).
 sendLCDCommand(0, B00000100 ); // Set Temp coefficent.
 sendLCDCommand(0, B00010100 ); // LCD bias mode 1:48.
 sendLCDCommand(0, B00100000 ); // LCD Basic Commands.
 sendLCDCommand(0, B00001100 ); // LCD in normal mode.

// E
 sendLCDCommand(1, B01111111);
 sendLCDCommand(1, B01001001);
 sendLCDCommand(1, B01001001);
 sendLCDCommand(1, B01001001);
 sendLCDCommand(1, B01001001);
 sendLCDCommand(1, B00000000);

// L
 sendLCDCommand(1, B01111111);
 sendLCDCommand(1, B01000000);
 sendLCDCommand(1, B01000000);
 sendLCDCommand(1, B01000000);
 sendLCDCommand(1, B01000000);
 sendLCDCommand(1, B00000000);

// D
 sendLCDCommand(1, B01111111);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B00111110);
 sendLCDCommand(1, B00000000);

// R
 sendLCDCommand(1, B01111111);
 sendLCDCommand(1, B00001001);
 sendLCDCommand(1, B00001001);
 sendLCDCommand(1, B00001001);
 sendLCDCommand(1, B01110110);
 sendLCDCommand(1, B00000000);

// I
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01111111);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B00000000);

// C
 sendLCDCommand(1, B00111110);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B01000001);
 sendLCDCommand(1, B00000000);
}

void loop() {
}

The output of the above sketch when uploaded to the Arduino is shown below:

img_0765
img_0764

How did I come up with those letter? I’ll get an example above, say letter ‘E’. If you look at the series of bits below, and flipping your head to the right while looking at the bits, you will see the letter ‘E’:

01111111
01001001
01001001
01001001
01001001
00000000

In the code, this should be:
sendLCDCommand(1, B01111111);
sendLCDCommand(1, B01001001);
sendLCDCommand(1, B01001001);
sendLCDCommand(1, B01001001);
sendLCDCommand(1, B01001001);
sendLCDCommand(1, B00000000);

Isn’t exciting to be experimenting? Let me know if you’ve done the same thing. Now, the goal of this exercise is to somehow give us an idea how a command is sent, data is written (or pixel is turned on) without the use of any external libraries. The next tutorial for the Nokia 5110 display will be using the common libraries to drive this display.

For comments and corrections, please do leave me a comment. I am still a beginner, and is open to correction. I hope to help other beginners like me as well.

Thank you very much!

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s