Arduino 矩阵键盘门锁:支持用户自定义密码与 EEPROM 断电保存
元件与物料
| Arduino UNO | ×1 | |
| 4x4 矩阵键盘 | ×1 | |
| 通用按钮 (开门按钮) | ×1 | |
| LCD I2C (1602/2004) | ×1 | |
| 线性电磁锁 | ×1 | |
| IRF510N MOSFET | 驱动电磁锁 | ×1 |
| 1 路继电器模块 | 替代方案 | ×1 |
所需工具
- 170 点迷你面包板
- 10 根 5cm 杜邦线
项目详解
经典门锁教程:Arduino + 4x4 键盘 + I2C LCD + 电磁锁/继电器。作者注明:实际工程不推荐电磁锁 (断电即开,不安全),建议改用机电一体锁体,兼容机械钥匙与电控开启。
核心器件说明
- 电磁锁 12V: 外接 12V 电源,IRF510N MOSFET 作开关。N 沟道 MOSFET:栅极施加 5V (Arduino 高电平) → 漏源导通 → 电磁锁得电打开;栅极低电平 → 截止 → 上锁。无需栅极电阻。
- 继电器模块: 3.3V/5V 兼容,输入逻辑与 MOSFET 相反 (低电平触发)。可控制 250VAC 电锁或同样驱动电磁锁。代码中仅需把开锁电平取反。
- 内部开门按钮: 按下 (高电平) 直接开锁 3 秒,含去抖动电阻。
- 4x4 键盘: 确认键用 'A',3x4 键盘可改为 '*' 或 '#',相应修改代码。

算法流程图

逻辑概览:待机 → '*' 输入密码 → 验证 → 开锁/报错 → '#' 修改密码 (需先验证旧密码) → 两次输入新密码对比 → 写入 EEPROM → 完成。内部按钮随时可开锁。
关键代码逻辑 (两版本仅开锁电平相反)
// 首次烧录:保持 EEPROM 读取代码注释
// 上传后取消注释 EEPROM.get() 循环并重新烧录 (仅需一次)
// 密码长度可变:初始 code[] 长度决定位数,sizeof(code) 自适应
完整代码:电磁锁版 (Keypad_doorlock_solenoid.ino)
#include <Keypad.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#define Solenoid 11
#define O_Button 10
#define I2C_ADDR 0x27
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
const byte numRows = 4, numCols = 4;
char keymap[numRows][numCols] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
char keypressed;
char code[] = {'6','6','0','1'}; // 默认 4 位密码
char code_buff1[sizeof(code)], code_buff2[sizeof(code)];
short a=0, i=0, s=0, j=0;
byte rowPins[numRows] = {9,8,7,6};
byte colPins[numCols] = {5,4,3,2};
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);
void setup() {
lcd.begin(16,2);
lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
lcd.setBacklight(HIGH);
lcd.home(); lcd.print("Standby");
pinMode(Solenoid, OUTPUT);
pinMode(O_Button, INPUT);
/* 首次烧录时注释以下循环
for(i=0; i<sizeof(code); i++) EEPROM.get(i, code[i]);
*/
// 取消注释后重新烧录,仅执行一次
}
void loop() {
keypressed = myKeypad.getKey();
if (keypressed == '*') { // 输入密码开锁
lcd.clear(); lcd.setCursor(0,0); lcd.print("Enter code");
GetCode();
if (a == sizeof(code)) OpenDoor();
else { lcd.clear(); lcd.print("Wrong"); }
delay(2000); lcd.clear(); lcd.print("Standby");
}
if (keypressed == '#') { ChangeCode(); lcd.clear(); lcd.print("Standby"); }
if (digitalRead(O_Button) == HIGH) { // 内部按钮
digitalWrite(Solenoid, HIGH); delay(3000); digitalWrite(Solenoid, LOW);
}
}
void GetCode() {
i=0; a=0; j=0;
while (keypressed != 'A') {
keypressed = myKeypad.getKey();
if (keypressed != NO_KEY && keypressed != 'A') {
lcd.setCursor(j,1); lcd.print("*"); j++;
if (keypressed == code[i] && i < sizeof(code)) { a++; i++; }
else a--;
}
}
keypressed = NO_KEY;
}
void ChangeCode() {
lcd.clear(); lcd.print("Changing code"); delay(1000);
lcd.clear(); lcd.print("Enter old code");
GetCode();
if (a == sizeof(code)) {
lcd.clear(); lcd.print("Changing code");
GetNewCode1(); GetNewCode2();
s=0;
for (i=0; i<sizeof(code); i++) if (code_buff1[i]==code_buff2[i]) s++;
if (s == sizeof(code)) {
for (i=0; i<sizeof(code); i++) { code[i]=code_buff2[i]; EEPROM.put(i, code[i]); }
lcd.clear(); lcd.print("Code Changed"); delay(2000);
} else { lcd.clear(); lcd.print("Codes are not"); lcd.setCursor(0,1); lcd.print("matching !!"); delay(2000); }
} else { lcd.clear(); lcd.print("Wrong"); delay(2000); }
}
void GetNewCode1() {
i=0; j=0;
lcd.clear(); lcd.print("Enter new code"); lcd.setCursor(0,1); lcd.print("and press A"); delay(2000);
lcd.clear(); lcd.setCursor(0,1); lcd.print("and press A");
while (keypressed != 'A') {
keypressed = myKeypad.getKey();
if (keypressed != NO_KEY && keypressed != 'A') {
lcd.setCursor(j,0); lcd.print("*"); code_buff1[i]=keypressed; i++; j++;
}
}
keypressed = NO_KEY;
}
void GetNewCode2() {
i=0; j=0;
lcd.clear(); lcd.print("Confirm code"); lcd.setCursor(0,1); lcd.print("and press A"); delay(3000);
lcd.clear(); lcd.setCursor(0,1); lcd.print("and press A");
while (keypressed != 'A') {
keypressed = myKeypad.getKey();
if (keypressed != NO_KEY && keypressed != 'A') {
lcd.setCursor(j,0); lcd.print("*"); code_buff2[i]=keypressed; i++; j++;
}
}
keypressed = NO_KEY;
}
void OpenDoor() {
lcd.clear(); lcd.print("Welcome");
digitalWrite(Solenoid, HIGH); delay(3000); digitalWrite(Solenoid, LOW);
}
完整代码:继电器版 (Keypad_doorlock_relay.ino)
仅 OpenDoor() 与按钮处理中继电器逻辑取反 (LOW 开锁, HIGH 上锁),其余完全相同。
原理图


制造工艺
- 银行金库内幕:历史、设计与安全未来
- 树莓派蓝牙近感智能门锁:手机离开自动上锁
- 多位置温度传感器系统,助力智能家居集成
- MotionSense:基于 Arduino 与 ESP8266 的智能入侵检测系统
- 3D 打印机防火卫士:智能传感器安全系统
- 基于 Arduino、键盘与线性执行器的密码门锁
- 基于 Arduino、Yaler 与 IFTTT 构建 Web 化 IoT 仪表盘
- Arduino 简易排斥式磁悬浮:电路与 DIY 指南
- 进阶遥控夹爪机器人:精密抓取 DIY 指南
- 进阶微控制器实验平台:ESP32、Arduino、PIC 与多传感器模块集成
- 铜电镀智能系统:基于 Arduino UNO 的可控电解装置
- CoroFence 热成像检测器:Panasonic GridEye + PIR + IoT 集成