By I Introduction This document details how I programmed a C167 to control a dot matrix LCD for UC Berkeley's EE40 robot competition. II The LCD The LCD is a HD44780-based Character-LCD. It has 2 rows of 16 characters. The LCD can display English letters, Arabic numbers, or even characters of your own design. III Interfacing the LCD The first step in getting the LCD to work is figuring out which pins are where.
The above is a shot of the LCD as it was finally mounted on the CalBot I built in 2001. The data bus wire wraps are visible on top. The LCD’s interface consists of 11 bits. 8 of these carry data (DB0-DB7), the remaining 3 are control bits (RS, R/W, E).
The RS (data/instruction select) bit tells the LCD whether we are going to send an instruction or a piece of data. The R/W (read/write) bit tells the LCD whether we wish to read from or to write to RAM.
The E (enable) bit tells the LCD when it should read the data lines. All of these bits need to be connected to different pins on the board. I decided to use port 3 because I wanted port 2 available for controlling the LED's, and the rest of the ports didn't have 11 bits. Having the LCD on just one port makes life pretty easy.
I connected RS to P30, R/W to P31, DB0-7 to P32 - P39, and E to P313. Finally, the LCD must connected to +5V and ground. I got a 5 volt regulator for this purpose. IV Programming the LCD Part 1 - Instructions Now that the LCD is attached to port 3, we can start telling it what to display. We will use two different functions: one for giving instructions, and one for giving data. Let's first look at a for the LCD. Page 5 gives the instructions that the LCD understands.
Before we send the LCD characters, we must initialize it. The first initialization command is 'Function Set'. DB7 and DB6 are zero, DB5 is 1. DB4 indicates data length (in our case '1' to indicate 6 bits), DB3 selects number of display lines ('1' for 2 display lines), DB2 selects the display font (necessarily '0'), and DB1 and DB0 don't matter (call them '0'). It is easier to think about the hexadecimal equivalent than trying to keep track of all of the ones and zeros. It is important at this point to understand how our board expresses ports. Port 3 is a 16 bit port, meaning that there are 16 pins represented by 16 bits (P315 - P30).
The port can also be addressed as a 2 byte hexadecimal word: 0x0000 - 0xFFFF. This provides a convenient way to either examine or set the contents of the port in one line of code.
Finally, it is important to note that the highest pin is the leftmost bit. For example, P3 = 0x0010 sets P34 to 1 and everything else to 0, not P38 to 1. So what hex command do we want to send to board? Remembering the above, we decided above we wanted to say 0b00111000 However, we wired RS and R/W to be the 'lowest' (rightmost) pins, so we have to append their values to the right hand side.
Doing so gives us: 0b Now we break it up into sets of four (from the right) and add up bits: 0b00 1110 0000 0x0 E 0 0xE0 So, we want to write 0xE0 to the LCD. Of course, 0xE0 isn't the only thing we'll be writing to the LCD. It would be useful, therefore, to write a function that takes data to be written as the argument and does the actual writing itself. Take a good look at the 'Write Operation' timing chart on page 4. Go ahead - I'll wait.
It took me and my partner two weeks to decipher. Here's what it says: First we set RS high or low (data/instruction) and R/W low (write).
Then we wait 140 ns. Then we set E high. Then we set our data pins. Then we wait 80 ns. Then we 'flip' E from high to low. Then we wait 10 ns and move on with our lives. Let's do that.
To send an instruction, we want to set RS and R/W both low and wait. P3 = 0x00; ourdelay(50); Then we set E high and wait. P3 = 0x2000; ourdelay(50); Then we set our data pins by OR'ing the port with our data. P3 = P3 0xE0; ourdelay(50); Finally, we flip E and wait. P3 = P3 & 0xDFFF; ourdelay(50); There are a few more initialization commands to give. We need to set the entry mode; I set my LCD to increment and not shift. I also give the 'Display ON/OFF Control' command to decided whether or not to have a cursor.
I use the cursor when developing code for the LCD; it comes in very handy when you miscount and are wondering where the cursor is. I turn it off when the LCD code is finished and I'm showing off to my friends. Finally, I clear the display. It is worth noting that this command takes much longer than most. You must make sure you wait long enough after clearing the display, or both you and the LCD will end up very confused. Part 2 - DataNow that are our LCD is initialized and ready, let's write something!
First we'll have to look at the characters the LCD knows: Our first character is a dash ('-'). Scanning the table above, we see that there's a dash in the second column, third from bottom: 0b00101101 = 0x2D. Then we'll need a space, 0x20, and a 'C', 0x43, and so on.
These hexadecimal values are what we want to send on the data lines. Because we are writing data to the LCD, we know RS will be 0 and R/W will be 1.
You can write a function that will take the hex value we want to write as an argument and deal with the other bits itself. V Tips and Tricks- The LCD has 16 characters per row.
Unfortunately, the cursor doesn't go to the beginning of row 2 after writing the final character of line 1. You can get to row 2 after writing the last character to row 1 by giving the 'Cursor Shift Right' command 23 times. A similar thing can be done to get to the beginning of row 1 from row 2. Even though the hardware docs say that port 3 can be used entirely for digital output, this isn't always the case. Some of the upper bits of Port 3 are also used by the serial port controller. Changing their value while debugging causes some boards to freeze entirely. Say we want to set bit 2 to equal 1.
The proportion of fixed video files to GIF0. 1 Added right- click menu Shell extensions, to support the right of call format factory, now supports right- click menu to convert the file and view the file information. Pad, PSP configuration cannot play of 3 Fixed a problem in flow. Update library Media. 4, ffdshow rev. Apr 24, 2010 Format Factory v2.30 Link: Si No. Format Factory, free and safe download. Format Factory latest version: The ultimate conversion software for PC. Format Factory is a multifunctional converter software. 30 Aug 2010 Format Factory v2.50. If you do not have an AfterDawn.com accout yet, please enter a nickname and your email address below. Format factory v2.30.
The command P3=0x0004 will accomplish this. However, it will also force all other bits to be 0.
We can change the bits we care about without affecting the others by using masks. A quick review of logical AND and OR identities: x OR 1 = 1 x OR 0 = x x AND 0 = 0 x AND 1 = x Say we want to set bit 2 to equal 1, and leave all other bits alone. To do this we OR port 3 with 0x0004: P3 = 0x0004. Bit 2 is OR'd with 1, so it is set high. The rest are OR'd with zero, and are therefore unmodified To force a value to 0, we use AND's. For example, to force bit 2 to 0, we say: P3 &= 0xFFFC If your board freezes when you execute a P3= instruction, try changing it to a mask instruction. If you don't put any delay (or not enough delay!) between the instructions you send to the LCD, it won't work.
Although the board has some very sophisticated and very precise general purpose timers, a quick-and-dirty can sometimes do the trick. I wrote a function that consisted of an empty for loop, and took an argument to determine how many times to go through it.
If you decide to do this, you can figure out how long the board takes to execute an empty for loop by having an LED be on for a certain number of loops and off for an equivalent number. Probe the LED with the oscilloscope and look at the period. There's a lot that can be done with an LCD.
Above is a photo of our final bot. The top row is a bar graph of ambient light. The bottom row displays information about the bot's reactions. If you have any questions, feel free to. Happy engineering!
Now that we know almost all that we need to know about interfacing the LCD to the microcontroller, we can jump right into programming. We know the sequence that we need to control the pins of the LCD from the previous tutorial. Lets list the sequence so we can understand how to create the program. If we want to send a command or a character to the LCD, we must first check to see if the LCD is busy or not. If not, then it is ok to send the command or character.
Let take a look at the sequence of instructions we need to use to check the busy status. Also, consider peeking at the.
Led
This has all of the georgous information and specifications that you could ever want to know about LCD's. Count on me to help decipher this information these tutorials. (1) Set the microcontroller port data direction to input.
Let's call this DDR port as DataDir (2) Set the pin connected to the LCD RW to ON (read mode) (3) Set the pin connected to the LCD RS to OFF (command mode) (4) Turn the enable on, then off after a tiny delay. (5) Read the D7 pin to determine if it is a 1 or a 0. (6) Do numbers 4 and 5 until the D7 is 0 (meaning that it is not busy). The above instructions would be contained in its own sub routine. We could call it something like CheckIfTheLCDIsBusy. It might look like this.
CheckIfBusy; PORTB = character; PORTD &= (1. DataDirMrLCDsControl = 1.
What does that do if you press the left button on the first screen, or the right button on the fourth screen? The reason I rewrote the code instead of just using the one on the RobotC Blog was that I didn't expect it to loop from screen 1 to 4 when the left button was pressed.
I'm not familiar with 'case,' and don't know what it does. If that works, then the only thing the code I wrote does differently is to mark which program was selected, and allow the user to keep scrolling through menus afterwords. Yours may well work better, I believe we were posting at the same time, your post was not there when I hit the reply button. I am not a programmer, I just keep hacking until I find something that works and then run with it.:D I would expect an example from someone who truly knows how to program to work smoother and look much cleaner than the crude examples I provide which are usually pieced together from sample programs.
In, we had an LCD menu with autonomous switching capabilities. To use the menu, you need a potentiometer and an LCD. The LCD left/right buttons are for switching which menu item is shown. (Analog sensor viewer, motor test, autonomous selector/starter, etc.) The potentiometer is for selecting a sub-menu item, when applicable. (Switch what analog sensor to view, which motor to test, which autonomous routine to select, etc.) The LCD center button is for executing an action. (Start selected autonomous routine, run motor test, calibrate line follower, etc.) There is probably a good way to do the same w/o a potentiometer.
Thank you for all the information! I am going to have our programmers look through this! How do you set-up the LCD in ROBOTC? Standard behavior is for ROBOTC to configure UART2 to be the LCD, you don't need to do anything. There's a line at the top of the code I posted that (I think) works. #pragma config(UARTUsage, UART1, uartVEXLCD, baudRate19200, IOPins, None, None) I don't have an exact idea what that does, or what any of it means. If you use that code and plug the LCD Screen into UART1 it will respond to commands.
This line of code is generated by the 'Motor&Sensors Setup' menu. It is configuring UART1 for use by the LCD instead of the default which is UART2. It is setting the baud rate (the communications speed, how many bits per second are sent to the LCD) to be 19200 as well as other parameters that have little meaning on the cortex. ROBOTC is available on several platforms (NXT, arduino etc) and this #pragma has some parameters which are platform dependent.
If you plan on using an LCD with your, there’s a good chance you’ll need to program it in Python at some point. Python is probably the most popular programming language for coding on the Raspberry Pi, and many of the projects and examples you’ll find are written in Python. In this tutorial, I’ll show you how to connect your LCD and program it in Python, using the RPLCD library. I’ll start with showing you how to connect it in either 8 bit mode or 4 bit mode. Then I’ll explain how to install the library, and provide examples for printing and positioning text, clearing the screen, and controlling the cursor. I’ll also give you examples for scrolling text, creating custom characters, printing data from a sensor, and displaying the date, time, and IP address of your Pi.
BONUS: I made a quick start guide for this tutorial that you can and go back to later if you can’t set this up right now. It covers all of the steps, diagrams, and code you need to get started. I’m using a here, but the examples will work with any LCD that uses the Hitachi HD44780 driver. You can also connect the LCD via I2C, which uses only two wires, but it requires some extra hardware.
Check out our article, to see how. I also go over in another article, but for now let’s focus on Python Here is the video version of this tutorial, where you can watch all of the example programs below in real time: Connecting the LCD There are two ways to connect the LCD to your Raspberry Pi – in 4 bit mode or 8 bit mode.
4 bit mode uses 6 GPIO pins, while 8 bit mode uses 10. Since it uses up less pins, 4 bit mode is the most common method, but I’ll explain how to set up and program the LCD both ways. Each character and command is sent to the LCD as a byte (8 bits) of data. In 8 bit mode, the byte is sent all at once through 8 data wires, one bit per wire.
In 4 bit mode, the byte is split into two sets of 4 bits – the upper bits and lower bits, which are sent one after the other over 4 data wires. Theoretically, 8 bit mode transfers data about twice as fast as 4 bit mode, since the entire byte is sent all at once. However, the LCD driver takes a relatively long time to process the data, so no matter which mode is being used, we don’t really notice a difference in data transfer speed between 8 bit and 4 bit modes. Wiring the LCD in 8 Bit Mode To connect your LCD in 8 bit mode set it up like this: The backlight and contrast are 10K Ohms, but they can be substituted with 1K to 3K Ohm resistors if you want. Wiring the LCD in 4 Bit Mode To connect the LCD to your Raspberry Pi in 4 bit mode, set it up like this. The potentiometers here can also be substituted with 1K or 3K Ohm resistors. Programming the LCD With Python If this is your first time writing and running a Python program, you might want to read, which will explain everything you need to know to run the examples below.
We’ll be using a Python library that provides a lot of useful functions. Its called the RLPCD library, and was written. Installing the RPLCD Library The RPLCD library can be installed from the Python Package Index, or PIP. It might already be installed on your Pi, but if not, enter this at the command prompt to install it: sudo apt-get install python-pip After you get PIP installed, install the RPLCD library by entering: sudo pip install RPLCD The example programs below use the Raspberry Pi’s physical pin numbers, not the BCM or GPIO numbers. I’m assuming you have your LCD connected the way it is in the diagrams above, but I’ll show you how to change the pin connections if you need to.
Write to the Display in 8 Bit Mode Let’s start with a simple program that will display “Hello world!” on the LCD. If you have a different sized LCD than the 16×2 I’m using (like a 20×4), change the number of columns and rows in line 2 of the code. Cols= sets the number of columns, and rows= sets the number of rows. You can also change the pins used for the LCD’s RS, E, and data pins. The data pins are set as pinsdata=D0, D1, D2, D3, D4, D5, D6, D7.
Text strings are written to the display using the lcd.writestring function. From RPLCD import CharLCD lcd = CharLCD(cols=16, rows=2, pinrs=37, pine=35, pinsdata=33, 31, 29, 23) lcd.writestring(u'Hello world!' ) Position the Text The text can be positioned anywhere on the screen using lcd.cursorpos = (ROW, COLUMN). The rows are numbered starting from zero, so the top row is row 0, and the bottom row is row 1. Similarly, the columns are numbered starting at zero, so for a 16×2 LCD the columns are numbered 0 to 15.
For example, the code below places “Hello world!” starting at the bottom row, fourth column. Import time from RPLCD import CharLCD lcd = CharLCD(cols=16, rows=2, pinrs=37, pine=35, pinsdata=33, 31, 29, 23) while True: lcd.writestring(u'Hello world!' ) time.sleep(1) lcd.clear time.sleep(1) Press Ctrl-C to exit the program. Turn the Cursor On and Off The RPLCD library provides several functions for controlling the cursor. You can have a block cursor, an underline cursor, or a blinking cursor.
Use the following functions to set the cursor:. Blinking block cursor: lcd.cursormode = CursorMode.blink. Line cursor: lcd.cursormode = CursorMode.line. Cursor off: lcd.cursormode = CursorMode.hide The code below places a blinking cursor after the last character of text. From RPLCD import CharLCD from RPLCD import CursorMode lcd = CharLCD(cols=16, rows=2, pinrs=37, pine=35, pinsdata=33, 31, 29, 23) lcd.writestring(u'Hello world!'
) lcd.cursormode = CursorMode.blink #lcd.cursormode = CursorMode.line #lcd.cursormode = CursorMode.hide Line Breaks Text will automatically wrap to the next line if the length of the text is greater than the column length of your LCD. You can also control where the text string breaks to the next line by inserting n r where you want the break to occur.
The code below will print “Hello” to the top row, and “world!” to the bottom row. From RPLCD import CharLCD import socket import fcntl import struct lcd = CharLCD(cols=16, rows=2, pinrs=37, pine=35, pinsdata=33, 31, 29, 23) def getipaddress(ifname): s = socket.socket(socket.AFINET, socket.SOCKDGRAM) return socket.inetntoa(fcntl.ioctl( s.fileno, 0x8915, struct.pack('256s', ifname:15) )20:24) lcd.writestring('IP Address:') lcd.cursorpos = (1, 0) lcd.writestring(getipaddress('eth0')) Custom Characters Each character on the LCD is an array of 5×8 of pixels.
You can create any pattern or character you can think of, and display it on the screen as a custom character. Check out for an interactive tool that creates the bit array used to define custom characters. First we define the character in lines 4 to 12 of the code below. Then we use the function lcd.createchar(0-7, NAME) to store the character in the LCD’s CGRAM memory. Up to 8 (0-7) characters can be stored at a time. To print the custom character, we use lcd.writestring(unichr(0)), where the number in unichr is the memory location (0-7) defined in lcd.createchar. Printing a Single Custom Character Take a look at this code, which prints a single smiley face character to the display.
Thanks for your explanation, it has been a great help to verify my “programming” skills on the Raspberry Pi 2 & 3. Certainly not everybody will start from scratch reading all your contributions (like me). I stumbled via a well known search engine into this wealth of great information and succesfully hacked my way through it.
Perhaps you may want to add a hint that these scripts will only work with Python 2.7 and the pin allocation is neither BCM or GPIO but physical position? Or did I miss something?
Thanks again, hoping to find more attractive help from your webpages when I have made my next steps. Getting error help me Traceback (most recent call last): File “DHTLCD.py”, line 15, in lcd = CharLCD(cols=16, rows=2, pinrs=37, pine=35, pinsdata=33, 31, 29, 23) File “/usr/local/lib/python2.7/dist-packages/RPLCD/init.py”, line 14, in init super(CharLCD, self).init(.args,.kwargs) File “/usr/local/lib/python2.7/dist-packages/RPLCD/gpio.py”, line 95, in init ‘must be either GPIO.BOARD or GPIO.BCM’% numberingmode) ValueError: Invalid GPIO numbering mode: numberingmode=None, must be either GPIO.BOARD or GPIO.BCM.
Output Print the numbers specified in the input file in an LCD display-style using s ``-' signs for the horizontal segments and s `` ' signs for the vertical ones. Each digit occupies exactly s + 2 columns and 2s + 3 rows. Be sure to fill all the white space occupied by the digits with blanks, including the last digit. There must be exactly one column of blanks between two digits. Output a blank line after each number. You will find an example of each digit in the sample output below. Sample Input 2 12345 0 0 Sample Output.