A Keypad + LCD with only 2 Pins?! No problem with the I2C Protocol!

//A Keypad + LCD with only 2 Pins?! No problem with the I2C Protocol!


-I2C Keypad with an Arduino-
Understanding the i2c protocol


All my content is free.

If you feel that my videos are helping and you would like to contribute, you can toss some coins in the Tip Jar via PayPal.

Select amount then click the “Donate” button.

Brainy-Bits Tip Jar Amount

In the last tutorial we saw how to use a i2c Expander module to connect a Bourns encoder and use 2 pins instead of eight to connect it to an Arduino.

In this one we’ll use it to connect a Keypad to an Arduino and again save some pins, and also have a quick overview on what and how the i2c protocol works.

I2C Expansion Module

Quick overview of the i2c protocol

I2C stands for “Inter-Integrated Circuit“, it allows to connect multiple modules or “slave”, and requires only 2 wires no matter the amount of connected modules, on an Arduino you can have up to 128 slave devices.

Each I2C device need to have a different address so the Arduino can send or get the information from the right module.

Those address are in hex values (ex. ox20), and most module give you the possibility to change the address by either soldering some pads or using dip switches like the I2C Expander module we used.

Some module have fixed address that cannot be changed, so you couldn’t use two of those modules on the same I2C bus.

We will see how to get around that in a future tutorial!

Btw you can also have more than one Arduino connected to the same I2C modules and be able to access them, of course not at the same time.

Even though I2C is pretty fast, it does have some overhead since for every 8 bits of information, there will be one extra bit for the i2c protocol.

I2C uses two pins or signals, one is SCL and the other is SDA.  Most Arduinos have only one I2C bus, one exception would be the Arduino Due which has two seperate I2C bus.

The pins (SCL and SDA) are predefined on Arduinos, for example on the UNO those are A4=SDA A5=SCL, and on the MEGA2560 those are 20=A4 and 21=SCL.

SCL provides the clock, and SDA is the data.

It’s good to know that the I2C protocol can communicate both ways, so can be used to send as well as receive information.

The I2C Expander Module VS I2C LCD Backpack


Both modules use the same chip at their core, the PCF8574T.

pcf8574 pinout

The PCF8574 is an 8-bit I/O expander designed to communicate on the I2C‑bus.

Each one of those 8 pins/ports (P0-P7) can be independently used as an input, like we used it for when connecting the Bourns encoder or as an output to control some LEDs for example.

So in the case of the I2C LCD Backpack module, those are used as output to send information to the LCD.

The main difference between those two modules, is their pinouts, the LCD Backpack pinout is made to fit on an LCD with additional outputs for the backlight.

The I2C-Expander on the other hand, has all 8 pins in order and clearly marked, make it easy to connect.

So why not just use the I2C LCD Backpack


Since both the I2C port Expander and the I2C LCD Backpack are pretty much the same, couldn’t I just use the LCD Backpack to connect the Bourns encoder?

Well that’s what I thought at first….

You see the LCD Backpack pinout is different, but it’s easy to see which pin is connected to which pin on the PCF8574 by using a multimeter.

But to my surprise, it seems that the PCF8574 I/O pin #3 is not connected to anything?!

I don’t know if the’re all like that, but all the ones i’ve tested had the same problem.  Maybe yours has all the pins connected properly but you’ll have to check that out with a multimeter.

Don’t know if those chinese version take bad or defect PCF8574 chips to create those cheap LCD Backpacks, maybe it’s a luck of the draw.

But if your project can make due with only 7 I/O pins then you can use the LCD Backpack as an I2C Expander since those other pins are properly connected.

Here’s the pinout for the I2C LCD backpack if you want to give it a try:


Connection Diagram


As you can see we are only using 2 Pins on the Arduino to control both the Keypad and the LCD:

I2C Expansion module connections:
5V and Ground from the Arduino and A4 – A5 to SDA and SCL on the I2C module

LCD Connections:
5v and Ground from the Arduino and A4 – A5 to SDA and SCL of the backpack

Keypad Connections:
The keypad has 7 pins, 4 of those from left to right are:
R1-R4 (These are the Rows of digits)

And the following 3 pins are:
C1-C3 (These are the Columns of digits)

We connect these in order (from left to right) to the I2C-Expander pins:

R1-R2-R3-R4-C1-C2-C3 —> P0-P1-P2-P3-P4-P5-P6


In this tutorial we will be using both the I2c LCD Backpack at address 0x27 and the I2C Expander at address 0x20.

We have a 12 keys keypad connected to the I2C Expander module P0 to P6 pins.  So instead of using 7 Pins on the Arduino, were’s using the I2C protocol and using only 2 Pins to read the Keypad as well as display the results on the LCD screen.

We are using a library for both the Keypad and the LCD, you can find the link to the libraries at the bottom of this page.

As always please check out the tutorial video for more information.

/* Arduino I2C-Keypad using an I2C_Expander module

Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!


#include <Keypad_I2C.h> // I2C Keypad library by Joe Young https://github.com/joeyoung/arduino_keypads
#include <LiquidCrystal_I2C.h>  // I2C LCD Library by Francisco Malpartida https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home

#define lcd_addr 0x27     // I2C address of typical I2C LCD Backpack
#define keypad_addr 0x20  // I2C address of I2C Expander module (A0-A1-A2 dip switch to off position)

// LCD Pins to I2C LCD Backpack - These are default for HD44780 LCD's
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

// Create instance for LCD called: i2c_lcd
LiquidCrystal_I2C i2c_lcd(lcd_addr,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

// Define the keypad pins
const byte ROWS = 4; 
const byte COLS = 3;
char keys[ROWS][COLS] = {

// Keypad pins connected to the I2C-Expander pins P0-P6
byte rowPins[ROWS] = {0, 1, 2, 3}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {4, 5, 6};    // connect to the column pinouts of the keypad

// Create instance of the Keypad name I2C_Keypad and using the PCF8574 chip
Keypad_I2C I2C_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS, keypad_addr, PCF8574 );

void setup() {
  i2c_lcd.begin (16,2); //  our LCD is a 16x2, change for your LCD if needed
  // LCD Backlight ON
  i2c_lcd.clear(); // Clear the LCD screen

void loop() {

  // Put value of pressed key on keypad in key variable
  char key = I2C_Keypad.getKey();

  // Light up key pressed on LCD
  switch (key) {
    case '1':

    case '2':

    case '3':

    case '4':

    case '5':

    case '6':

    case '7':

    case '8':

    case '9':

    case '0':

    case '*':

    case '#':

As you saw, using an I2C Expander is pretty easy and if your project needs a Keypad, now you won’t have to sacrifice a bunch of pins to use one.

The I2C expander module can also be used as an output device to control some LEDs for example, I’ll might do a tutorial on this soon.

Thank you for stopping by!


Copy and Paste the above code/sketch in your Arduino IDE software.

Link to the libraries used in this tutorial:

By | 2019-03-15T19:13:02-04:00 March 15th, 2019|Tutorials|


  1. InfoBoxESP8266 August 25, 2020 at 3:50 am - Reply

    HI There, Thanks for the great article.

    A theoretical question…
    I have a Nokia 5110 LCD connected with a PCF8574 LCD Backpack (working), which
    leaves a few pins of the PCF8574 exposed. Would it somehow be possible to use some of the
    unused pins on the module, for, say, some extra buttons or LED’s?

  2. Renesme December 17, 2019 at 1:33 pm - Reply

    Can I get your email? I have something to consult.

    Also,why “make Keymap is not declared in this scope” appears when I tried to upload. What should I do? I just copied your exact code,what’s wrong?

  3. Don November 14, 2019 at 11:43 am - Reply

    Trying to compile tis sketch and get the rollowing:-
    Arduino: 1.8.10 (Windows 10), Board: “Arduino/Genuino Uno”

    i2ckp4:27:84: error: no matching function for call to ‘LiquidCrystal_I2C::LiquidCrystal_I2C(int, int, int, int, int, int, int, int)’

    LiquidCrystal_I2C i2c_lcd(lcd_addr,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);


    In file included from C:\Users\Vosper\Documents\Arduino\i2ckp4\i2ckp4.ino:11:0:

    C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:57:3: note: candidate: LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t, uint8_t, uint8_t)

    LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);


    C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:57:3: note: candidate expects 3 arguments, 8 provided

    C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate: constexpr LiquidCrystal_I2C::LiquidCrystal_I2C(const LiquidCrystal_I2C&)

    class LiquidCrystal_I2C : public Print {


    C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate expects 1 argument, 8 provided

    C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate: constexpr LiquidCrystal_I2C::LiquidCrystal_I2C(LiquidCrystal_I2C&&)

    C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate expects 1 argument, 8 provided

    i2ckp4:44:24: error: ‘makeKeymap’ was not declared in this scope

    Keypad_I2C I2C_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS, keypad_addr, PCF8574 );


    i2ckp4:44:85: error: ‘PCF8574’ was not declared in this scope

    Keypad_I2C I2C_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS, keypad_addr, PCF8574 );


    C:\Users\Vosper\Documents\Arduino\i2ckp4\i2ckp4.ino: In function ‘void setup()’:

    i2ckp4:51:11: error: ‘class LiquidCrystal_I2C’ has no member named ‘setBacklightPin’; did you mean ‘setBacklight’?




    i2ckp4:51:41: error: ‘POSITIVE’ was not declared in this scope



    Multiple libraries were found for “Keypad_I2C.h”
    Used: C:\Users\Vosper\Documents\Arduino\libraries\Keypad_I2C-master
    Multiple libraries were found for “LiquidCrystal_I2C.h”
    Used: C:\Users\Vosper\Documents\Arduino\libraries\LiquidCrystal_I2C
    Not used: C:\Users\Vosper\Documents\Arduino\libraries\NewLiquidCrystal_lib
    Multiple libraries were found for “Wire.h”
    Used: C:\Program
    exit status 1
    no matching function for call to ‘LiquidCrystal_I2C::LiquidCrystal_I2C(int, int, int, int, int, int, int, int)’

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

  4. james o bronson October 19, 2019 at 12:10 pm - Reply

    I just wired this up using a 4×4 keypad. The one thing I ran into is that I had to get the Keypad_I2C.h by unzipping the file from Joe Young and just putting the Keypad_I2C folder in my libraries folder. Otherwise I was getting an error. But this vastly improved my keypad, LCD wiring. Much neater and less points of failure.

  5. bill July 8, 2019 at 11:05 pm - Reply

    The P3 line goes to the base of the transistor and to a 4.7K pull-up resistor on the LCD I2C module, so some careful reworking of the board is possible to make the P3 output available. Remove the transistor and the associated resistor (an ohmmeter will show you which resistor is connected to the base pad for the transistor), then run a wire from the transistor base pad to your P3 data output.

  6. David Brandon March 30, 2019 at 9:39 am - Reply

    Hi Just happened by your very nice work. Thought I would mention, based on the code you show, I think P3 is tied to the back-light control device on the I2C LCD backpack. Hence you do not find it connected to any of the solder headers. Really nice work I will try to get back and read them all. Brandon

Leave A Comment