In one of my arduino projects I needed a keyboard with more than 4x4 keys and I wanted to use less pins.

I deside to use I2C bus for connection my future keyboard to arduino, because I2C needs only 2 pins.

For keypad I deside to use port extender chip MCP23017.

The elecrtic schema is on the picture below:

Totaly this solution can provide 64 buttons.

The jampers J1-J3 is used for setting device address on I2C bus. Connect A0-A2 chip ports to GND or Vcc throug jampers to set address. If all ports set to GND the device address wil be 0x20.

The connector J4 is used to connect I2C bus: SDA keyboard port must be connected to SDA arduino port and SCL keyboard port must be connected to SCL arduino port.

For power this keyboard is enoght 3.3 volts.

Chip U1 - MCP23017

Resisters R1-R10 - 1 kOm

Capacity C1 - 10uF 16v

For using this keyboard I wrote the library.

i2c_keyboard.h

#ifndef KEYPAD_H
#define KEYPAD_H

#include <Arduino.h>

#define KEYPAD 0x21

class Keypad {
	public:
		char last_result = 0;
		char keys[7][7] = {
							{'A', 'B', 'C', 'D', 'E', 'F', 'G'},
							{'H', 'I', 'J', 'K', 'L', 'M', 'O'},
							{'P', 'Q', 'R', 'S', 'T', 'U', 'V'},
							{'W', 'X', 'Y', 'Z', '1', '2', '3'},
							{'4', '5', '6', '7', '8', '9', '0'},
							{'+', '-', '/', '%', '*', '=', '$'},
							{'!', '?', '>', '<', '.', '#', '@'}
						};
		
		Keypad(void);
		~Keypad(void);
		
		void Init(void);
		char Wait_key();
		char Get_key();
};

#endif

 

 i2c_keyboard.cpp

#include "keypad.h"
#include "Wire.h"

Keypad::Keypad(void) {
};


Keypad::~Keypad(void) {
};


void Keypad::Init(void) {
  Wire.begin();
  // set lines to output
  Wire.beginTransmission(0x20);
  Wire.write(0x01); // IODIRB regiser
  Wire.write(0x00); // set all port lines to output
  Wire.endTransmission();
};


char Keypad::Get_key(void) {
  byte input = 0;
  byte row = 0;
  char key = 0;
	
  for(int i=0; i<8; i++) {
    Wire.beginTransmission(0x20);
    Wire.write(0x13);      // address block B
    Wire.write((byte)0x01 << i);  // all lines to logical 1	
    Wire.endTransmission();

    Wire.beginTransmission(0x20);
    Wire.write(0x12);
    Wire.endTransmission();
    Wire.requestFrom(0x20, 1);
    input=Wire.read();
 
    if (input > 0) {
      row = i;
      break;
    }
  }
	
  if (input > 0) {
    if (input == 4) input = 3;
    if (input == 8) input = 4;
    if (input == 16) input = 5;
    if (input == 32) input = 6;
    if (input == 64) input = 7;
    if (input == 128) input = 8;
    key = keys[row][input-1];
  } else {
    key = 0;
  } 
  return key;
};


char Keypad::Wait_key(void) {
  bool exit_flag = false;
  char result;
	
  do {
    result = Get_key();
    if (result != 0) {
      if (result != last_result) {
        exit_flag = true;
      }
    } else {
      last_result = 0;
    }
  } while (!exit_flag); 
  last_result = result;
	
  return result;
};

 

Arduino example:

#include <SPI.h>
#include "keypad.h"

Keypad kbd;       // Клавиатура

char ch = 0;              // переменная для хранения символа от клавиатуры

void setup() {
  Serial.begin(9600);  
  kbd.Init();
}

void loop() {
  ch = kbd.Wait_key();
  Serial.print("ch=");
  Serial.println(ch);
}

 

And at the end, some photos of the result:

Project files:

schema - keypad.dch

library - keypad.zip