Interfacing Arduino to LCD Screen w/4bit data.

Dear Mem,

Fiiiuuu !!! These are major words !!!

The task is really complex. Thank you much for what you have done.

If it works, I will be very happy.

Will tell you.

OldBeaver

Ok, here is the complete file. Make a copy of your exisiting version of LiquidCrystal.cpp (perhaps call it: LiquidCrystal.cpp.org) then replace everything in LiquidCrystal.cpp with the code below. Delete the file LiquidCrystal.o and recompile

#include "LiquidCrystal.h"

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "WProgram.h"

// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set: 
//    DL = 1; 8-bit interface data 
//    N = 0; 1-line display 
//    F = 0; 5x8 dot character font 
// 3. Display on/off control: 
//    D = 0; Display off 
//    C = 0; Cursor off 
//    B = 0; Blinking off 
// 4. Entry mode set: 
//    I/D = 1; Increment by 1 
//    S = 0; No shift 
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).


LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
  uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
  uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) :
  _four_bit_mode(0), _rs_pin(rs), _rw_pin(rw), _enable_pin(enable)
{
  _data_pins[0] = d0;
  _data_pins[1] = d1;
  _data_pins[2] = d2;
  _data_pins[3] = d3; 
  _data_pins[4] = d4;
  _data_pins[5] = d5;
  _data_pins[6] = d6;
  _data_pins[7] = d7; 
  
  pinMode(_rs_pin, OUTPUT);
  pinMode(_rw_pin, OUTPUT);
  pinMode(_enable_pin, OUTPUT);
  
  for (int i = 0; i < 8; i++)
    pinMode(_data_pins[i], OUTPUT);
 
  command(0x38);  // function set: 8 bits, 1 line, 5x8 dots
  command(0x0C);  // display control: turn display on, cursor off, no blinking
  command(0x06);  // entry mode set: increment automatically, display shift, right shift
  clear();
}

LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
  uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) :
  _four_bit_mode(1), _rs_pin(rs), _rw_pin(rw), _enable_pin(enable)
{
  _data_pins[0] = d0;
  _data_pins[1] = d1;
  _data_pins[2] = d2;
  _data_pins[3] = d3; 
  
  pinMode(_rs_pin, OUTPUT);
  pinMode(_rw_pin, OUTPUT);
  pinMode(_enable_pin, OUTPUT);
  
  for (int i = 0; i < 4; i++)
    pinMode(_data_pins[i], OUTPUT);

  command(30);
  delayMicroseconds(5000);
  command(30);
  delayMicroseconds(100);
  command(30);
  delayMicroseconds(100);
  command(20);
  delayMicroseconds(100);
  
  command(0x28);        //Function Set, D=0, N=1, F=0 (4 bits, 2 line, 5x8 dots)
  delayMicroseconds(80);
  command(0x08);        //Display ON/OFF Control', D=0, C=0, B=0 (display off, cursor off, blink off)
  delayMicroseconds(80);
  command(0x01);            //Clear Display
  delayMicroseconds(5000); 
  command(0x06);            //Entry Mode Set, I/D=1, S=0 (increment addresses, do not shift display)
  delayMicroseconds(80);  
  command(0x0C);            //Display ON/OFF Control, D=1, C=0, B=0 (display on, cursor off, blink off)
  delayMicroseconds(80);
}

void LiquidCrystal::home()
{
  command(0x02);  // set cursor position to zero
  delayMicroseconds(2000);
}

void LiquidCrystal::setCursor(int col, int row)
{
  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
  command(0x80 | (col + row_offsets[row]));
}

void LiquidCrystal::command(uint8_t value) {
  send(value, LOW);
}

void LiquidCrystal::write(uint8_t value) {
  send(value, HIGH);
}

void LiquidCrystal::send(uint8_t value, uint8_t mode) {
  digitalWrite(_rs_pin, mode);
  digitalWrite(_rw_pin, LOW);

  if (_four_bit_mode) {
    for (int i = 0; i < 4; i++) {
      digitalWrite(_data_pins[i], (value >> (i + 4)) & 0x01);
    }
    
    digitalWrite(_enable_pin, HIGH);
      //delayMicroseconds(1);   //added
    digitalWrite(_enable_pin, LOW);
    
    for (int i = 0; i < 4; i++) {
      digitalWrite(_data_pins[i], (value >> i) & 0x01);
    }

    digitalWrite(_enable_pin, HIGH);
    digitalWrite(_enable_pin, LOW);
  } else {
    for (int i = 0; i < 8; i++) {
      digitalWrite(_data_pins[i], (value >> i) & 0x01);
    }

    digitalWrite(_enable_pin, HIGH);
      //delayMicroseconds(1);  // added 
    digitalWrite(_enable_pin, LOW);
  }
}

Understood.

OOOpps, I erased old file.

Made that but I am not sure if correctly.

Will replace with the complete file, it is better.

OldBeaver

PS: I am doing it all with version 12 of Arduino compiler.

Will do now with version 16, but will keep a copy of the old file.

Tks a lot.

Unfortunately, it didn´t compile in Arduino 16.

It did in Arduino 12, but once updated, problem continues.

As I am not sure I did the correct sustitution, I am downloading Arduino 12 and will install it again.

One question:

I soldered the for holes of the LCD display to the shield. May that be causing a problem?

OldBeaver

I can't see any of the pictures in this thread.

Yes, you are right. I can´t post them either.

I think you can see them here:

http://www.flickr.com/photos/33747648@N05

Please tell me if you still cannot see them.

Tks,

OldBeaver

When powered up, do you get the same sequence of characters every time?

If you press the reset button on the Arduino do you get the same charcters as power up? If different, do you get the same characters every time you press reset?

One last question. Have you tested this LCD in 8 bit mode?

Oldbeaver, try a sketch that prints all the ascii character set from 20 to 255. Print the sequential letters at 16 chars per line on four lines and pause a few seconds after each 64 characters. See if you can detect a pattern on the display that may give a clue to the nature of the problem.

Mem,

This is the routine I made:

/* ========================= Millis Counter =========================*/

#include <LiquidCrystal.h>
int b;
/* ------- create object to control an LCD GMD1602K -------*/
LiquidCrystal lcd(12, 11, 10, 6, 7, 8, 9); //

/* ==================== SETUP ======================================== /
void setup(){
pinMode(13,OUTPUT); // flash the LED each second
/
--------------------- Configure pin modes -------------------------*/
}

void loop(){

b = 79;
lcd.print(b);
delay(50);
lcd.print(b, DEC);
delay(50);
lcd.print(b, HEX);
delay(50);
lcd.print(b, OCT);
delay(50);
lcd.print(b, BIN);
delay(50);
lcd.print(b, BYTE);

lcd.setCursor(8,0);
lcd.print(b);
b=b+1;
}

(couln´t copy from the clipboard, don´t know how to call it here).

What is printed is just weird characters, the only difference is that the dominant character printed is kind of “C,” but facing left. It corresponds to Standard Character Pattern 1111 x 1100, on the table

Cannot insert here. I sent it attached to a mail.

OldBeaver

That code won't help, you need to sequence through the ascii character set to see if you can see a some kind of relationship between sequential characters on the display. Just lcd.print(b,BYTE) for each value of b starting at something like 40. If there is a pattern take a picture and post on flickr

An alternative might be to print just one character several times and look for a pattern. I'm guessing that Mem is thinking along the same lines that your data is arriving but, the timing of the data bits is off. If this is the case, you may not see a repeat in the pattern in a short sequence. This is why I asked if your pattern duplicates on power up or reset. If it is duplicating, you're getting your data bits, just at the wrong time. Also, are you sure your LCD supports 4 bit? Just a thought...

Dear Mem,

I contacted the guy that sold me my Arduino clone and the LCD.

He said: this LCD works with LCD4bit library only. (I know this isn´t totally true, as we (you and me) made it work with some liquidCrystal library too.

However, he gave me the connection scheme that I had at the beginning. I had asked him before, but, what he sent to me didn´t work out. Today I insisted, and voila! now the LCD screen is working again.

The only problem is that it is using digital pin 2 in Arduino.

This is the sequence:

LCD Pins 1 - GND 2 - 5V 3 - Contrast LCD 4 - RS to pin 12 of Arduino 5 - RW to GND 6 - E to pin 2 of Arduino 7 - nc 8 - nc 9 - nc 10 - nc 11 - D4 to pin 7 Arduino 12 - D5 to pin 8 Arduino 13 - D6 to pin 9 Arduino 14 - D7 to pin 10 arduino 15 - 5V 16 - resistor to bcklit ilumination

The screen and the shield were very clean at first. Now, after the long battle (which I think is not finished yet), they look dirty and tipsy.

But at last IT IS WORKING !!! :)

Now we need to see how we can use digital pin 2 again, to take advantage of the interrupt command, which is needed in my project.

OldBeaver

I presume you have it working with the LCD4Bit library. If so, to use pin 11 for the enable pin instead of 2, in LCD4Bit.cpp change the line

define Enable 2 // LCD pin 2

To

define Enable 11 // LCD pin 11

Delete the LCD4Bit.o file and recompile.

UncleBone, Mem,

Well, thank you for all the help, and sorry for the mess.

As you can see, it was my fault for not having a backup of the working wiring. It must be taken in consideration to avoid this sort of thing from happening in the future.

Mem: yes, I will change that wire to see if I can recover digital pin 2 for input. Tks.

OldBeaver

PS: I uploaded pictures of the working version of shield and LDC screen to flickr.

Mem,

The compiler claims to be an error on LiquidCrystal:

"LyquidCrystal.cpp error: stray '/240? in program"

This error message repeats from line 29 to line 139 of the lybrary I suppose. However, it isn´t using it, is it?

And, the wire to pin 11 didn´t work out. A black Block is printed, and the cursor blinks.

OldBeaver

Actually, the version 12 compiler gives the many error messages.

However, the version 16 compiler do not. Anyway, it don´t show any results on the LCD screen.

Could you clarify what is happening. If you compile the library with version 0016 using pin 2 does it work? If not, what were the circumstances that did work?

Mem,

Sorry for the delay. I got a cold, and am in bed (again).

Besides, I had an almost complete answer typed for you, and all my text evaporated. This ia my daughter´s notebook, and when I write too fast, the cursor jumps to previous lines ?

This were the circumstances under which the thing worked out:

1) I loaded the LCD4bit library to both compilers versions (V.12 & V.16).

2) I replaced the #include liquidcrystal instruction with the #include LCD4bit one in the sketch.

3) I re-wired the LCD to Arduino using this -6 wires only- scheme: http://www.flickr.com/photos/33747648@N05/3673392772/ (it has the pins connections in the comment).

The sketch passed through with both compilers.

There is Documentation on Arduino.cc site /LCD/Lcd4bits . Remember my LCD is a Xiamen GDM 1602K.

None of compilers worked if I connect the enable wire (yellow on my scheme) with pin 10 on the Arduino.

However,

I remember quite well that all my sketches were working fine with the liquidcrystal library, using the instruction LiquidCrystal lcd(12, 11, 6, 7,8,9,10) or such (I don´t have my sketches in this computer).

The problem started when I rewired and made a fatal mistake: didn´t document the wiring that was working.

I also remember, that you made a change of pin 2 for pin 6 for the enable, so I freed pin 2.

I don´t remember if you introduced a new wire in my wiring scheme.

That, because the liquidcrystal library uses 7 instead of 6 wires. The soft part of it I have recorded in my sketches. The hardware part of it I may have on my old pictures.

It is raining outside, I have a cold, we are entering to winter station here, and my office is in a separate build close to house. But my wife will not allow me to get out! ;D

HOWEVER,

Sorry, this computer is crazy. My posting went out involuntarily.

However, maybe I will ask her to bring my notebook here.

Oldbeaver.

If it works with LCD4Bit with Enable on pin 2 and you want to rewire it so Enable is on pin 6, in LCD4Bit.cpp change:

define Enable 2 // pin 2

To

define Enable 6 // pin 6

and move the wire connected to Arduino pin 2 over to Arduino pin 6.

Good luck with that cold ;)