Проблема с кодовым замком

Михаил Груничев
Offline
Зарегистрирован: 25.06.2017

Всем привет. Есть такая проблемка. Хочу добавить в кодовый замок функцию возврата на экран приветствия, по истечению некоторого времени (скажем 10 секунд) , если пароль введён не полностью и висит на экране ввода.

Тоесть мне нужно, чтобы после нажатия какой либо клавиши, он считал 10 секунд (и при этом программа не останавливалась) и если никакая клавиша не была, то автоматически возвращался начальный экран...никак не могу понять как это реализовать. Спасибо заранее за помощь.

#include <Password.h>
#include <Keypad.h>
#include <LiquidCrystal.h>

Password password = Password("3355770");  // Пароль
int dlugosc = 7;                          // Длина пароля

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
// Значки состояния замка
byte unlocked[8] = {
  0b11111,
  0b10001,
  0b10000,
  0b10000,
  0b11111,
  0b10101,
  0b10001,
  0b11111
};

byte locked[8] = {
  0b11111,
  0b10001,
  0b10001,
  0b10001,
  0b11111,
  0b10101,
  0b10001,
  0b11111
};

int p = 9;   // Выход пъезоэлемента на 9 пин
int ledRed = 10;
int ledGreen = 11;
int relay = 12;
int ilosc; // Число нажатий
// Таймер обратного отсчёта на 10 секунд
int runTimer = 1;
int runFor = 10; // Время в секундах
const byte ROWS = 4; // 4 строки
const byte COLS = 3; // 3 столбца

char keys[ROWS][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {2, 3, 4, 5}; // Подключить к выводам строк
byte colPins[COLS] = {6, 7, 8};    // Подключить к выводам столбцов

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
  Serial.begin(9600);
  keypad.addEventListener(keypadEvent);
  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(p, OUTPUT);
  pinMode(relay, OUTPUT);
  
  digitalWrite(ledRed, HIGH);
  digitalWrite(ledGreen, LOW);
  digitalWrite(relay, HIGH);

  lcd.begin(16, 2);
  lcd.createChar(0, unlocked);
  lcd.createChar(1, locked);
  lcd.setCursor(1, 0);
  lcd.print("  :Welcome:");
  lcd.setCursor(0, 1);
  lcd.print("PLEASE ENTER PIN");
  startupsound();
}

// Настраиваем таймер
void timer() {
  for (int timer = runFor; timer > 0; --timer) {
    if (timer >= 10) {
      lcd.setCursor(14, 0);
    } else {
      lcd.setCursor(14, 0);
      lcd.print("0");
      lcd.setCursor(15, 0);
    }
    lcd.print(timer);
    blink();
    delay(1000);
    }
}

// Мигаем светодиодом
void blink() {
  digitalWrite(ledRed, HIGH);
  delay(50);
  digitalWrite(ledRed, LOW);
}

//Индикация нажатия кнопок
void clickbuttonindication() {
        digitalWrite(ledGreen, HIGH);
        tone(p, 900);
        delay(50);
        noTone(p);
        digitalWrite(ledGreen, LOW);
}

void startupsound() {
  tone(p, 1000);
  delay(500);
  noTone(p);
}

// Звук открытия
void unlockedsound() {
  tone(p, 500);
    delay(100);
    noTone(p);
    tone(p, 600);
    delay(100);
    noTone(p);
    tone(p, 800);
    delay(100);
    noTone(p);
}  
// Звук закрытия
void lockedsound() {
  tone(p, 800);
    delay(100);
    noTone(p);
    tone(p, 600);
    delay(100);
    noTone(p);
    tone(p, 500);
    delay(100);
    noTone(p);
}
// Индикация неверного пароля 
void wrongpinindication() {
  digitalWrite(ledRed, LOW);
    tone(p, 200);
    delay(100);
    noTone(p);
    digitalWrite(ledRed, HIGH);
    tone(p, 200);
    delay(100);
    noTone(p);
    digitalWrite(ledRed, LOW);
    tone(p, 200);
    delay(150);
    noTone(p);
}


void loop()
{
  keypad.getKey();
}
void keypadEvent(KeypadEvent eKey)
{
  switch (keypad.getState())
  {
    case PRESSED:
      clickbuttonindication();
      
      int i;
      for ( i = 1; i <= 1; i++ )
     
      Serial.print("Pressed: ");
      Serial.println(eKey);
      switch (eKey)
      {
        /*
        case '#':
        break;

        case '*':
        break;
        */

        default:
          ilosc = ilosc + 1;
          password.append(eKey);
      }

      if (ilosc == 1)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("*_");
      }
      if (ilosc == 2)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("**_");
      }
      if (ilosc == 3)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("***_");
      }
      if (ilosc == 4)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("****_");
      }
      if (ilosc == 5)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("*****_");
      }
      if (ilosc == 6)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("******_");
      }
      if (ilosc == 7)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("*******_");
      }
      if (ilosc == 8)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("********");
      }
      if (ilosc == 9)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("*********");
      }
      if (ilosc == 10)
      {
        lcd.clear();
        lcd.setCursor(1, 0);
        lcd.print("   < PIN >");
        lcd.setCursor(0, 1);
        lcd.print("**********");
      }
      if (ilosc == dlugosc)
      {
        delay(250);
        checkPassword();
        ilosc = 0;
      }
  }
}


// Проверка пароля
void checkPassword()
{
  if (password.evaluate())
  {
    int i;
    for ( i = 1; i <= 2; i++ )
      ilosc = 0;
// Верный пароль: Открываем дверь, считаем 10 секунд, закрываем дверь, сбрасываем пароль, возвращаемся на экран приветствия.    
    delay(300);
    digitalWrite(ledRed, LOW);
    digitalWrite(ledGreen, HIGH);
    digitalWrite(relay, LOW);

    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print(" << UNLOCKED >>");
    lcd.setCursor(7, 0);
    lcd.write((uint8_t)0);
    
    unlockedsound();
    delay(1000);

    timer();
    
    digitalWrite(ledRed, HIGH);
    digitalWrite(ledGreen, LOW);
    digitalWrite(relay, HIGH);

    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("  << LOCKED >>");
    lcd.setCursor(7, 0);
    lcd.write((uint8_t)1);
    
    lockedsound();
    delay(1000);

    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("  :Welcome:");
    lcd.setCursor(0, 1);
    lcd.print("PLEASE ENTER PIN");
    password.reset();
  }
  else
  {
    int i;
    for ( i = 1; i <= 1; i++ )
      ilosc = 0;
// Неверный пароль: Сбрасываем пароль, пищим, считаем 10 секунд, возвращаемся на экран приветствия    
    password.reset();
    delay(300);

    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print(" WRONG PIN");
    lcd.setCursor(0, 1);
    lcd.print("<ACCESS DENIED!>");

    wrongpinindication();
    delay(1000);

    timer();

    digitalWrite(ledRed, HIGH);
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print(" TRY AGAIN");
    tone(p, 150);
    delay(500);
    noTone(p);
    delay(500);

    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("  :Welcome:");
    lcd.setCursor(0, 1);
    lcd.print("PLEASE ENTER PIN");
  }
}

 

vvadim
Offline
Зарегистрирован: 23.05.2012

зачем вам в коде столько делеев?

b707
Offline
Зарегистрирован: 26.05.2017

с таким познаниями программирования - не мудрено, что не знаете. От кода жуть берет. Почитайте какую-нибудь книжку о циклах, что ли. Что у вас происходит в строке 170, как вы думаете? Зачем вам сотня строк от 170-х до 270х?

Михаил Груничев
Offline
Зарегистрирован: 25.06.2017

По-другому пока не умею)

b707
Offline
Зарегистрирован: 26.05.2017

Михаил Груничев пишет:
По-другому пока не умею)

учитесь. Чтобы правильно вставить задержку 10 сек - нужно перписать код без делеев

Михаил Груничев
Offline
Зарегистрирован: 25.06.2017

Можешь примерно объяснить что именно выкинуть из кода и как переделать?

DIVGENY
Offline
Зарегистрирован: 23.08.2016

каждый delay() останавливает выполнение программы и контролер выполняет каждый такт одну инструкцию nop - ничего. просто подсчитайте, какое время у вас контролер делает ничего, именно делает.

тебе правильно уже обьяснили - выкинь delay() из кода, но просто замениь его уже не получится, придется переписывать код с использованием.... ну можно почитать тему рядом с твоей например

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Для начала почитайте blink without delay.

Прочувствуйте, чем оне отличается от обычного blink.

Переришите blink without delay для случая 4-5 светодиодов с разными частотами мигания.

2. Теперь потренируйтесь с реализацией в освоеной технике последовательности действий.

Выберите какую-нибудь мелодию. Достаточно 3-5 нот различной длительности.

Запрограммируйте ее при помощи освоенной техники, для чего заведите переменную состояния, которая должна соответствовать текущей ноте. Если непонятно, как, ищите в И-нете по словам "конечный автомат".

3. Проверьте, что все сделанное в п.2. использует массивы и циклы. Если нет - переделайте. Сделайте мелодию на 20-30 нот.

 

Думаю, после этого Вы способны будете нужным образом переделать Ваш скетч.