Проект кодового замка, как это часто бывает, был создан в результате потребности в этом. Итак, хороший друг попросил меня спроектировать самую дешевую и простую в использовании систему контроля доступа, которую можно использовать для защиты входной двери объекта, оснащенного электромагнитным замком. Дополнительным требованием, которому должно было отвечать проектируемое устройство, была необходимость оснащения его дружественным и оригинальным пользовательским интерфейсом, который должен был отличаться от имеющихся в продаже устройств. Так родилась конструкция этого кодового замка, который, я надеюсь, найдет множество практических применений. Рекомендации: замок пригодится во многих целях и избавит вас от необходимости носить с собой ключ.
Принципиальная схема предлагаемого решения кодового замка показана на рисунке 1. Это несложная микропроцессорная система, сердцем которой является небольшой микроконтроллер ATtiny2313, выполняющий все предполагаемые функции. Микроконтроллер управляет работой 7-сегментного светодиодного индикатора (с общим анодом), используя встроенную в структуру систему таймер-счетчик Timer0 и прерывание от сравнения значения счетчика со значением регистра OCR0A, благодаря известному механизму мультиплексирования последовательных разрядов дисплея (частота прерывания составляет 240 Гц, что дает 60 Гц/разряд), обслуживает управляющий элемент, представляющим собой энкодер со встроенной кнопкой, используя для этого внешнее прерывание INT0, инициируемое задним фронтом на выводе PD2/INT0 микроконтроллера, а также управляет работой реле REL (с помощью транзистора), которое является исполнительным механизмом.
Рисунок 1.
Как было сказано, управление светодиодным дисплеем последовательное, поэтому для реализации данного функционала требуется меньшее количество выводов микроконтроллера. В этом решении катоды светодиодного дисплея подключены напрямую к порту PORTB микроконтроллера через токоограничивающие резисторы, а четыре общих анода через типовые транзисторные каскады (PNP) к порту PORTD. В перерыве между сравнением значения счетчика Timer0 со значением регистра OCR0A, которое вызывается каждые 4,167 мс (около 240 Гц), PORTB отправляет значение следующей отображаемой цифры. затем включается соответствующий общий анод светодиодного индикатора (через транзисторный каскад, управляющий портом PORTD) и процесс повторяется последовательно для каждого из разрядов. Это типичное решение, обычно используемое в микропроцессорных системах. Тем не менее ниже я представлю очень наглядную программную реализацию упомянутого механизма. Для начала необходимые определения приведены в примере 1.
Пример кода 1. Заголовочный файл механизма мультиплексирования светодиодного дисплея #define SEG_DDR DDRB #define SEG_PORT PORTB // Определения конфигурации отдельных сегментов (катодов) #define SEG_A PB7 #define SEG_B PB0 #define SEG_C PB2 #define SEG_D PB4 #define SEG_E PB5 #define SEG_F PB6 #define SEG_G PB1 #define SEG_DP PB3 // Катодный порт, как выходной порт #define SEG_AS_OUTPUT SEG_DDR = 0xFF // Все сегменты (катоды) заглушены (активное состояние «0», потому что мы напрямую управляем катодами светодиодов) #define SEG_BLANK SEG_PORT = 0xFF #define COM_DDR DDRD #define COM_PORT PORTD // Определение конфигурации отдельных общих анодов #define COM_DIG0 PD6 #define COM_DIG1 PD4 #define COM_DIG2 PD5 #define COM_DIG3 PD3 // Общий анодный порт как выходной порт #define COM_AS_OUTPUT COM_DDR |= (1<<COM_DIG3)|(1<<COM_DIG2)|(1<<COM_DIG1)|(1<<COM_DIG0) // Все общие аноды выключены (активное состояние "0", т.к. мы управляем базами PNP-транзисторов) #define COM_BLANK COM_PORT |= (1<<COM_DIG3)|(1<<COM_DIG2)|(1<<COM_DIG1)|(1<<COM_DIG0) // Определение бита, отвечающего за мигание цифры #define BLINKING_BIT 0b10000000 // Индекс пустой цифры в массиве DIGITS #define BLANK_DIGIT_NR 16
Две таблицы, размещенные во Flash памяти, упрощают функцию прерывания, отвечающую за механизм мультиплексирования, при этом повышая читабельность самого кода. В первой из таблиц (DIGITS [17]) хранится комбинация сегментов светодиодного индикатора (A…G), соответствующих изображениям отдельных цифр и букв A…F (плюс комбинация, отвечающая за гашение дисплея), а второй ( COMS[4] ) хранит значения, переписывание которых общих анодов LED дисплеев, PORTD в порт, включает соответствующую цифру дисплея (0…3, считая справа). Кроме того, в Digit[4] был объявлен небольшой массив который сохраняет значение последовательных цифр, которые будут отображаться на светодиодном дисплее. Упомянутые выше определения показаны в примере 2.
Пример кода 2. Необходимые определения переменных механизма мультиплексирования светодиодных дисплеев // Определения цифр дисплея (активное состояние "0", т.к. мы управляем напрямую катодами светодиодов) const uint8_t DIGITS[17] PROGMEM = { (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)), //0 (uint8_t) ~((1<<SEG_B)|(1<<SEG_C)), //1 (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)), //2 (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_G)), //3 (uint8_t) ~((1<<SEG_B)|(1<<SEG_C)|(1<<SEG_F)|(1<<SEG_G)), //4 (uint8_t) ~((1<<SEG_A)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_F)|(1<<SEG_G)), //5 (uint8_t) ~((1<<SEG_A)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)), //6 (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)), //7 (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)), //8 (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_F)|(1<<SEG_G)), //9 (uint8_t) ~((1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)), //A (uint8_t) ~((1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)), //b (uint8_t) ~((1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)), //c (uint8_t) ~((1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)), //d (uint8_t) ~((1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)), //E (uint8_t) ~((1<<SEG_A)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)), //F 0xFF // пусто }; // Определения для порта, управляющего общими анодами светодиодных дисплеев (активное состояние «0», т.к. мы управляем базами PNP-транзисторов) const uint8_t COMS[4] PROGMEM = { (uint8_t) ~(1<<COM_DIG0), // Анод 0 цифры (первая справа) (uint8_t) ~(1<<COM_DIG1), // Анод 1 цифры (uint8_t) ~(1<<COM_DIG2), // Анод 2 цифры (uint8_t) ~(1<<COM_DIG3) // Анод 3 цифры (первая слева) }; volatile uint8_t Digit[4]; // Переменная, в которой хранится значение, отображаемое на светодиодном дисплее volatile uint8_t dpON; // Переменная, отвечающая за отображение десятичной точки
Необходимые определения у нас уже есть — пришло время для первой функции, задача которой инициировать процесс мультиплексирования, состоящий из настройки портов управления и настройки и запуска таймера Timer0, включая его прерывания от сравнения значения счетчика со значением регистра OCR0A. Упомянутая функция инициализации приведена в примере 3.
Пример кода 3. Функция инициализации механизма мультиплексирования светодиодных дисплеев void initMultiplex(void) { // Общие порты анода и катода в качестве выхода с неактивными состояниями на выходах SEG_BLANK; SEG_AS_OUTPUT; COM_BLANK; COM_AS_OUTPUT; // Настройка Timer0 для генерации прерывания для поддержки мультиплексирования светодиодного дисплея (240 Гц) TCCR0A = (1<<WGM01); // Режим СТС TCCR0B = (1<<CS01)|(1<<CS00); // Предделитель = 64 OCR0A = 64; //240 Hz (каждые 4.167ms) TIMSK |= (1<<OCIE0A); // Запускаем прерывание по сравнению канала A for(uint8_t i=0; i<4; ++i) Digit[i] = BLANK_DIGIT_NR; // Гасим все цифры }
Пришло время для последнего элемента «головоломки», т. е. функции обработки прерывания Timer0, отвечающей за реализацию механизма мультиплексирования светодиодного дисплея, показанного в примере 4.
Пример кода 4. Функция обработки прерывания Timer0, отвечающая за реализацию механизма мультиплексирования светодиодных дисплеев ISR(TIMER0_COMPA_vect) { static uint8_t Nr; // Номер следующей цифры для отображения static uint8_t timer4ms; // 4 мс программный таймер для управления миганием цифр на светодиодном дисплее register uint8_t currDigit = Digit[Nr]; // Оптимизация изменчива COM_BLANK; // Отключаем общие аноды светодиодных дисплеев if(currDigit & BLINKING_BIT) // Проверяем, активирована ли функция мерцания для данной цифры (установлен 7-й бит переменной) { if(++timer4ms & 0x20) SEG_PORT = pgm_read_byte(&DIGITS[currDigit & (~BLINKING_BIT)]); else SEG_BLANK; // Выводим данные } else SEG_PORT = pgm_read_byte(&DIGITS[currDigit & (~BLINKING_BIT)]); // Получить следующую цифру в катодный порт if(Nr==0 && dpON) SEG_PORT &= ~(1<<SEG_DP); // Поддержка десятичной точки в позиции 0 COM_PORT &= pgm_read_byte(&COMS[Nr]); // Включить соответствующий общий анод (активное состояние "0") Nr = (Nr+1) & 0x03; }
Как и было обещано во введении, использование переменных DIGITS [17] и COMS [4] (в частности) сделало функцию очень короткой и читабельной, что должно быть главным правилом при реализации любых функций системных прерываний. Кроме того, введен дополнительный функционал в виде обработки мигания цифр светодиодного индикатора, который используется в программе обслуживания устройства для сигнализации факта редактирования выбранного элемента. Эта функциональность активируется независимо для каждой цифры дисплея путем установки старшего бита, соответствующего ее переменной Digit [4] .
Вот вам и детали реализации механизма мультиплексирования цифр светодиодного дисплея. С одной стороны, это достаточно несложный вопрос, с другой стороны, не всегда понятный начинающим электронщикам.
Монтаж
На рисунке 2 представлена схема сборки платы электронного замка. Установку следует начинать с припайки 4-х перемычек, положения которых отмечены графически на печатной плате. Затем припаиваем резисторы и конденсаторы, затем полупроводниковые элементы и, наконец, механические элементы, такие как разъемы PWR и LOCK, реле REL и энкодер CODE. При установке светодиодного дисплея его следует поднять от поверхности платы устройства примерно на 2 мм, чтобы верхняя плоскость находилась на одном уровне с верхней поверхностью корпуса.
Рисунок 2.
Правильно собранный с использованием запрограммированного микроконтроллера, прибор не требует настройки и должен работать сразу после включения питания. В зависимости от цвета светодиодного индикатора может потребоваться подбор номинала резисторов, ограничивающих ток отдельных его сегментов (R3…R10). Код пользователя по умолчанию — «0000». Этот код можно восстановить в аварийной ситуации, замкнув 5-й вывод микроконтроллера (обозначенный на плате как DEF) на минус источника питания при включении устройства.
Использование
При создании ПО я старался максимально упростить работу с замком, сохранив необходимый функционал. Это важно, поскольку единственным регулирующим элементом является энкодер со встроенной кнопкой, поэтому для достижения высокой эргономики работы необходимо было хорошо продумать соответствующие механизмы. Во-первых, есть режим настройки, который можно запустить только при включении устройства нажатием кнопки, встроенной в вал энкодера. Этот режим позволяет установить время срабатывания (0…5 секунд) реле, сопровождающего отпирание/блокировку кодового замка. Если время установлено на 0 с, реле остается включенным все время после блокировки кодового замка и выключенным после разблокировки.
Выход из режима настройки возможен повторным нажатием кнопки, встроенной в вал энкодера. В этот момент переходим в режим ожидания устройства (дисплей выключен). Что немаловажно, по умолчанию после включения питания (или выхода из режима настройки) замок остается разблокированным.
Нажатие на вал энкодера активирует режим ввода кода пользователя для блокировки замка. Сопровождается миганием первой цифры справа и возможностью ее изменения поворотом оси энкодера (в диапазоне "0"..."9", "А"..."F"). Подтверждение введенной цифры осуществляется нажатием кнопки, встроенной в вал энкодера. В этот момент цифра переместится на одну позицию влево и перестанет мигать, а первая цифра справа снова начнет мигать, указывая на то, что ее можно редактировать. Другими словами, код вводится слева направо (если смотреть на код, начиная со старшей цифры), редактируемая в данный момент цифра всегда отображается на первой позиции справа, а ранее введенные цифры сдвигаются на соответствующее количество позиций слева. Повторяем эти действия 4 раза,
О том, что замок заблокирован, сигнализирует десятичная точка на дисплее в положении 0, даже когда устройство находится в режиме ожидания. Также стоит подчеркнуть, что для удобства пользователя введен дополнительный механизм, благодаря которому мы можем пропускать ввод пользовательского кода, используемого для блокировки замка, принимая по умолчанию ранее использованный и запомненный код блокировки. Для этого после входа в режим ввода кода пользователя (из режима ожидания) нажмите и удерживайте вал энкодера более длительное время, после чего кодовый замок будет заблокирован (и реле среагировало соответствующим образом) и произойдет переключение в режим ожидания. В этот момент (после блокировки замка) нажатие на вал энкодера активирует режим ввода кода пользователя (как и раньше), но на этот раз для разблокировки замка.
Ввод правильного кода разблокирует замок (вызовет соответствующую реакцию реле), а ввод неправильного кода приводит к переходу устройства в режим ожидания и ввода нового кода разблокировки. Если вы остаетесь в режиме ввода кода пользователя (мигает первая цифра справа) и не завершаете этот процесс в течение 5 секунд, устройство переходит в режим ожидания. Это время отсчитывается каждый раз заново после любого редактирования. Кроме того, для индикации рабочего состояния устройство отображает несколько текстовых сообщений, которые вместе с их описанием приведены в таблице 1.
Сообщение | Описание |
dEF | Произведен сброс пароля, по умолчанию: "0000" |
Err | Пароль введен неправильно |
OPEn | Замок открыт |
cLOSE | Замок закрыт |
Фалы к статье "Кодовый замок на ATtiny2313" | |
Описание:
Файл прошивки микроконтроллера |
|
Размер файла: 1.54 KB Количество загрузок: 106 | Скачать |
Комментарии
Можете дать чертёж платы для этого замка в формате LAY ???