Page 1 of 1

MOP-AL404C Data Display Writing

Posted: Sun Oct 05, 2008 6:49 pm
by TimVukman
Hi:

I am obviously missing something fundamental with regard to writing data to this display. I suspect it is related to the character generator and / or display memory and how to set these up or use them properly.

I have been able to get the top half and bottom half of the display intitialized and it looks like it ought to be working.

I have DEBUG status messages in my code and I can confirm that I am writing what I think I am writing out to the display.

I am doing something wrong in writing data as there is no data being displayed and the cursor does not move to indicate that a write has happened.

I have included my code.

Thanks for your help

Tim Vukman

Code: Select all

// LCD Routines for MOP-AL404C
//  October 2008
//   Tim Vukman
//****************************************************************************************
//  LCD Pin Definitions
//****************************************************************************************
int  RS   = 12;   // Arduino Digital 12
//   DB0 - DB3 tied to GROUND
//   DB4 - DB8    // Arduino Digital 8 to Digital 11
//                // Conveniently maps to PortB 0 - PortB 4
int  CE1  =  7;   // Enable 1 line
int  CE2  =  6;   // Enable 2 line
//****************************************************************************************
//  LCD Send Command
//****************************************************************************************
// cmd will receive the command value in hex
// delay1 will receive the first delay value
// delay2 will receive the second delay value
// bank will receive either Enable 1 or Enable 2 depending on what is being updated
//****************************************************************************************
void LcdCommandWrite(char cmd, unsigned int delay1, unsigned int delay2, char bank) 
     {
      digitalWrite(RS,  LOW);                      // Set RS to 0 for command
      digitalWrite(bank,HIGH);                     // Raise the enable line
      PORTB = ((cmd & 0xF0) >>4);                  // Write the high nibble to PORTB
      Serial.print("LCD Command Upper Nibble :");  // DEBUG - description label
      Serial.println(PORTB, HEX);                  // DEBUG - value to display in IDE
      digitalWrite(bank, LOW);                     // Lower the enable line
      digitalWrite(RS,  HIGH);                     // Set RS to 1 for data
      delay(delay1);                               // Delay 
      digitalWrite(RS, LOW);                       // Set RS to 0 for command      
      digitalWrite(bank, HIGH);                    // Raise the enable line
      PORTB = ((cmd & 0x0F));                      // Write the low nibble to PORTB
      Serial.print("LCD Command Lower Nibble :");  // DEBUG - description label
      Serial.println(PORTB, HEX);                  // DEBUG - value to display in IDE
      digitalWrite(bank, LOW);                     // Lower the enable line
      digitalWrite(RS,  HIGH);                     // Set RS to 1 for data     
      delay(delay2);                               // Delay    
     }
//****************************************************************************************
//  LCD Send Data
//****************************************************************************************
// data will receive the data value in hex
// delay1 will receive the first delay value
// delay2 will receive the second delay value
// bank will receive either Enable 1 or Enable 2 depending on what is being updated
//****************************************************************************************
void LcdDataWrite(char data, unsigned int delay1, unsigned int delay2, char bank) 
     {
      digitalWrite(RS, HIGH);                      // Set RS to 1 for data       
      digitalWrite(bank,HIGH);                     // Raise the enable line
      PORTB = ((data & 0xF0) >>4);                 // Write the high nibble to PORTB
      Serial.print("LCD Data Upper Nibble :");     // DEBUG - description label
      Serial.println(PORTB, HEX);                  // DEBUG - value to display in IDE
      digitalWrite(bank, LOW);                     // Lower the enable line
      digitalWrite(RS, LOW);                       // Set RS to 0 for command     
      delay(delay1);                               // Delay 
      digitalWrite(RS, HIGH);                      // Set RS to 1 for data       
      digitalWrite(bank, HIGH);                    // Raise the enable line
      PORTB = ((data & 0x0F));                     // Write the high nibble to PORTB
      Serial.print("LCD Data Lower Nibble :");     // DEBUG - description label
      Serial.println(PORTB, HEX);                  // DEBUG - value to display in IDE    
      digitalWrite(bank, LOW);                     // Lower the enable line
      digitalWrite(RS,  LOW);                      // Set RS to 0 for command 
      delay(delay2);                               // Delay      
     }
//****************************************************************************************
//  LCD Initialization
//****************************************************************************************
void setup(void) 
     {
      pinMode(CE1, OUTPUT);                        // Set Arduino Digital 7 as OUTPUT E1
      pinMode(CE2, OUTPUT);                        // Set Arduino Digital 6 as OUTPUT E2
      DDRB = DDRB | B00011111;                     // Set Arduion Digital 8 - 11 to OUTPUT
      delay(50);                                   // Delay
      Serial.begin(9600);                          // DEBUG - Start IDE communication      
      Serial.println("Init Top Half");             // DEBUG - Status Message
      delay(100);                                  // Delay
      Serial.println("1st Function Set ");         // DEBUG - Status Message      
      LcdCommandWrite(0x33, 10, 10, CE1);          // Wake up LCD top
      delay(10);                                   // Delay
      Serial.println("2nd Function Set ");         // DEBUG - Status Message        
      LcdCommandWrite(0x32, 10, 10, CE1);          // Set LCD to 2 Line
      delay(10);                                   // Delay
      Serial.println("3rd Function Set ");         // DEBUG - Status Message        
      LcdCommandWrite(0x2C, 10, 10, CE1);          // Set LCD to 4 bit with Cursor
      delay(5);                                    // Delay
      Serial.println("Display on / off ");         // DEBUG - Status Message 
      LcdCommandWrite(0x0E, 5, 5, CE1);            // Set Set cursor not blinking and display on
      delay(5);                                    // Delay
      Serial.println("Set Entry Mode ");           // DEBUG - Status Message       
      LcdCommandWrite(0x01, 5, 5, CE1);            // Set cursor to home
      delay(5);                                    // Delay
// Set up Bottom Half of LCD
      Serial.println("Init Bottom Half");          // DEBUG - Status Message  
      delay(100);                                  // Delay
      Serial.println("1st Function Set ");         // DEBUG - Status Message       
      LcdCommandWrite(0x33, 10, 10, CE2);          // Wake up LCD bottom
      delay(10);                                   // Delay
      Serial.println("2nd Function Set ");         // DEBUG - Status Message        
      LcdCommandWrite(0x32, 10, 10, CE2);          // Set LCD to 2 Line
      delay(10);                                   // Delay
      Serial.println("3rd Function Set ");         // DEBUG - Status Message        
      LcdCommandWrite(0x2C, 10, 10, CE2);          // Set LCD to 4 bit with Cursor  // function set:
      delay(5);                                    // Delay
      Serial.println("Display on / off ");         // DEBUG - Status Message 
      LcdCommandWrite(0x0E, 5, 5, CE2);            // Set cursor not blinking and display on
      delay(5);                                    // Delay
      Serial.println("Set Entry Mode ");           // DEBUG - Status Message       
      LcdCommandWrite(0x01, 5, 5, CE2);            // Set cursor to home
      delay(5);                                    // Delay
      //                    
     }
void loop (void) 
     {
      Serial.print("Loop ");
      LcdCommandWrite(0x02, 10, 10, CE1);  // set cursor position to zero top 2 lines
      LcdCommandWrite(0x02, 10, 10, CE2);  // set cursor position to zero bottom 2 lines      
   // Write the welcome message 
      LcdDataWrite(0x48, 5, 5, CE1);       // no character cursor flashing at home position                                   
      LcdDataWrite('e', 5, 5, CE1);        // another always on cursor at Line 2 Column 9
      LcdDataWrite(0x6C, 5, 5, CE1);
      LcdDataWrite('l', 5, 5, CE1);
      LcdDataWrite(0x6F, 5, 5, CE1);
      delay(500);          
   // Write the welcome message 
      LcdDataWrite(0x48, 5, 5, CE2);       // no character cursor flashing at home position                                   
      LcdDataWrite('e', 5, 5, CE2);        // another always on cursor at Line 2 Column 9
      LcdDataWrite(0x6C, 5, 5, CE2);
      LcdDataWrite('l', 5, 5, CE2);
      LcdDataWrite(0x6F, 5, 5, CE2); 
     }
[/code]

Posted: Mon Oct 06, 2008 11:36 am
by Clark
Hi Tim,

I've got a colleague taking a look at our own initialization code for the LK404-25 unit to try to offer some tips there. I've also noticed you have no control over the R/W line; I assume you've got that grounded. This might be something you'll look to incorporate for some more advanced debugging capability, especially on initialization. I'd also suggest moving your serial debug messages until after you're done toggling the lines, and possibly lengthening the delay between commands.

That should give you a little to think about while my colleague looks over her code, if you have anything to add in the mean time, please do.

Thanks,
~Troy

Posted: Mon Oct 06, 2008 12:07 pm
by TimVukman
Hi Troy:

Thanks. R/W is wired to ground for sure. I was avoiding trying to code a read function as it would not be required once it is up and running.

I will move the debug lines as you have suggested.

I lifted the values in my initialization from a post in this forum that was about initialization problems. When I compare the HEX values used with the table in the manual, I don't see how the values were chosen as my interpretation would be for different numbers.

Maybe I am not reading the table properly. I know that a standard LCD parallel module usually wants to see 0x30 three times before you start handing it commands. In my setup values, I found myself putting these values back in even though I thought it would be a different value. Unfortunately, the values that I was choosing were setting the display to single line - and I thought I was setting up 4bit / 8it.

I also often see a white letter P on a black background in every character position on the upper to lines. It is clearing when I intilize, but it is there when I first power on the display - some of the time.

I have no reason to believe that my values are correct. I can only say that it removes the faint boxes and sets up an underline as a cursor.

I am most intersted to find out what your colleague's code might reveal.

TimVuman

Posted: Mon Oct 06, 2008 4:31 pm
by Raquel
Hi Tim,

Just a quick note, I see you have D0 to D3 of the display tied to ground?
Please leave them disconnected.

Posted: Mon Oct 06, 2008 4:42 pm
by TimVukman
Hi Raquel:

I tied them to ground as everything I found on the internet indicated that it was a good idea.

I shall float them instead.

Ok, I have taken the lines off of ground. I do not get characters.

I do get a number of cursor flashes cycling through the display.

The cursor appears to be at 1,1 for both the upper pair of lines and the lower pair.

I also see a cursor flash briefly at Line 2 Column 9, Line 4 Column 9, Line 2 Column 38, Line 4 Column 38. I did have that before.

Thanks

Tim

Posted: Mon Oct 06, 2008 4:44 pm
by TimVukman
This isn't really a reply. I am just posting some information that I found. I may be the only person who didn't know it, but someone else with limited knowledge of these things might follow me.

Code: Select all

Instruction Table Supplemental Information

R/W  Stands for Read / Write
     0 = Read
     1 = Write
     
RS   Not Sure what it Stands for
     0 = Instruction
     1 = Data
     
Function Set should be written first
This controls data length, number of display lines and font size
DL   Data Length
     0 = 4 bit
     1 = 8 bit
     
N    Number of Lines
     0 = 1 Line
     1 = 2 Lines
     
F    Font Pattern
     0 = 5x10
     1 = 5x 8
     
Entry Mode
This controls cursor direction and display shift
I/D  Increment / Decrement
     0 = Decrement Cursor position counter
     1 = Incrment Cursor position counter
     
SH   Shift
     0 = Shift Disabled
     1 = Shift Enabled
     
Cursor or Display Shift
This controls whether the cursor is stationary and the
deplay shifts or the display is stationary and the cursor
moves.  It also controls the direction
S/C  Shift / Cursor
     0 = Cursor Moves
     1 = Display Shifts
     
R/L  Right / Left
     0 = Left
     1 = Right
     
Display On / Off Control
This controls turning the display on and off as well
as the cursor and the blinking capability
D    Display
     0 = Off
     1 = On
   
C    Cursor
     0 = Off
     1 = On
     
B    Blinking
     0 = Off
     1 = On
[/quote]

Posted: Tue Oct 07, 2008 9:31 am
by Raquel
Hello Tim,

Please check out this link. On the top of the list is the data sheet for the HD44780U. Check out page 46 for the initialization instruction for the 4 bit interface.

Since you have a 40x4 display that has 2 controllers, as I see you have done on your code, make sure you initialize each controller.

Hope this helps.

Posted: Tue Oct 07, 2008 1:05 pm
by TimVukman
Hi Raquel:

Thank you very much for the link that you posted. That is a very complete and much appreciated manual. I wish I had known that it was there.

You can delete what I put up if you like.

I think I should be able to get this going from here. Obviously there is nothing in my code that is setting addresses or calling any characters.

Let me do my homework and I will post when I have something to report or a final solution at hand.

Your time and effort are appreciated

TimVukman

Posted: Wed Oct 08, 2008 8:53 am
by TimVukman
Hi:

Here is an update on progress after reviewing the full Hitachi manual.

I suspect I have a timing issue in my code. In reading the Hitachi manual I am comfortable that I am sending the correct commands - certainly for initialization, and I can see what I have sent so they are verified.

I downloaded a 4bit LCD library for the Arduino from their web site last night and created a new code list based on that. I can confirm that I do get characters printing on the display using that library. They are not being pulled from the English characters, but rather the Japanese.

I will be deconstructing the code from the library to figure out what it is doing that is different than what I am doing.

It appears as though they are writing the nibble to the display and then toggling the Enable line.

I am raising the Enable line, writing the nibble and then dropping the Enable line.

Can you confirm which way this should be done?

Also, the manual for this display is showing all of the timing in nanoseconds, so if I am sending milliseconds, am I missing the windows by taking too long to send?

Please advise

thanks

Tim

Posted: Wed Oct 08, 2008 2:56 pm
by Raquel
Hi Tim,

You need to write / present the data on the data lines then set the enable line, wait for x amount of delay, then clear the enable line.

As per timing, the nanoseconds specifications are mostly for min time delays, so going over to milliseconds is not a problem.

Let me know how it turns out.

Posted: Wed Oct 08, 2008 4:57 pm
by TimVukman
Hi Raquel:

Thanks for the response. It was Figure 9 in the 4 bit transfer example on page 22 of Hitachi's document that made it look like enable goes high before the data is presented.

I appreciate the confirmation on the order for engaging the enable pin properly. My code would be incorrect at this time.

I am pleased to have something that I can try to correct to resolve this.

I should know more later tonight.

Thanks

Tim

Posted: Wed Oct 08, 2008 7:30 pm
by TimVukman
Hi Raquel:

I promised an update, so here we go.

I decided that there had to be something out there that would work for me with this display to at least make sure that the display is ok and that it's only the programmer that needs work.

As I indicated in an earlier post, I had grabbed a 4bit library from the Arduino site (that is my current development environment) and it worked except that it printed garbage.

Tonight I downloaded the 8bit library and after changing their files to match my wiring I am pleased to report that I am writing characters of my own choosing to the display.

For the project that I am intending this Arduino to go into, I can't afford the 11 pins that I need to run this as an 8 bit display. I ordered a new LCD from your site this morning that is 2 lines by 20 characters and supports I2C.

My clock chip is I2C and I have an interface chip for the keypad that is I2C and my original goal was always an I2C display.

I should get the new LCD tomorrow.

I am very happy with this one and I will use it in another project. As time permits, I will work on disecting the library (I am learning how to program in C which is why I am using the Arduino. It was cheap and easier to set up than the MicroChip products I was using in Assembler)

I will get this working with a 4bit library based on the code structure that I posted earlier or I will use it on a 40Pin processor where I can afford to give up the pin count. It would be a good status display for a network based microprocessor controlled specialized server.

Thank you so much for your help. I really appreciate it.

Regards,

Tim