Problem in LiquidCrystal lib (20x4)

First post to this forum but I think I know what I am talking about (you can correct me if you want, I can take it).

I setup an Arduino with a 16x2 display and all works great.
I found a 20x4, hooked it up and things all worked OK.
Next I had a few 16x4 and plugged one in and things did not line up properly.

Looking at the code:

void LiquidCrystal::setCursor(uint8_t col, uint8_t row)
{
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if ( row > _numlines ) {
row = _numlines-1; // we count rows starting w/0
}

command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

Notice that the offset does not change based on characters per line (no way of knowing).

Not sure if this is 'clean' bit it worked for me.

Needed a place to save number of characters so in Begin I added:

void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
_numcols = cols;
_currline = 0;

Then in setCursor I added/changed it like this:void LiquidCrystal::setCursor(uint8_t col, uint8_t row)
{
// 16 Cols int row_offsets[] = { 0x00, 0x40, 0x10, 0x50 };
// 20 Cols int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
int row_offsets[] = { 0x00, 0x40, 0x10, 0x50 };
if(_numcols == 20) {
row_offsets[2] = 0x14;
row_offsets[3] = 0x54;
}

if ( row > _numlines ) {
row = _numlines-1; // we count rows starting w/0
}

command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

It now works for me with 16x2, 16x4, 20x2 and 20x4. It only changed the 4 line displays. I don't see any reason it will mess anything else up.

Any comments? How do we get this into the lib if no one else see problems in it?

Thanks
Tim

164 display memory is sometimes organized a bit differently than the 162 and 20*4 displays. it is normal.

Any comments? How do we get this into the lib if no one else see problems in it?

I have commented on this many times. The LiquidCrystal library does not use the information that it has from the lcd.begin() statement to modify the starting addresses for lines 3 and 4 of the 16x4 modules. There is no known way for mere mortals to get this corrected.

Don

Edit: Here's a link from almost two years ago: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1253367247

Also: @tlaren: You might want to modify the forum topic to say 16x4 instead of 20x4.

164 display memory is sometimes organized a bit differently than the 162 and 20*4 displays.

The 16x4 display memory is always organized a bit differently than the 162 and 204 displays.

it is normal.

It is normal for the display to be organized that way when you consider the technical limitations that existed when the LCD controller was designed. It is not normal for the library to ignore this fact, it is a flaw in the library. The last time I tried to have the library fixed I was rebuffed, but shortly thereafter Lady Ada's fixes were incorporated. Her fixes resulted in a library that actually worked which was the main reason for the modifications, but she didn't deal with this part.

Don

Edit: Search for the LiquidCrystal440 library. John fixed this problem while modifying the library for 40x4 displays.

I've just posted in the software forum on this subject.

Without copying and pasting, the thrust of the posting is to ask if anyone has written a scrolling routine to overcome this problem? I started to, but soon ran into the limits of my programming skills.

Jim

jimford:
I've just posted in the software forum on this subject.

Without copying and pasting, the thrust of the posting is to ask if anyone has written a scrolling routine to overcome this problem? I started to, but soon ran into the limits of my programming skills.

Jim

What kind of scrolling are you trying to get? Describe it and someone may have already done it and can share their codes.

liudr:
What kind of scrolling are you trying to get? Describe it and someone may have already done it and can share their codes.

Thanks for the reply.

I want to scroll a line of around 60 characters from right to left, on the top line of a 16x2 display. It's to display the software version of a project on start-up. The array is assigned to by RCS from within Emacs eg - char version[] = "$Id$";. I only want to do this the once on initial start-up.

Jim

This is an example code, which requires my phi_prompt library support. It essentially does what you want.
From my documentation:

  1. void scroll_text(char * src, char * dst, char dst_len, short pos);
    You can use this function to animate a line of text. If you have a long message and you want to animate it by scrolling it, you can call this function.
    The src points to the source char array. The dst is the buffer that will be filled by the string cut from the source starting at position pos with length dst_len. So your dst char array should be at least dst_len+1 long.
    Eg.
void horizontal_scroll_demo()
{

char thankyou[]="Thank you for using phi_prompt!";
char buffer[15];
lcd.clear();
for (byte i=0;i<47;i++)
{
scroll_text(thankyou,buffer,14,i-14);
lcd.setCursor(1,1);
lcd.print(buffer);
wait_on_escape(250);
}
}

The above function scrolls the char array thankyou and displays it on the LCD as an animation. Notice that when i<14, the position is negative, corresponding to amount of blank spaces before the first character. This helps the animation.

Where to find phi-prompt library:

I use this function scroll_text() to automatically scroll items on my menus to show long items. It is around 1:40 into this following video:

I've just posted in the software forum on this subject.

Since you started that second thread it would be appropriate to respond to the posts there as well as the ones here.

Don

liudr:
This is an example code, which requires my phi_prompt library support. It essentially does what you want.

It certainly looks like just what I need. I've downloaded and printed the docs and am now going to have a coffee and read them.

Many thanks.

Jim

floresta:

I've just posted in the software forum on this subject.

Since you started that second thread it would be appropriate to respond to the posts there as well as the ones here.

You're quite right - I'll do so.

(I clicked the 'Notify' button on this and the other thread, expecting to get an email notification of replies, but have received no notification from either.)

Jim

jimford:

liudr:
This is an example code, which requires my phi_prompt library support. It essentially does what you want.

It certainly looks like just what I need. I've downloaded and printed the docs and am now going to have a coffee and read them.

Many thanks.

Jim

Alright! The documentation is pretty long though.

If you need all the library features, you are certainly welcome to read the whole thing and use the whole library. If all you need right now is the scrolling text, you can just put this together with the previous code, and replace wait_on_escape(250) by delay(250):

void scroll_text(char * src, char * dst, char dst_len, short pos)
{
  for (byte j=0;j<dst_len;j++)
  {
    if ((pos<0)||(pos>strlen(src)-1))
    {
      dst[j]=' ';
    }
    else dst[j]=src[pos];
    pos++;
  }
  dst[dst_len]=0;
}

That will get you started.

The wait_on_escape(250) is a delay while polling all buttons so it quits after time expires or button presses. These buttons are discrete tactile buttons hooked to digital pins.

liudr:
If all you need right now is the scrolling text, you can just put this together with the previous code, and replace wait_on_escape(250) by delay(250):

void scroll_text(char * src, char * dst, char dst_len, short pos)

{
  for (byte j=0;j<dst_len;j++)
  {
    if ((pos<0)||(pos>strlen(src)-1))
    {
      dst[j]=' ';
    }
    else dst[j]=src[pos];
    pos++;
  }
  dst[dst_len]=0;
}

It looks like the above, plus your earlier code, will be all I need. Thanks again!

Jim

(I clicked the 'Notify' button on this and the other thread, expecting to get an email notification of replies, but have received no notification from either.)

This is most likely accomplished by means of 'cookies'. Since it is working for us you might want to make sure that cookies are enabled in your browser. It's under the menu Tools | Options | Privacy on my version of Firefox and probably something similar on the others.

Don

floresta:

(I clicked the 'Notify' button on this and the other thread, expecting to get an email notification of replies, but have received no notification from either.)

This is most likely accomplished by means of 'cookies'. Since it is working for us you might want to make sure that cookies are enabled in your browser. It's under the menu Tools | Options | Privacy on my version of Firefox and probably something similar on the others.

Don

I've just checked - the messages were in the junk folder of my ISP account. I've added the email address to the whitelist.

Jim

liudr:
If all you need right now is the scrolling text, you can just put this together with the previous code, and replace wait_on_escape(250) by delay(250):

void scroll_text(char * src, char * dst, char dst_len, short pos)

{
  for (byte j=0;j<dst_len;j++)
  {
    if ((pos<0)||(pos>strlen(src)-1))
    {
      dst[j]=' ';
    }
    else dst[j]=src[pos];
    pos++;
  }
  dst[dst_len]=0;
}




That will get you started.

The wait_on_escape(250) is a delay while polling all buttons so it quits after time expires or button presses. These buttons are discrete tactile buttons hooked to digital pins.

Just what I needed - it works perfectly!

Although I can usually cobble together a working C/C++ program, I'm not a programmer and got stuck on this problem. I'll sit and digest how your routine works - and learn something!

Thanks again.

Jim

Jim, You are very welcome. As always, spreading the words of these libraries/codes is always welcome too.

liudr:
Jim, You are very welcome. As always, spreading the words of these libraries/codes is always welcome too.

And good for business too!

I followed the link to your site and was impressed enough by your 'phi 2 shield' to order one. I look forward to having a play!

;^)

Jim

Great! Let me know if you have any questions on the shield. FYI, I'm reorganizing source codes. I'm getting out of my current web host (mediafire.com, like a spam place) and try to move all codes to google code. Let me know if you see broken links.

liudr:
FYI, I'm reorganizing source codes.

One point regarding your library:

I had a browse and see that you use #defines. I thought they were deprecated in C++ and consts were what should be used. Is there any reason why you use #define?

Jim