#include <LiquidCrystal_I2C.h> // Supported in Tinkercad for I2C LCD
#include <Wire.h> // For I2C communication
// Keypad setup (manual scanning for 4x4)
const int rowPins[4] = {5, 4, 3, 2}; // Rows
const int colPins[4] = {9, 8, 7, 6}; // Columns
char keyMap[4][4] = { // Key layout
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
// LCD setup (I2C at address 0x27; change to 0x3F if needed)
LiquidCrystal_I2C lcd(0x27, 16, 2); // Address, columns, rows
void setup() {
Serial.begin(9600); // For console output
// Set up keypad pins
for (int i = 0; i < 4; i++) {
pinMode(rowPins[i], OUTPUT);
digitalWrite(rowPins[i], HIGH); // Rows high by default
pinMode(colPins[i], INPUT_PULLUP); // Columns as inputs with pull-ups
}
lcd.init(); // Initialize LCD
lcd.backlight(); // Turn on backlight
lcd.clear();
lcd.print("Keypad ready"); // Initial message
Serial.println("Keypad ready. Press a key...");
}
void loop() {
char key = getKey(); // Get pressed key
if (key != '\0') { // If a key was pressed
Serial.print("Key pressed: ");
Serial.println(key);
// Display on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Key pressed: ");
lcd.print(key);
delay(300); // Basic debounce
}
}
// Manual function to scan keypad
char getKey() {
for (int r = 0; r < 4; r++) {
digitalWrite(rowPins[r], LOW); // Set current row low
for (int c = 0; c < 4; c++) {
if (digitalRead(colPins[c]) == LOW) { // Key pressed
while (digitalRead(colPins[c]) == LOW); // Wait for release
digitalWrite(rowPins[r], HIGH); // Reset row
return keyMap[r][c];
}
}
digitalWrite(rowPins[r], HIGH); // Reset row
}
return '\0'; // No key
}