HD44780-compatible LCD and 74HC164

Hi,

I found a nice device, containing 4 Buttons, a 4 way digital controller and a 2x16 LC Display HD44780-compatible controlled by a serial to parallel converter(?) 74HC164. This device was a controller for some game-console tool or such (X-Assist).

I identified the wiring and connected 2 pins of my Arduino with the 74HC164 (data and clock, data also connected to the R/S pin of the display) and another pin with the E(nable) of the display.

A test programm can write something(*) to the display.

(*) I used random bits ;D that sometimes when I randomly init the display, leads to readable characters on the display.

I tried to adapt the init from http://www.arduino.cc/playground/Code/LCD3wires but with no luck so far.

  • So should I rip the 74HC164 and use a HEF4094 so that I can use the lib above?
  • Ask here for help to change the code (the bit magic is beyond my understanding) in the example above? ;-)
  • other suggestions?

I really cant use a solution with 6 pins, I need the other pins for the buttons and the output of my project.

Thanks, Carsten

http://www.nxp.com/acrobat_download/datasheets/74HC_HCT164_3.pdf

http://www.standardics.nxp.com/products/hef/datasheet/hef4094b.pdf

The pinout on the 164 is different.

Pin 2 is the same on both but pin 1 on the 164 needs to be tied high as it's just a duplicate of 2.

You don't need the strobe hooked up afaikt. There is no output enable so it doesn't need hooked up. The library may require both to be defined.

So trace and hook pin 1 to 10K resistor then to +5, pin 2 to serial data from arduino, clock and data lines from arduino to the 164 and proper voltage and grounds and try it. If it works you've found a chip that only needs two lines I think.

Your main problem will be an inability to see if it's all working unless you have a logic probe or oscope.

Thanks for your answer.

I think I will try with the hardware I have here some more, it seems to me that I am close.

However when this fails I will cut some wires and rewire the cable to the display which is in my opinion all I need to do.

With my little understanding of electronics and logic I may be wrong but I cant see a reason why it should not work wit just two lines, maybe some smaller code changes are needed.

Carsten ::)

So far so good.

Here a picture of this nice hardware. I plan to use this for a camera control.

I can init the display as it seems and print out text.

I cant send commands after printing something, e.g. a “clear” command clears something but afterwards, random garbish is printed to the display instead the text.

Same for cursor commands etc.

For now I am using 4 pins on the arduino.

The shiftOut(DATA, CLOCK, LSBFIRST, pattern); seems not to work, for my case, it always misses one bit.

/*
 * X Assist LCD Test
 *
 */

// Pins
int CLOCK = 2;
int DATA = 3;
int EEEE = 4;
int RS = 5;
int LED = 13;

void setup()
{
  pinMode(CLOCK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(EEEE, OUTPUT);
  pinMode(RS, OUTPUT);
  initLCD();
}


void sendByte(byte pattern)
{
  delay(1);
  digitalWrite(EEEE, LOW);  
  for (byte i=0; i <= 7; i++){
    digitalWrite(CLOCK, LOW);  
    //    delay(1);
    digitalWrite(DATA, pattern & (1<<(7-i)));  
    digitalWrite(LED, pattern & (1<<(7-i)));  
    //    delay(1);
    digitalWrite(CLOCK, HIGH);  
  }

  digitalWrite(EEEE, HIGH);    
  //  delay(5);
}


void sendSByte(byte pattern)
{
  digitalWrite(EEEE, LOW);    
  delay(1);
  shiftOut(DATA, CLOCK, LSBFIRST, pattern);
  digitalWrite(EEEE, HIGH);    
  delay(1);
}


void initLCD()
{
  delay(105);
  digitalWrite(RS, LOW);  
  delay(5);  
  sendByte(B00110000);
  delay(60);
  sendByte(B00110000);
  delay(60);
  sendByte(B00110000);
  delay(60);
  sendByte(B00110000);
  delay(60);
  sendByte(B00111000); //2 Lines 5x7pixel
  sendByte(B00001000);   
  sendByte(B00000001); 
  sendByte(B00000110);  //Decrement  Display Shift 
  sendByte(B00001111);  // Cursor 
  delay(60);
  delay(5);
  sendByte(B0001000);
  delay(60);
//  sendByte(B0000010);
//  delay(5);
  digitalWrite(RS, HIGH);   
}

void printIn(char msg[]) {
  unsigned int i;
  for (i=0;i < strlen(msg);i++){
    sendByte(msg[i]);
  }
}

void loop()
{
  int i;
  printIn("Hallo Arduino! ");

  delay(1000);

// Not working
  digitalWrite(RS, LOW);    
//    sendByte(B0001000);
  digitalWrite(RS, HIGH);    
  delay(5);

  /*
  for (int i=49; i <= 102; i++){
   sendByte(i);
   delay(10);
   }
   delay(1000);
   */

}

Carsten

Success!

// Send a byte
void sendByte(byte pattern)
{
  shiftOut(DATA, CLOCK, MSBFIRST, pattern);
  digitalWrite(EEEE, LOW);    
  delayMicroseconds(700); //600 min?
  digitalWrite(EEEE, HIGH);    
}

I found my error, and by the way I found that the shiftOut also works. My error was that I set the E(nable) line before sending the data which caused weird things.

Carsten

PS: I am now really keen to test if it would also work with 2 pins (using the 74HC164 as multiplexer for the signal lines (E,RS,RW) and 4bit mode) :-?

Nice photo! Thanks for posting that.

Really nice device :wink: I can see the prices for these go up on *bay.

Here is a small video of the operation: http://vimeo.com/3556807.

/*
 * X Assist LCD Test
 *
 */

// Pins (Note: Change to defines)
int CLOCK = 2; //on the 74HC164
int DATA = 3;  //on the 74HC164 (means A1/A2 interconnected)
int EEEE = 4;  //on the display
int RS = 5;    //on the display

int BUTA = 6;
int BUTB = 7;

int PADL = 8;
int PADR = 10;
int PADD = 9;
int PADU = 11;

int LED = 13;

// Buffer for text
byte line[80];

// cursor position
byte cx = 0;
byte cy = 0;


void setup()
{
  pinMode(CLOCK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(EEEE, OUTPUT);
  pinMode(RS, OUTPUT);

  pinMode(BUTA, INPUT);
  pinMode(BUTB, INPUT);
  pinMode(PADR, INPUT);
  pinMode(PADL, INPUT);
  pinMode(PADU, INPUT);
  pinMode(PADD, INPUT);
  initLCD();
//  Serial.begin(38400);
}


// Send a byte
void sendByte(byte pattern)
{
  shiftOut(DATA, CLOCK, MSBFIRST, pattern);
  digitalWrite(EEEE, LOW);    
  delayMicroseconds(700); //600 min?
  digitalWrite(EEEE, HIGH);    
}

// Send a byte COMMAND
void sendCMD(byte pattern)
{
  digitalWrite(RS, LOW);    
  shiftOut(DATA, CLOCK, MSBFIRST, pattern);
  digitalWrite(EEEE, LOW);    
  delayMicroseconds(700); //600 min?
  digitalWrite(EEEE, HIGH);    
  digitalWrite(RS, HIGH);    
}


void initLCD()
{
  delay(105);
  digitalWrite(RS, LOW);  
  delay(5);  
  sendByte(B00110000);
  delay(60);
  sendByte(B00110000);
  delay(60);
  sendByte(B00110000);
  delay(60);
  sendByte(B00110000);
  delay(60);
  sendByte(B00111000); //2 Lines 5x7pixel
  sendByte(B00001000);   
  sendByte(B00000001); 
  sendByte(B00000110);  //Decrement  Display Shift 
  sendByte(B00001110);  // Cursor  D C B
  delay(60);
  delay(5);
  sendByte(B0000001);
  delay(60);
  digitalWrite(RS, HIGH);   
  sendCMD(0x03);   // HOME  

  // Init the line buffer
  for (int i=0;i < 80;i++){
    line[i] = 48+16;
  }

}

void printIn(char msg[]) {
  unsigned int i;
  for (i=0;i < strlen(msg);i++){
    sendByte(msg[i]);
  }
}


void loop()
{
  // Delete current character (Buttons are LOW active)
  if (digitalRead(BUTA)  == LOW) {     
    line[cx+(0x40*cy)] = 32; //SPACE 
    sendByte(byte(line[cx+(0x40*cy)]));
    sendCMD(0x10);   // Cursor Left
    delay(150);
  } 
  // Switch Lines
  if (digitalRead(BUTB)  == LOW) {     
    cy = (cy + 1) & 1;  // & 1 means x modulo 2
    sendCMD(0x80+cx+(0x40*cy));   // Cursor
    delay(200);
  } 
  // Cursor right
  if (digitalRead(PADR)  == LOW) {     
    cx = (cx + 1) & 15 ;// & 1 means x modulo 16
    sendCMD(0x80+cx+(0x40*cy));   // Cursor 
    delay(200);
  } 
  // Cursor left
  if (digitalRead(PADL)  == LOW) {     
    cx = (cx - 1) & 15; // & 1 means x modulo 16
    sendCMD(0x80+cx+(0x40*cy));   // Cursor 
    delay(200);
  } 
  // Char up
  if (digitalRead(PADU)  == LOW) {        
    line[cx+(0x40*cy)] = char((int(line[cx+(0x40*cy)])-1)); 
    sendByte(byte(line[cx+(0x40*cy)]));
    sendCMD(0x10);   // Cursor Left
    delay(150);

  } 
  // Char down
  if (digitalRead(PADD)  == LOW) {     
    line[cx+(0x40*cy)] = char((int(line[cx+(0x40*cy)])+1)); 
    sendByte(byte(line[cx+(0x40*cy)]));
    sendCMD(0x10);   // Cursor Left
    delay(150);
  } 

}

Just found the source of that gadget: http://www.psillustrated.com/psillustrated/hard_rev.php/262/xploder-professional-playstation.html

Carsten

Awesome awesome awesome!

I love it! Reminds me alot of why I even started getting interested in the Arduino.. the ability to pick up almost anything electrical, and with the right experience (and some luck), you can interface the two and do as you please!

Good job, and agreed, thanks for the pictures and code, still on the climb to learning code, every bit helps. Been taking a look at using LCDs without libraries (just to.. well, do it!) and this offers a hands-on approach :)

Keep up the good work, haxx0rs up some more old school devices :D

A HD44780 and 74xx164? Seems right up my alley. mircho here and I just finished off a library for just that :) http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1243195750 Maybe it works with your hardware, probably with some modification if the RS-line is also tied to the data output. http://code.google.com/p/arduinoshiftreglcd/

EDIT: Oh, and of course it depends on your hardware :p The library use the LCD in 4-bit mode only as shown in the schematics. But you could at least get the functions from it, makes it easier to use.

Hi Carsten,

Nice investigative work. Please tell me, can these OEM displays be purchased surplus somewhere or did you just stumble onto a single unit?

TIA. Kind regards, Mike

Sadly I only found one in my brothers in law drawer ;-)

Carsten