يحتوي هذا المقال على روابط تسويق بالعمولة مُعلَّمة بعلامة *. بصفتي شريكًا في برنامج Amazon Associates، أربح من عمليات الشراء المؤهلة، دون أي تكلفة إضافية عليك. يساعد ذلك على إبقاء الشروحات مجانية.
ملخص سريع
تقرأ لوحة Arduino Uno كلمة مرور من لوحة مفاتيح 4×4 وتعرض الرسائل الإرشادية على شاشة LCD مقاس 16×2 بواجهة I2C. يظهر كل مفتاح تكتبه على شكل نجمة. وعندما تكون كلمة المرور صحيحة، يدور محرك سيرفو SG90 ويحرّر المزلاج. هذا نموذج عرض مكتبي: يقوم السيرفو مقام قفل كهربائي حقيقي، وكلمة المرور مخزنة نصًا صريحًا داخل برنامج Arduino (Sketch). لا تستخدمه قفلًا وحيدًا لباب حقيقي.
من أجل الفيديو بنيت بابًا تجريبيًا صغيرًا: لوح من الخشب الرقائقي داخل إطار من مقاطع الألومنيوم المبثوقة، مع مشبكَي ورق (Binder Clips) يعملان كمفصّلتين. ويحرّك السيرفو مزلاجًا معدنيًا أسطوانيًا.
كيف يعمل القفل
لوحة المفاتيح هي جهاز الإدخال. تحتوي على 16 مفتاحًا (0–9 وA–D و* و#) مرتبة في مصفوفة: 4 أسلاك للصفوف و4 أسلاك للأعمدة، مع مفتاح واحد عند كل تقاطع. يؤدي الضغط على مفتاح إلى توصيل صفّه بعموده، لذلك تحتاج المفاتيح الـ 16 إلى 8 أطراف (Pins) فقط. تقوم مكتبة Keypad بتفعيل الصفوف واحدًا تلو الآخر وتقرأ الأعمدة لتحديد المفتاح المضغوط.
شاشة LCD بواجهة I2C هي وحدة الإخراج. تعرض “Enter Password” (أدخل كلمة المرور) ما دام الباب مقفلًا، ونجمة واحدة لكل مفتاح تكتبه، و“Door is OPEN” (الباب مفتوح) بعد إدخال كلمة مرور صحيحة، و“Wrong Password” (كلمة مرور خاطئة) بعد إدخال كلمة خاطئة. ناقل I2C ناقل بسلكين: يحمل SDA البيانات ويحمل SCL إشارة الساعة. محوّل I2C لوحة صغيرة ملحومة على ظهر الشاشة (وتسمى أيضًا Backpack). وبفضله تحتاج شاشة LCD إلى سلكي الإشارة هذين إضافة إلى 5 V وGND، بدلًا من ستة أسلاك إشارة أو أكثر.
محرك السيرفو يحرّك المزلاج. عندما تُدخل كلمة المرور الصحيحة وتؤكدها بالضغط على #، يدور السيرفو من زاوية القفل (LOCK_ANGLE، والقيمة الافتراضية 0°) إلى زاوية الفتح (UNLOCK_ANGLE، والقيمة الافتراضية 90°) ويحرّر المزلاج. ويعيده الضغط على * إلى وضع القفل. وإذا لم تتعامل مع محركات السيرفو من قبل، فاقرأ شرحي عن محرك السيرفو.
منطق كلمة المرور وتسلسل عمل النظام
يخزّن البرنامج كلمة المرور (الافتراضية “1234”) في متغير من نوع String، أي متغير نصي. يُضاف كل مفتاح تكتبه (0–9، A–C) إلى مخزن مؤقت للإدخال (Input Buffer)، وهو متغير String ثانٍ يحفظ المفاتيح التي كتبتها حتى الآن. عندما تضغط #، يقارن البرنامج محتوى المخزن المؤقت بكلمة المرور المخزنة. فإذا تطابقا فُتح الباب؛ وإلا عرضت شاشة LCD رسالة خطأ. يمسح المفتاح * الإدخال أو يعيد قفل الباب، ويعمل المفتاح D كمفتاح حذف للخلف (Backspace).
التسلسل الكامل:
- تعرض شاشة LCD عبارة “Enter Password” في السطر 1 و“and #” في السطر 2، والمعنى: اكتب كلمة المرور ثم اضغط #.
- تكتب كلمة المرور على لوحة المفاتيح، وتعرض شاشة LCD نجمة واحدة (*) لكل مفتاح.
- اضغط # لإرسال الإدخال. تقارن لوحة Arduino ما أدخلته بكلمة المرور المخزنة.
- إذا كانت صحيحة، يدور السيرفو إلى زاوية الفتح (90° افتراضيًا) وتعرض شاشة LCD “Door is OPEN / Enter * to close”.
- يبقى الباب مفتوحًا حتى تضغط *. عندها يعود السيرفو إلى زاوية القفل (0°).
- إذا كانت كلمة المرور خاطئة، تعرض شاشة LCD “Wrong Password / Try again” لمدة 1.5 ثانية، ثم تعرض “Enter Password” من جديد.
المكونات المطلوبة (قائمة المواد)
معظم القطع موجودة في أطقم Arduino القياسية للمبتدئين (Starter Kits).
| المكوّن | الكمية | مطلوب / اختياري | الغرض | ملاحظات |
|---|---|---|---|---|
| Arduino Uno (أو لوحة متوافقة) | 1 | مطلوب | المتحكم الدقيق الرئيسي | Nano: الأطراف نفسها كما في Uno. Mega: وصّل SDA بالطرف 20 وSCL بالطرف 21 بدلًا من A4 وA5 |
| لوحة مفاتيح مصفوفية 4×4 | 1 | مطلوب | إدخال كلمة المرور (8 أطراف) | النوع الغشائي (Membrane، رقيق ومرن) هو الأسهل تركيبًا |
| شاشة LCD مقاس 16×2 مع محوّل I2C | 1 | مطلوب | الرسائل الإرشادية وعرض النتيجة | تحقق من عنوان I2C: عادةً 0x27 أو 0x3F |
| محرك سيرفو SG90 | 1 | مطلوب | يحرّك المزلاج | يتغذى من مزود الطاقة الخارجي 5 V (انظر توصيلات السيرفو) |
| أسلاك التوصيل (Jumper) | ~20 | مطلوب | جميع التوصيلات | من ذكر إلى ذكر ومن ذكر إلى أنثى |
| لوحة التجارب (Breadboard) | 1 | مطلوب | بناء النماذج الأولية | بنصف الحجم أو بالحجم الكامل |
| مزود طاقة خارجي 5 V (1 A أو أكثر) | 1 | مطلوب | تغذية السيرفو | قد تؤدي تغذية USB وحدها إلى إعادة تشغيل Arduino عندما يتحرك السيرفو |
| مزلاج باب صغير أو آلية قفل | 1 | اختياري | باب أو صندوق للعرض | مزلاج مطبوع بالطباعة ثلاثية الأبعاد (3D) أو جاهز من السوق |
مخطط الدائرة والتوصيلات
تستخدم شاشة LCD طرفي I2C وهما A4 وA5، وتستخدم لوحة المفاتيح ثمانية أطراف رقمية (من D2 إلى D9)، ويتصل سلك إشارة السيرفو بالطرف D10.

توصيلات شاشة LCD
| طرف I2C في شاشة LCD | طرف Arduino | ملاحظات |
|---|---|---|
| SDA | A4 | خط بيانات I2C |
| SCL | A5 | خط ساعة I2C |
| VCC | 5 V | الطاقة |
| GND | GND | الأرضي |
توصيلات لوحة المفاتيح
| طرف لوحة المفاتيح | الوظيفة | طرف Arduino |
|---|---|---|
| الطرف 1 | الصف 1 | D9 |
| الطرف 2 | الصف 2 | D8 |
| الطرف 3 | الصف 3 | D7 |
| الطرف 4 | الصف 4 | D6 |
| الطرف 5 | العمود 1 | D5 |
| الطرف 6 | العمود 2 | D4 |
| الطرف 7 | العمود 3 | D3 |
| الطرف 8 | العمود 4 | D2 |
توصيلات السيرفو
| سلك السيرفو | يتصل بـ | ملاحظات |
|---|---|---|
| الإشارة (برتقالي/أصفر) | D10 | إشارة السيرفو. تعمل مكتبة Servo على أي طرف رقمي؛ والطرف D10 غير مستخدم في هذه الدائرة |
| VCC (أحمر) | القطب + لمزود الطاقة الخارجي 5 V | لا توصل هذا القطب + بالطرف 5V في Arduino؛ يُوصل الأرضي فقط بين الدائرتين |
| GND (بني/أسود) | الطرف GND لمزود الطاقة، موصول بالطرف GND في Arduino | أرضي مشترك |
يسحب محرك SG90 نحو 100 mA عندما يتحرك بحرية، ويصل سحبه إلى نحو 650 mA في حالة التوقف (Stall)، أي عندما يُعاق عمود الدوران، مثلًا بسبب مزلاج عالق. يوفر منفذ USB القياسي 500 mA، لذلك ينخفض الجهد وقد تعيد لوحة Arduino تشغيل نفسها (Reset). غذِّ السيرفو من مزود طاقة خارجي 5 V بتيار مقنن 1 A أو أكثر. وصّل الطرف GND لمزود الطاقة بالطرف GND في Arduino كي تشترك الدائرتان في المرجع نفسه 0 V (أرضي مشترك).
برنامج Arduino (Sketch)
قبل الرفع، ثبّت مكتبتين عبر Sketch → Include Library → Manage Libraries: مكتبة “LiquidCrystal I2C” من تطوير Frank de Brabander ومكتبة “Keypad” من تطوير Mark Stanley وAlexander Brevig. يعرض مدير المكتبات (Library Manager) اسم الأولى بمسافة، بينما يستدعيها البرنامج باسم LiquidCrystal_I2C.h. توجد عدة مكتبات LCD تحمل الاسم نفسه وتستخدم أوامر مختلفة؛ ويحتاج هذا البرنامج إلى مكتبة Frank de Brabander تحديدًا لأنه يستدعي lcd.init(). أما مكتبتا Wire وServo فتأتيان مع Arduino IDE.
/**
Password Door Lock
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>
// LCD
#define LCD_ADDR 0x27
LiquidCrystal_I2C lcd(LCD_ADDR, 16, 2);
// Servo
#define SERVO_PIN 10
#define LOCK_ANGLE 0
#define UNLOCK_ANGLE 90
Servo lockServo;
// Keypad
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Password
String PASSWORD = "1234";
String input = "";
bool doorUnlocked = false;
void lcdPromptLocked() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Enter Password");
lcd.setCursor(0,1);
lcd.print("and #");
}
void lcdPromptUnlocked() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Door is OPEN");
lcd.setCursor(0,1);
lcd.print("Enter * to close");
}
void lockDoor() {
lockServo.write(LOCK_ANGLE);
doorUnlocked = false;
lcdPromptLocked();
input = "";
}
void unlockDoor() {
lockServo.write(UNLOCK_ANGLE);
doorUnlocked = true;
lcdPromptUnlocked();
input = "";
}
void wrongPasswordMsg() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Wrong Password");
lcd.setCursor(0,1);
lcd.print("Try again");
delay(1500);
lcdPromptLocked();
input = "";
}
void handleKey(char k) {
if (doorUnlocked) {
if (k == '*') lockDoor();
return;
}
if (k == '#') {
if (input == PASSWORD) unlockDoor();
else wrongPasswordMsg();
return; // keep the new LCD screen
} else if (k == '*') {
input = "";
lcdPromptLocked();
return; // keep the new LCD screen
} else if (k == 'D') {
if (input.length() > 0) input.remove(input.length()-1);
} else {
if (input.length() < 8) input += k;
}
lcd.setCursor(0,1);
for (unsigned int i = 0; i < 8; i++) lcd.print(i < input.length() ? '*' : ' '); // one '*' per typed key, blanks the rest
}
void setup() {
lcd.init();
lcd.backlight();
lockServo.attach(SERVO_PIN);
lockDoor();
}
void loop() {
char key = keypad.getKey();
if (key) handleKey(key);
}
شرح الكود
1) المكتبات والكائنات
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include <Keypad.h> #include <Servo.h> // LCD #define LCD_ADDR 0x27 LiquidCrystal_I2C lcd(LCD_ADDR, 16, 2); // Servo #define SERVO_PIN 10 #define LOCK_ANGLE 0 #define UNLOCK_ANGLE 90 Servo lockServo;
تتولى المكتبات الأربع اتصال I2C (Wire)، والتحكم في شاشة LCD (LiquidCrystal_I2C)، ومسح لوحة المفاتيح (Keypad)، والتحكم في السيرفو (Servo). يُنشأ الكائنان lcd وlockServo هنا ويُستخدمان في جميع أجزاء البرنامج.
2) إعدادات العتاد (الأطراف والزوايا)
#define LCD_ADDR 0x27 #define SERVO_PIN 10 #define LOCK_ANGLE 0 #define UNLOCK_ANGLE 90
يمنح الأمر #define قيمة ثابتة اسمًا؛ وقبل الترجمة البرمجية (Compiling) يُستبدل الاسم بالقيمة في كل مواضع البرنامج. LCD_ADDR هو عنوان I2C لمحوّل I2C الخاص بشاشة LCD. تستخدم معظم المحوّلات العنوان 0x27، وبعضها يستخدم 0x3F. ماسح I2C هو برنامج قصير يجرّب كل عناوين I2C ويطبع على الشاشة التسلسلية (Serial Monitor) كل عنوان يستجيب. والشاشة التسلسلية هي نافذة Arduino IDE التي تعرض النصوص التي ترسلها اللوحة عبر USB. شغّل الماسح إذا ظهرت على شاشة LCD مربعات دون نص، ثم اضبط LCD_ADDR على العنوان الذي يعرضه. SERVO_PIN هو الطرف الذي يحمل إشارة السيرفو. ويحدد LOCK_ANGLE وUNLOCK_ANGLE وضعَي السيرفو؛ اضبطهما بما يناسب مدى حركة المزلاج لديك.
3) ترتيب لوحة المفاتيح وتوصيلاتها
const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = { ... };
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
تربط المصفوفة keys شبكة المفاتيح 4×4 بالمحارف المقابلة لها. يجب أن تطابق أطراف الصفوف (9، 8، 7، 6) وأطراف الأعمدة (5، 4، 3، 2) توصيلاتك. في معظم لوحات المفاتيح الغشائية يكون الطرف 1 هو أقصى طرف إلى اليسار عندما تكون المفاتيح مواجهة لك: الأطراف 1–4 هي الصفوف 1–4، والأطراف 5–8 هي الأعمدة 1–4. وتتولى مكتبة Keypad أيضًا إزالة الارتداد (Debouncing): فعند الضغط على مفتاح ترتد نقاط تلامسه بين الفتح والإغلاق لبضعة أجزاء من الألف من الثانية، وتقوم المكتبة بترشيح ذلك بحيث تُحتسب الضغطة الواحدة مرة واحدة.
4) حالة كلمة المرور والمتغيرات
String PASSWORD = "1234"; String input = ""; bool doorUnlocked = false;
يحفظ PASSWORD كلمة المرور التي يجب على المستخدم إدخالها: حتى 8 محارف من 0–9 وA–C. ولا يمكن أن تتضمن كلمة المرور المفاتيح D و* و#، لأنها تعمل على الترتيب كحذف للخلف ومسح وإرسال. لتغيير كلمة المرور، ابحث عن السطر String PASSWORD = "1234";، واستبدل 1234 بكلمة المرور الجديدة، ثم ارفع البرنامج مرة أخرى. يحفظ المتغير input المفاتيح التي كُتبت حتى الآن، ويتتبع المتغير doorUnlocked ما إذا كان الباب مفتوحًا.
ملاحظة: يحجز الصنف String الذاكرة أثناء تشغيل البرنامج. لا يحتوي المتحكم ATmega328P في لوحة Uno إلا على 2 KB من ذاكرة RAM، وقد تؤدي التعديلات الكثيرة على متغيرات String إلى تقسيم الذاكرة الحرة إلى فجوات صغيرة لا يمكن استخدامها بعد ذلك (التجزؤ، Fragmentation). وبالنسبة إلى قفل يعمل 24/7، تكون مصفوفة char ثابتة أكثر أمانًا. مصفوفة char هي صف من المحارف بحجم ثابت يحجزه المترجم (Compiler) مرة واحدة، لذلك لا تسبب تجزؤ الذاكرة.
5) دوال مساعدة لشاشات LCD
void lcdPromptLocked() { ... } // "Enter Password" / "and #"
void lcdPromptUnlocked() { ... } // "Door is OPEN" / "Enter * to close"
لكل شاشة دالة خاصة بها، لذلك تغيّر أي رسالة في موضع واحد فقط.
6) الدوال المساعدة للتحكم في الباب
void lockDoor() { ... }
void unlockDoor() { ... }
تُدير الدالة lockDoor() السيرفو إلى LOCK_ANGLE، وتضبط doorUnlocked على false، وتعرض رسالة حالة القفل، وتمسح المخزن المؤقت للإدخال. أما الدالة الثانية فتفعل العكس: تُدير السيرفو إلى UNLOCK_ANGLE، وتضبط doorUnlocked على true، وتعرض “Door is OPEN / Enter * to close”، وتمسح المخزن المؤقت أيضًا.
7) التنبيه عند إدخال كلمة مرور خاطئة
void wrongPasswordMsg() { ... }
عندما لا يتطابق الإدخال، تعرض شاشة LCD “Wrong Password / Try again” لمدة 1.5 ثانية (delay(1500))، ثم تعود إلى رسالة حالة القفل ويُمسح الإدخال. يمنحك هذا التوقف وقتًا لقراءة الرسالة.
8) المنطق المركزي للإدخال: handleKey()
void handleKey(char k) { ... }
تحدد الدالة handleKey() ما تفعله كل ضغطة مفتاح:
- الباب مفتوح: لا يُقبل إلا المفتاح *، ويستدعي lockDoor(). وتُتجاهل جميع المفاتيح الأخرى ما دام الباب مفتوحًا.
#(إرسال): يقارن المخزن المؤقت للإدخال بـ PASSWORD. فإذا تطابقا فُتح الباب؛ وإلا ظهرت رسالة كلمة المرور الخاطئة.*(مسح): عندما يكون الباب مقفلًا، يمسح * المخزن المؤقت للإدخال ويعيد رسالة شاشة LCD إلى وضعها الأولي.D(حذف للخلف): يحذف آخر محرف من المخزن المؤقت للإدخال. يقع المفتاح D في الزاوية السفلية اليمنى بجوار #، لذلك يسهل الوصول إليه عند تصحيح خطأ في الكتابة.- أي مفتاح آخر (0–9، A، B، C): يُضاف إلى المخزن المؤقت للإدخال ما دام يحتوي على أقل من 8 محارف.
بعد كتابة مفتاح أو الضغط على D، يعيد آخر سطرين في handleKey() كتابة السطر 2 من شاشة LCD بنجمة واحدة لكل محرف في المخزن المؤقت، لذلك لا تظهر كلمة المرور نفسها على الشاشة أبدًا. ينتهي فرعا # و* بالأمر return، لذلك تبقى الشاشة التي عرضاها (مثل “Door is OPEN / Enter * to close”) كما هي.
9) الدالة Setup: التهيئة لمرة واحدة
void setup() {
lcd.init(); lcd.backlight();
lockServo.attach(SERVO_PIN);
lockDoor(); // start locked
}
تعمل الدالة setup() مرة واحدة عند التشغيل وبعد كل إعادة تشغيل (Reset). فهي تهيّئ شاشة LCD، وتشغّل الإضاءة الخلفية، وتربط السيرفو بالطرف D10، وتستدعي lockDoor()، لذلك يبدأ القفل دائمًا في وضع القفل ويعرض “Enter Password”.
10) الدالة Loop: قراءة المفاتيح والاستجابة لها
void loop() {
char key = keypad.getKey();
if (key) handleKey(key);
}
تفحص الدالة keypad.getKey() لوحة المفاتيح مرة واحدة في كل دورة من loop() وتُرجع المفتاح المضغوط، أو 0 عندما لا يكون أي مفتاح مضغوطًا. يسمى هذا الفحص المتكرر الاستطلاع الدوري (Polling). وباستثناء التوقف لمدة 1.5 s بعد كلمة مرور خاطئة، لا يتوقف البرنامج للانتظار أبدًا (Blocking)، لذلك يسجل كل ضغطة مفتاح فورًا.
كيفية اختبار القفل ومعايرته
اختبر كل جزء قبل تركيب القفل على باب أو داخل صندوق.
التحقق من إدخال لوحة المفاتيح
أضف Serial.begin(9600); إلى setup()، وغيّر السطر الموجود في loop() إلى if (key) { Serial.println(key); handleKey(key); }. ارفع البرنامج، وافتح الشاشة التسلسلية (Serial Monitor) بسرعة 9600 baud (وهي سرعة النقل التي يحددها Serial.begin(9600)) واضغط كل مفتاح: يجب أن يظهر المحرف المقابل له. احذف أسطر التصحيح (Debug) بعد ذلك.
التحقق من عرض شاشة LCD
بعد التشغيل، تعرض شاشة LCD “Enter Password” في السطر 1 و“and #” في السطر 2. في النسخة التي بنيتها، ظهر في السطر 1 أولًا صف من المربعات، ثم ظهرت الرسالة بمجرد بدء تشغيل البرنامج. لا تعني المربعات إلا أن الشاشة موصولة بالطاقة لكنها لم تتلقَّ أي أوامر بعد. عملت شاشتي مع العنوان الافتراضي 0x27. إذا لم تظهر الرسالة، فراجع صفوف LCD الثلاثة في جدول استكشاف الأخطاء وإصلاحها.
اختبار اتجاه السيرفو وزواياه
أدخل كلمة المرور الصحيحة واضغط #. يجب أن يدور السيرفو من 0° إلى 90° (أو إلى القيم التي ضبطتها لـ LOCK_ANGLE وUNLOCK_ANGLE). إذا دار في الاتجاه الخاطئ، فبدّل بين قيمتي LOCK_ANGLE وUNLOCK_ANGLE. ثم اضبط القيمتين بخطوات صغيرة (مثلًا 10° و80°) حتى يُعشَّق المزلاج ويتحرر بسلاسة. تحتاج بعض المزاليج إلى المدى الكامل من 0° إلى 180°، ويكفي بعضها الآخر المدى من 0° إلى 45°.
التحقق من المحاذاة الميكانيكية
ارفع البرنامج أولًا: تحرّك الدالة setup() السيرفو إلى LOCK_ANGLE. ثم اضغط ذراع السيرفو (Horn، وهو الذراع البلاستيكي المثبت على عمود الدوران) على العمود بحيث يُبقي لسان المزلاج في وضع القفل. كرّر دورة الفتح وإعادة القفل عدة مرات وتأكد من أن المزلاج لا يعلق ولا ينحشر. في بابي التجريبي، يستقر السيرفو في حامل بلاستيكي مثبت على اللوح بالبراغي، وتربط قطعة منحنية من سلك صلب ذراعَ السيرفو بمقبض المزلاج الأسطواني. وتُدخل الزاويتان الافتراضيتان 0° و90° اللسان وتُخرجانه.
الاختبار مع تغذية السيرفو من مصدر خارجي
إذا اهتز السيرفو أو أعادت لوحة Arduino تشغيل نفسها عندما يتحرك السيرفو، فغذِّ السيرفو كما هو موضح في قسم توصيلات السيرفو.
استكشاف المشكلات الشائعة وإصلاحها
| المشكلة | السبب المحتمل | الحل |
|---|---|---|
| الإضاءة الخلفية لشاشة LCD لا تعمل | لا تصل الطاقة إلى شاشة LCD | تحقق من الطرفين VCC (5 V) وGND على محوّل I2C. |
| الإضاءة الخلفية تعمل، لكن لا يظهر شيء | التباين منخفض جدًا | أدر المقاومة المتغيرة الخاصة بالتباين (Potentiometer، وهي المقاومة الزرقاء الصغيرة القابلة للضبط على محوّل I2C) ببطء حتى يظهر نص أو صف من المربعات. |
| مربعات دون نص | لا تتلقى شاشة LCD أي أوامر: عنوان I2C خاطئ أو خطأ في توصيل SDA/SCL | تحقق من SDA (A4) وSCL (A5). شغّل برنامج ماسح I2C واضبط LCD_ADDR على العنوان الذي يعرضه (عادةً 0x27 أو 0x3F). |
| لوحة المفاتيح لا تستجيب | خطأ في التوصيل | تأكد من أن أسلاك لوحة المفاتيح الثمانية موصولة بالأطراف من D2 إلى D9 كما في جدول التوصيلات. |
| المفاتيح تُرجع محارف خاطئة | أطراف الصفوف والأعمدة مبدّلة أو بترتيب خاطئ | أعد ترتيب المصفوفتين rowPins وcolPins لتطابقا توصيلاتك. |
| السيرفو يهتز أو يتسبب في إعادة تشغيل Arduino | السيرفو يتغذى من USB | غذِّ السيرفو من مزود الطاقة الخارجي 5 V (1 A أو أكثر) ووصّل الأرضيين معًا (انظر توصيلات السيرفو). |
| السيرفو يدور في الاتجاه الخاطئ | قيمتا LOCK_ANGLE وUNLOCK_ANGLE مبدّلتان | بدّل بين القيمتين. |
| زاوية الفتح لا تحرّر المزلاج | الزاوية لا تناسب الآلية | اضبط UNLOCK_ANGLE بخطوات قدرها 5–10° حتى يتحرر المزلاج. |
| كلمة المرور الصحيحة تُظهر دائمًا “Wrong” | كلمة المرور في PASSWORD أطول من 8 محارف (يتوقف الإدخال عند 8)، أو تحتوي على D أو * أو # (هذه المفاتيح لا تصل إلى الإدخال أبدًا)، أو فيها خطأ في الكتابة | اطبع المتغير input على الشاشة التسلسلية (Serial Monitor) لترى ما الذي تجري مقارنته. |
| السيرفو يعمل مرة واحدة ثم يتوقف | هبوط في الجهد (Brownout) عند بدء حركة السيرفو | أضف مكثفًا كهروليتيًا سعته 470 µF (بجهد مقنن 10 V أو أكثر) بين الطرفين 5 V وGND الخاصين بالسيرفو، قريبًا من السيرفو. انتبه إلى القطبية: الساق الطويلة (+) توصل بـ 5 V، والساق الموجودة في الجهة المخططة (−) توصل بـ GND. أو استخدم مزود طاقة أقوى. |
| خطأ في الترجمة البرمجية (Compilation): لم يُعثر على المكتبة | المكتبات غير مثبتة | ثبّت مكتبتي LiquidCrystal I2C وKeypad عبر مدير المكتبات (Library Manager) في Arduino IDE (تأتي مكتبتا Wire وServo مع بيئة التطوير). |
تخصيص القفل وتطويره
تحسينات برمجية
- كلمة مرور مخزنة في EEPROM: خزّن كلمة المرور في ذاكرة EEPROM، وهي ذاكرة صغيرة داخل Arduino تحتفظ بمحتواها دون طاقة. وبذلك تبقى كلمة المرور محفوظة بعد إعادة التشغيل. أضف وضع “تغيير كلمة المرور” على المفتاح A: يُدخل المستخدم كلمة المرور القديمة ثم الجديدة. عندها يعمل A كمفتاح تحكم ولا يمكن أن يكون جزءًا من كلمة المرور بعد ذلك.
- الحظر المؤقت بعد المحاولات الفاشلة: أضف عدّادًا يعطّل الإدخال لمدة 30–60 ثانية بعد 3 محاولات خاطئة. يبطئ ذلك التخمين بالقوة الغاشمة (Brute Force، أي تجربة كلمة مرور تلو الأخرى): فمع حظر لمدة 60 s بعد كل 3 محاولات خاطئة، تستغرق تجربة كل كلمات المرور المكونة من أربعة أرقام، وعددها 10,000، أكثر من يومين.
- كلمات مرور متعددة للمستخدمين: خزّن مصفوفة من كلمات المرور الصالحة بحيث تكون لكل شخص كلمة مرور خاصة به.
- مؤقت إعادة القفل التلقائي: أعد قفل الباب إذا لم يضغط أحد * خلال مدة محددة (مثلًا 10 ثوانٍ).
تحسينات العتاد
- التنبيه الصوتي بالطنان (Buzzer): أضف طنانًا يصدر صفيرًا عند كل ضغطة مفتاح، ونغمة عند إدخال كلمة المرور الصحيحة، وإنذارًا بعد الإخفاقات المتكررة. يصفّر الطنان النشط (Active Buzzer) عند ضبط طرفه على HIGH (5 V)؛ أما الطنان السلبي (Passive Buzzer) فيحتاج إلى tone() لإصدار الصوت. لا يستخدم البرنامج أعلاه أي طنان.
- المرحّل (Relay) والقفل الكهربائي للإطار (Electric Strike): للتركيب الدائم، استبدل السيرفو بوحدة مرحّل (Relay Module)، وهي مفتاح تشغّله لوحة Arduino وتطفئه عبر طرف واحد. يتحكم المرحّل في قفل كهربائي للإطار (Electric Strike، وهو جزء في إطار الباب يحرّر المزلاج كهربائيًا) أو في قفل مغناطيسي (مغناطيس كهربائي يُبقي الباب مغلقًا). تعمل هذه الأقفال عادةً بجهد 12 V من مزود طاقة خاص بها. ينفتح القفل المغناطيسي عند انقطاع الطاقة (Fail-safe)؛ أما الأقفال الكهربائية للإطار فتتوفر بنوع Fail-safe أو Fail-secure (يبقى مقفلًا دون طاقة)، لذلك اختر النوع عن قصد.
- بطارية احتياطية: خلية Li-ion (3.7 V) مع وحدة شحن ومحوّل رافع للجهد 5 V (Boost Converter، وهو وحدة ترفع الجهد إلى 5 V) تُبقي القفل عاملًا أثناء انقطاع الكهرباء.
- بلوتوث (HC-05): يتيح لك فتح القفل من تطبيق على الهاتف. لكنه يضيف طريقًا ثانيًا للدخول، لذلك غيّر رمز PIN الافتراضي للاقتران في الوحدة (غالبًا 1234 أو 0000). يشرح درسي عن وحدة بلوتوث HC-05 التوصيلات والاقتران.
خيارات الوصول والأمان
- الوصول عبر RFID: يقرأ قارئ RFID (مثل RC522) البطاقات اللاتلامسية وميداليات المفاتيح. أضفه بجانب لوحة المفاتيح للحصول على مصادقة ثنائية العامل: بطاقة إضافة إلى كلمة مرور.
- تسجيل البيانات: سجّل محاولات الوصول مع طوابع زمنية من وحدة RTC (ساعة الوقت الحقيقي) طراز DS3231 على بطاقة SD.
- كشف العبث: يكشف مستشعر الاهتزاز أو مفتاح القصبة المغناطيسي (Reed Switch، وهو تلامس يتبدل وضعه عندما يبتعد مغناطيس مثبت على الباب) محاولات الدخول بالقوة ويطلق إنذارًا.
الأسئلة الشائعة
لا تحتوي لوحة المفاتيح 3×4 على العمود A–D، لذلك تفقد وظيفة الحذف للخلف بالمفتاح D؛ أما * (المسح/إعادة القفل) و# (الإرسال) فيبقيان عاملين. اضبط COLS على 3، واحذف العمود الأخير من المصفوفة keys، وحدد ثلاثة أطراف في colPins، ووصّل سبعة أسلاك بدلًا من ثمانية.
خزّنها باستخدام مكتبة EEPROM في Arduino: اكتب كلمة المرور في EEPROM عند تغييرها واقرأها مجددًا في setup(). تتحمل كل خلية EEPROM نحو 100,000 عملية كتابة، لذلك لا تكتب إلا عند تغيير كلمة المرور.
المصادر والدروس ذات الصلة
توثيق المكتبات
- مكتبة LiquidCrystal_I2C: مستودع GitHub مع التوثيق والأمثلة.
- مكتبة Keypad: الكود المصدري والأمثلة على GitHub.
شروحات OmArTronics ذات الصلة
- التحكم بمحرك سيرفو بعصا التحكم (Joystick) وشاشة OLED: التحكم في السيرفو وعرض المخرجات على الشاشة.
- التحكم في LED وباب سيرفو بجهاز تحكم IR عن بُعد مع Arduino: النوع نفسه من الأبواب العاملة بالسيرفو، لكنه يُفتح بجهاز تحكم عن بُعد بالأشعة تحت الحمراء بدلًا من لوحة المفاتيح.
- شرح وحدة البلوتوث HC-05/HC-06: الأساس لإضافة البلوتوث.
- رادار Arduino باستخدام مستشعر الموجات فوق الصوتية ومحرك السيرفو: مشروع آخر بمحرك السيرفو، مع مستشعر موجات فوق صوتية يمسح المكان ذهابًا وإيابًا.

رأي واحد حول “Arduino Password Door Lock with Keypad and LCD”