Friday, December 6, 2013

Character LCD I2C Library for Arduino

With I²C Display Module, you can easily connect character LCD (Liquid Crystal Display) to your Arduino via I²C protocol, thus saving a lot of valuable pins usually used for parallel connection (at least 6 pins: 2 control pins - RS and EN - and 4 data pins D7, D6, D5, and D4 for 4-bit mode). With I²C (a.k.a. TWI /  Two Wires Interface), you need only two pins. Even better, those two pins can also be shared with other I2C-based peripherals.

Note: in Arduino Uno, SDA is pin A4, SCL is pin A5. For other models, please check corresponding pin diagram.

The only drawback of using these modules is (beside a little additional cost for purchasing I²C display module) is speed reduction, but it's negligible since you don't need to update lot of data at high speed with such character-based display device (might be different story with graphics LCD, they do need to fetch a lot of bitmap data).

You might want to use new LiquidCrystal_I2C library, please download most recent version (v1.2.1) in zipped file (485 Kb), generously contributed by F. Malpartida. Extract it to your Arduino working folder under library sub-folder (i.e., My Document\Arduino\libraries).

There are several Character LCD I²C modules on the market, you should use correct initialization code which might be slightly different for each device.

Include required library at beginning of your sketch as follow:
#include 'Wire.h'
#include 'LiquidCrystal_I2C.h'

Next step is to instantiate the LCD object by calling LiquidCrystal_I²C class constructor. This constructor accepts parameter in following order: addr, en, rw, rs, d4, d5, d6, d7, bl, blpol
  • addr is I²C address of the module. It's unique for each device, check with your I²C module supplier to get the correct address. Usually, they are set to 0x20, 0x27, or 0x38
  • en is bit index for Enable (EN) pin.
  • rw is bit index for Read/Write Selector (RW) pin.
  • rs is bit index for Register Selector (RS) pin.
  • d4d5d6d7 are bit indexes for upper 4-bit of data pins
  • bl is bit index for backlight pin.
  • blpol polarity of backlight pin, might be differs according to the LCD being used. Value is either POSITIVE or NEGATIVE (enum declared in LCD.h).
The first argument (addr) is mandatory, that means you have to manually specify the address of your I²C device. Other arguments are optional, if not specified they will be set to default values (bit#6 for en, bit#5 for rw, bit#4 for rs, bit#0 for d4, bit#1 for d5, bit#2 for d6, bit#3 for d7). If bl is omitted, backlight state won't be modified (default to value set by the I²C module). Default value for blpol is POSITIVE.

Those bit indexes are required for the library to send correct signal to appropriate pins since different I²C modules has different pin mapping.

Some example of initialization codes (try them to find one that suitable for your device), instantiated on object lcd:
  • LiquidCrystal_I2C lcd (0x20,2,1,0,4,5,6,7,3,POSITIVE);
  • LiquidCrystal_I2C lcd (0x27,2,1,0,4,5,6,7,3,POSITIVE);
  • LiquidCrystal_I2C lcd (0x20,4,5,6,0,1,2,3,7,NEGATIVE);
Finally, initialize the LCD by invoking begin() method which accepts two arguments: column count and row count. Example: for 16x2 display, invoke lcd.begin(16,2); For 20x4 display, invoke lcd.begin(20,4);

I2C LCD Display 20x4 Sample Sketch

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Instantiate lcd object
LiquidCrystal_I2C lcd( 0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE );

// Custom character patterns
const uint8_t charBitmap[][8] = {
   { 0xc, 0x12, 0x12, 0xc, 0, 0, 0, 0 },
   { 0x6, 0x9, 0x9, 0x6, 0, 0, 0, 0 },
   { 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0, 0x0 },
   { 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0, 0x0 },
   { 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0x0 },
   { 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0x0 },
   { 0x0, 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0x0 },
   { 0x0, 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0x0 }
};

void setup() {
  // initialize the lcd
  lcd.begin( 20, 4 ); 
  
  // create custom chars
  for( uint8_t i = 0; i < 8; i++ ) {
    lcd.createChar ( i, (uint8_t *)charBitmap[ i ] );
  }

  lcd.setCursor( 3, 2 );                  
  lcd.print( "LCD 20x4 DEMO" );
  lcd.setCursor( 0, 3 );
  lcd.print( "azTech @ vcc2gnd.com" );

}

void loop() {
   register uint8_t i;
   // Animate
   lcd.home();   
   for( i = 20; i--; ) lcd.write( random( 8 ) );
   lcd.setCursor( 0, 1 );
   for( i = 20; i--; ) lcd.write( random( 8 ) );   
   delay( 200 );
}
Watch the result on demo video below...

2 comments:

  1. 'NEGATIVE' was not declared in this scope

    ReplyDelete
  2. That's what i keep getting, i've come to the conclusion that nobody seems to know the answer to this

    ReplyDelete