Topics

► Games

► Music

► Clocks

► GPS

► Tools

► Tutorials

By processor

► ATtiny85

► ATtiny84

► ATtiny841

► ATtiny2313

► ATtiny861

► ATmega328

► ATmega1284

About Me

About Me

Feeds

RSS feed

Text Display for the Arduino Uno

28th August 2016

This article describes a simple scrolling text display which provides 8 lines of 21 characters per line. It provides a convenient way to display text from an Arduino for debugging, or as an interface to an application:

TextDisplay.jpg

The text display is based on a 1.3" 128x64 SPI OLED display, a small display about 3.5cm (1.4") wide with a very clear, bright monochrome display, and based on the SSD1306 driver chip. It is available from Adafruit [1], or in the UK from Proto-PIC [2] or Makersify [3].

The text display is also compatible with the 1.3" 128x64 SPI 7-pin OLED displays available from Banggood [4] or AliExpress. These are based on a slightly different driver chip, the SH1106, which supports displays up to 132 pixels wide, so two small changes have to be made to the program to accommodate this. These are implemented by a constant SH1106 which should be set to 0 for SSD1306 displays, and 1 for SH1106 displays.

The program is derived from my Tiny Terminal, and uses the hardware scrolling provided by the display to give very fast screen update when scrolling a screenful of text.

Adafruit provide a text and graphics display library that also supports graphics, but its disadvantage is that it needs a 1Kbyte RAM buffer to hold a display image. This text terminal doesn't require any RAM, and so is ideal for applications where memory is at a premium.

Plotting characters

The text display writes characters to successive character positions on the display. When you reach the end of the bottom line of the display it scrolls the display up, just like on a terminal, so you always see the last 8 lines written to the display. The scrolling is handled automatically by the display's Display Offset command.

Here's a simplified example showing how characters are plotted to the display. First we define the bitmap definitions of the character set. Here are the definitions for the first eight characters 0x20 (space) to 0x27 (quote):

const uint8_t CharMap[96][6] PROGMEM = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 }, 
{ 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00 }, 
{ 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00 }, 
{ 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 }, 
{ 0x36, 0x49, 0x56, 0x20, 0x50, 0x00 }, 
{ 0x00, 0x08, 0x07, 0x03, 0x00, 0x00 } ...

Then here's the routine to plot a character:

void PlotChar (char c, uint8_t line, uint8_t column) {
  column = column*6+2*SH1106;
  Command(0xB0 + (line & 0x07));
  Command(0x00 + (column & 0x0F)); // Column start low
  Command(0x10 + (column >> 4));   // Column start high
  for (uint8_t col = 0; col < 6; col++) {
    Data(pgm_read_byte(&CharMap[(c & 0x7F)-32][col]));
  }
}

where a call to Command() writes a control command to the display, and a call to Data() writes a data byte to the display. For example, to plot an "A" (ASCII 65) in column 0 of the bottom line of the display the call would be:

PlotChar(65, 7, 0);

The full text display program provides bitmaps for the 96 characters from ASCII 0x20 (space) up to 0x7F, and they are stored in program memory to save RAM space on the ATmega328.

Control characters

Characters are printed to the text display using the routine Display(). This calls PlotChar() to print the characters 32 to 127, and handles control characters. It uses the variable Scroll to take account of the number of lines by which the display has been scrolled:

void Display (char c) {
  static uint8_t Line = 0, Column = 0, Scroll = 0;
  if (c >= 32) {                   // Normal character
    PlotChar(c, Line+Scroll, Column++);
    if (Column > 20) {
      Column = 0;
      if (Line == 7) ScrollDisplay(&Scroll); else Line++;
    }
  } else if (c == 12) {            // Clear display
    for (uint8_t p=0; p < 8; p++) ClearLine(p);
    Line = Scroll;
    Column = 0;
  } else if (c == 13) {            // Return
    Column = 0;
    if (Line == 7) ScrollDisplay(&Scroll); else Line++;
  } 
}

Currently the only control characters supported are Clear, which clears the display, and Return, which returns the printing position to the start of the next line, scrolling the display if necessary.

Scrolling the display

The display is scrolled by the following routine, that also updates the scroll position, *scroll:

void ScrollDisplay (uint8_t *scroll) {
  ClearLine(*scroll);
  *scroll = (*scroll + 1) & 0x07;
  Command(0xD3);
  Command(*scroll << 3);
}

This calls ClearLine() to clear the top line of the display before scrolling it around to the bottom of the display:

void ClearLine (uint8_t line) {
  Command(0xB0 + line);
  Command(0x00); // Column start low
  Command(0x00); // Column start high
  for (uint8_t b = 0 ; b < 128 + 4*SH1106; b++) Data(0);
}

This clears 128 bytes of display memory, or 132 bytes in the case of the SH1106-based displays.

The circuit

Here's the circuit for the text display:

TextDisplayArduino.gif

I built it on the Arduino ProtoShield from Sparkfun [5].

Here's the full program of the text display for the Arduino: Text Display Program.

Update

31st August 2016: I've updated the above description and program to include support for SH1106-based 128x64 SPI OLED displays.


  1. ^ Monochrome 1.3" 128x64 SPI OLED Graphic Display on Adafruit.
  2. ^ Monochrome 1.3" 128x64 OLED Graphic Display on Proto-PIC.
  3. ^ Monochrome 1.3" 128x64 OLED Graphic Display on Makersify.
  4. ^ 1.3 Inch 7 Pin White OLED 128x64 SPI Interface Display Module on Banggood.
  5. ^ Arduino ProtoShield Kit on Sparkfun.

blog comments powered by Disqus