/* Elegant Keypad extendable to Keyboard
Details at:
https://www.instructables.com/An-Elegant-Keypad-Extendable-to-Keyboard/
Github repository:
https://github.com/QuteNZ/An-Elegant-Keypad-extendable-to-Keyboard.git
and Demo Video:
https://youtu.be/oLSrkSVk7Mg
===============================================
A typical keypad uses matrix configuration for microcontroller.
C1 C2 C3
| | |
R1 ---1, 2, 3
R2 ---4, 5, 6
R3 ---7, 8, 9
R4 ---*, 0, #
in which, total IOs taken are number of Rows plus number of Columes.
For a 4X3 matrix keypad, number of IOs can be reduced with 4 diodes as configured below:
C1 C2 C3 C4
| | | |
R1 --- 1/ | 2/ | 3/ | --cDa-- |
R2 --- 4/ | 5/ | --cDa-- | 6/ |
R3 --- 7/ | --cDa-- | 8/ | 9/ |
R4 ---cDa--| star/ | 0/ | #/ |
Then the 4x3 matrix was transformed to 4x4 one with diodes between Row & Column.
The software can recongnise a key press by appling a voltage to each row in turn
while observing the state of the remainning port pin, which are configured as inputs.
ATtiny85, 8MHz
PB5 =|1 U 8|= VCC
PB3 =|2 7|=2--> SCL
PB4 =|3 6|= PB1
GND =|4 5|=0--> SDA
*/
#include <TinyWireM.h> // I2C Master lib for ATTinys which use USI
#include "LiquidCrystal_I2C.h" // for LCD w/ GPIO MODIFIED for the ATtiny85
#define GPIO_ADDR 0x27 // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A
LiquidCrystal_I2C lcd(GPIO_ADDR, 16, 2); // set address & 16 chars / 2 lines
const int debounceTime = 160;
const int rowPins[4] = {PB1, PB3, PB4, PB5}; // Shared row/column pins by diode
char key;
const char keymap[4][4] = { //D for 1N4048 Diode
{'1', '2', '3', 'D'} ,
{'4', '5', 'D', '6'} ,
{'7', 'D', '8', '9'} ,
{'D', '*', '0', '#'}
};
void setup() {
//Serial.begin(9600); no serial for TINY
TinyWireM.begin(); // initialize I2C lib
lcd.init(); // initialize the lcd
lcd.backlight(); // affiche un message sur le LCD.
lcd.print("Elegant Keypad");
lcd.setCursor(0, 1); // positionnement début ligne2
lcd.print("ATtiny85 Version");
delay (2000);
lcd.clear();
lcd.print(" Elegant Keypad");
lcd.setCursor(0, 1);
// Initialize all pins as inputs with pull-ups
for (int i = 0; i < 4; i++) {
pinMode(rowPins[i], INPUT_PULLUP);
}
//Serial.println("ready!");
}
void loop() {
for (int active = 0; active < 4; active++) {
// Set one pin as OUTPUT HIGH
pinMode(rowPins[active], OUTPUT);
digitalWrite(rowPins[active], LOW);
// Check other pins for HIGH signal
for (int i = 0; i < 4; i++) {
if (i == active) continue; //Skip the output itself
pinMode(rowPins[i], INPUT_PULLUP);
if (digitalRead(rowPins[i]) == LOW) {
delay(debounceTime);
while (digitalRead(rowPins[i]) == LOW)
; //Waiting for key release
key = keymap[i][3-active];
lcd.print(key);
//Serial.print("Key Pressed: ");
//Serial.print(key);
delay(debounceTime); // debounce
}
}
pinMode(rowPins[active], INPUT_PULLUP); // Reset active pin to input
}
}