Pages: [1]   Go Down
Author Topic: LCD4Bit code to support 4 lines  (Read 908 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using the LCD4Bit library to connect to a DisplayTech 204A (HD44780-compatible) 4x20 LCD display.
Everything worked fine, except it didn't appear that lines 3 and 4 of the display were supported.
I made some additions/changes to the cursorTo() function in LCD4Bit.cpp and now lines 3 and 4 work fine. [Remember that if you edit a library's .h or .cpp file, you need to delete the .o file, and then Verify/Compile within the Arduino IDE for the changes to take effect.]
I am still in my first week with the Arduino, so if I've missed something, or posted in the wrong place, please have mercy. smiley-wink
/Bob

void LCD4Bit::cursorTo(int line_num, int x){
  //first, put cursor home
  commandWrite(CMD_HOME);

  //if we are on a 1-line display, set line_num to 1st line, regardless of given
  if (g_num_lines==1){
    line_num = 1;
  }
  if (line_num == 2){
    commandWrite(0xC0);      //DDRAM address 0x40
      //was:
      //x += 40;
  }
  if (line_num == 3){
      commandWrite(0x94); //DDRAM address 0x14
  }
  if (line_num == 4){
      commandWrite(0xD4); //DDRAM address 0x54
  }
  //advance the cursor to the right according to position. (second line starts at position 40).
  for (int i=0; i<x; i++) {
    commandWrite(0x14); //shift cursor one position right
  }
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As a further refinement, I just rewrote the function from scratch so that it's a little smaller and much faster:

void LCD4Bit::cursorTo(int line_num, int x){
        commandWrite(CMD_HOME);            
      int row_address[] = {0x00,0x40,0x14,0x54};      //DDRAM addresses for lines 1 to 4
      commandWrite(row_address[line_num-1] + x + 128);  //128 to set high bit for command
}


Logged

Copenhagen / Denmark
Offline Offline
Edison Member
*
Karma: 5
Posts: 2360
Do it !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

cool

Maybee you can get a "post permission" in the playgruond and upload your revised code?

Making the size of a lib. smaller is a good thing.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mikmo,

Happy to do so, but in other open source projects there is a "module owner" of some sort coordinating all the changes in order to avoid random people (like me!) changing the library. Does the Arduino community have a similar notion?

thanks,
/Bob
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
As a further refinement, I just rewrote the function from scratch so that it's a little smaller and much faster:

void LCD4Bit::cursorTo(int line_num, int x){
        commandWrite(CMD_HOME);            
      int row_address[] = {0x00,0x40,0x14,0x54};      //DDRAM addresses for lines 1 to 4
      commandWrite(row_address[line_num-1] + x + 128);  //128 to set high bit for command
}


As someone struggling to get the 4bit library to work with my LCDs, I am happy to hear that the code is being actively worked.

I am curious why you invoke  commandWrite(CMD_HOME);   doesn't issuing the cursor positioning command that follows make this redundant?
  
Also, you could save a few more bytes by making the row_address array an unsigned char instead of an int.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mem,
Good call on both counts! Thanks.
1) The first time I looked at the HD44780 datasheet, I thought it said that the cursor home command did more than reposition the cursor-- something about resetting the display shift... But your comment prompted me to read it again, and to try doing without the cursor home command, which seems to work just fine.
2) As you suggest, we can save 4 bytes by changing the array from int to byte.
All of which leaves just:

//move the cursor to the given absolute position.  line numbers start at 1.
void LCD4Bit::cursorTo(int line_num, int x){
      byte row_address[] = {0x00,0x40,0x14,0x54};      //DDRAM addresses for lines 1 to 4
      commandWrite(row_address[line_num-1] + x + 128);  //128 to set high bit for command
}
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 267
dinosaur cork
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Arduinobob,

When you finally get some attention, and permission, to change the library maybe take a look at this  issues too.  If the pin assignments for the datapins are not in order the code breaks. This came up with a module that was hardwired, and where I didn't have four consecutive pins. But it could just as easily arise in a prototyping situation, and generate irritating errors just because pin assignments are used as index constants.



Posts: 114
      
4bit LCD library code fixes
18.11.2007 at 05:10:46  
The 4bit LCD library has some too-clever coding that should probably be changed.
 
 
Code:

int DB[] = {7, 8, 9, 10};  //wire these to DB4~7 on LCD.


  for (int i=DB[0]; i <= DB[3]; i++) {

    digitalWrite(i,val_nibble & 01);
    val_nibble >>= 1;

  }



 
the for loop will break if the pin values for DB[0] - DB[3] are not in order.
This came up on a board with the pins hardwired to an LCD, so it's not just theoretical.
 
I think this is the fix, although I haven't tested it. I'm not sure whether I can declare variable
j there, but you get the idea.
 

Code:
 for (int i=0; i <= 3; i++) {
 
   int j = DB[i];
    digitalWrite(j,val_nibble & 01);
    val_nibble >>= 1;

  }


paulb
 
 
« Last Edit: December 17, 2007, 11:29:36 pm by paulb » Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's a nice simple solution.

You can declare j like that but it's not necessary to do so, the following is equivalent.
Code:
for (int i=0; i <= 3; i++) {
      digitalWrite(DB[i],val_nibble & 01);


 The documentation should note that the pin assignments must be such that they map onto the LCD pins in ascending order:
  DB0->LCD DB4,  DB[1]->LCD DB5 etc.
« Last Edit: December 18, 2007, 03:27:36 am by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

paulb and mem,
Your proposed change looks great to me.
One question: why must the DB[] pins be in ascending order? Just from reading the code fragment you proposed (I haven't tried it), it appears to me that pins could be assigned in any order, eg int DB[] = {5, 7, 10, 9};
This would greatly increase the likelihood of an error in wiring, but the code would work, wouldn't it?
/Bob
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Bob,
The pins need to be wired in ascending order with the first assigned pin in the array wired to LCD DB4. It's the assignment order of the array that matters,  not the pin numbers,  because of the way the bits are shifted in the for loop.

Your example will work if  pins 5,7,10,9 are wired to DB4,DB5,DB6,DB7 respectively
« Last Edit: December 18, 2007, 02:18:50 pm by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mem,
I think we're saying the same thing. The first Arduino pin number in the array must be wired to DB4, the second to DB5, the third to DB6, etc, but the Arduino pin numbers themselves need not be in any particular order, as the 5,7,10,9 example sought to illustrate. Sorry for not being more clear!
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bob, I think we are saying the same thing, just not quite clear enough smiley-wink. Do you want  to have a go rewording the following to make it less confusing to future users of the new code

'pin assignments must be such that they map onto the LCD data pins in ascending order with whatever pin is assigned to DB[0] wired to LCD DB4, DB[1] wired to LCD DB5 etc.'
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think that wording is amply clear. Besides, any remaining ambiguity can be resolved by consulting the source code. smiley
Logged

Greenwood, Indiana
Offline Offline
God Member
*****
Karma: 0
Posts: 508
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your explanation is less confusing mem.
Logged

If it was designed by man it can be repaired by man.

Pages: [1]   Go Up
Jump to: