Espruino:Примеры/Однокнопочный замок
Однокнопочный замок[1]
Очевидно, что для создания электронного замка идеально подходит кнопочная панель. Но что если вам не хочется возиться с проводами, вы ограничены в пространстве или вообще хотите спрятать дверь. В этом случае можно воспользоваться всего одной кнопкой и с её помощью ввести код по принципу, схожему с азбукой Морзе. Этим мы в этой статье и займёмся.
Нам понадобится
- Одна плата Espruino Original
Подсоединение
На данном этапе ничего подсоединять не надо – мы просто воспользуемся светодиодами и кнопкой, встроенными в плату.
Код
Первый шаг – это создание ответа на нажатие на кнопку. Подключитесь к Espruino и вставьте код ниже в левую часть Web IDE:
function buttonWatcher(e) {
console.log(e.time);
}
setWatch(buttonWatcher, BTN, {edge:"falling", repeat:true});
Нажмите на кнопку (на ту, что находится вдали от USB-коннектора, потому что та, что ближе к нему, выполняет сброс платы). Когда вы её отпустите, Espruino должна напечатать время (согласно Espruino) того, когда была нажата кнопка. Иногда время будет печататься несколько раз – из-за дребезга контактов. Дело в том, что сама кнопка механическая, и иногда её контакты «дребезжат» после нажатия или отпускания кнопки, в результате чего она несколько раз очень быстро включается и выключается. Нам нужно определять этот дребезг и избавляться от него.
Вставьте в Web IDE код ниже. Он изменяет функцию, вызываемую при нажатии на кнопку – теперь она не печатает время в консоли, а измеряет время между нажатиями, и если это время больше 0.1 секунд, то печатает в консоли сообщение «Зарегистрировано нажатие!»
var lastPress = 0;
function buttonWatcher(e) {
var timeDiff = e.time - lastPress;
lastPress = e.time;
console.log(timeDiff);
if (timeDiff>0.1) console.log("Зарегистрировано нажатие!");
}
Теперь давайте создадим функцию onPress(), которая будет вызываться при нажатии на кнопку. Она считает количество нажатий, но если с момента последнего нажатия пройдёт больше одной секунды, она этот счётчик нажатий обнулит.
var lastPress = 0;
// Количество нажатий на кнопку:
var pressCount = 0;
// Таймаут, срабатывающий спустя секунду после нажатия:
var timeout;
function onTimeout() {
timeout = undefined;
pressCount = 0;
console.log("Таймаут!");
}
function onPress(timeDiff) {
pressCount++;
console.log(pressCount);
// Если у нас остался таймаут от другого нажатия, удаляем его:
if (timeout) clearTimeout(timeout);
// Спустя одну секунду после текущего нажатия запускаем onTimeout():
timeout = setTimeout(onTimeout, 1000);
}
function buttonWatcher(e) {
var timeDiff = e.time - lastPress;
lastPress = e.time;
if (timeDiff>0.1) onPress(timeDiff);
}
setWatch(buttonWatcher, BTN, {edge:"falling", repeat:true});
Теперь нажимаем на кнопку несколько раз. Код начнёт отсчитывать количество нажатий, но если вы в течение одной секунды не будете нажимать на кнопку, в консоли будет напечатано сообщение «Таймаут!», и счётчик будет сброшен. Теперь давайте сделаем кодовый замок, изменив код в функции onTimeout().
var code = [3,1,2]; // код, который надо ввести, чтобы открыть замок
var digit = 0; // то, на какой цифре кода мы находимся
function setLocked(isLocked) {
// Включаем красный или зелёный светодиод
// в зависимости от того, правильный ли введён код или нет:
digitalWrite([LED1,LED2,LED3], isLocked ? 0b100 : 0b010);
// Спустя две секунды выключаем светодиод:
setTimeout(function() {
digitalWrite([LED1,LED2,LED3], 0);
}, 2000);
}
function onTimeout() {
timeout = undefined;
// Проверяем вводимый код:
if (pressCount == code[digit]) {
digit++; // переходим к следующей цифре
if (digit >= code.length) {
console.log("Вот и конец кода – открываем!");
setLocked(false);
// Снова переходим в начало кода:
digit = 0;
} else {
console.log("Правильная цифра – переходим к следующей!");
}
} else {
console.log("Неправильно! Возвращаемся в начало");
setLocked(true);
digit = 0;
}
pressCount = 0;
}
Вот и всё! Теперь, если вы введёте с помощью кнопки код вроде...
[нажатие] ... [нажатие] ... [нажатие], ждём секунду, [нажатие], ждём секунду, [нажатие] ... [нажатие]
...на плате на 2 секунды загорится зелёный светодиод, что будет означать, что код верный. Если вы ошибётесь, загорится красный светодиод.
Вы можете без труда поменять (замковый) код в (программном) коде и даже его размер, просто отредактировав строчку с массивом code[]. Например, вот так:
code = [5,1,3,4];
Итоговый код
Если вы просто хотите ввести код в правую часть IDE, так целиком он выглядит вот так:
var lastPress = 0;
var pressCount = 0;
var timeout;
var code = [3,1,2];
var digit = 0;
function setLocked(isLocked) {
// Включаем красный или зелёный светодиод
// в зависимости от того, правильный ли был введён код или нет:
digitalWrite([LED1,LED2,LED3], isLocked ? 0b100 : 0b010);
// Спустя две секунды выключаем светодиод:
setTimeout(function() {
digitalWrite([LED1,LED2,LED3], 0);
}, 2000);
}
function onTimeout() {
timeout = undefined;
// Проверяем вводимый код:
if (pressCount == code[digit]) {
digit++; // переходим к следующей цифре
if (digit >= code.length) {
console.log("Вот и конец кода – открываем!");
setLocked(false);
// Снова переходим в начало кода:
digit = 0;
} else {
console.log("Правильная цифра – переходим к следующей!");
}
} else {
console.log("Неправильно! Возвращаемся в начало");
setLocked(true);
digit = 0;
}
pressCount = 0;
}
function onPress(timeDiff) {
pressCount++;
console.log(pressCount);
// Если у нас остался таймаут от другого нажатия, удаляем его:
if (timeout) clearTimeout(timeout);
// Спустя одну секунду после текущего нажатия запускаем onTimeout():
timeout = setTimeout(onTimeout, 1000);
}
function buttonWatcher(e) {
var timeDiff = e.time - lastPress;
lastPress = e.time;
if (timeDiff>0.1) onPress(timeDiff);
}
setWatch(buttonWatcher, B12, { repeat:true, edge:'falling' });
Что дальше
Далее можно запрограммировать то, что будет делать замок после того, как вы введёте правильный код. Для этого нужно отредактировать функцию setLocked(). Например, вы можете подключить к контакту B13 серводвигатель и написать в коде следующее:
function setLocked(isLocked) {
// Включаем красный или зелёный светодиод
// в зависимости от того, правильный ли был введён код или нет:
digitalWrite([LED1,LED2,LED3], isLocked ? 0b100 : 0b010);
// Спустя две секунды выключаем светодиод:
setTimeout(function() {
digitalWrite([LED1,LED2,LED3], 0);
}, 2000);
// Теперь управляем серводвигателем.
// Передаём ему импульсы в течение одной секунды (50 х 20 мс),
// чтобы переместить его на новое место:
var servoPos = isLocked ? 0 : 1;
var servoPulses = 0;
var interval = setInterval(function() {
digitalPulse(B13, 1, 1+servoPos);
servoPulses++;
if (servoPulses>50) clearInterval(interval);
}, 20);
}
См.также
Внешние ссылки