Проект 10. Сейф (кодовый замок)

Устройство которое сможет надежно сохранить ваши ценности. Для открытия кодового замка необходимо ввести правильную последовательность чисел.

Описание работы:

Для начала работы подключите питание к Arduino. Загорится светодиод сигнализирующий об открытии сейфа, сервопривод повернут на 90 градусов. а на экране высветятся цифры от 0 до 99.

Для закрытия сейфа необходимо ввести кодовую последовательность, для этого вращайте потенциометры влево или вправо. Индикатор условно поделен пополам. Левую сторону индикатора регулирует потенциометр во 2 посадочной площадке. Правую сторону индикатора регулирует потенциометр в 6 посадочной площадке. Потенциометры регулируются в диапазоне от 0 до 99. После того, как вы выставили нужную последовательность, запомните ее и нажмите на кнопку. Светодиод погаснет, сервопривод повернется в 0 градусов, а сейф закроется. Установленная кодовая последователь на индикаторе мигнет три раза и высветятся другие числа.

Для того, чтобы открыть сейф необходимо ввести ту же самую последовательность и нажать кнопку. Устройство автоматически будет выключать экран когда вы закрыли сейф и ничего не будете настраивать (не крутите потенциометры и не нажимаете кнопку). Если вы введете неправильную последовательность индикатор мигнет три раза. Как только вы ввели правильную комбинацию, светодиод на кнопке опять загорится, а сервопривод повернется в 0 градусов, указывая но то, что замок открыт.

Закрыть замок -> установить код -> нажать кнопку -> светодиод погаснет.

Открыть замок -> установить код -> нажать кнопку -> светодиод зажжется.

Нам понадобится:

Для реализации проекта нам необходимо установить следующие библиотеки:

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Схема сборки:

  • Полученный результат представлен на рисунке ниже.

Код программы:

#include <Servo.h>                                               // Подключаем библиотеку Servo.
Servo servo;                                                     // Объявляем объект для работы с сервоприводом.
                                                                 //
#include <iarduino_4LED.h>                                       // Подключаем библиотеку iarduino_4LED.
iarduino_4LED dispLED(A2, 2);                                    // Объявляем объект для работы с функциями библиотеки iarduino_4LED, с указанием выводов дисплея ( CLK , DIO ).
                                                                 //
const uint8_t pinKeyPotLeft = A0;                                // Объявляем пин для работы с левым потенциометром.
const uint8_t pinKeyPotRight = A3;                               // Объявляем пин для работы с правым потенциометром.
                                                                 //
const uint8_t pinKeyLedBlue = 10;                                // Объявляем пин для работы со светодиодом синей кнопки.
const uint8_t pinKeyBlue = 6;                                    // Объявляем пин для работы с синей кнопкой.
const uint8_t pinServo = 11;                                     // Определяем № вывода к которому подключён сервопривод.
                                                                 //
const uint8_t dreb = 10;                                         // Константа для подавления дребезга потенциометра.
                                                                 //
int menu;                                                        // Переменная меню событий.
int Left;                                                        // Переменная значений левого потенциометра.
int Right;                                                       // Переменная значений правого потенциометра.
                                                                 //
String LeftChar;                                                 // Переменная значений левого потенциометра в строковом формате.
String RightChar;                                                // Переменная значений правого потенциометра в строковом формате.
String times;                                                    // Переменная значений потенциометров для вывода на индикатор.
                                                                 //
uint8_t codeLeft;                                                // Переменная для хранения кода с левого потенциометра.
uint8_t codeRight;                                               // Переменная для хранения кода с правого потенциометра.
                                                                 //
int prevLeft;                                                    // Переменная предыдущего значения левого потенциометра.
int prevRight;                                                   // Переменная предыдущего значения правого потенциометра.
                                                                 //
int prevLeftDat;                                                 // Переменная предыдущего значения левого потенциометра без масштабирования.
int prevRightDat;                                                // Переменная предыдущего значения правого потенциометра без масштабирования.
                                                                 //
int i, k;                                                        // Переменные счета.
                                                                 //
bool around = true;                                              // Переменная события разрешает/запрещает изменение вывода значений потенциометров на индикаторе.
bool event = true;                                               // Переменная события разрешает/запрещает нажатие кнопки.
long prevMicros;                                                 // Переменная предыдущих значений счетчика.
                                                                 //
void ReadingValues();                                            // Функция чтения значения с потенциометров.
void ShowTime();                                                 // Функция вывода значений на индикатор.
                                                                 //
void setup()                                                     //
{                                                                //
  servo.attach(pinServo);                                        // Присоединяем сервопривод к выводу pinServo.
  pinMode(pinKeyBlue, INPUT);                                    // Переводим вывод pinKeyBlue в режим входа.
  pinMode(pinKeyLedBlue, INPUT);                                 // Переводим вывод pinKeyLedBlue в режим входа.
  dispLED.begin();                                               // Инициируем LED дисплей.
  dispLED.light(7);                                              // Устанавливаем максимальную яркость свечения LED индикатора.
  menu = 1;                                                      // Задаем событие 1.
}                                                                //
                                                                 //
void loop()                                                      //
{                                                                //
  switch(menu)                                                   // Переменная меню события.
  {                                                              //
    case 1:                                                      // Событие 1.
    ReadingValues();                                             // Функция чтения значения с потенциометров.
    ShowTime();                                                  // Функция вывода значений на индикатор.
    if (digitalRead(pinKeyBlue) && event)                        // Если нажата кнопка и событие нажатие кнопки разрешено.
    {                                                            //
      codeLeft  = Left;                                          // Сохраняем значения левого потенциометра.
      codeRight = Right;                                         // Сохраняем значения правого потенциометра.
      menu = 2;                                                  // Разрешаем переход к событию 2.
      around = !around;                                          // Изменили событие.
    }                                                            //
                                                                 //
    servo.write(90);                                             // Устанавливаем сервопривод на 90 градусов.
    digitalWrite(pinKeyLedBlue, HIGH);                           // Включаем светодиод на кнопке.
    if (micros() - prevMicros > 1000000) {event = true;}         // Если прошла секунда, разрешаем событие нажатие кнопки.
    break;                                                       // Выходим из оператора case.
                                                                 //
    case 2:                                                      // Событие 2.
    for (k = 0; k <= 3; k++)                                     // В цикле осуществляем мигание.
    {                                                            //
      dispLED.clear();                                           // Очищаем дисплей.
      digitalWrite(pinKeyLedBlue, LOW);                          // Гасим светодиод на кнопке.
      delay(500);                                                // Задержка 500 мс.
                                                                 //
      ShowTime();                                                // Функция вывода значений на индикатор.
      digitalWrite(pinKeyLedBlue, HIGH);                         // Зажигаем светодиод на кнопке.
      delay(500);                                                // Задержка 500 мс.
    }                                                            //
    digitalWrite(pinKeyLedBlue, LOW);                            // Гасим светодиод на кнопке.
    servo.write(0);                                              // Устанавливаем сервопривод на 0 градусов.
    menu = 3;                                                    // Разрешаем переход к событию 3.
    prevLeftDat = 0;                                             // Обнуляем переменную значений с левого потенциометра без масштабирования.
    prevRightDat = 0;                                            // Обнуляем переменную значений с правого потенциометра без масштабирования.
    break;                                                       // Выходим из оператора case.
                                                                 //
    case 3:                                                      // Событие 3.
    ReadingValues();                                             // Функция чтения значения с потенциометров.
    ShowTime();                                                  // Функция вывода значений на индикатор.
    if (Right == prevRight && Left == prevLeft){i++;}            // Если предыдущее значение потенциометра равно новому, то увеличиваем переменную счета.
    else{i = 0;}                                                 // Если не равно, обнуляем переменную счета.
    prevLeft = Left;                                             // Сохраняем новое значение левого потенциометра в предыдущую переменную.
    prevRight = Right;                                           // Сохраняем новое значение правого потенциометра в предыдущую переменную.
    if (i > 500){menu = 4;}                                      // Если переменная счета превысило значение 500, то разрешаем переход к событию 4.
                                                                 //
    if (digitalRead(pinKeyBlue))                                 // Если нажата синяя кнопка.
    {                                                            //
      if (codeLeft == Left && codeRight == Right)                // Сравниваем сохраненные значения коды и установленные заново. Если совпадают.
      {                                                          //
        digitalWrite(pinKeyLedBlue, HIGH);                       // Зажигаем светодиод.
        servo.write(90);                                         // Устанавливаем сервопривод на 90 градусов.
        menu = 1;                                                // Разрешаем переход событию 1.
        event = false;                                           // Запрещаем событие нажатия кнопки.
        prevMicros = micros();                                   // Сохраняем предыдущее значение таймера.
      }                                                          //
      else                                                       // Если не совпадают, то мигаем индикатором.
      {                                                          //
        for (k = 0; k <= 3; k++)                                 // В цикле осуществляем мигание.
        {                                                        //
          dispLED.light(1);                                      // Устанавливаем небольшую яркость свечения LED индикатора.
          delay(500);                                            // Задержка 500 мс.
          dispLED.light(7);                                      // Устанавливаем максимальную яркость свечения LED индикатора.
          delay(500);                                            // Задержка 500 мс.
        }                                                        //
      }                                                          //
    }                                                            //
    break;                                                       // Выходим из оператора case.
                                                                 //
    case 4:                                                      // Событие 4.
    dispLED.clear();                                             // Очищаем индикатор.
    i = 0;                                                       // Обнуляем переменную счета.
    ReadingValues();                                             // Функция чтения значения с потенциометров.
    if (Right != prevRight || Left != prevLeft){menu = 3;}       // Если предыдущее значения потенциометров не равны новым, то разрешаем переход к событию 3.
    prevLeft = Left;                                             // Сохраняем новое значение левого потенциометра в предыдущую переменную.
    prevRight = Right;                                           // Сохраняем новое значение правого потенциометра в предыдущую переменную.
    if (digitalRead(pinKeyBlue)){menu = 3;}                      // Если нажата кнопка, то разрешаем переход к Событию 3.
    break;                                                       // Выходим из оператора case.
  }                                                              //
}                                                                //
                                                                 //
void ReadingValues()                                             // Функция чтения значения с потенциометров.
{                                                                //
  if (  analogRead(pinKeyPotLeft) - prevLeftDat   > dreb  ||     // Если разность между новым значением левого потенциометра и предыдущим значением левого потенциометра больше переменной дребезга левого потенциометра.
        analogRead(pinKeyPotLeft) - prevLeftDat   < -dreb ||     // Если разность между новым значением левого потенциометра и предыдущим значением левого потенциометра меньше переменной дребезга левого потенциометра.
        analogRead(pinKeyPotRight) - prevRightDat > dreb  ||     // Если разность между новым значением правого потенциометра и предыдущим значением правого потенциометра больше переменной дребезга правого потенциометра.
        analogRead(pinKeyPotRight) - prevRightDat < -dreb    )   // Если разность между новым значением правого потенциометра и предыдущим значением правого потенциометра меньше переменной дребезга правого потенциометра.
  {                                                              //
    prevLeftDat = analogRead(pinKeyPotLeft);                     // Сохраняем новое значение левого потенциометра в предыдущую переменную.
    prevRightDat = analogRead(pinKeyPotRight);                   // Сохраняем новое значение правого потенциометра в предыдущую переменную.
    if (around)                                                  // Если событие изменения вывода значений на индикатор разрешено.
    {                                                            //
      Left = map(analogRead(pinKeyPotLeft), 0, 1015, 0, 99);     // Считываем значения левого потенциометра, масштабируя в диапазон от 0 до 99.
      Right = map(analogRead(pinKeyPotRight), 0, 1015, 0, 99);   // Считываем значения правого потенциометра, масштабируя в диапазон от 0 до 99.
    }                                                            //
    else                                                         // Если событие изменения вывода значений на индикатор неразрешено.
    {                                                            //
      Left = map(analogRead(pinKeyPotLeft), 0, 1015, 99, 0);     // Считываем значения левого потенциометра, масштабируя в диапазон от 99 до 0.
      Right = map(analogRead(pinKeyPotRight), 0, 1015, 99, 0);   // Считываем значения правого потенциометра, масштабируя в диапазон от 99 до 0.
    }                                                            //
  }                                                              //
}                                                                //
                                                                 //
void ShowTime()                                                  // Функция показа времени.
{                                                                //
  if (Left>=0 && Left<10)                                        // Если количество времени у левого игрока от 0 до 9.
  {LeftChar = (String) "0" + Left;}                              // Добавляем спереди ноль и переводим в строковое значение.
  else{LeftChar = (String) Left;}                                // Иначе просто переводим количество времени в строковое значение.
                                                                 //
  if (Right>=0 && Right<10)                                      // Если количество времени у правого игрока от 0 до 9.
  {RightChar = (String) "0" + Right;}                            // Добавляем спереди ноль и переводим в строковое значение.
  else{RightChar = (String) Right;}                              // Иначе просто переводим количество времени в строковое значение.
                                                                 //
  times = LeftChar + RightChar;                                  // Присваиваем общей переменной количество времени левого и правого игрока.
  dispLED.print(times);                                          // Выводим значение на индикатор.
}                                                                //

Алгоритм работы:

В начале скетча (до кода setup) выполняются следующие действия:

В коде setup выполняются следующие действия:

  • Присоединяем сервопривод к выводу pinServo.
  • Переводим вывод pinKeyBlue, pinKeyLedBlue в режим входа.
  • Инициируем LED дисплей.
  • Устанавливаем максимальную яркость свечения LED индикатора.
  • Разрешаем переход к событию 1.

В коде loop выполняются следующие действия:

  • Событие 1.
  • Считываем значение с потенциометров с помощью функции "ReadingValues()".
  • Выводим значения потенциометров с помощью функции "ShowTime()".
  • Если нажата кнопка, то сохраняем кодовую последовательность, разрешаем переход к событию 2 и изменяем событие вывода значений потенциометра в другом диапазоне на противоположное .
  • Устанавливаем сервопривод на 180 градусов.
  • Включаем светодиод на кнопке.
  • Разрешаем событие нажатия кнопки, если прошла одна секунда с момента начала этого события.
  • Событие 2.
  • Осуществляем мигание с помощью цикла, в котором сначала очищаем дисплей, гасим светодиод и ждем 500 мс, затем выводим на дисплей значения потенциометров, зажигаем светодиод, ждем 500 мс и так три раза.
  • Гасим светодиод, устанавливаем на сервопривод 0 градусов, разрешаем переход к событию 3 и обнуляем переменные значений с левого и правого потенциометра без масштабирования.
  • Событие 3.
  • Считываем значение с потенциометров с помощью функции "ReadingValues()".
  • Выводим значения потенциометров с помощью функции "ShowTime()".
  • Если оба предыдущих значения потенциометра равно новому, то увеличиваем переменную счета. А если не равно, обнуляем переменную счета.
  • Сохраняем новые значения левого и правого потенциометров в предыдущие переменные.
  • Если переменная счета больше 500, то разрешаем переход к событию 4.
  • Если нажата кнопка, то сравниваем кодовую последовательность с новыми установленными значениями потенциометров. Если совпадают, то зажигаем светодиод, устанавливаем сервопривод а 180 градусов., разрешаем переход к событию 1, запрещаем события нажатия кнопки, сохраняем нынешнее значение счетчика. Если не равны, тогда три раза мигаем экраном, в цикле убавляя и прибавляя яркость подсветки, через каждый 500 мс.
  • Событие 4.
  • Очищаем индикатор.
  • Обнуляем переменную счета.
  • Считываем значение с потенциометров с помощью функции "ReadingValues()".
  • Если значения изменились, то разрешаем переход к события 3.
  • Сохраняем новые значения левого и правого потенциометров в предыдущие переменные.
  • Если нажата кнопка, то разрешаем переход в событие 3.
  • функции "ReadingValues()". В ней убираем дребезг потенциометров, а именно значения на потенциометрах не в масштабе должны быть больше или меньше предыдущих значений на 10 единиц. Тогда сохраняем текущие значения потенциометров не в масштабе и сохраняем текущие значения потенциометров масштабе в зависимости от диапазона.
  • Функция "ShowTime()". В ней преобразуем время целочисленного значения в строковое, добавляя ноль, где это необходимо. А так же выводим раз в пол секунды общее время и мигающую точку по центру, для событий 1 и 7. Для остальных событий выводим время и точку постоянно.
Ссылки

Обсуждение