Trying to understand LCD...

Greetings, all. This is my 1st post here and I am a noobie to the arduino world. I'm using an Uno and Arduino IDE 1.0.1.

I have recently purchased a 4 x 20 LCD from jameco.com.
Product Link: http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_2118686_-1
A link to the data sheet for the product is available there as well. However, because I am a noob, there is much on the data sheet I simply don't understand.

I'm having difficulty understanding the pin outs of the device and exactly how this thing can hook up to the Arduino and get stable results. I have spent some time soldering short solid-wire jumpers to the LCD board so it can be plugged into a breadboard, and I'm using flexible jumper wires to connect the display from the breadboard to the Arduino. At this point, I am using the 5v Power, Ground, and the TX out from the Arduino (connected to the RS232 Serial In of the display).

The display lights up and displays characters. However, none of the LCD sample libraries/code for Arduino seem to work. They look to me like they're using a parallel LCD... This one is a serial LCD. All I can get on the display is random characters (garbage).

Also, according to the data sheet for the product, it is capable of I2C. If someone could instruct me on how to utilize this display that way it would be greatly appreciated.

Thanks to all of you for any help.

grpace

Looks like the unit will accept serial input at 9600 baud, but you'll have trouble using the normal hardware serial port TX output for output like this. Probably why you've had issues.

Search the forum for the SoftSerial library, which does what you want. You'll attach the RX to a different pin and use that pin for output.

-br

Thank You billroy for such a quick response!
I am trying the SoftSerial library, but still not getting valid results. There is apparently something I'm missing.

grpace

You'll get better help if you post all your code.

Cheers,

-br

I'm just trying to use the SoftwareSerial example included with the IDE.

I am trying the SoftSerial library, but still not getting valid results. There is apparently something I'm missing.

You have your circuit and your code right in front of you and yet you cannot tell what is wrong. How do you expect someone else to be able to help you when they have even less information?

In addition to posting your code you should also post a photograph of your hookup and also give a description of what you expect to be happening along with a description of what is actually happening.

Don

To floresta...
You make a good point. A bit brash I might say, but a good point just the same.select

Hopefully, the following photo links will work and help...

The display on the breadboard:
http://grpace.net/arduino/photos/lcd/Breadboard1.png
There are 2 sets of solder points. According to the spec sheet (from left to right):

  1. RX | RS232 In
  2. VSS | Ground
  3. VDD | 5v for logic

  1. SPISS| SPI Slave Select
  2. SDO | No Connect
  3. SCK/SCL | Serial Clock
  4. SDI/SDA | Serial Data In [SPI] / Serial Data [I2C]
  5. VSS | Ground
  6. VDD | 5v for logicselect

As you should be able to see in the photo, I have the two 5v and Grounds jumpered together on the breadboard.
A "top view" of it is here: http://grpace.net/arduino/photos/lcd/Breadboard2.png. Sorry... Couldn't get a clearer photo.

The color coding used on the wires:
Red = 5 volt
Grey = Ground
Yellow = Data In (both RS232 and SPI/I2C connections)
Blue = Serial Clock
Purple = SPI Slave Select

Now...
Using flexible jumper wires, I have 5v and Ground from the Arduino to the 5v and Grounds that are jumpered together on the breadboard.
I am also jumpering digital pin 3 on the Arduino to the RS232 Serial In (the display's RX pin) on the breadboard.
I am also attempting to use the Arduino's example SoftwareSerial library code to communicate with the display.

It seems to be displaying, but with some garbage characters thrown on the display, as can be seen here:
http://grpace.net/arduino/photos/lcd/Display.png

I hope I have explained all of this well. I really would appreciate any help in understanding what's happening here. If anyone needs further clarification, please feel free to ask.

Thank all of you in advance !

grpace

Good explanation of the hardware. Thank you.

You'll get better help if you post all your code, too.

-br

It is an i2c/spi/uart lcd - a pic acts like the interface between a typical hd44780 and the outside world.

You should look at the command section of the datasheet to see how to drive it (in your mode, and which commands to send).

It is a good lcd, much better than the typical one with a dumb io expanders.

You make a good point. A bit brash I might say, but a good point just the same.

No one ever accused me of being diplomatic.

It seems to be displaying, but with some garbage characters thrown on the display, as can be seen here:

Unless I have missed something you still haven't posted your code.

My crystal ball tells me that you might be using lcd.println instead of lcd.print. This will cause problems with a regular parallel interface and may or may not cause problems with some of the intelligent (microprocessor based) serial interfaces depending on how they are programmed.

Don

It is a good lcd, much better than the typical one with a dumb io expanders.

There is a trade off to consider when choosing between the intelligent and the dumb I/O expanders.

The intelligent ones are much easier to use but you are at the mercy of the person who did the programming. If they have implemented all of the LCD controller capabilities that you want to use and if they have not crippled any of the capabilities that you want to use, then the microprocessor based implementations are probably better.

If you go with the dumb variety then you are responsible for all of the coding and your host microprocessor has more work to do but you do have more control over the implementation of the inherent capabilities of the LCD controller.

Don

Wow !! Thanks to all of you folks for your input !!

OK... Here's the code I'm trying:

/*
Code to test a serial 4x20 LCD display using Arduino Uno
A modified version of the SoftwareSerial example included with the Arduino IDE
------------------------------------------------------------------------------

From the original example:
  Software serial multple serial test
 
 Receives from the hardware serial, sends to software serial.
 Receives from software serial, sends to hardware serial.
 
 The circuit: 
 * RX is digital pin 2 (connect to TX of other device)
 * TX is digital pin 3 (connect to RX of other device)
 
 created back in the mists of time
 modified 9 Apr 2012
 by Tom Igoe
 based on Mikal Hart's example
 
 This example code is in the public domain.
 -----------------------------------------------------------------------------
 */
 
 
boolean debug = true;
 
#include <SoftwareSerial.h>

SoftwareSerial lcd(2, 3); // RX, TX

void setup() {
     if (debug) {
        Serial.begin(9600);
        while (!Serial) {
               ; // wait for serial port to connect. Needed for Leonardo only
        }
        Serial.println("LCD Test");
     }
     
     // set the data rate for the LCD's SoftwareSerial port
     lcd.begin(9600);
     delay(100);  // data sheet states 100mS is required upon power-up for the display's controller to initialize 
     
     lcdClearDisplay();
     lcdBlinkingCursorOn();
     
     if (debug) { // show the display's current status
        lcdReportSelf();
     }
     
     lcdClearDisplay();
     lcd.write("\nHello, world !!    "); // drops the "H" without the \n in front of the character string. Why ??
     lcd.write("Line2");                 // completely skips the 2nd line of the display
     lcdSetCursor(0);                    // displays garbage instead of repositioning the cursor
}

void loop() {

}



////////////////////////////////////////////////////////////////////////////
// LCD Command Set
//--------------------------------------------------------------------------
// Specific to: New Haven Serial LCD Display, 4x20
// Manufacturer Part Number: NHD-0420D3Z-FL-GBW-V3
//--------------------------------------------------------------------------
void lcdReportSelf() {
     lcdDisplayFirmwareVersion(); delay(3000);
     lcdDisplayBaudRate();        delay(3000);
     lcdDisplayI2CAddress();      delay(3000);
} 

void lcdDisplayOn()                        { lcd.write(254); lcd.write(65);                         }
void lcdDisplayOff()                       { lcd.write(254); lcd.write(66);                         }
void lcdSetCursor(byte position)           { lcd.write(254); lcd.write(95); lcd.write(position);    }
void lcdCursorHome()                       { lcd.write(254); lcd.write(70);                         }
void lcdUnderlineCursorOn()                { lcd.write(254); lcd.write(71);                         }
void lcdUnderlineCursorOff()               { lcd.write(254); lcd.write(72);                         }
void lcdCursorLeft()                       { lcd.write(254); lcd.write(73);                         }
void lcdCursorRight()                      { lcd.write(254); lcd.write(74);                         }
void lcdBlinkingCursorOn()                 { lcd.write(254); lcd.write(75);                         }
void lcdBlinkingCursorOff()                { lcd.write(254); lcd.write(76);                         }
void lcdBackspace()                        { lcd.write(254); lcd.write(78);                         }
void lcdClearDisplay()                     { lcd.write(254); lcd.write(81);                         }
void lcdSetContrast(byte value)            { lcd.write(254); lcd.write(82); lcd.write(value);       }
void lcdSetBacklightBrightness(byte value) { lcd.write(254); lcd.write(83); lcd.write(value);       }
void lcdMoveDisplayLeft()                  { lcd.write(254); lcd.write(85);                         }
void lcdMoveDisplayRight()                 { lcd.write(254); lcd.write(86);                         }
void lcdChangeBaudRate(byte newbaudrate)   { lcd.write(254); lcd.write(97); lcd.write(newbaudrate); }
void lcdChangeI2CAddress(byte newaddress)  { lcd.write(254); lcd.write(98); lcd.write(newaddress);  }
void lcdDisplayFirmwareVersion()           { lcd.write(254); lcd.write(112);                        }
void lcdDisplayBaudRate()                  { lcd.write(254); lcd.write(113);                        }
void lcdDisplayI2CAddress()                { lcd.write(254); lcd.write(114);                        }

Also, as an added befit to debugging this thing...
A short video of the code/display in action is here:
http://grpace.net/arduino/photos/lcd/lcd.DebugDemo.AVI

If you'll kindly notice, the second line of the display is being completely skipped. Also, the || at the end is being generated by trying to reposition the cursor (see the code). I have triple-checked the command set on the data sheet and tried to make sure I'm sending the correct command sequence.

I'm sure it's likely something simple I'm missing, but I haven't been able to put my finger on it.

Again...
THANK ALL OF YOU FOR YOUR RESPONSES !!

grpace

  1. you probably want to observe the timing requirement specified in the datasheet.
  2. you will need to move cursor to the 2nd line first in order to "print" to that line.

To be more specific, if you look at the datasheet, the "clear screen" command requires 1.5ms to execute.

So if you send display data to the screen within that 1.5ms window, data is lost.

To be safe, you should add delays of appropriate length (as specified in the datasheet) to your various commands.

For example, your clear lcd screen would be something like this:

void lcdClearDisplay()                     { lcd.write(254); lcd.write(81); delay(2);}

Just to be safe.

also (just a query on my thinking) doesn't lcd.write only output one byte whereas lcd.print prints a string?
or is this a function of the different LCD setups?

  1. you probably want to observe the timing requirement specified in the datasheet.

This is what is causing your missing character after the 'Clear screen'.

  1. you will need to move cursor to the 2nd line first in order to "print" to that line.

And, since they don't seem to have implemented the 'Set DDRAM Address' capability of the LCD controller (unless I missed it), you are going to have to calculate how many times you must use the 'Move the cursor right one place' command to get where you want to go.

You might want to follow the LCD Addressing link at http://web.alfredstate.edu/weimandn for some background information on this task. Make sure you read the 40x2 stuff before you go to the 20x4 information.

Running a program that displays a string of 80 consecutive displayable characters, with a short delay between each, will help you follow what is going on.

Don

EDIT: I missed it. You need to use the 'Set cursor' command. The information at the link I posted should still be of value. I will take another look in the morning but right now I think the information in the table on page 9 of the New Haven datasheet is a bit messed up.

I'm happy to report that all things seem to be working well, now !!

Special thanks to all that have replied:
billroy, dhenry and most of all, floresta (don).
[Virtual handshake going on here] !!

To dhenry:
Thank you for pointing out the timing to me. Changes have been incorporated into the code.

Don, If you hadn't pointed me to the information you did, it would have taken me days to study/understand what was actually going on! The information is invaluable. And you are right about page 9 of the Data Sheet... Unless my conversions are wrong, 0x00 to 0xFF is only 16 characters. They have the Line1 and Line2 "line span" incorrect on the Data Sheet.

Now, addressing the garbage that was being displayed...
MY FAULT !! I inadvertently hit the wrong key on the calculator when doing the HEX to DEC conversion. I corrected that, and the garbage went away ! The lcdSetCursor() function now works as it should.

I'll be adding a few functions to the LCD code to be able to clear / print to specific lines on the display. When it all works I will post the function package for this particular LCD here for anyone to have and use.

Again, thanks to all of you !!
Help like this is why I LOVE Open Source stuff !!!

grpace

MY FAULT !! I inadvertently hit the wrong key on the calculator when doing the HEX to DEC conversion.

Your problem is that you are doing the conversion at all. The values were given in HEX in the datasheet and that is the way you should have written the functions. The very best that you can do is get the conversion correct, the compiler/assembler always does the conversion correctly.

Don

Yes, Don, I may have shot myself in the foot there a little.

There is still something I'm not understanding on the Data Sheet...
Specifically page 4 of the Date Sheet...
How to switch this display into it's different possible modes.

The Data Sheet describes jumper combinations between R1 and R2, but I have no clue as to what they are referring to.

If you wouldn't mind revisiting the photos/video I posted earlier...
Is that that 2 solder points on the right side of the display's board ???
The Data Sheet doesn't make this clear.

And... by the way...
This display will eat a 9v battery fast !
Even when the Uno is connected to the USB, it dims out after a couple of minutes.

Correction...
Fully charged 9v battery... display is bright and clear.
10 minutes of use... Text on the display dims out and is unreadable.
Put a meter on the battery... 8.62 volts.
The Data Sheet states it should run on 5 volts.

grpace