Anleitungen, Arduino

[Arduino] Connecting a Nokia 5110 display to Arduino

The “Connecting a Nokia 5110 display to Arduino” tutorial is finished. Have a look at the three parts and enjoy.

[Arduino] Connecting a Nokia 5110 display to Arduino –
Part1: Wiring

[Arduino] Connecting a Nokia 5110 display to Arduino –
Part2: Explaining the code library

[Arduino] Connecting a Nokia 5110 display to Arduino –
Part3: 5×7 bit ASCII representation

Advertisements
Standard
Anleitungen, Arduino

[Arduino] Connecting a Nokia 5110 display to Arduino – Part3: 5×7 bit ASCII representation

In this part of the Nokia 5110 display tutorial I am going to explain the representation of an single ASCII character on the display. Let’s have a look on the code again. In the top part of the code a very long array is defined:

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 %
...

Let’s examine the code for the explanation mark(!) in line two.

{0x00, 0x00, 0x5f, 0x00, 0x00} //21 !

Every character in this code example is displayed in an 5×7 matrix. This means that every hex-value (byte) of data represents one row in this matrix. As you can see the first and last two bytes of the explanation mark data is empty/null so that only the row in the middle is filled. As you remember we set the display controller to draw the data horizontally that means that every byte of data is saved row after row. If the controller reaches the 84th byte of data it jumps to the next column. Have a closer look at point 7.7 of the PDC8544 datasheet to undertand this fact.

Have a look at this picture to understand the 5×7 pattern.

Describing image of the representation of an ASCII character with a grid of 5x7 bits

As you can see the eighth bit of data is not part of the actual character. It is used to create a margin at the bottom of the symbol.
The data is written into the controllers memory by using the LcdWrite() method.

void LcdWrite(byte dc, byte data) {
  digitalWrite(PIN_DC, dc); //Data or Command?
  digitalWrite(PIN_SCE, LOW); //Enable chip
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data); //Shift data bit by bit, most significant bit first
  digitalWrite(PIN_SCE, HIGH); //Disable chip
}

The first parameter defines whether  the passed data is a command for the controller or just data to be written into the memory (like a single character). After the DC pin is set to HIGH or LOW and the chip is enabled to receive data, the actual data transfer starts. The data is shifted bit by bit into the memory of the controller starting with the most significant bit (MSB). That means the the first bit (from left) is put into the memory first. This pixel will be passed bit after bit into the last column of the 5×7 matrix. Have a look at the above picture to understand that fact.

The method LcdCharacter() does exactly the same for every byte (row of data) for an defined ASCII character of the already mentioned array.

void LcdCharacter(char character) {
  LcdWrite(LCD_D, 0x00); //Writes empty row
  for (int index = 0; index < 5; index++) {
    LcdWrite(LCD_D, ASCII[character - 0x20][index]); //Finds the passed character in the ASCII array and writes it row by row (byte by byte)
  }
  LcdWrite(LCD_D, 0x00); //Writes empty row
}

That’s all. I hope I could help to set your Nokia 5110 display up and run it with your Arduino.

Standard
Anleitungen, Arduino

[Arduino] Connecting a Nokia 5110 display to Arduino – Part2: Explaining the code library

In this second part of the Nokia 5110 display tutorial I will explain the code library from the Arduino website. I’ve chosen the second example written by Jim Park. The main topic of this post is the initialization of the display by code. The presentation of a character will be treated in the third and last chapter of this tutorial.

Lets start with the definitions:

 #define PIN_SCE 12
 #define PIN_RESET 10
 #define PIN_DC 9
 #define PIN_SDIN 11
 #define PIN_SCLK 13
 #define PIN_LED 6
 #define LCD_C LOW //Send command
 #define LCD_D HIGH //Send data
 #define LCD_X 84
 #define LCD_Y 48

The first part describes the wiring, which I explained in the last tutorial. Then there are two constants set called LCD_C and LCD_D. The first one is used to send a LOW to the controllers D/C port. This LOW indicates that the following eight bits represent a command that has to be interpreted by the controller. Sending a HIGH to the controller indicates that the following byte of data shall be written into the memory of the controller and finally be shown on the display.

The last two constants define the width (LCD_X) and height (LCD_Y) of the display measured in pixels.

After that a long constant array of ASCII character has been defined. As already mentioned this part will be explained in the next chapter. So let’s take a look on the setup()-method now.

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

So this one looks quite easy. We are just calling two methods. The first one is LcdInitialise():

void LcdInitialise(void) {
 pinMode(PIN_SCE, OUTPUT);
 pinMode(PIN_RESET, OUTPUT);
 pinMode(PIN_DC, OUTPUT);
 pinMode(PIN_SDIN, OUTPUT);
 pinMode(PIN_SCLK, OUTPUT);
 pinMode(PIN_LED, OUTPUT);
 //Needed to initialize the display. Without reset display might get damageed
 digitalWrite(PIN_RESET, LOW);
 digitalWrite(PIN_RESET, HIGH);
 LcdWrite(LCD_C, 0x21 ); // LCD Extended Commands.
 LcdWrite(LCD_C, 0xB1 ); // Set LCD Vop (Contrast). //B1
 LcdWrite(LCD_C, 0x04 ); // Set Temp coefficent. //0x04
 LcdWrite(LCD_C, 0x13 ); // LCD bias mode 1:48. //0x13
 LcdWrite(LCD_C, 0x0c ); // LCD in normal mode. 0x0d for inverse
 LcdWrite(LCD_C, 0x20); // Set chip active, user basic instructions, use horizontal adressing
 LcdWrite(LCD_C, 0x0C); //No Operation
 digitalWrite(PIN_LED, HIGH); //Enables the backlight of the display
}

In the first part of the method the ports on the Arduino are set to output-mode. The next part performs a reset of the displays memory by giving the display a LOW followed by a HIGH. As the comment says this is needed (because the datasheet says so in chapter 8.1) otherwise the display might get damaged.

The next lines contain some commands represented by a hex value. Let’s have a look on the following line:

LcdWrite(LCD_C, 0x20);

The value of LCD_C is a LOW. The value 0x20 is represented binary as 0010 0000. So we have an binary 1 on the third bit. If you now take a look at  Table 1 on page 14  of the datasheet you see the following table:

Example of an instruction for the PCD8544 controller

The first rows shows the state of the D/C port and the other eight rows describe the value of the data bits. As you can see the command “Function set” has an 1 on the third position. The first three (least significant bits) are named PD, V and H. This values are described in table 2 on the same page.

Description of the Function Set command of the PCD8544

So with the value 0010 0000 and the D/C port on LOW we are setting

  • the PD value to 0, which means the chip is active
  • the V value to 0, which enables the horizontal addressing
  • and the H value to 0, which enables the basic instruction set

Sending a 0010 0010 (0x22) command for example would enable the vertical addressing.

The last call in the setup()-method is the LCDClear() command:

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

The LCDClear() method loops through the whole memory and sets it to 0 with the effect that the displays gets blank.  The PDC8544 expects always a set of eight bit (one byte) of data at once. So the number of pixels (LCD_X*LCD_Y) has to be divided by eight to get the correct number of memory slots to fill. Each of this slots saves one byte of data which is filled with 0x00 or 0000 0000.

Using this code your display will be (hopefully) initialized correctly but should remain without any content. In the next part we will fill it with some text.

Standard