4x20 LCD HD47780, skips line

I'm using the LiquidCrystal library with my 4x20 LCD. I think I've got it set up right.. everything works.

When I use setCursor(1,0); it goes to line two like expected, but when I'm inputting data from anything, when it needs to goto the next line, it skips line 2, goes to line 3, then to line 2, then finally line 4. I'm sure it has something to do with my code, I did a search but wasn't really sure what to search for, so sorry if it's already been answered! And I didn't see any functions for it on the Arduino tutorials, so I'm a bit lost! (no surprise :D)

Here's my code, it's using VirtualWire to receive data and post it to the LCD, just two words at the moment for testing.

Right now, the code is set to start on line two, so when it starts displaying, line two first fills up, then line 4, then line 1, then line 3.

Any pointers in cleaning up code would be appreciated as well:D

// receiver.pde
//
// Simple example of how to use VirtualWire to receive messages
// Implements a simplex (one-way) receiver with an Rx-B1 module
//
// See VirtualWire.h for detailed API docs
// Author: Mike McCauley (mikem@open.com.au)
// Copyright (C) 2008 Mike McCauley
// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $

#include <VirtualWire.h>
#include <LiquidCrystal.h>
#undef int
#undef abs
#undef double
#undef float
#undef round

// In this case, the minimum:  RS,R/W,EN,D4,D5, D6, D7
              LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);

void setup()
{
    Serial.begin(9600);      // Debugging only
    Serial.println("setup");
    lcd.begin(20, 4);  // begins LCD, 20 columns, 4 rows(lines)
    delay(20);
    lcd.clear();
    delay(20);
    lcd.print("ready to begin");

    // Initialise the IO and ISR
    vw_set_rx_pin(2);  // sets receiver to 2 to clear pin for LCD
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);       // Bits per sec
    vw_rx_start();       // Start the receiver PLL running
    lcd.setCursor(0,1);
}

void loop()
{
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    

    if (vw_get_message(buf, &buflen)) // Non-blocking
    {
      int i;

        digitalWrite(13, true); // Flash a light to show received good message
      // Message with a good checksum received, dump it.
      Serial.print("Got: ");
      
      for (i = 0; i < buflen; i++)
      {
          Serial.print(buf[i]);
          Serial.print(" ");
            lcd.print(buf[i]);
      }

      Serial.println("");
        lcd.print(" ");
        digitalWrite(13, false);
    }
}

The current version of the LiquidCrystal library does not appear to handle automatic positioning to the next line. The behavior you see is due to the way the character memory in the LCD is organized.

You can call the setCursor function in your code to control what line to use.

That's kind of what I was afraid of, well shucks! Thanks anyway, shouldn't be too hard to code around it. :slight_smile:

First line 1, then 3, 2 and 4? It's in line (hm, pun...) with whats in the function setCursor in the LiquidCrystal library. Also in many derived libraries. I thought there was something strange about that one. It's a line saying:

LiquidCrystal.cpp

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

I guess it should say:

int row_offsets[] = { 0x00, 0x14, 0x40, 0x54 };

You could try and change your copy of the library to that? Remember to delete the LiquidCrystal.o file before starting the Arduino IDE, so it rebuilds a new one.

Hey awesome, I'm on my way home then I'll give that a shot Raron, but keep in mind! The new release of the IDE is out, 0017! No need to delete the .o file when you're fixing the libraries. (or so says the notes:D)

Cheers!:smiley:

EDIT

I just edited the .cpp, I think you mis-understood, or I didn't explain correct.

When the LCD is scrolling, just printing, it starts on line 1, where it should. Then when it's time to goto the next line, it jumps down to three, after line three is full, then line two fills up, then finally line 4.

After looking in the .cpp I realized there was an "Autoscroll function" I'll look into using this, I tried the example.. does.. kind of what I want, but I'd rather the whole LCD scroll as it should.

Thanks again:D Hopefully you have another cool-way to edit my way out of things!:slight_smile:

When the LCD is scrolling, just printing, it starts on line 1, where it should. Then when it's time to goto the next line, it jumps down to three, after line three is full, then line two fills up, then finally line 4.

Ah okay, in that case I think the library actually is correct for decoding the rows. Even if it looks a bit odd. Unfortunately I don't have any cool ways to fix your problem then, just a boring one :stuck_out_tongue: Don't write past position 20, or it'l show up on another line it seems.

But, did you try the setCursor method to place it on another line (with an unmodified library)?

I did use setCursor, and it does work, each row works correctly in terms of that. I can set it to any 1 letter on the LCD.
The only problem I have with using setCursor, is I'm not always sure what the size of the information is going to be, so it could throw it off even more if the information's too long, or too short.

But yes indeed, anytime there's more than 20, the remaining skip down to row 3. Maybe I initialized it wrong? I'm able to use all 4 rows, but it's scroll definintions set to 2 row? I dunno. Because when it's set on 16, 2 it scrolls the same exact way as if it was setup on 20, 4, well minus 4 letters.

I'm surprised that wasn't fixed in the new LiquidCrystal update.

As mentioned in reply #1, the current LiquidCrystal does not handle scrolling, the functionality you see is built into the LCD and I agree that its not very useful. The 16,2 you send in the begin function is not used for scrolling (in the current version I don't think its used for anything), but its wrong to say that functionality you want that is not yet implimented is a bug.

I'm not always sure what the size of the information is going to be?

Handling scrolling is not easy because different applications may want the behavior to be different. For example, you may want characters that wont fit on a line to start displaying on the next line. But what should happen to any text already on the next line – should it get erased, scrolled or overwritten. If you set the cursor to a line and start writing characters, what should happen to the existing characters?

Can you describe the full extent of display functionality you want for your application?

I'm sorry, I wasn't implying it was a bug, I guess I was just assuming that using the lcd.begin(20, 4); would recognize there are 4 lines, and automatically move information to the 2nd line.

I was saying when I start the program as a 16x2 LCD, using my 20x4 LCD.. I get the same exact results. It skips the 2nd row, fills up the 3rd.. then fills up the 2nd. I could careless if it scrolls, I would just like the rows to fill up in the correct order.
Maybe it has to do with the fact that I have it connected using fewer pins.. rather than d0-d7, just d4-d7.

It's going to be displaying information inputted from my computer, or other arduino. Setting up a wireless debug station if you will.
I plan on using a standalone arduino with the LCD and a wireless receiver and hopefully keep it in a semi-permanent project box. I just want to be able to view what I'm outputting from one receiver, since I will be using 2 receivers, one for a robot and one for the base.
It will output different values depending on what I send, IE sensor values, battery status, if it's stuck, cute little messages.. lol a variety of stuff.
Just a general debug station, receiving anything I send (or the bot) and displays the information.

I'm surprised that wasn't fixed in the new LiquidCrystal update.

I wasn't implying it was a bug

It's a good idea to avoid suggesting something needs fixing if you don't want to imply that it's broken.

Connecting all the data pins won't address your issue; the library does not handle the case where characters are written beyond the displayable columns.

The most common way that this is solved is to control the position of all the text in your sketch. For example, have a specific row and column to display IE sensor value, another position for battery status etc. That way the display shows the latest information in the places of your choosing and does not scroll. I think that's the way every project I have seen here handles display on an LCD. Of course you could also have a line that contains freeform information such as debug strings.

If you really want to emulate the kind of scrolling done by something like the serial monitor you probably need to keep all 80 displayable characters in a memory buffer (on your sketch or in a modified version of the library). Its doable but with only a 20 by 4 line display area I think it may not be worth the effort.

I guess I was just assuming that using the lcd.begin(20, 4); would recognize there are 4 lines, and automatically move information to the 2nd line.

I guess that's what assuming does for you..
I'm just confused on what the point of setting it up as a (20,4) if it works the same exact way on (16,2).. Information displays exactly the same, first line.. third line.. second line.. fourth line.

But regardless, I think the idea of setting the data in a specific area is a good idea, and probably my best bet.
But yes, when I'm debugging and just receiving constant data, it just throws me off.

Is there any advantage over using 8 pins compared to 4? Besides (I'm assuming.. again) changing form 4-bit to 8-bit? (assuming as I have not much clue of what I'm talking about, if you didn't notice.:D)

Thanks for the words of wisdom, learning bit by bit.. and every bit helps! :smiley:

I guess that's what assuming does for you.

Yep, Murphy's law states that undocumented functionality never works the way you want.

The parameter for number of lines is used to initialize the LCD, the number of columns is not used in the current version. The developer may have included it so any future functionality added to the library would not change the interface.

Using the 8 bit interface will theoretically give slightly faster performance but I would think the difference is imperceptible. In practice there is no real benefit to using 8 pins.