Skip to main content

СИСТЕМА КОНТРОЛЯ ДОСТУПА 🔐

БАЗОВАЯ РЕАЛИЗАЦИЯ

Логика работы:

Пользователь вводит код с матричной клавиатуры
Система проверяет код в EEPROM
При правильном коде: сервопривод открывает замок, зеленый светодиод
При неправильном: счетчик ошибок, при 3 ошибках - блокировка на 30 сек
Зуммер дает звуковую обратную связь
Красный/желтый/зеленый светодиоды показывают статус

Компоненты:

  • ✅ Матричная клавиатура 4x4
  • ✅ Сервопривод SG90
  • ✅ Светодиоды: красный, желтый, зеленый
  • ✅ Зуммер (пищалка)
  • ✅ Arduino Uno
  • ✅ Резисторы, провода, макетка
  • ✅ ✅ Дополнительно: LCD дисплей для отображения статуса

Схема подключения:

Матричная клавиатура:
  R1 → pin 9, R2 → pin 8, R3 → pin 7, R4 → pin 6
  C1 → pin 5, C2 → pin 4, C3 → pin 3, C4 → pin 2

Сервопривод (замок):
  Signal → pin 10
  VCC → 5V (через блок питания при необходимости)
  GND → GND

Светодиоды:
  Красный → pin 11 → резистор 220Ω → GND
  Желтый → pin 12 → резистор 220Ω → GND  
  Зеленый → pin 13 → резистор 220Ω → GND

Зуммер:
  + → pin A0, - → GND

ЛОГИКА РАБОТЫ 🔄

Псевдокод для обсуждения:

// АРХИТЕКТУРА СИСТЕМЫ:
СОСТОЯНИЯ: [ОЖИДАНИЕ]  [ПРОВЕРКА]  [ДОСТУП_РАЗРЕШЕН]  [ЗАКРЫТИЕ]
                         
                         └→ [ДОСТУП_ЗАПРЕЩЕН]  [БЛОКИРОВКА]

// ОСНОВНОЙ ЦИКЛ:
обрабатываем_нажатия_клавиатуры()

в_зависимости_от_состояния:
  случай ОЖИДАНИЕ:
    если (введен_код):
      переходим_в_состояние(ПРОВЕРКА)
      
  случай ПРОВЕРКА:
    проверяем_код_в_EEPROM()
    если (код_верный):
      переходим_в_состояние(ДОСТУП_РАЗРЕШЕН)
    иначе:
      увеличиваем_счетчик_ошибок()
      переходим_в_состояние(ДОСТУП_ЗАПРЕЩЕН)
      
  случай ДОСТУП_РАЗРЕШЕН:
    открываем_замок()
    сбрасываем_счетчик_ошибок()
    через_5_секунд  закрываем_замок()
    
  случай ДОСТУП_ЗАПРЕЩЕН:
    если (ошибок >= 3):
      переходим_в_состояние(БЛОКИРОВКА)
    иначе:
      через_2_секунды  переходим_в_состояние(ОЖИДАНИЕ)
      
  случай БЛОКИРОВКА:
    блокируем_систему_на_30_сек()
    после_разблокировки  переходим_в_состояние(ОЖИДАНИЕ)

управляем_индикацией() // светодиоды + зуммер

ДЕТАЛЬНАЯ РЕАЛИЗАЦИЯ АЛГОРИТМОВ

Структура данных системы:

#include <Keypad.h>
#include <Servo.h>
#include <EEPROM.h>

#define CODE_LENGTH 4
#define MAX_ATTEMPTS 3
#define LOCK_TIME 30000 // 30 секунд

enum SystemState { 
  WAITING_INPUT, 
  CHECKING_CODE, 
  ACCESS_GRANTED, 
  ACCESS_DENIED, 
  SYSTEM_LOCKED 
};

class AccessControlSystem {
private:
  SystemState currentState;
  char enteredCode[CODE_LENGTH + 1];
  byte codeIndex;
  int attemptCount;
  unsigned long stateStartTime;
  unsigned long lockStartTime;
  Servo doorLock;
  
public:
  void initialize();
  void update();
  void handleKeypad();
  void changeState(SystemState newState);
  bool validateCode();
  void controlIndicators();
  void openDoor();
  void closeDoor();
};

Обработка клавиатуры:

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);

void handleKeypad() {
  char key = keypad.getKey();
  
  if (key && currentState == WAITING_INPUT) {
    if (key == '#') { // Enter code
      enteredCode[codeIndex] = '\0';
      changeState(CHECKING_CODE);
    } else if (key == '*') { // Clear code
      codeIndex = 0;
      memset(enteredCode, 0, sizeof(enteredCode));
    } else if (codeIndex < CODE_LENGTH) { // Add digit
      enteredCode[codeIndex++] = key;
      tone(BUZZER_PIN, 1000, 100); // звуковой отклик
    }
  }
}

Управление состояниями:

void changeState(SystemState newState) {
  currentState = newState;
  stateStartTime = millis();
  
  switch(newState) {
    case CHECKING_CODE:
      if (validateCode()) {
        changeState(ACCESS_GRANTED);
      } else {
        changeState(ACCESS_DENIED);
      }
      break;
      
    case ACCESS_GRANTED:
      openDoor();
      attemptCount = 0;
      break;
      
    case ACCESS_DENIED:
      attemptCount++;
      tone(BUZZER_PIN, 2000, 500); // звук ошибки
      if (attemptCount >= MAX_ATTEMPTS) {
        changeState(SYSTEM_LOCKED);
      }
      break;
      
    case SYSTEM_LOCKED:
      lockStartTime = millis();
      break;
  }
}

Работа с EEPROM и проверка кода:

bool validateCode() {
  char storedCode[CODE_LENGTH + 1];
  
  // Читаем код из EEPROM
  for (int i = 0; i < CODE_LENGTH; i++) {
    storedCode[i] = EEPROM.read(i);
  }
  storedCode[CODE_LENGTH] = '\0';
  
  return strcmp(enteredCode, storedCode) == 0;
}

void changeCode(char newCode[CODE_LENGTH + 1]) {
  // Записываем новый код в EEPROM
  for (int i = 0; i < CODE_LENGTH; i++) {
    EEPROM.write(i, newCode[i]);
  }
}

Управление замком и индикацией:

void openDoor() {
  doorLock.write(90); // Открыть замок
  digitalWrite(GREEN_LED_PIN, HIGH);
  digitalWrite(RED_LED_PIN, LOW);
  tone(BUZZER_PIN, 1500, 300); // звук успеха
}

void closeDoor() {
  doorLock.write(0); // Закрыть замок
  digitalWrite(GREEN_LED_PIN, LOW);
}

void controlIndicators() {
  switch(currentState) {
    case WAITING_INPUT:
      digitalWrite(YELLOW_LED_PIN, HIGH);
      digitalWrite(RED_LED_PIN, LOW);
      break;
      
    case SYSTEM_LOCKED:
      // Мигающий красный при блокировке
      digitalWrite(RED_LED_PIN, (millis() % 500) < 250);
      break;
      
    case ACCESS_DENIED:
      digitalWrite(RED_LED_PIN, HIGH);
      break;
  }
}

Таймеры и автоматические переходы:

void updateStateTimers() {
  unsigned long currentTime = millis();
  
  switch(currentState) {
    case ACCESS_GRANTED:
      if (currentTime - stateStartTime > 5000) { // 5 секунд открыто
        closeDoor();
        changeState(WAITING_INPUT);
      }
      break;
      
    case ACCESS_DENIED:
      if (currentTime - stateStartTime > 2000) { // 2 секунды показа ошибки
        changeState(WAITING_INPUT);
      }
      break;
      
    case SYSTEM_LOCKED:
      if (currentTime - lockStartTime > LOCK_TIME) { // Разблокировка
        changeState(WAITING_INPUT);
      }
      break;
  }
}

УСЛОЖНЕНИЯ И ВАРИАЦИИ 🎛️

1. Многоуровневый доступ:

enum AccessLevel { LEVEL_USER, LEVEL_ADMIN, LEVEL_MASTER };

AccessLevel checkAccessLevel(char code[CODE_LENGTH + 1]) {
  // Проверяем код в разных сегментах EEPROM
  if (validateCodeInRange(code, 0, 3)) return LEVEL_USER;
  if (validateCodeInRange(code, 4, 7)) return LEVEL_ADMIN;
  if (validateCodeInRange(code, 8, 11)) return LEVEL_MASTER;
  return LEVEL_USER; // по умолчанию
}

2. Ведение лога доступа:

struct AccessLog {
  char code[CODE_LENGTH + 1];
  unsigned long timestamp;
  bool accessGranted;
};

void logAccessAttempt(char code[CODE_LENGTH + 1], bool granted) {
  // Сохраняем в EEPROM с циклической перезаписью
  static int logIndex = 0;
  AccessLog logEntry;
  
  strcpy(logEntry.code, code);
  logEntry.timestamp = millis();
  logEntry.accessGranted = granted;
  
  EEPROM.put(100 + logIndex * sizeof(AccessLog), logEntry);
  logIndex = (logIndex + 1) % 10; // храним последние 10 записей
}

3. RFID расширение:

#include <MFRC522.h>

void handleRFID() {
  if (mfrc522.PICC_IsNewCardPresent()) {
    if (mfrc522.PICC_ReadCardSerial()) {
      String rfidUid = "";
      for (byte i = 0; i < mfrc522.uid.size; i++) {
        rfidUid += String(mfrc522.uid.uidByte[i], HEX);
      }
      
      if (validateRFID(rfidUid)) {
        changeState(ACCESS_GRANTED);
      }
    }
  }
}

ОЛИМПИАДНАЯ СВЯЗЬ 🏆

СВЯЗЬ С РЕАЛЬНЫМИ ОЛИМПИАДНЫМИ ЗАДАНИЯМИ:

// Аналогично задачам на конечные автоматы:
"Реализовать систему с множеством состояний и сложными переходами"

// Аналогично задачам на работу с периферией:
"Интегрировать различные устройства в единую систему"

// Аналогично задачам на алгоритмы обработки данных:
"Реализовать систему хранения и проверки данных с защитой"

Критерии успеха в олимпиадах:

  • Целостность системы - все компоненты работают согласованно
  • Надежность - обработка ошибок и граничных случаев
  • Безопасность - защита данных и противодействие взлому
  • Пользовательский интерфейс - интуитивное управление и обратная связь

Типичные олимпиадные ошибки:

  • Отсутствие обработки ошибок - система падает при неправильном вводе
  • Жесткие задержки - использование delay() вместо millis()
  • Небезопасное хранение - коды в открытом виде
  • Слабая индикация - пользователь не понимает состояние системы

МЕТОДИЧЕСКИЕ СОВЕТЫ 👨‍🏫

Поэтапная реализация:

// ЭТАП 1: Отдельные компоненты
testKeypad();
testServo();
testLEDs();

// ЭТАП 2: Базовая интеграция
handleKeypadInput();
if (codeCorrect) openDoor();

// ЭТАП 3: Система состояний
implementStateMachine();
addErrorHandling();

// ЭТАП 4: Безопасность и надежность
addEEPROMStorage();
implementLockoutSystem();
addAuditLog();

Визуализация для понимания:

🏗️  Архитектура системы:

[Клавиатура] → [Ардуино] → [Сервопривод]
    ↓              ↓           ↓
[Ввод кода]  → [Проверка] → [Открытие]
    ↓              ↓           ↓
[Обратная   ← [Индикация] ← [Статус]
 связь]                     [Логирование]

Практические упражнения:

Упражнение 1: “Тестирование надежности”

  • Проверить работу системы при неправильных вводах
  • Протестировать восстановление после сбоев питания
  • Оценить устойчивость к электромагнитным помехам

Упражнение 2: “Улучшение безопасности”

  • Реализовать шифрование кодов в EEPROM
  • Добавить задержки при неправильном вводе
  • Внедрить систему одноразовых кодов

Упражнение 3: “Расширение функциональности”

  • Добавить режим программирования новых кодов
  • Реализовать удаленное управление через Bluetooth
  • Создать мобильное приложение для мониторинга

Диагностика проблем:

  • Сервопривод не двигается → проверьте питание и сигнальный провод
  • Клавиатура не реагирует → проверьте подключение строк и столбцов
  • EEPROM не сохраняет данные → убедитесь в правильности адресации
  • Система зависает → добавьте watchdog таймер

Критерии оценки проекта:

  • 4 балла - стабильная работа базовой системы доступа
  • +2 балла - надежная система состояний с обработкой ошибок
  • +2 балла - безопасное хранение данных и защита от взлома
  • +2 балла - расширенные функции и профессиональный интерфейс

РЕАЛЬНОЕ ПРИМЕНЕНИЕ 🏢

Где это используется:

  • Системы контроля доступа - в офисах, предприятиях, жилых домах
  • Банковские сейфы - многофакторная аутентификация
  • Парковочные системы - управление шлагбаумами
  • Умный дом - управление доступом в помещения

Профессиональные аналоги:

  • Системы RFID контроля доступа - карточки и брелоки
  • Биометрические сканеры - отпечатки пальцев, распознавание лиц
  • Многофакторная аутентификация - комбинация разных методов
  • Системы мониторинга и отчетности - ведение логов доступа