My Pi Description

My Experiences With the Raspberry Pi -- Tracking My Learning -- My Pi Projects
Showing posts with label Hitachi HD44780 Display Controller.. Show all posts
Showing posts with label Hitachi HD44780 Display Controller.. Show all posts

Monday, April 8, 2013

16 X 2 LCD Display Times Square Scroll, Continued

This is a continuation of the prior post about the Times Square Scroll display on a 16 character by 2 line LCD Display.  The entire Python code for that program is at the top of that blog post.  I discussed a code fragment for a simplier version that only displays on the top line of the display.  That fragment replaced lines 49 through 75.  It's now time to discuss the two line version.  So that the reader will not have to go back and forth between this post and the last post, I have repeated the code fragment for the top line only display and made a code fragment that corresponds to lines 49 through 75 of the complete program.
Code Fragment for Top Line Only Display
Code Fragment for Two Line Display
Recall in the prior post I showed that it is possible to have a garbled display of the text where previously entered characters on the other display line, and newly entered characters both get displayed.  Recall Fig. 5 from the last post.
There are two opportunities for this to occur with the two line display.  We have the end of the address space situation discussed in the last post.  Recall, if we don't take corrective action, the next character will be displayed on the wrong display line.  That situation will be solved in nearly the same manner as we solved it before.
The end of the address space situation is solved in the four lines, 12 to 15, in the top line only display.  The four lines, 17 to 20, handle this in the two line display.  The code is very similar but the two line display must deal with characters on both lines.  The two line version simply subtracts 28h from the address counter if the address counter reaches 28h or 68h.  I'm going to explain line 18 further in my next post which talks about hexadecimal numbers.
Now let's discuss the second cause of a garbled display.  When we have completed the first pass through the text on the top line, we move down to the bottom line.  However, the characters that we put into the top line memory are still in that memory.  Eventually, as we add more characters to the bottom line, and the Visible Memory window continues to move, the characters that are in the top line memory start to become visible.  When we finish the bottom line, we move to the top line and the old bottom line characters evenually start to show up.  This goes on and on until we push the switch to stop the program from running.
I solve that problem by overwriting the old characters with spaces.  Evety time I finish writing a character to the display, I erase a character before I write the next character.  I could not allow the display to shift automatically after I write a character.  Code line 1 of the top line only version does not appear in the two line version.  After I write a character (code line 11), I write a space to the same address position on the other display line (code lines 12 and 13).  I then restore the address counter back to the line I was writing characters to, and increment the address counter (code line 14, and increment by adding 81h rather than 80h to the address counter).  Finally, I manually shift the display to the left, which moves the Visible Memory window to the right (code line 15).
For example, if I write a character to memory position 10h on the top line, I write a space to memory position 50h, overwriting any character that was there.  Look at Figures 2,3, or 4 in the last post for reference.
Code line 12 of the two line version will be discussed further in the next post.

Wednesday, April 3, 2013

16 X 2 LCD Display Times Square Scroll

Here is a more complex program using the LCD display.  Just watch the video to see what the program does:
Here is the python code:
As you can see, the Times Square Scroll program asks the user to input text.  That text enters at the right end of the LCD display, on the top line, and scrolls to the left.  Once the entire text has gone to the display, it starts over on the bottom line.  Once all of the text has appeared on the bottom line it repeats to the top line.  This continues until the user pushes the switch and stops the process.
There is not a great deal of additional code to make the Times Square Scroll program work.  The shortness of the code, however, belies the fact that it is somewhat complex and requires a pretty good understanding of the 44780 display controller.  Remember that all of the code from the file LCD_2X16.py is imported into this program.
The display controller has two internal memories.  One is the character memory that converts an ASCII character to a pattern of dots that correspond to the letter, number, or symbol you see on the display.  It is the other memory, however, that concerns us.  This memory, called the Display Data RAM, contains 80 memory locations (80 eight bit bytes).  When you send a character to the display controller, it goes into this RAM.
The first 40 memory locations are devoted to the top line of the display, and they correspond to memory addresses 00h to 2Fh.  The bottom line's 40 memory locations are found at addresses 40h to 67h.  The data sheet for the display controller uses Hexadecimal notation for memory addresses, so, I will be using Hexadecomal notation too.  While there are 80 memory locations, only a maximum of 32 characters appear on the display.  Obviously, characters in some some of the memory are visible, and some are not.  To make it easier to determine what is visible, we can define a window corresponding to the visible portion of the memory.  Let's call that the Visible Memory window.  Take a look at Fig. 1, below.  It is a graphical representation of Display Data RAM.  I have indicated the Visible Memory window with a red rectangle.  It is important to know that this window can be moved to display characters in different memory locations, but it will always be the same size.
I am going to talk about sending characters to the memory.  Actually, we will be writing the ASCII equivalent of the characters to the memory.  For example, if we want a space, 20h, or 32 decimal will be written.  We'll keep it simple and say we are sending a space to the memory.
If you want a simple display project, like in my previous blog, you would not need to concern yourself with the Display Data RAM and my Visible Memory window.  Figure 1, shows how the memory was utilized in the previous blog.  The Visible Memory window stayed put and there were never any characters placed in the memory locations that were not visible.  The Times Square Scroll, however, makes plenty use of the Visible Memory window.
Figure 1.
There are two other important memory elements within the 44780 controller chip.  The first is the instruction register.  The commands (as opposed to characters) you write to the controller go there.  Pages 23 through 29 of the controller's data sheet explain the commands quite well.  That other important element is the address counter.  The address counter contains the memory location that will receive the next character.  You can write to the address counter if you wish to change where the next character will go - the code does this frequently.  It is important to know that once you write a character into a memory location, the controller will increment (or decremen) the contents of the address counter.  In this way you don't have to keep changing the address counter yourself.  As a matter of fact, you can't stop the address counter from incrementing or decrementing.
Before we look at the code for this two line version of the Times Square Scroll, I have a simpler version that uses the top line only.  The code fragment, below, replaces lines 49 through 75 above.  It's a little easier to understand.
Let's assume the user has asked to send "Now is the time for all good men to come to the aid of their party" to the display.  Recall that I said you can change the contents of address counter, and that is what I do in line 3 and 6.   I set it to the position just to the right of the Visible Memory window and upload it to the display controller.  In line 1, I commanded the controller to make a left shift after I upload each character.  Line 1 also says to increment the address counter after uploading each character.  If I had been writing in a language that reads from right to left, Hebrew, for example, I would have told it to decrement the address counter.  When I start to upload characters, the first character "N" goes to position 10h.  See Figure 2.
Figure 2.
After uploading the "N", the display does a left shift.  Hitachi considers the shift direction from the point of view of the character.  From my point of view, the Visible Window moves one position to the right.  In effect, it moves the "N" one position to the left.  The "N" is now within the Visible Window, so it appears on the display.  See Figure 3.
Figure 3.
When the "o" is uploaded, the address counter has been incremented to 11h (by the controller), which again, is one position to the right of the Visible Window.  Once uploaded, the "o" becomes visible because the controller shifts the Visible Window. See Figure 4.  This process continues as each character is added to the display.
Figure 4.
What happens once the address counter has gotten to the end of the memory space of the top line (address 27h)?  Lines 12 to 15 of the code handle that situation.  If those lines of code were not there, the address counter would move to the beginning of the bottom line.  As more characters are added, characters that were previously uploaded to the top line, and still in memory, would also start to be visible.  Old characters would be seen on the top line while new characters are seen on the bottom line.  Eventually, old and new characters would be seen on both lines and you get a mess like in figure 5.
Figure 5.
Code lines 12 to 15 along with line 3 address that problem.  We keep track of the address counter, and when it reaches the memory address beyond the end of the top tine (28h), we simply set it to the beginning address of the top line, 00h.  Note that the Visible Window will now split in two parts.  See Figures 6 and 7.
I could have avoided the problem in another way.  I could have told the display controller that I had a one line display. I could have written:
lcd_byte(0x20, LCD_CMD)
By saying I had a one line display, I could have dispensed with code lines 12 to 15.  However, I knew the one line display was going to be a precursor to my ultimate two line Times Square Scroll.  The two line version, also has code similar to lines 12 to 15.
Figure 6.
Figure 7.
That's enough to absorb for now. I'm going to save the rest of the discussion of the Times Square Scroll for the next blog entry.

Wednesday, March 27, 2013

16 X 2 LCD Input Text and Display

Here is a more practical program that asks you to input text and then displays that text on the LCD display.  The challenge here was to parse the input text so that words were not broken up.  Click on the video to see it work:
Here is python code for this program:
I apologize that the name of the program in the video (LCD_Module_1,py) does not match the name in the Gist file (LCD_Disploy2Lines.py). Somewhere along the way, after I made the video, I changed the file name to make the name more meaningful, at least to me.
The program does not take into account individual words of more that 16 characters in length.
Notice line 16 of the code. That makes LCD_2X16.py (discussed in the last post) part of this program.

Saturday, March 23, 2013

16 X 2 LCD Base Code

I am finally getting to the code.  I will spread this over three posts.  The first code will be the base module that will be imported into python programs for two other projects.  The base module can, of course, be run by itself. If it is run by itself, the LCD will display what you see in the photograph in the header of this blog.  
I did not originate the base module.  I based it on the code found at Matt Hawkins blog (referenced previously).  I added to it, made some modifications, and made it more suitable to be imported into other projects.  Matt was not the originator of the code either.  I believe the original code was modified from code for the Audunio and appears in Micky Skyler's Adafruit tutorial, "Drive a 16x2 LCD with Raspberry Pi" that is referenced in the previous post.  That tutorial presents a python class for the display controller called Adadruit_CharLCD.py.  This code is quite comprehensive and I believe others took what they needed from it for their code.  This is my version of that code, my base module:
You will need to have RPI.GPIO installed to control the GPIO pins on the PI.  I believe some distributions already include it.  Micky Skyler's Adafruit tutorial covers how to get it if you need it.  
Lines 23 and 24 are probably for my situation only.  More on this in my next post.  
If you want to understand the code you have to read it along with the Hitachi data sheet for the HD4478U.  Pages 24 and 25 have the pertinent information.  
Lines 40 through 42 of the code are particularly interesting (and I can't take any credit for this code). The HD44780 must be initialized before it can be used.  See Figure 24 on page 46 for the sequence of events to initialize the chip.  There are timing requirements between steps like "Wait for more than 4.1ms".  The PI is slow enough that we don't have to worry about the timing.  
The initialization starts (line 40 of the code) with the controller in 8 bit mode, not four bit mode.  The first two commands have DB7 - DB4 (data bus pins) set to 0011 which corresponds to hex 3, so the first two hex 3's are sent, one hex 3 at a time in line 40. The next two commands are 0011 and 0010, corresponding to hex 3 and hex 2, which are sent to the controller by line 41.  The next line, 0010 specifies 4 bit operation which is hex 2 (8 bit operation would be 0011), while the following line has N = 1 for a two line display and F = 0 for 5x8 dots.  Therefore the forth command is 1000, or 8 hex. Code line 42 sends those two commands, hex 2 and hex 8, to the controller.  I'll leave the rest of the initialization commands for you to figure out for yourself.  
For those unfamiliar with hexadecimal numbers, I plan to devote a post to hex, binary and decimal numbers and bit manipulation.
Line 105, if __name__ == '__main__', was something that I did not understand at first.  I saw quite a few questions about it on forums, so I guess I was not the only person who wanted to know.  Why do we need this line at all?  I need it because I intend to import this base module into a couple of other programs for my next posts.  This will save me from copying lines 12 to 102 into the new programs, and you will only see the new code giving a cleaner presentation.  
So how do you interpret line 105?  You can consider __name__ and __main__ to be python interpreter or internal variables.  When you run my base module, LCD_2X16.py, the interpreter assigns '__main__' to __name__.  Since line l05 evaluates to true, the code following that line will run, outputting the text to the display.  However, I have imported LCD_2X16.py into other programs by writing from LCD_2X16 import * in those programs.   If I then run one of those programs, everything from LCD_2X16.py will be part of the calling program.  However, when if __name__ == '__main__' is reached it will compute to false because __name__ now equals 'LCD_2X16', not '__main__' thus the test code will be ignored.  Pretty neat!  if __name__ == '__main__' is only written in the base module, not my other programs.

Thursday, March 7, 2013

16 X 2 LCD Display Project - Hardware

Programming a display seemed like a good starting project to get my feet wet with the Pi.  The header at the top of this page shows the hardware I purchased for this project.  There is the Adafruit Pi Dish that includes the breadboard.  The Pi Dish becomes the base that holds the Raspberry Pi and the breadboard. I like the fact that the Pi is secured and not just hanging by the ribbon cable. 
And yes, I know, I forgot to remove the brown paper from the top and bottom of the clear plastic of the Pi Dish.  By the time I remembered, I already had evertthing connected.
Connecting the Pi to the breadboard is the Adafruit Pi Cobbler breakout kit.  This is a small PCB that plugs into the breadboard and a ribbon cable that connects the PCB to the Pi's GPIO pins.  Adafruit has another Pi Cobbler with the ribbon cable on the side.  This makes the labels on one side of the PCB easier to read because the cable is not in the way.
The display is a 16 alphanumeric character by two line LCD display by Lumix, purchased from Newark/element 14 electronics.  This is a reflective type display so does not need a backlight.  I kind of wish I had purchased the transmissive type LCD display.  Adafruit has a number of color options for these sexier displays.  Transmissive displays, of course, have a backlight. 
I purchased Adafruit's Wire Bundle to make the connections on the breadboard.  The blue device is a three pin 10K potentiometer used to adjust the contrast.  It would have been better to purchase a 1K pot as the ideal contrast setting is closer to the 0 ohm resistance.  The white, square, device with the black "4" is a momentary switch.  Since my Pi is controlled from my desktop, I use the switch to have the program wait for me to get over to the Pi before having the Pi do its stuff. The blue rectangular device to the right of the switch is an Adafruit, 4 channel I2C-safe Bi-directional Logic Level Converter.  If I want the Pi to read an output from the display, a channel of the converter must be connected between the display pin and the Pi's GPIO pin.  A logic high from a display pin is nominally 5v, which would be fatal to the Pi.   The converter, or level shifter, will convert 5v from the display to 3.3v to the Pi, and 3.3v from the Pi to 5v to the display.  If it is not necessary for the Pi to read a display pin, it is not necessary to use the converter.  The display is capable of interpreting 3.3v from the Pi as a logic high signal.  In the photo in the header, the converter is not wired into the circuit.  I did experiment by reading the "busy" bit from the display.  In that case, I did use the converter.  There will be more on this experiment in a later post.
I was happy to see that a data sheet was available for the LCD display.  However, it does not tell you much beyond the dimensions, electrical characteristics, and pin-outs.  The little block diagram on the second page shows a "LCD Controller LSI and Driver".  You need the data sheet for that device, but they don't tell you what the device is.  I went to the Raspberry Pi's great webpage and used their forum to ask if anyone knew what that LCD controller was.  Rick Seiden responded to my post saying that the chip is a HD44780.  Here is the data sheet for the Hitachi HD44780U.
My next post will discuss connections made between the display and the Pi.