LCD wraps output to 1 or 2 columns

Hi

I had my SerLCD setup and it worked well. Today it started to act weird. (After changing something seemingly unrelated in the code. I changed it back but it didn't help.)

I wrote the following test code to understand the problem better:

#include <SoftwareSerial.h>

SoftwareSerial LCD = SoftwareSerial(0, 2);

void setup()
{
  pinMode(2, OUTPUT);
  LCD.begin(9600);
}

int x = 0;
void loop()
{
  lcd_clear();
  lcd_goto(x,0);
  LCD.print("world");
  delay(1000);
 
  lcd_clear();
  lcd_goto(x,1);
  LCD.print("hello");
  delay(1000);

  x = (x + 1) & 0x0F;
}

void lcd_goto(int x, int y) { //x=0-15, y=0-1
  x = x & 0x0f;
  y = y & 0x01;
  lcd_do(0x80 | (y << 6) | x);
}
void lcd_clear(){
  lcd_do(0x01);
}
void lcd_do(int command){
  LCD.print(0xFE, BYTE);
  LCD.print(command, BYTE);
  delay(5);
}

What I would expect:

The word "world" should appear in the top row of the LCD, then the word "hello" in the bottom row.
This should first happen starting from column 0, then again in column 1, 2 etc.

What actually happens:
This actually more or less works as above, but only for columns 2 to 15. But when the words should appear in column 0, it seems to wrap around and only 2 characters appear in the first column:

d _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
l _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Instead of:

w o r l d _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

When starting in column 1 it seems to somehow wrap around in the first two columns:

d w _ _ _ _ _ _ _ _ _ _ _ _ _ _
l o _ _ _ _ _ _ _ _ _ _ _ _ _ _

Instead of:

w o r l d _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Any ideas what could be wrong?

At some point every computer user learns the importance of backups. Similarly, at some point every programmer learns the same thing. It looks like you have reached that point. You had some code that was working, you changed it and it didn't work, you "changed it back" and it still didn't work. It seems that you really didn't successfully change it back. In the future when you want to make changes to some code that works well you should make the changes to a copy of that code.

There are no standards for serial LCD implementation so we can't determine if your command syntax is correct without more information. What serial LCD hardware are you using? What serial LCD software are you using? From your examples it looks like your display is a 16x2 but that information should be stated as well.

There are exactly zero comments in your code. If you don't express what you are trying to do then how can we determine if you are doing it correctly?

This actually more or less works as above, but only for columns 2 to 15.

Does it work properly when you enter the actual column and row numbers as opposed to trying to calculate that information?

Don

My code is under source control.

I'm sorry I didn't include more information about the LCD hardware in the first place. It's a "SparkFun SerLCD V2.5 Serial Enabled 16x2 LCD" based on a HD44780 controller.
SerLCD_V2_5.PDF
SerLCD-v2-schematic.pdf
HD44780.pdf

I'm not sure what you mean by serial LCD software. I use the arduino 0022 release and its SoftwareSerial.h library. As you can see in the example test code above I just use that to send strings to print and to send some 0xFE control commands.

I'm also sorry about the lack of comments. (there is one in there :sweat_smile:)
void setup() // Sets up the LCD on pin 2 so I can send commands and display text
void lcd_do(int command) // sends a control "command" byte to the LCD
void lcd_clear() // sends the "clear" command 0x01 that clears all text from the LCD
void lcd_goto(int x,int y) // moves the cursor position where text will be printed to column "x", row "y"
void loop() // the test code. Alternates between printing "world" on row 0 and "hello" on row 1. cycles the starting position "x" from 0 to 15.

I hope this clear things up. If not please let me know what parts are still unclear.

If I replace the code in loop() with the following to specify the position directly (as you asked) I still only get output in the first column. (It should print the word "world" in the first row instead.)

void loop()
{
  lcd_clear();
  lcd_goto(0,0);
  LCD.print("world");
  delay(1000);
}

In fact even if I replace it with the following code it only touches the first column. (It should print the word "world" all over the place instead.)

void loop()
{
  LCD.print("world");
}

I fear that in the other code some other special command that I don't know about might have been sent by accident. (But I don't know this. For all I know it could be a hardware problem.)

I hoped someone here would be familiar enough with these sort of problems that they could recognize it as a common newbie mistake or something.

Thanks for your reply and any further input you or anyone else might have.

void loop()
{
  LCD.print("world");
}

You are trying to print the word "world" over and over again. The serial interface is relatively slow but the LCD controller is even slower. The LCD controller can't keep up and you get garbage. Since the LCD memory does not have to be refreshed, put this code in setup.

void loop()
{
  lcd_clear();
  lcd_goto(0,0);
  LCD.print("world");
  delay(1000);
}

This one has an additional problem. The instruction to clear the LCD takes much more time to execute than most of the other instructions so the aforementioned problem gets even worse. You do not have to reset the cursor the 0,0 since the clear instruction does that. Again, none of this belongs in loop.

Don

I know this does not need to be in a loop; I just wanted to answer your question:

Does it work properly when you enter the actual column and row numbers as opposed to trying to calculate that information?

(To my understanding, the single print in a loop should write "worldworldworld..." etc., not just "world". But this is not really important.)

However moving the code to the setup does not change the result significantly.

void setup()
{
  pinMode(2, OUTPUT);
  LCD.begin(9600);
  lcd_clear();
  delay(1000);
  LCD.print("world");
}

void loop()
{
}
d _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
l _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Concerning the timing: I added a (probably excessive) delay of one second after the clear command above. It also did not help. Thanks for the idea though!

(What length of delay would you consider appropriate? The HD44780 document linked above specifies the execution times of most commands as 37 microseconds, the "return home" as 1.52 milliseconds, but omits the value for the "clear display" command on page 24. I originally used a delay of 5 milliseconds as you can see in the code of lcd_do in the original post.)

I guess I am confused, but I haven't done much with serial LCDs and then only in assembly language with a different serial board.

The SoftwareSerial.h library allows you to communicate on pins other than 0 and 1 etc (see below). It has nothing to do with the LCD other than the fact that you are using it to communicate with what we now know is a Sparkfun serial interface device. You have to send that device commands that it understands and it converts those commands to the standard HD44780 commands that the LCD module understands.

SoftwareSerial LCD = SoftwareSerial(0, 2);

This is telling the SoftwareSerial library to use pins 0 and 2, probably not a good idea since pin 0 is used by the hardware serial interface..

I still don't see where you have involved any library that deals with the LCD commands themselves. For example, where does lcd_goto() come from?

Don

I think the library is intentionally missing, direct control seems to be the word (two words) of the day.

no245,
Do you have the correct sequency for the display, to initialize it properly?
Iwould like to see and test that too. I'm just too lazy to look for it myself, too much english in the instructions.

Cheers,
Kari

I'm not aware of any LCD libraries that I am/should/could be using. I more or less followed the SparkFunSerLCD article here on arduino.cc.

That's also where the pin 0 comes from:

SoftwareSerial LCD = SoftwareSerial(0, txPin);
// since the LCD does not send data back to the Arduino, we should only define the txPin

Do you think I should use SoftwareSerial(2, 2)? Or some other unused input pin?

lcd_goto() is defined in the original post above. It's a generalization of selectLineOne(), selectLineTwo() and goTo() from SparkFunSerLCD

GaryP,

Do you have the correct sequency for the display, to initialize it properly?

I'm not sure what you mean. There's no initialization code beyond what I posted above. I closely followed SparkFunSerLCD, which doesn't really do anything besides setting up the SoftwareSerial. The HD44780 datasheet mentions on page 23:

An internal reset circuit automatically initializes the HD44780U when the power is turned on.

too much english in the instructions.

I'm not sure what instructions you are referring to.

Thanks for your input.

too much english in the instructions.

I'm not sure what instructions you are referring to.

Thanks for your input.
[/quote]

Never mind, seems like an ability to read between the lines is not common...
:wink:

Well, should you try to google and look for "Arduino" + "LCD-libraries"? I bet you save many hours of valuable time with the answer.

Try this: arduino lcd library +"serial lcd" - Google Search

Cheers,
Kari

ooook... :roll_eyes:
Top three results for that are:

I guess I'm not reading between the lines again...

(Keep in mind the code used to work perfectly fine. I suspect there's some hardware setting I accidentally set or whatever. But I don't see one that could explain the observed behavior.)

Cheers

no245:
I guess I'm not reading between the lines again...

Well, there was nothing between the lines this time.
:slight_smile:

I think I tried to help in a matter that I know nothing about, never tried serial LCD, and perhaps those libraries don't help a bit. So my first assume was close enough, no libraries needed, just direct control like you were already doing.

Anyway, I'm looking forward to learn more about little details of serial LCD's.

Kari

Yeah, I have been crossthinking different topics. Just red this topic again from the beginning. Sorry!

Cheers,
Kari

That's ok.

Thanks for trying to help anyway!

I more or less followed the SparkFunSerLCD article here on arduino.cc.

With all due respect anyone can post anything in the Arduino playground. Do you want proof that the moon is made from blue cheese? Just give me a few minutes and then check Wikipedia.

Do you think I should use SoftwareSerial(2, 2)? Or some other unused input pin?

No, Yes. I wouldn't use the same pin number for both Tx and Rx. It looks like the playground code is doubling up on the receive pin knowing that the Sparkfun controller won't be sending anything there.

lcd_goto() is defined in the original post above. It's a generalization of selectLineOne(), selectLineTwo() and goTo() from SparkFunSerLCD

OK I found it! Are you sure that the compiler is doing the logical operations the way that you expect it to? I would start out by sending the specific numbers that the Sparkfun controller is expecting. After you get that working then you can see if you can calculate values that give you the same results.

Do you have the correct sequency for the display, to initialize it properly?

This is done by the Sparkfun controller.

An internal reset circuit automatically initializes the HD44780U when the power is turned on.

Don't bet on it. Read the datasheet - including the notes.

Don

How about this one:
http://www.arduino.cc/playground/Code/SLCD

Kari

Don,
Hmm, this doesn't belong here really, but is that playground full of not well tested and possibly bad instructions? Anybody can send their creations there and look like it's made by someone who looks like he/she knows what they are saying? That's not good...

Cheers,
Kari

And anyone can post anything in the Arduino forum. :wink:

I wouldn't use the same pin number for both Tx and Rx.

Ok, I'll try that later. (I doubt it will help, since this used to work fine. But it's worth a try I guess.)

Are you sure that the compiler is doing the logical operations the way that you expect it to?

Why, is the arduino compiler known for such bugs? I didn't check the generated assembly (is there an easy way to do that with the Arduino tools?) if you mean that. I'm fairly certain the code is correct though.

I would start out by sending the specific numbers that the Sparkfun controller is expecting.

I already did that in the second post (after you asked me to ;)) and it made no difference.

Don't bet on it. Read the datasheet - including the notes.

That quote is from the datasheet actually. I don't see any other information about initialization. (But I'm not sure what I would be looking for.)

How about this one:
http://www.arduino.cc/playground/Code/SLCD

Well, apparently that site is unreliable. :wink:
Also the code in that library looks really equivalent, except that it uses HardwareSerial.h instead of SoftwareSerial.h.

Are you sure that the compiler is doing the logical operations the way that you expect it to?

Why, is the arduino compiler known for such bugs? I didn't check the generated assembly (is there an easy way to do that with the Arduino tools?) if you mean that. I'm fairly certain the code is correct though.

They aren't bugs, they are more like quirks. The people who coded the compiler meant one thing and the people using it interpret things differently. Kind of like operating system menus or error messages. Take a look through the avrfreaks forum sometimes and see how many of the professional programmers there are beating their brains out trying to get the compiler to do what they intended.

Don't bet on it. Read the datasheet - including the notes.

That quote is from the datasheet actually. I don't see any other information about initialization. (But I'm not sure what I would be looking for.)

Find the quote in the datasheet (p.23) and then look at the note directly below it, in the middle of the page.

Note:    If the electrical characteristics conditions listed under the table Power Supply Conditions Using 
         Internal Reset Circuit are not met, the internal reset circuit will not operate normally and will fail to 
         initialize   the   HD44780U.   For   such   a   case,   initial-ization   must   be   performed   by   the   MPU   as 
         explained in the section, Initializing by Instruction.

Follow the LCD initialization link at http://web.alfredstate.edu/weimandn for a complete explanation.

Don

GaryP:
Don,
Hmm, this doesn't belong here really, but is that playground full of not well tested and possibly bad instructions? Anybody can send their creations there and look like it's made by someone who looks like he/she knows what they are saying? That's not good...

Cheers,
Kari

It's not bad either - you just have to be skeptical. It would be nice if only experienced programmers who have thoroughly tested their projects posted them in the playground but I don't think that is always the case. I believe that with a resource like this they are relying on the Arduino community as a whole to make any necessary corrections but most of the playground readers probably do not feel that they are experienced enough to correct something that has been posted there by someone else.

Don

I think I didn't really get the structure of the playground, I realized that it has ton of links around, where code actually are, and there's a chance to comment them pros and cos.

So, just have to be patient and test the code that might be usable for your application, if problems exists, then the forum is here waiting.
:slight_smile:

Cheers,
Kari