После очередного конфликта между детьми (младшее поколение безнадёжно испортило домашнюю работу старшего) я принял решение изготовить детский, но полнофункциональный сейф, для надёжного хранения домашних работ 😉
Первую версию сейфа я решил сделать из г0вна и палок подручного материала, чтобы в случае неудачи не было обидно за потраченные деньги. А в случае удачи я повторю проект уже на более качественном уровне, учитывая полученный опыт.
Запланированный принцип действия всего устройства прост: деревянная коробка, кодовый замок управляемый Arduino, и механический засов, сдвигаемый сервоприводом. Итак, приступим!
Механическая часть
Сейф выполнен в виде ящика, собранного из кусков ДСП, завалявшихся в гараже. В качестве замка я использовал обычный шпингалет, но сначала его пришлось немного доработать. Я наклеил на него кусочки пластика таким образом, чтобы ручка могла передвигаться только вдоль шпингалета, не отклоняясь в стороны и не защёлкиваясь. В качестве аварийного способа открытия сейфа, задняя стенка может сниматься, конечно если открутить большое количество саморезов, удерживающих её.
Электронные компоненты
Здесь я приведу список используемой электроники со ссылками на продавцов и приблизительными ценами.
- Arduino Nano — 3$
- Сервопривод 9g — 1$
- Клавиатура 4х4 — 1$
- Литиевый Аккумулятор 18650 — 4$
- Контейнер для 18650 — 0.5$
- Блок защита+зарядки TP4056 — 0,5$
- Бустер — повышатель напряжения до 5вольт — 0.5$
- Кнопочный выключатель — 0.4$
Итого, общие расходы на электронику составляют около 11$.
Конечно, компоненты можно найти и дешевле, если заказывать сразу по несколько штук и экономить на стоимости доставки.
16-кнопочная клавиатура снабжена двухсторонним скотчем на обороте, что делает очень удобным её монтаж на дверце. А шлейф этой клавиатуры выглядит тонким и ненадёжным, нуждается в дополнительной защите.
Схема подключения
Вся система питается от одного аккумулятора 18650. Через выключатель и модуль защиты TP4056, напряжение от него поступает на повышающий модуль до 5 вольт (полярность на выходе повышающего модуля я указал неточно, при подключении проверьте полярность тестером). От него питается контроллер и сервопривод. Клавиатура же не требует отдельного питания. Модуль защиты аккумулятора TP4056 может работать и как зарядное устройство, если на него подать стабилизированное напряжение 5вольт на контакты + и + (на схеме они не задействованы, расположены в верхней части защитной платы) или просто на его разъём Micro-USB. Получить это напряжение можно с любого современного зарядного устройства от мобильника.
Логика работы сейфа предполагает, что пользователь должен включать питание кнопочным выключателем только когда требуется открыть или закрыть замок, остальное время простоя выключатель должен быть выключен для экономии заряда аккумулятора. Конечно можно было заморочиться с режимом ожидания, засыпанием и просыпанием контроллера, выпаиванием светодиодов с контроллера для экономии питания и т.д., но всё таки это только первый пробный образец! Так что пока — просто выключатель, и может быть в будущем выведу наружу шнур для внешней зарядки аккумулятора… На тот случай, если пользователь забудет выключатель во включённом положении и разрядит аккумулятор.
В процессе настройки к схеме был ещё подключена пищалка, которая озвучивала нажатия кнопок. Однако в процессе испытаний выяснилось что пищалка при работе нагревается, а это значит что заряд аккумулятора частично расходуется впустую. По этой причине окончательная версия собрана без пищалки.
Если конструкция приживётся в доме, можно заказать в фирме Смайл-мебель крой Ламинированной ДСП для сборки более красивой коробки, и продумать систему резервного питания или внешней зарядки аккумулятора.
Программная часть
Полный текст скетча я приведу в конце статьи, а пока озвучу только самые важные моменты.
Контроллер постоянно опрашивает клавиатуру. Кнопка # отвечает за ЗАКРЫТИЕ замка в любом случае. Пароль указывается в начале скетча, может быть любой длины, и в нём можно использовать любые символы клавиатуры за исключением закрывающего символа #.
Кнопки сброса нет. Перед паролем можно нажимать любые кнопки, затем нажать кнопки пароля в нужной последовательности и замок откроется!
Любое движение сервопривода (на открытие или на закрытие) сопровождается двухсекундной паузой после команды, на случай если перемещение будет слишком медленным или на пути шпингалета окажется некое препятствие. После этой паузы — происходит Detach, то есть сервопривод логически отключается от контроллера и перестаёт давить на шпингалет. Таким образом, если в это время вы захотите провернуть сервопривод рукой, то вы не встретите сопротивления.
В тексте программы, командами myservo.write(хх); задаются углы поворота сервопривода для открытия и закрытия замка. В моём случае это 40 и 140 градусов соответственно, но вы можете задавать свои значения, в интервале от нуля до 180.
Скетч снабжён отладочными сообщениями в порт, которые не содержат пароль 😉
Демонстрация работы
Скетч
#include <Keypad.h>
#include <Servo.h>
Servo myservo;
const byte ROWS = 4; // 4 строки
const byte COLS = 4; // 4 столбца
char keys[ROWS][COLS] = {
{‘1′,’2′,’3′,’A’},
{‘4′,’5′,’6′,’B’},
{‘7′,’8′,’9′,’C’},
{‘*’,’0′,’#’,’D’}
};
char pass[] = {‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’}; // тут задаётся пароль каждый символ в отдельных кавычках
int passlen=0;
int r=0;
byte rowPins[ROWS] = {5,6, 7, 8};
byte colPins[COLS] = {9, 10, 11, 12};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup(){
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
digitalWrite(1, LOW);
digitalWrite(2, HIGH);
Serial.begin(9600);
passlen=sizeof(pass)/sizeof(char);
Serial.print(«Вычисленная длина пароля «);
Serial.println(passlen);
}
void loop(){
char key = keypad.getKey();
if (key){
Serial.println(key); // Передаем название нажатой клавиши в сериал порт
// tone(4, (int)key*10, 50); // Издаем звуковой сигнал длиной 50 миллисекунд
if (key==pass[r])
{r=r+1;} else {r=0;}
Serial.println(r);
if (r==passlen)
{
Serial.println(«ОТКРЫТО!!!»);
myservo.attach(3);
myservo.write(40);
delay(2000);
myservo.detach();
}
if (key==’#’)
{
Serial.println(«ЗАКРЫТО!!!»);
r=0;
myservo.attach(3);
myservo.write(140);
delay(2000);
myservo.detach();
}
}
}