LCD Tutorial

 

This Arduino LCD tutorial will teach you how to connect an LCD display to an Arduino, and learn a little about hardware interrupts.


LCD_hookup_6

The LCD used here is 16 x 2 which means you have two rows with 16 characters per row. That’s actually a fairly small display but it’s enough for this project, and they are cheap. Learning to use one is pretty simple as there is a library and examples included with the Arduino environment. Here is the LCD, these come with a pin strip that you can solder on, which makes it easy to attach to a breadboard.

LCD

I mentioned earlier how the Arduino Due operates at 3.3 V and not 5 V like most of the other Arduinos, what that actually refers to is the digital outputs, the analog inputs, and the digital to analog conversion outputs (DAC1 & DAC2). The board still has a 5V supply, and that’s what we’ll use to power the LCD. We can still use the 3.3V outputs from the Arduino Due to run the LCD. Technically this isn’t the way it should be done, but an output of 3.3V qualifies as a HIGH or logical true on a 0 to 5 V scale. In other words we are using a 3.3V device to run a 5V device. You have to be very careful when combining 5V devices and 3.3V devices, this way works fine since we are using 3.3v device to “drive” something that can handle 5V, but if you do the opposite, use 5V to “drive” something that is designed to handle 3.3 v, then in all likelihood you will destroy something. I’ll say more about this later. Before we get to that, lets just display something on the LCD. You might find the datasheet helpful.

First, connect the LCD pin labeled Vss to GND, there will be a lot of GND connections, the white wire connects GND to a row of the breadboard, and the LCD pin labeled Vdd to 5V.

Next, connect the LCD pin labeled V0 to the base of the potentiometer that comes with the LCD, ( this will control the brightness of the LCD). Connect one leg of the potentiometer to GND ( one on the left ), and the other leg to 5V.

Next connect the LCD pin labeled ‘RW’ to GND, the LCD pin labeled ‘E’ to port 11, and the LCD pin labeled RS to port 12.

Next we connect the LCD data lines (DB) as follows. DB4 to port 5, DB5 to port 4, DB6 to port 3, and DB7 to port 2.

Finally, we need to connect the LCD pin labeled K to GND, and connect the diode that came with the LCD, the Anode is connected to +V, and the cathode ( the side with the stripe ) is connected to the LCD pin labeled ‘A’.

Now that you have it all wired up, lets upload some code to display a simple phrase.

// include the library code:
#include <LiquidCrystal.h>

void displayLCD( char* line1, char* line2);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{
   // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  // Print a message to the LCD.
  displayLCD("Hello", "World!" );
}

void loop()
{
  // do nothing 
}

// routine to display text on the LCD
void displayLCD( char* line1, char* line2)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(line1);
  lcd.setCursor(0,1);
  lcd.print(line2);
}

 

 

As you can see, the code for writing to a LCD is made very simple with the LiquidCrystal library, you only need 5 lines of code to get a message displayed

#include <LiquidCrystal.h>                    // include the library
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);        // call the lcd constructor
lcd.begin(16, 2);                             // call begin
lcd.setCursor(0,0);                           // set the cursor to the first row, first column
lcd.print("Hello"); 

// routine to display text to the LCD
void displayLCD( char* line1, char* line2)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(line1);
  lcd.setCursor(0,1);
  lcd.print(line2);
}

Now that we have a basic LCD example working, lets expand this example and learn something about hardware interrupts. A lot of times what you’ll see is in the loop section of a sketch is an if statement that checks one of the digital inputs, like this.

   
  if( digitalRead(pin))
    Serial.println("test");

Every time the loop runs, you are checking the input value. This isn’t necessarily a bad way to do things, and will work most of the time, but it has some disadvantages, one is that if you set a variable by reading a port in your loop function, and then you have a lot of other code that needs to execute, the value on the port could change before you’ve gotten to the next iteration of the loop, so you are still doing things with a variable set to a value, but that value has changed, this may or may not be a problem depending on your program. Most of the time this isn’t going to matter for the hobbyist because Arduino’s run fast enough that it doesn’t matter. Another way that it can cause problems is if you have an application that you’re trying to run at a very high speed ( e.g. a DDS based theremin), if you are checking ports every time you run the loop function but the value on those ports hasn’t changed since the last time you were in the loop function, you effectively wasted processing time by checking those ports, this will become more apparent if you have a lot of sensors hooked up. Again this isn’t very common, but it is possible. Using hardware interrupts solves both of these problems in that you never actually check the value on the port but rather you assign an interrupt to the port you are using and write a function to be called when the state of the port changes. This also makes for much cleaner code in my opinion. If you’re coming from more of a desktop programming background then an interrupt is probably kind of new to you, it’s not something you encounter very often with programming a PC ( I never have). There are quite a number of things to consider when using interrupts, for example you can’t pass parameters or return a value from the interrupt function. Also what happens if an interrupt is called while a different interrupt function is still executing. I won’t go into much more detail here since out hardware interrupt routines are pretty simple, but if you want to know more, take a look at http://www.gammon.com.au/forum/?id=11488.

Let’s write a program that simulates rolling a pair of dice. Every time you push a button, a pair of random numbers from 1 to 6 will be displayed on the LCD screen, and we’ll use a hardware interrupt to detect the button press.

First we need to hookup a button, here is one example of where you need to be careful with mixing voltage levels, we are using a push button to change the voltage on one of the digital inputs, so we want to hook up the button to the 3.3V supply, not the 5V as we have been doing so far. You also want to add a current limiting resistor when adding a button, 10k works fine. Connect one side of the button to 3.3V, connect the other side of the button to the digital input, then connect a resistor from the button to GND. Do you understand how this works? When the button is open (i.e. not pressed) the Arduino input is connected to GND, so the input is LOW, and little to no current flows. When the button is pressed, you are connecting 3.3V to the input, but the input is still connected to GND as well, without the resistor you would be shorting your PWR directly to ground with nothing in between but a switch. The switch has a tiny internal resistance, so a very large current would flow, much larger than the Arduino can provide, and your just begging for something to burn up or break. By adding the resistor, when the switch is pressed you are always going to have a resistance of at least 10k, and the current will be very small.


Here is the code with an interrupt function, go ahead and upload it, then we can discuss how the code works.

// include the library code:
#include <LiquidCrystal.h>

#define btnNextPin 10

int lastInterrupt = 0; // time since last interrupt, for switch debouncing
void BtnNext();

void displayLCD( char* line1, char* line2);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{ 
  pinMode(btnNextPin, INPUT);  
  attachInterrupt(btnNextPin, BtnNext, CHANGE);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  // Print a message to the LCD.
  displayLCD("Press to roll", "" );
}

void loop()
{
 // do nothing, interrupts will handle it
}

// interrupt handler for next button
void BtnNext()
{
  if( millis() - lastInterrupt < 500 )
   {
     return;
   } 
  else
   {
     lastInterrupt = millis();
     int r1 = random(1,7);
     int r2 = random(1,7);
     char dice[16];
     sprintf(dice, "%d %d", r1, r2);
     displayLCD("Press to roll", dice);
   } 
}

// routine to display text to the LCD
void displayLCD( char* line1, char* line2)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(line1);
  lcd.setCursor(0,1);
  lcd.print(line2);
}

The code that runs the LCD is pretty much the same as what was done in the last example. Whats new here is the interrupt function. First lets look at the code you need to set up the interrupt. You need to declare the function BtnNext(), it must have return type void and cannot have parameters.

void BtnNext();
 
void BtnNext()
{
  if( millis() - lastInterrupt < 500 )
   {
     return;
   } 
  else
   {
     lastInterrupt = millis();
     int r1 = random(1,7);
     int r2 = random(1,7);
     char dice[16];
     sprintf(dice, "%d %d", r1, r2);
     displayLCD("Press to roll", dice);
   } 
}

Then to associate the interrupt function with a change on one of the Arduino ports, we call.

attachInterrupt(btnNextPin, BtnNext, CHANGE);

Lets look at how the actual interrupt function works. The millis(); function returns the number of milliseconds since the program started, we are using that to check that the interrupt code has not executed for at least half a second. This is to prevent problems with switch bounce, when you press a button or flip any switch, the metal contacts will literally bounce a tiny bit, the digital inputs of the Arduino are sensitive enough to read these bounces as individual button presses, so that pressing a button once can actually be recorded as numerous button presses. These bounces will happen faster that 500 milliseconds, so if we wait that long, we’ll ignore the bounces, and just receive a single button press.

The rest of the code is just calling the random(1,7) function, which will return a number between 1 and 6 (inclusive). Then we use the sprintf() function to take the two random integers and convert them into a string, which is then passed to displayLCD().


Intro->SOS->LCD Tutorial->Servo Tutorial->Timer Interrupts->Hacking Servos->Tone generator->DDS Tone Generator->Theremin 1->Theremin 2->RTTL Songs

 Posted by at 3:53 pm

  4 Responses to “LCD Tutorial”

  1. “the Anode is connected to GND, and the cathode ( the side with the stripe ) is connected to the LCD pin labeled ‘A’.”

    The Anode has to go to +ve; doesn’t work otherwise. A bit of checking with other circuits solved it when it didn’t work for me.

  2. Sorry where you wrote:
    “Finally, we need to connect the LCD pin labeled K to GND, and connect the diode that came with the LCD, the Anode is connected to GND, and the cathode ( the side with the stripe ) is connected to the LCD pin labeled ‘A’.”
    there is an error because the diode is connected so:

    anode to +V and the catode to pin A of lcd.
    Sorry for my bad English.
    Best regards

    Demetrio

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)


Time limit is exhausted. Please reload CAPTCHA.