Difference between revisions of "16 X 2 LCD Keypad Shield for Arduino"
(→Schematic) |
Qian.zhang (talk | contribs) (→Introduction) |
||
(63 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
== Introduction == | == Introduction == | ||
− | LCD keypad | + | We wanted to make it easier for people to get these LCD into their projects so we devised a shield that lets you control a 16x2 Character LCD backlight with a potentiometer AND 5 keypad pins using 6 digital pins on the Arduino! |
− | |||
− | + | This shield is perfect for when you want to build a stand-alone project with its own user interface. The 4 directional buttons plus select button allows basic control without having to attach a bulky computer. | |
− | * | + | *Comes with a 16x2 green backlight LCD, negative display |
+ | *Plug and play with any Arduino 'classic' - UNO, duemilanove, diecimilla, etc. | ||
+ | *Uses 6 pins of Arduino to control LCD and A0 pin for 5 buttons. | ||
− | + | ||
− | + | ||
− | + | The LCD and Keypad Shield gives you a handy 16-character by 2-line display, 5 buttons and a controllable backlight, plug it straight in on top of your Arduino board or other project shields. The display is set behind the shield for a low profile fitment and nice look and we've included panel mounting screw holes in the corners. | |
− | + | ||
− | The | + | It's great when you want to build a stand-alone project with its own user interface that doesn't require a computer attached to send commands to your Arduino. |
+ | |||
+ | Works perfectly in 4-bit mode with the "LiquidCrystal" library included with the Arduino IDE, allowing you to control the LCD with a total of just 6 digital I/O lines. We've deliberately picked D4-D9 so that it doesn't interfere with pins required by other popular products such as the Ethernet Shield and EtherTen, so you can stack this on top of other shields to give you a local display. | ||
+ | |||
+ | The buttons provide "left", "right", "up", "down", and "select" while using just one analog input. That leaves the other analog inputs free for you to use in your projects. | ||
+ | |||
+ | The LCD backlight is connected to a potentiometer can be controlled for on/off, brightness. | ||
+ | |||
+ | |||
+ | [[File:N07DH WITHOUT PACKAGED FRONT.jpg|640px]] | ||
− | + | [[File:N07DH WITHOUT PACKAGED BACK.jpg | 640px]] | |
− | |||
− | |||
− | + | [[File:N07DH PACKAGED FRONT.jpg|640px]] | |
− | [[File: | + | [[File:N07DH PACKAGED BACK.jpg|640px]] |
== Features == | == Features == | ||
− | * | + | *16x2 LCD using HD44780-compatible display module (black characters on green background). |
− | + | *5 buttons on one analog input (A0). | |
− | * | + | *LCD backlight with current limiting, brightness and on/off controllable by a adjustable potentiometer. |
+ | *Recessed LCD, panel mount screw holes and button layout suitable for panel or cabinet mounting if desired. | ||
+ | *Reset button. | ||
+ | *Power supply smoothing capacitor. | ||
− | + | == Application Ideas == | |
+ | '''test code''' | ||
+ | <syntaxhighlight lang="c"> | ||
+ | #include <LiquidCrystal.h> | ||
+ | #include <LCDKeypad.h> | ||
+ | LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); | ||
+ | char msgs[5][16] = {"Right Key OK ", | ||
+ | "Up Key OK ", | ||
+ | "Down Key OK ", | ||
+ | "Left Key OK ", | ||
+ | "Select Key OK" }; | ||
+ | int adc_key_val[5] ={50, 200, 400, 600, 800 }; | ||
+ | int NUM_KEYS = 5; | ||
+ | int adc_key_in; | ||
+ | int key=-1; | ||
+ | int oldkey=-1; | ||
− | == | + | void setup() |
+ | { | ||
+ | lcd.begin(16, 2); | ||
+ | lcd.clear(); | ||
+ | lcd.setCursor(0,0); | ||
+ | lcd.print(" helle! "); | ||
+ | lcd.print(" welcome!"); | ||
+ | lcd.setCursor(0,1); | ||
+ | lcd.print(" LinkSprite"); | ||
+ | lcd.print(" LCD Shield"); | ||
+ | delay(1000); | ||
+ | |||
+ | lcd.setCursor(0,0); | ||
+ | for (char k=0;k<26;k++) | ||
+ | { | ||
+ | lcd.scrollDisplayLeft(); | ||
+ | delay(400); | ||
+ | } | ||
+ | lcd.clear(); | ||
+ | lcd.setCursor(0,0); | ||
+ | lcd.print("ADC key testing"); | ||
+ | } | ||
+ | void loop() | ||
+ | { | ||
+ | adc_key_in = analogRead(0); // read the value from the sensor | ||
+ | key = get_key(adc_key_in); // convert into key press | ||
+ | if (key != oldkey) // if keypress is detected | ||
+ | { | ||
+ | delay(50); // wait for debounce time | ||
+ | adc_key_in = analogRead(0); // read the value from the sensor | ||
+ | key = get_key(adc_key_in); // convert into key press | ||
+ | if (key != oldkey) | ||
+ | { | ||
+ | lcd.setCursor(0, 1); | ||
+ | oldkey = key; | ||
+ | if (key >=0) | ||
+ | { | ||
+ | lcd.print(msgs[key]); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | delay(100); | ||
+ | } | ||
+ | // Convert ADC value to key number | ||
+ | int get_key(unsigned int input) | ||
+ | { | ||
+ | int k; | ||
+ | for (k = 0; k < NUM_KEYS; k++) | ||
+ | { | ||
+ | if (input < adc_key_val[k]) | ||
+ | { | ||
+ | return k; | ||
+ | } | ||
+ | } | ||
+ | if (k >= NUM_KEYS)k = -1; // No valid key pressed | ||
+ | return k; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
== Cautions == | == Cautions == | ||
Line 38: | Line 121: | ||
== Schematic == | == Schematic == | ||
− | *[ | + | *[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/1602+LCD+Shield+Sch.pdf Schematic in PDF] |
== Specification == | == Specification == | ||
+ | |||
+ | |||
+ | |||
+ | {| border="1" cellspacing="0" width="100%" | ||
+ | |- | ||
+ | ! scope="col" style="width: 50%" align="center" | Item | ||
+ | ! scope="col" align="center" | Min | ||
+ | ! scope="col" align="center" | Typical | ||
+ | ! scope="col" align="center" | Max | ||
+ | ! scope="col" align="center" | Unit | ||
+ | |- | ||
+ | ! scope="row" | Voltage | ||
+ | | align="center" | 4.3 | ||
+ | | align="center" | 5.0 | ||
+ | | align="center" | 5.7 | ||
+ | | align="center" | V | ||
+ | |- | ||
+ | ! scope="row" | Current | ||
+ | | align="center" | 39.6 | ||
+ | | align="center" | 53.3 | ||
+ | | align="center" | 65.0 | ||
+ | | align="center" | mA | ||
+ | |- | ||
+ | ! scope="row" | Dimension | ||
+ | | align="center" colspan="3" | 79.5x55.1x16.6 | ||
+ | | align="center" | mm | ||
+ | |- | ||
+ | ! scope="row" | Net Weight | ||
+ | | align="center" colspan="3" | 55.0 | ||
+ | | align="center" | g | ||
+ | |} | ||
== Pin definition and Rating == | == Pin definition and Rating == | ||
+ | |||
+ | *A0: Buttons | ||
+ | *D4: LCD bit 4 | ||
+ | *D5: LCD bit 5 | ||
+ | *D6: LCD bit 6 | ||
+ | *D7: LCD bit 7 | ||
+ | *D8: LCD RS | ||
+ | *D9: LCD Enable | ||
+ | *LCD backlight with current limiting, brightness and on/off controllable by D10. | ||
== Mechanic Dimensions == | == Mechanic Dimensions == | ||
+ | |||
+ | |||
+ | [[File:图片1.jpg]] | ||
+ | [[File:图片2.jpg]] | ||
== Usage == | == Usage == | ||
− | |||
− | + | The 16x2 LCD And Keypad Shield is very simple to use because it's fully compatible with the Arduino "LiquidCrystal" library. You can initialise the LCD and display messages on it with just a few lines of code, but it also gives you the flexibility to do more advanced projects such as display menu items and select them using the buttons. | |
+ | |||
+ | '''Power Requirements''' | ||
+ | The LCD & Keypad Shield requires a good 5V power supply to ensure the backlight fully illuminates and the display contrast is high, and if you power your Arduino from USB with the LCD Shield attached you may experience a voltage drop over the USB cable. If you have trouble with display contrast or backlight brightness, try attaching a power supply of around 7 to 9Vdc to the 2.1mm DC jack on the Arduino. A typical symptom in an undervoltage situation is that one line of the LCD will show pale rectangles in place of the characters, and the other line will show nothing at all. The Arduino may even continue running normally because it's quite happy at just 4V or so, but the LCD & Keypad Shield won't function. | ||
+ | '''Library Requirements''' | ||
+ | All the hard work of interfacing with the LCD Shield is handled by the LiquidCrystal library, which is included as part of the official Arduino distribution. You can check whether you have it installed by starting up the IDE and looking under Files -> Examples -> LiquidCrystal. If it exists, you're good to go. | ||
+ | |||
+ | '''Minimal Display Example''' | ||
+ | |||
+ | To start up the LCD and display a message, open a new sketch in the Arduino IDE and paste in the following code: | ||
+ | |||
+ | <syntaxhighlight lang="c"> | ||
+ | |||
+ | #include <LiquidCrystal.h> | ||
+ | |||
+ | LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | lcd.begin(16, 2); | ||
+ | lcd.print("hello, world!"); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | // your main loop code here... | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Reading The Buttons''' | ||
+ | |||
+ | |||
+ | The LCD Shield includes 5 buttons designed for use as navigational or control input. The buttons are arranged in a handy pattern and referred to as UP, DOWN, LEFT, RIGHT, and SELECT, but of course it's totally up to your sketch to decide what to do when any particular button is pressed. | ||
+ | |||
+ | All the buttons are connected to a single analog input, A0, using a chain of resistors that causes a different reference voltage to be applied to A0 depending on which button is pressed. This section of the shield schematic shows the input buttons and associated resistors: | ||
+ | |||
+ | |||
+ | [[File:Lcd-button-ladder.png | 400px]] | ||
+ | |||
+ | As you can see, if no button is being pressed the voltage on A0 will be pulled all the way up to 5V by the 2K resistor called R6. In that situation none of the other resistors have any effect at all, and the analog reading on A0 will be hard on the upper limit of 1023. Therefore if you perform an analogRead() call on A0 and it returns 1023 (or any value above about 1000) you know that no buttons are being pressed. | ||
+ | |||
+ | Now consider what happens if the "DOWN" button is pressed. Now A0 is being presented with a voltage that is divided between the 2K resistor that is trying to pull it up to 5V, and the 330R and 620R resistors in series (totaling 950R) that are trying to pull it down to 0V. The voltage presented to A0 in that case is about 1.61V, which means if you perform an analogRead() on A0 it will return a value of about 329. So if you read a value of about 329 from A0 you know the "DOWN" button is being pressed. | ||
+ | |||
+ | The same principle applies for the other buttons, with the voltages and equivalent analogRead() values shown on the schematic above. | ||
+ | |||
+ | This is a neat way to provide a whole set of input buttons while only using up one of the I/O pins on your Arduino, leaving more pins free for use in your project. | ||
+ | |||
+ | |||
+ | '''Complex Example''' | ||
+ | |||
+ | The extensive example below combines a number of techniques to demonstrate how to show messages on the LCD, read from the buttons, and change the display message depending on which buttons are pressed. | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="c"> | ||
+ | /* | ||
+ | |||
+ | This example code is in the public domain. | ||
+ | |||
+ | --------------------------------------------------------------------- | ||
+ | |||
+ | This program demonstrates button detection, LCD text/number printing, | ||
+ | and LCD backlight control on the Freetronics LCD & Keypad Shield, connected to an Arduino board. | ||
+ | |||
+ | |||
+ | Pins used by LCD & Keypad Shield: | ||
+ | |||
+ | A0: Buttons, analog input from voltage ladder | ||
+ | D4: LCD bit 4 | ||
+ | D5: LCD bit 5 | ||
+ | D6: LCD bit 6 | ||
+ | D7: LCD bit 7 | ||
+ | D8: LCD RS | ||
+ | D9: LCD E | ||
+ | D10: LCD Backlight (high = on, also has pullup high so default is on) | ||
+ | |||
+ | ADC voltages for the 5 buttons on analog input pin A0: | ||
+ | |||
+ | RIGHT: 0.00V : 0 @ 8bit ; 0 @ 10 bit | ||
+ | UP: 0.71V : 36 @ 8bit ; 145 @ 10 bit | ||
+ | DOWN: 1.61V : 82 @ 8bit ; 329 @ 10 bit | ||
+ | LEFT: 2.47V : 126 @ 8bit ; 505 @ 10 bit | ||
+ | SELECT: 3.62V : 185 @ 8bit ; 741 @ 10 bit | ||
+ | */ | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | Includes | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | #include <LiquidCrystal.h> // include LCD library | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | Defines | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | // Pins in use | ||
+ | #define BUTTON_ADC_PIN A0 // A0 is the button ADC input | ||
+ | #define LCD_BACKLIGHT_PIN 10 // D10 controls LCD backlight | ||
+ | // ADC readings expected for the 5 buttons on the ADC input | ||
+ | #define RIGHT_10BIT_ADC 0 // right | ||
+ | #define UP_10BIT_ADC 145 // up | ||
+ | #define DOWN_10BIT_ADC 329 // down | ||
+ | #define LEFT_10BIT_ADC 505 // left | ||
+ | #define SELECT_10BIT_ADC 741 // right | ||
+ | #define BUTTONHYSTERESIS 10 // hysteresis for valid button sensing window | ||
+ | //return values for ReadButtons() | ||
+ | #define BUTTON_NONE 0 // | ||
+ | #define BUTTON_RIGHT 1 // | ||
+ | #define BUTTON_UP 2 // | ||
+ | #define BUTTON_DOWN 3 // | ||
+ | #define BUTTON_LEFT 4 // | ||
+ | #define BUTTON_SELECT 5 // | ||
+ | //some example macros with friendly labels for LCD backlight/pin control, tested and can be swapped into the example code as you like | ||
+ | #define LCD_BACKLIGHT_OFF() digitalWrite( LCD_BACKLIGHT_PIN, LOW ) | ||
+ | #define LCD_BACKLIGHT_ON() digitalWrite( LCD_BACKLIGHT_PIN, HIGH ) | ||
+ | #define LCD_BACKLIGHT(state) { if( state ){digitalWrite( LCD_BACKLIGHT_PIN, HIGH );}else{digitalWrite( LCD_BACKLIGHT_PIN, LOW );} } | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | Variables | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | byte buttonJustPressed = false; //this will be true after a ReadButtons() call if triggered | ||
+ | byte buttonJustReleased = false; //this will be true after a ReadButtons() call if triggered | ||
+ | byte buttonWas = BUTTON_NONE; //used by ReadButtons() for detection of button events | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | Init the LCD library with the LCD pins to be used | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); //Pins for the freetronics 16x2 LCD shield. LCD: ( RS, E, LCD-D4, LCD-D5, LCD-D6, LCD-D7 ) | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | setup() | ||
+ | Called by the Arduino framework once, before the main loop begins | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | void setup() | ||
+ | { | ||
+ | //button adc input | ||
+ | pinMode( BUTTON_ADC_PIN, INPUT ); //ensure A0 is an input | ||
+ | digitalWrite( BUTTON_ADC_PIN, LOW ); //ensure pullup is off on A0 | ||
+ | //lcd backlight control | ||
+ | digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //backlight control pin D3 is high (on) | ||
+ | pinMode( LCD_BACKLIGHT_PIN, OUTPUT ); //D3 is an output | ||
+ | //set up the LCD number of columns and rows: | ||
+ | lcd.begin( 16, 2 ); | ||
+ | //Print some initial text to the LCD. | ||
+ | lcd.setCursor( 0, 0 ); //top left | ||
+ | // 1234567890123456 | ||
+ | lcd.print( "LinkSprite 16x2" ); | ||
+ | // | ||
+ | lcd.setCursor( 0, 1 ); //bottom left | ||
+ | // 1234567890123456 | ||
+ | lcd.print( "Btn:" ); | ||
+ | } | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | loop() | ||
+ | Arduino main loop | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | void loop() | ||
+ | { | ||
+ | byte button; | ||
+ | byte timestamp; | ||
+ | |||
+ | //get the latest button pressed, also the buttonJustPressed, buttonJustReleased flags | ||
+ | button = ReadButtons(); | ||
+ | //blank the demo text line if a new button is pressed or released, ready for a new label to be written | ||
+ | if( buttonJustPressed || buttonJustReleased ) | ||
+ | { | ||
+ | lcd.setCursor( 4, 1 ); | ||
+ | lcd.print( " " ); | ||
+ | } | ||
+ | //show text label for the button pressed | ||
+ | switch( button ) | ||
+ | { | ||
+ | case BUTTON_NONE: | ||
+ | { | ||
+ | break; | ||
+ | } | ||
+ | case BUTTON_RIGHT: | ||
+ | { | ||
+ | lcd.setCursor( 4, 1 ); | ||
+ | lcd.print( "RIGHT" ); | ||
+ | break; | ||
+ | } | ||
+ | case BUTTON_UP: | ||
+ | { | ||
+ | lcd.setCursor( 4, 1 ); | ||
+ | lcd.print( "UP" ); | ||
+ | break; | ||
+ | } | ||
+ | case BUTTON_DOWN: | ||
+ | { | ||
+ | lcd.setCursor( 4, 1 ); | ||
+ | lcd.print( "DOWN" ); | ||
+ | break; | ||
+ | } | ||
+ | case BUTTON_LEFT: | ||
+ | { | ||
+ | lcd.setCursor( 4, 1 ); | ||
+ | lcd.print( "LEFT" ); | ||
+ | break; | ||
+ | } | ||
+ | case BUTTON_SELECT: | ||
+ | { | ||
+ | lcd.setCursor( 4, 1 ); | ||
+ | lcd.print( "SELECT-FLASH" ); | ||
+ | |||
+ | //SELECT is a special case, it pulses the LCD backlight off and on for demo | ||
+ | digitalWrite( LCD_BACKLIGHT_PIN, LOW ); | ||
+ | delay( 150 ); | ||
+ | digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //leave the backlight on at exit | ||
+ | delay( 150 ); | ||
+ | |||
+ | /* an example of LCD backlight control via macros with nice labels | ||
+ | LCD_BACKLIGHT_OFF(); | ||
+ | delay( 150 ); | ||
+ | LCD_BACKLIGHT_ON(); //leave the backlight on at exit | ||
+ | delay( 150 ); | ||
+ | */ | ||
+ | |||
+ | /* | ||
+ | // an example of LCD backlight control via a macro with nice label, called with a value | ||
+ | LCD_BACKLIGHT(false); | ||
+ | delay( 150 ); | ||
+ | LCD_BACKLIGHT(true); //leave the backlight on at exit | ||
+ | delay( 150 ); | ||
+ | */ | ||
+ | |||
+ | break; | ||
+ | } | ||
+ | default: | ||
+ | { | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | // print the number of seconds since reset (two digits only) | ||
+ | timestamp = ( (millis() / 1000) % 100 ); //"% 100" is the remainder of a divide-by-100, which keeps the value as 0-99 even as the result goes over 100 | ||
+ | lcd.setCursor( 14, 1 ); | ||
+ | if( timestamp <= 9 ) | ||
+ | lcd.print( " " ); //quick trick to right-justify this 2 digit value when it's a single digit | ||
+ | lcd.print( timestamp, DEC ); | ||
+ | /* | ||
+ | //debug/test display of the adc reading for the button input voltage pin. | ||
+ | lcd.setCursor(12, 0); | ||
+ | lcd.print( " " ); //quick hack to blank over default left-justification from lcd.print() | ||
+ | lcd.setCursor(12, 0); //note the value will be flickering/faint on the LCD | ||
+ | lcd.print( analogRead( BUTTON_ADC_PIN ) ); | ||
+ | */ | ||
+ | //clear the buttonJustPressed or buttonJustReleased flags, they've already done their job now. | ||
+ | if( buttonJustPressed ) | ||
+ | buttonJustPressed = false; | ||
+ | if( buttonJustReleased ) | ||
+ | buttonJustReleased = false; | ||
+ | } | ||
+ | /*-------------------------------------------------------------------------------------- | ||
+ | ReadButtons() | ||
+ | Detect the button pressed and return the value | ||
+ | Uses global values buttonWas, buttonJustPressed, buttonJustReleased. | ||
+ | --------------------------------------------------------------------------------------*/ | ||
+ | byte ReadButtons() | ||
+ | { | ||
+ | unsigned int buttonVoltage; | ||
+ | byte button = BUTTON_NONE; // return no button pressed if the below checks don't write to btn | ||
+ | |||
+ | //read the button ADC pin voltage | ||
+ | buttonVoltage = analogRead( BUTTON_ADC_PIN ); | ||
+ | //sense if the voltage falls within valid voltage windows | ||
+ | if( buttonVoltage < ( RIGHT_10BIT_ADC + BUTTONHYSTERESIS ) ) | ||
+ | { | ||
+ | button = BUTTON_RIGHT; | ||
+ | } | ||
+ | else if( buttonVoltage >= ( UP_10BIT_ADC - BUTTONHYSTERESIS ) | ||
+ | && buttonVoltage <= ( UP_10BIT_ADC + BUTTONHYSTERESIS ) ) | ||
+ | { | ||
+ | button = BUTTON_UP; | ||
+ | } | ||
+ | else if( buttonVoltage >= ( DOWN_10BIT_ADC - BUTTONHYSTERESIS ) | ||
+ | && buttonVoltage <= ( DOWN_10BIT_ADC + BUTTONHYSTERESIS ) ) | ||
+ | { | ||
+ | button = BUTTON_DOWN; | ||
+ | } | ||
+ | else if( buttonVoltage >= ( LEFT_10BIT_ADC - BUTTONHYSTERESIS ) | ||
+ | && buttonVoltage <= ( LEFT_10BIT_ADC + BUTTONHYSTERESIS ) ) | ||
+ | { | ||
+ | button = BUTTON_LEFT; | ||
+ | } | ||
+ | else if( buttonVoltage >= ( SELECT_10BIT_ADC - BUTTONHYSTERESIS ) | ||
+ | && buttonVoltage <= ( SELECT_10BIT_ADC + BUTTONHYSTERESIS ) ) | ||
+ | { | ||
+ | button = BUTTON_SELECT; | ||
+ | } | ||
+ | //handle button flags for just pressed and just released events | ||
+ | if( ( buttonWas == BUTTON_NONE ) && ( button != BUTTON_NONE ) ) | ||
+ | { | ||
+ | //the button was just pressed, set buttonJustPressed, this can optionally be used to trigger a once-off action for a button press event | ||
+ | //it's the duty of the receiver to clear these flags if it wants to detect a new button change event | ||
+ | buttonJustPressed = true; | ||
+ | buttonJustReleased = false; | ||
+ | } | ||
+ | if( ( buttonWas != BUTTON_NONE ) && ( button == BUTTON_NONE ) ) | ||
+ | { | ||
+ | buttonJustPressed = false; | ||
+ | buttonJustReleased = true; | ||
+ | } | ||
+ | |||
+ | //save the latest button value, for change event detection next time round | ||
+ | buttonWas = button; | ||
+ | |||
+ | return( button ); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == pcDuino Sample Code == | ||
== FAQ == | == FAQ == | ||
Line 60: | Line 489: | ||
== Support == | == Support == | ||
− | If you have questions or other better design ideas, you can go to our [http:// | + | If you have questions or other better design ideas, you can go to our [http://linksprite.invisionzone.com/ forum] to discuss or creat a ticket for your issue at [http://www.linksprite.com/support/ linksprite support]. |
== Resources == | == Resources == | ||
− | *[ | + | *PDF Files |
− | + | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/lcd-datasheet-dfr0009.pdf LCD Datasheet] | |
− | *[ | + | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/HD44780.pdf HD44780 Datasheet] |
+ | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/ZYMC1602-17.pdf 16x2 LCD Datasheet] | ||
− | * | + | *ZIP Files |
+ | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/LCD4Bit_mod.zip LCD 4Bit Mod] | ||
+ | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/LCD4Bit_mod(for+Arduino+1.0.5-r2).zip LCD 4Bit Mod for Arduino 1.0.5-r2/Arduino 1.5.6-r2] | ||
+ | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/lcd-keypad-library-dfr0009.zip LCD Keypad Library] | ||
+ | **[https://s3.amazonaws.com/linksprite/Shields/16X2+LCD+Keypad+shield/key-grabber-library-v2-dfr0009.zip Key Grabber Library V2] | ||
== How to buy == | == How to buy == | ||
+ | Here to buy 16 X 2 LCD Keypad Shield for Arduino on store [http://store.linksprite.com/linksprite-16x2-lcd-keypad-shield-for-arduino-version-a/ A] or [http://store.linksprite.com/linksprite-16x2-lcd-keypad-shield-for-arduino-version-b/ B] | ||
== See Also == | == See Also == |
Latest revision as of 05:12, 6 September 2015
Contents
Introduction
We wanted to make it easier for people to get these LCD into their projects so we devised a shield that lets you control a 16x2 Character LCD backlight with a potentiometer AND 5 keypad pins using 6 digital pins on the Arduino!
This shield is perfect for when you want to build a stand-alone project with its own user interface. The 4 directional buttons plus select button allows basic control without having to attach a bulky computer.
- Comes with a 16x2 green backlight LCD, negative display
- Plug and play with any Arduino 'classic' - UNO, duemilanove, diecimilla, etc.
- Uses 6 pins of Arduino to control LCD and A0 pin for 5 buttons.
The LCD and Keypad Shield gives you a handy 16-character by 2-line display, 5 buttons and a controllable backlight, plug it straight in on top of your Arduino board or other project shields. The display is set behind the shield for a low profile fitment and nice look and we've included panel mounting screw holes in the corners.
It's great when you want to build a stand-alone project with its own user interface that doesn't require a computer attached to send commands to your Arduino.
Works perfectly in 4-bit mode with the "LiquidCrystal" library included with the Arduino IDE, allowing you to control the LCD with a total of just 6 digital I/O lines. We've deliberately picked D4-D9 so that it doesn't interfere with pins required by other popular products such as the Ethernet Shield and EtherTen, so you can stack this on top of other shields to give you a local display.
The buttons provide "left", "right", "up", "down", and "select" while using just one analog input. That leaves the other analog inputs free for you to use in your projects.
The LCD backlight is connected to a potentiometer can be controlled for on/off, brightness.
Features
- 16x2 LCD using HD44780-compatible display module (black characters on green background).
- 5 buttons on one analog input (A0).
- LCD backlight with current limiting, brightness and on/off controllable by a adjustable potentiometer.
- Recessed LCD, panel mount screw holes and button layout suitable for panel or cabinet mounting if desired.
- Reset button.
- Power supply smoothing capacitor.
Application Ideas
test code <syntaxhighlight lang="c">
- include <LiquidCrystal.h>
- include <LCDKeypad.h>
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); char msgs[5][16] = {"Right Key OK ",
"Up Key OK ", "Down Key OK ", "Left Key OK ", "Select Key OK" };
int adc_key_val[5] ={50, 200, 400, 600, 800 }; int NUM_KEYS = 5; int adc_key_in; int key=-1; int oldkey=-1;
void setup() {
lcd.begin(16, 2); lcd.clear(); lcd.setCursor(0,0); lcd.print(" helle! "); lcd.print(" welcome!"); lcd.setCursor(0,1); lcd.print(" LinkSprite"); lcd.print(" LCD Shield"); delay(1000); lcd.setCursor(0,0); for (char k=0;k<26;k++) { lcd.scrollDisplayLeft(); delay(400); } lcd.clear(); lcd.setCursor(0,0); lcd.print("ADC key testing");
} void loop() {
adc_key_in = analogRead(0); // read the value from the sensor key = get_key(adc_key_in); // convert into key press if (key != oldkey) // if keypress is detected { delay(50); // wait for debounce time adc_key_in = analogRead(0); // read the value from the sensor key = get_key(adc_key_in); // convert into key press if (key != oldkey) { lcd.setCursor(0, 1); oldkey = key; if (key >=0) { lcd.print(msgs[key]); } } } delay(100);
} // Convert ADC value to key number int get_key(unsigned int input) {
int k; for (k = 0; k < NUM_KEYS; k++) { if (input < adc_key_val[k]) { return k; } } if (k >= NUM_KEYS)k = -1; // No valid key pressed return k;
} </syntaxhighlight>
Cautions
The warnings and wrong operations possible cause dangerous.
Schematic
Specification
Item | Min | Typical | Max | Unit |
---|---|---|---|---|
Voltage | 4.3 | 5.0 | 5.7 | V |
Current | 39.6 | 53.3 | 65.0 | mA |
Dimension | 79.5x55.1x16.6 | mm | ||
Net Weight | 55.0 | g |
Pin definition and Rating
- A0: Buttons
- D4: LCD bit 4
- D5: LCD bit 5
- D6: LCD bit 6
- D7: LCD bit 7
- D8: LCD RS
- D9: LCD Enable
- LCD backlight with current limiting, brightness and on/off controllable by D10.
Mechanic Dimensions
Usage
The 16x2 LCD And Keypad Shield is very simple to use because it's fully compatible with the Arduino "LiquidCrystal" library. You can initialise the LCD and display messages on it with just a few lines of code, but it also gives you the flexibility to do more advanced projects such as display menu items and select them using the buttons.
Power Requirements
The LCD & Keypad Shield requires a good 5V power supply to ensure the backlight fully illuminates and the display contrast is high, and if you power your Arduino from USB with the LCD Shield attached you may experience a voltage drop over the USB cable. If you have trouble with display contrast or backlight brightness, try attaching a power supply of around 7 to 9Vdc to the 2.1mm DC jack on the Arduino. A typical symptom in an undervoltage situation is that one line of the LCD will show pale rectangles in place of the characters, and the other line will show nothing at all. The Arduino may even continue running normally because it's quite happy at just 4V or so, but the LCD & Keypad Shield won't function.
Library Requirements
All the hard work of interfacing with the LCD Shield is handled by the LiquidCrystal library, which is included as part of the official Arduino distribution. You can check whether you have it installed by starting up the IDE and looking under Files -> Examples -> LiquidCrystal. If it exists, you're good to go.
Minimal Display Example
To start up the LCD and display a message, open a new sketch in the Arduino IDE and paste in the following code:
<syntaxhighlight lang="c">
- include <LiquidCrystal.h>
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );
void setup() {
lcd.begin(16, 2); lcd.print("hello, world!");
}
void loop() {
// your main loop code here...
}
</syntaxhighlight>
Reading The Buttons
The LCD Shield includes 5 buttons designed for use as navigational or control input. The buttons are arranged in a handy pattern and referred to as UP, DOWN, LEFT, RIGHT, and SELECT, but of course it's totally up to your sketch to decide what to do when any particular button is pressed.
All the buttons are connected to a single analog input, A0, using a chain of resistors that causes a different reference voltage to be applied to A0 depending on which button is pressed. This section of the shield schematic shows the input buttons and associated resistors:
As you can see, if no button is being pressed the voltage on A0 will be pulled all the way up to 5V by the 2K resistor called R6. In that situation none of the other resistors have any effect at all, and the analog reading on A0 will be hard on the upper limit of 1023. Therefore if you perform an analogRead() call on A0 and it returns 1023 (or any value above about 1000) you know that no buttons are being pressed.
Now consider what happens if the "DOWN" button is pressed. Now A0 is being presented with a voltage that is divided between the 2K resistor that is trying to pull it up to 5V, and the 330R and 620R resistors in series (totaling 950R) that are trying to pull it down to 0V. The voltage presented to A0 in that case is about 1.61V, which means if you perform an analogRead() on A0 it will return a value of about 329. So if you read a value of about 329 from A0 you know the "DOWN" button is being pressed.
The same principle applies for the other buttons, with the voltages and equivalent analogRead() values shown on the schematic above.
This is a neat way to provide a whole set of input buttons while only using up one of the I/O pins on your Arduino, leaving more pins free for use in your project.
Complex Example
The extensive example below combines a number of techniques to demonstrate how to show messages on the LCD, read from the buttons, and change the display message depending on which buttons are pressed.
<syntaxhighlight lang="c">
/*
This example code is in the public domain. --------------------------------------------------------------------- This program demonstrates button detection, LCD text/number printing, and LCD backlight control on the Freetronics LCD & Keypad Shield, connected to an Arduino board. Pins used by LCD & Keypad Shield: A0: Buttons, analog input from voltage ladder D4: LCD bit 4 D5: LCD bit 5 D6: LCD bit 6 D7: LCD bit 7 D8: LCD RS D9: LCD E D10: LCD Backlight (high = on, also has pullup high so default is on) ADC voltages for the 5 buttons on analog input pin A0: RIGHT: 0.00V : 0 @ 8bit ; 0 @ 10 bit UP: 0.71V : 36 @ 8bit ; 145 @ 10 bit DOWN: 1.61V : 82 @ 8bit ; 329 @ 10 bit LEFT: 2.47V : 126 @ 8bit ; 505 @ 10 bit SELECT: 3.62V : 185 @ 8bit ; 741 @ 10 bit
- /
/*--------------------------------------------------------------------------------------
Includes
*/
- include <LiquidCrystal.h> // include LCD library
/*--------------------------------------------------------------------------------------
Defines
*/
// Pins in use
- define BUTTON_ADC_PIN A0 // A0 is the button ADC input
- define LCD_BACKLIGHT_PIN 10 // D10 controls LCD backlight
// ADC readings expected for the 5 buttons on the ADC input
- define RIGHT_10BIT_ADC 0 // right
- define UP_10BIT_ADC 145 // up
- define DOWN_10BIT_ADC 329 // down
- define LEFT_10BIT_ADC 505 // left
- define SELECT_10BIT_ADC 741 // right
- define BUTTONHYSTERESIS 10 // hysteresis for valid button sensing window
//return values for ReadButtons()
- define BUTTON_NONE 0 //
- define BUTTON_RIGHT 1 //
- define BUTTON_UP 2 //
- define BUTTON_DOWN 3 //
- define BUTTON_LEFT 4 //
- define BUTTON_SELECT 5 //
//some example macros with friendly labels for LCD backlight/pin control, tested and can be swapped into the example code as you like
- define LCD_BACKLIGHT_OFF() digitalWrite( LCD_BACKLIGHT_PIN, LOW )
- define LCD_BACKLIGHT_ON() digitalWrite( LCD_BACKLIGHT_PIN, HIGH )
- define LCD_BACKLIGHT(state) { if( state ){digitalWrite( LCD_BACKLIGHT_PIN, HIGH );}else{digitalWrite( LCD_BACKLIGHT_PIN, LOW );} }
/*--------------------------------------------------------------------------------------
Variables
*/
byte buttonJustPressed = false; //this will be true after a ReadButtons() call if triggered byte buttonJustReleased = false; //this will be true after a ReadButtons() call if triggered byte buttonWas = BUTTON_NONE; //used by ReadButtons() for detection of button events /*--------------------------------------------------------------------------------------
Init the LCD library with the LCD pins to be used
*/
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); //Pins for the freetronics 16x2 LCD shield. LCD: ( RS, E, LCD-D4, LCD-D5, LCD-D6, LCD-D7 ) /*--------------------------------------------------------------------------------------
setup() Called by the Arduino framework once, before the main loop begins
*/
void setup() {
//button adc input pinMode( BUTTON_ADC_PIN, INPUT ); //ensure A0 is an input digitalWrite( BUTTON_ADC_PIN, LOW ); //ensure pullup is off on A0 //lcd backlight control digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //backlight control pin D3 is high (on) pinMode( LCD_BACKLIGHT_PIN, OUTPUT ); //D3 is an output //set up the LCD number of columns and rows: lcd.begin( 16, 2 ); //Print some initial text to the LCD. lcd.setCursor( 0, 0 ); //top left // 1234567890123456 lcd.print( "LinkSprite 16x2" ); // lcd.setCursor( 0, 1 ); //bottom left // 1234567890123456 lcd.print( "Btn:" );
} /*--------------------------------------------------------------------------------------
loop() Arduino main loop
*/
void loop() {
byte button; byte timestamp; //get the latest button pressed, also the buttonJustPressed, buttonJustReleased flags button = ReadButtons(); //blank the demo text line if a new button is pressed or released, ready for a new label to be written if( buttonJustPressed || buttonJustReleased ) { lcd.setCursor( 4, 1 ); lcd.print( " " ); } //show text label for the button pressed switch( button ) { case BUTTON_NONE: { break; } case BUTTON_RIGHT: { lcd.setCursor( 4, 1 ); lcd.print( "RIGHT" ); break; } case BUTTON_UP: { lcd.setCursor( 4, 1 ); lcd.print( "UP" ); break; } case BUTTON_DOWN: { lcd.setCursor( 4, 1 ); lcd.print( "DOWN" ); break; } case BUTTON_LEFT: { lcd.setCursor( 4, 1 ); lcd.print( "LEFT" ); break; } case BUTTON_SELECT: { lcd.setCursor( 4, 1 ); lcd.print( "SELECT-FLASH" ); //SELECT is a special case, it pulses the LCD backlight off and on for demo digitalWrite( LCD_BACKLIGHT_PIN, LOW ); delay( 150 ); digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //leave the backlight on at exit delay( 150 ); /* an example of LCD backlight control via macros with nice labels LCD_BACKLIGHT_OFF(); delay( 150 ); LCD_BACKLIGHT_ON(); //leave the backlight on at exit delay( 150 ); */ /* // an example of LCD backlight control via a macro with nice label, called with a value LCD_BACKLIGHT(false); delay( 150 ); LCD_BACKLIGHT(true); //leave the backlight on at exit delay( 150 ); */ break; } default: { break; } } // print the number of seconds since reset (two digits only) timestamp = ( (millis() / 1000) % 100 ); //"% 100" is the remainder of a divide-by-100, which keeps the value as 0-99 even as the result goes over 100 lcd.setCursor( 14, 1 ); if( timestamp <= 9 ) lcd.print( " " ); //quick trick to right-justify this 2 digit value when it's a single digit lcd.print( timestamp, DEC );
/*
//debug/test display of the adc reading for the button input voltage pin. lcd.setCursor(12, 0); lcd.print( " " ); //quick hack to blank over default left-justification from lcd.print() lcd.setCursor(12, 0); //note the value will be flickering/faint on the LCD lcd.print( analogRead( BUTTON_ADC_PIN ) );
- /
//clear the buttonJustPressed or buttonJustReleased flags, they've already done their job now. if( buttonJustPressed ) buttonJustPressed = false; if( buttonJustReleased ) buttonJustReleased = false;
} /*--------------------------------------------------------------------------------------
ReadButtons() Detect the button pressed and return the value Uses global values buttonWas, buttonJustPressed, buttonJustReleased.
*/
byte ReadButtons() {
unsigned int buttonVoltage; byte button = BUTTON_NONE; // return no button pressed if the below checks don't write to btn //read the button ADC pin voltage buttonVoltage = analogRead( BUTTON_ADC_PIN ); //sense if the voltage falls within valid voltage windows if( buttonVoltage < ( RIGHT_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_RIGHT; } else if( buttonVoltage >= ( UP_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( UP_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_UP; } else if( buttonVoltage >= ( DOWN_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( DOWN_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_DOWN; } else if( buttonVoltage >= ( LEFT_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( LEFT_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_LEFT; } else if( buttonVoltage >= ( SELECT_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( SELECT_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_SELECT; } //handle button flags for just pressed and just released events if( ( buttonWas == BUTTON_NONE ) && ( button != BUTTON_NONE ) ) { //the button was just pressed, set buttonJustPressed, this can optionally be used to trigger a once-off action for a button press event //it's the duty of the receiver to clear these flags if it wants to detect a new button change event buttonJustPressed = true; buttonJustReleased = false; } if( ( buttonWas != BUTTON_NONE ) && ( button == BUTTON_NONE ) ) { buttonJustPressed = false; buttonJustReleased = true; } //save the latest button value, for change event detection next time round buttonWas = button; return( button );
} </syntaxhighlight>
pcDuino Sample Code
FAQ
Please list your question here:
Support
If you have questions or other better design ideas, you can go to our forum to discuss or creat a ticket for your issue at linksprite support.
Resources
- PDF Files
- ZIP Files
How to buy
Here to buy 16 X 2 LCD Keypad Shield for Arduino on store A or B
See Also
Other related products and resources.
Licensing
This documentation is licensed under the Creative Commons Attribution-ShareAlike License 3.0 Source code and libraries are licensed under GPL/LGPL, see source code files for details.