// simple project using Arduino UNO and 128x64 SSD1306 IIC OLED Display to create a keypad
// created by upir, 2024
// youtube channel: https://www.youtube.com/upir_upir
// YOUTUBE VIDEO: https://youtu.be/eVH5z8sqCOc
// Links from the video:
// 0.96" OLED Display Module: https://temu.to/k/ei3lbsuam7s
// Rechargeable 18650 Battery: https://temu.to/k/e2vy2cqa0e9
// Complete Arduino Starter Kit: https://temu.to/k/euvswx85rv4
// Arduino UNO R3 Compatible Development Board: https://temu.to/k/ee1cm51rrk6
// Arduino Nano V3 Mini Microcontroller: https://temu.to/k/eg6w4zvdynp
// 5pcs 1.3" High-Contrast OLED Display Modules: https://temu.to/k/ev9xu0jv0gy
// ESP32 Lithium 18650 Battery: https://temu.to/k/e511wfro8p4
// 128x64 SSD1306 OLED Display 1.54": https://s.click.aliexpress.com/e/_DCYdWXb
// 128x64 SSD1306 OLED Display 0.96": https://s.click.aliexpress.com/e/_DCKdvnh
// 128x64 SSD1306 OLED Display 2.42": https://s.click.aliexpress.com/e/_DFdMoTh
// Arduino UNO: https://s.click.aliexpress.com/e/_AXDw1h
// Arduino breadboard prototyping shield: https://s.click.aliexpress.com/e/_ApbCwx
// Image2cpp (convert array to image): https://javl.github.io/image2cpp/
// Photopea (online graphics editor like Photoshop): https://www.photopea.com/
// Related videos with Arduino UNO and 128x64 OLED screen:
// Arduino OLED menu: https://youtu.be/HVHVkKt-ldc
// U8g vs U8g2: https://youtu.be/K5e0lFRvZ2E
// Arduino Parking Sensor - https://youtu.be/sEWw087KOj0
// Turbo pressure gauge with Arduino and OLED display - https://youtu.be/JXmw1xOlBdk
// Arduino Car Cluster with OLED Display - https://youtu.be/El5SJelwV_0
// Knob over OLED Display - https://youtu.be/SmbcNx7tbX8
// Arduino + OLED = 3D ? - https://youtu.be/kBAcaA7NAlA
// Arduino OLED Gauge - https://youtu.be/xI6dXTA02UQ
// Smaller & Faster Arduino - https://youtu.be/4GfPQoIRqW8
// Save Image from OLED Display to PC - https://youtu.be/Ft2pRMVm44E
#include <Arduino.h>
#include <U8g2lib.h> // library for drawing on the display
#include <Wire.h> // library requires for IIC communication
#include <Adafruit_Keypad.h> // library for keypad
// display intialization
U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // page mode
const byte ROWS = 4; // number of rows
const byte COLS = 4; // number of columns
//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
// state of individual buttons 0 = up, 1 = down
byte btn_states[ROWS][COLS];
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// 'icon_key', 18x8px, generated using image2cpp website
const unsigned char epd_bitmap_icon_key [] PROGMEM = {
0x00, 0x78, 0x00, 0x00, 0x84, 0x00, 0xfe, 0x33, 0x01, 0x01, 0x78, 0x01, 0xdd, 0x7b, 0x01, 0x55,
0x32, 0x01, 0x55, 0x84, 0x00, 0x22, 0x78, 0x00
};
char btn_label[2] = "-"; // helper label for rendering on the display
char pincode_label[5] = "----"; // code string
byte pincode_label_pos = 0; // which digit would be changed in the code string
void setup(void) {
u8g2.begin(); // start the u8g2 library
Serial.begin(115200); // start serial communication for debugging
customKeypad.begin(); // initialize the custom keypad using the keypad library
}
void loop(void) {
customKeypad.tick(); // get button states
while (customKeypad.available()) { // if some button state was changed
keypadEvent e = customKeypad.read(); // read the button details
//Serial.print((char)e.bit.KEY);
if (e.bit.EVENT == KEY_JUST_PRESSED) { // button was pressed
btn_states[e.bit.ROW][e.bit.COL] = 1; // save the state to the array
}
else if (e.bit.EVENT == KEY_JUST_RELEASED) { // button was unpressed
btn_states[e.bit.ROW][e.bit.COL] = 0; // change button state
pincode_label[pincode_label_pos] = (char)e.bit.KEY; // update the code string
pincode_label_pos++; // next time, update the following character
if (pincode_label_pos > 4) { // if the last digit was updated, revert back to empty string
pincode_label[0] = '-';
pincode_label[1] = '-';
pincode_label[2] = '-';
pincode_label[3] = '-';
pincode_label[4] = 0; // last char is NULL = 0, that sets the end of the string
pincode_label_pos = 0; // next time, start updating the string from the first character
}
}
}
// u8g2 drawing on the OLED display
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_profont11_tr); // set small font
// draw labels for keypad
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
btn_label[0] = keys[j][i]; // set button label value
int xpos = 80 + (i * 13); // calculate X position
int ypos = 16 + (j * 13); // calculate Y position
// if the button is pressed = draw background rectangle
if (btn_states[j][i] == 1) {
u8g2.setDrawColor(1);
u8g2.drawRBox(xpos - 3, ypos - 9, 11, 11, 2);
}
// set the drawing mode of labels to XOR = invert the background color
u8g2.setFontMode(1);
u8g2.setDrawColor(2);
u8g2.drawStr(xpos, ypos, btn_label); // draw the label for the button
}
}
// PIN label and key icon
u8g2.setDrawColor(1);
u8g2.setFont(u8g2_font_profont11_tr); // small font
u8g2.drawStr(35, 20, "PIN");
u8g2.drawXBMP(12, 12, 18, 8, epd_bitmap_icon_key); // draw key image
//u8g2.setFont(u8g2_font_profont22_tn); -- only digits
// draw pincode label with the 2px outline
u8g2.setFont(u8g2_font_profont22_tr); // big font
u8g2.drawRFrame(2, 27, 60, 24, 2); // rounded frame
u8g2.drawFrame(3, 28, 58, 22); // frame
u8g2.drawStr(9, 46, pincode_label); // draw the CODE string
} while ( u8g2.nextPage() ); // required for u8g2 page drawing function
}