3 wires interface for LCD display

This post is based on the work made previously by tomek in wiring LCD displays using 4 bits. The basic idea is to group the 7 pins that are needed to drive the LCD in only 3 using a shift register. This is a cheap alternative to serial LCDs.


Figure 1: schematic by Philip Warner

The schematic shows that wiring the LCD is a simple operation. It has been drawn in a way that makes it possible to develop this as part of a single sided PCB including a variable resistor to control the LCD's contrast. Note that the pin-out of the LCD module may differ slightly from the pin-out depicted; some LCD modules have pins 15 and 16 on the left side, before pin 1.


Figure 2: wiring the components

In this picture we see the actual connections on a breadboard. Everything runs on the power from the USB powered board. The code below includes a couple of functions that will print integer numbers to the LCD, as well as single characters.

Also available is a library: Attach:LCD3WireLibrary.zip. To remain command-compatible with the LCD4BitLibrary, this library does not contain the number-formatting code which is included in the code below.

/* LCD display with 3 wires
 * ------------------------
 *
 * based on previous examples by Tomek. 
 * This program will use shiftout to send 
 * data to a shift register with strobe that 
 * will transfer the serial into parallel data
 *
 * the pin-out for LCD displays is standard and there is plenty
 * of documentation to be found on the internet.
 *
 * (cleft) 2007 Dojodave for K3 and SADI
 * http://www.arduino.cc
 *
 */

// pins to be used on Arduino
int led = 13;
int count = 0;
int Dout = 11;
int STR = 12;
int CLK = 10;

// the Qx in the order they are connected on the chip
int DI = 1;
int RW = 2;
int Enable = 3;
int DB[] = {
  7, 6, 5, 4};

void LcdInit() {
  delay(100);
  // initialize LCD after a short pause
  // needed by the LCD's controller

  /////////// 4 pin initialization
  LcdCommandWrite(0x03); // function set:
  // 4 pin initialization
  delay(64);
  LcdCommandWrite(0x03); // function set:
  // 4 pin initialization
  delay(50);
  LcdCommandWrite(0x03); // function set:
  // 4 pin initialization
  delay(50);
  LcdCommandWrite(0x02); // function set:
  // 4 pin initialization
  delay(50);
  LcdCommandWrite(0x2C); // function set:
  // 4-bit interface, 1 display lines, 5x7 font
  /////////// end of 4 pin initialization 

  delay(20);
  LcdCommandWrite(0x06); // entry mode set:
  // increment automatically, no display shift
  delay(20);
  LcdCommandWrite(0x0E); // display control:
  // turn display on, cursor on, no blinking
  delay(20);
  // clear display, set cursor position to zero
  LcdCommandWrite(0x01); 
  delay(100);

  LcdCommandWrite(0x80); // display control:
  delay(20);
}

void sendByteOut(int value) {
  shiftOut(Dout, CLK, LSBFIRST, value);
  digitalWrite(STR, HIGH);
  delayMicroseconds(10);
  digitalWrite(STR,LOW);
}

void LcdCommandWrite(int value) {
  int i = 0;
  int value1 = 0;
  int control = 0; // stores DI and RW
  digitalWrite(STR,LOW); // set the strobe LOW
  control = value >> 8; // get the control signals DI and RW
  control <<= 5; // shift the control signals to the left
  value1 = value;
  value1 >>= 4; //send the first 4 databits (from 8) 
  value1 |= control; // set the control values
  value1 &= 239; // set Enable LOW
  sendByteOut(value1);
  value1 |= 16; // Set Enable HIGH
  sendByteOut(value1);
  value1 &= 239; // set Enable LOW
  sendByteOut(value1);

  delay(1);

  value &= 15; // set HByte to zero 
  value |= control; // set the control values
  value &= 239; // set Enable LOW
  sendByteOut(value);
  value |= 16; // Set Enable HIGH
  sendByteOut(value);
  value &= 239; // set Enable LOW
  sendByteOut(value);
}

void LcdDataWrite(int value) {
  int i = 0;
  int value1 = 0;
  digitalWrite(STR,LOW); // set the strobe LOW
  value1 =value;
  value1 >>= 4; //send the first 4 databits (from 8) 
  value1 |= 64; // set DI HIGH
  value1 &= 223; // set RW LOW
  value1 &= 239; // set Enable LOW
  sendByteOut(value1);
  value1 |= 16; // Set Enable HIGH
  sendByteOut(value1);
  value1 &= 239; // set Enable LOW
  sendByteOut(value1);

  delay(1);

  value &= 15; // set HByte to zero 
  value |= 64; // set DI HIGH
  value &= 223; // set RW LOW
  value &= 239; // set Enable LOW
  sendByteOut(value);
  value |= 16; // Set Enable HIGH
  sendByteOut(value);
  value &= 239; // set Enable LOW
  sendByteOut(value);
}

// efficient way of multiplying numbers by themselves
int pow(int base, int expo) {
  int temp = 1;
  for (int c = 1; c <= expo; c++) {
    temp *= base;
  }
  return temp;
}

// checks out how many digits there are in a number
int estimateDigits(int nr) {
  int dec = 10;
  int temp = 1;
  int div = nr/dec;
  while (div > 0) {
    dec *= 10;
    div = nr/dec;
    temp++;
  }
  return temp;
}

// shows numbers on the display
void LcdNumberWrite(int nr) {
  int digits = estimateDigits(nr);
  LcdNumberWrite(nr, digits);
}

// this function help us to write numbers 
// with more than one digit
void LcdNumberWrite(int nr, int digits) {
  for (int i = digits-1; i >= 0; i--) {
    int dec = pow(10,i);
    int div = nr/dec;
    LcdDataWrite(div+48); 
    if (div > 0) {
      nr -= div*dec; 
    }
  }
}

void setup (void) {
  int i = 0;
  for (i=CLK; i <= STR; i++) {
    pinMode(i,OUTPUT);
  }
  LcdInit();
  LcdCommandWrite(0x0F); //  cursor blink
  delay(10);
}

void loop (void) {
  LcdCommandWrite(0x02); // set cursor position to zero
  delay(10);

  // Write the message
  //like this
  LcdDataWrite('L');
  LcdDataWrite('c');
  LcdDataWrite('d');

  //or like this
  int wrote[] = {
    'D', 'i', 's', 'p', 'l', 'a', 'y', ' '  };
  for ( count = 0; count<=7; count++) {
    LcdDataWrite(wrote[count]);
  } 

  LcdDataWrite('w');
  LcdDataWrite('i');
  LcdDataWrite('t');
  LcdDataWrite('h');
  LcdDataWrite(' ');

  // and Numbers over 9 easily like this
  LcdNumberWrite(3);
  LcdDataWrite(' ');

  LcdDataWrite('P');
  LcdDataWrite('i');
  LcdDataWrite('n');
  LcdDataWrite('s');

  delay(3000);
}


TODO

  • migrate all the commands to a library format --> 20080310 library by Aldo Hoeben
  • redo the schematics and pictures --> 20080310 new schematic by Philip Warner

HISTORY

For more information write to: d.cuartielles [at] arduino.cc