Как установить время на 15 секунд

Если пользователь использовал один пароль после закрытия сервопривода, пароль будет действителен в течение 15 секунд, а затем не будет работать. Остальные 9 будут аналогичны

Вот код, который мне нужен для установки

int locker = 13;
int lockerState = 0;
const int buzzer = 49;
String readString;

#include <Servo.h>
Servo myservo;
int pos = 0;

void setup() {
  Serial.begin(9600);
  pinMode(locker, OUTPUT);
  pinMode(buzzer, OUTPUT);
  myservo.attach(9);
}

void loop() {
  lockerState = digitalRead(locker);
  while (Serial.available()) {
    delay(3);  
    char c = Serial.read();
    readString += c;
  }

  if (readString.length() >0) {
    Serial.println(readString);
    if ((readString == "2028") || (readString =="1234") || (readString =="1294") || (readString =="4795") || (readString =="5651") || (readString =="7616") || (readString =="5648") || (readString =="1487") || (readString =="7095") || (readString =="2554"))
    {
      digitalWrite(locker, HIGH);
      for (pos = 0; pos <= 180; pos += 1) {
      myservo.write(pos);
      delay(30);
      }
      delay(5000);
      digitalWrite(locker, LOW);
      /* for (pos = 180; pos >= 1; pos -= 1) {
      myservo.write(pos);
      delay(30);
      } */
      readString="";
    }
      /* else if (readString == "proceed") {
        digitalWrite(locker, HIGH);
        for (pos = 0; pos <= 180; pos += 1) {
        myservo.write(pos);
        delay(30);
        }
      digitalWrite(locker, LOW);
      readString="";
      } */
      if (readString == "decline") {
         digitalWrite(locker, HIGH);
         for (pos = 180; pos >= 0; pos -= 1) {
         myservo.write(pos);
         delay(30);
         }
      digitalWrite(locker, LOW);
      readString="";
      }

    else {
      tone(buzzer, 500);
      delay(1000);
      noTone(buzzer);
      delay(1000);
      readString="";
  }
 }
}

, 👍0


1 ответ


1

В программировании во многих случаях проектирование структур данных важнее, чем сам код. Если у вас есть структура данных, которая имеет смысл, код работает очень естественно. Я думаю, что это один из тех случаях, поэтому давайте начнем с рассмотрения того, какие данные вам нужно хранить для каждого ваших паролей:

  • сам пароль (назовем его кодом)
  • использовался ли он когда-либо, и если да, то истек ли срок его действия.
  • если он использовался, но срок его действия еще не истек: когда он использовался для первый раз

Это можно сохранить в объекте со следующими полями данных:

const char * const code;
enum { UNUSED, USED, EXPIRED } status;
uint32_t first_use;  // действует, если статус == ИСПОЛЬЗУЕТСЯ

Теперь подумайте, какие действия вы хотите выполнить с таким пароль:

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

Исходя из этих требований, я предлагаю следующий класс:

const uint32_t PASS_LIFE_TIME = 15000;

class Password {
public:
    Password(const char *c)
        : code(c), status(UNUSED) {}
    bool matches(const char *entry) {
        return strcmp(code, entry) == 0;
    }
    void update() {  // срок действия истекает, если это необходимо
        if (status == USED && millis() - first_use > PASS_LIFE_TIME) {
            status = EXPIRED;
        }
    }
    bool use() {  // возвращает true в случае успеха
        if (status == UNUSED) {
            status = USED;
            first_use = millis();
        }
        update();
        return status != EXPIRED;
    }
private:
    const char * const code;
    enum { UNUSED, USED, EXPIRED } status;
    uint32_t first_use;  // действует, если статус == ИСПОЛЬЗУЕТСЯ
};

Теперь вам нужно хранить все пароли в массиве и пару функции для работы с коллекцией паролей в целом:

const int PASS_COUNT = 10;

Password passwords[PASS_COUNT] = { "2028", "1234", "1294",
    "4795", "5651", "7616", "5648", "1487", "7095", "2554" };

void update_all_passwords()
{
    for (int i = 0; i < PASS_COUNT; i++)
        passwords[i].update();
}

// Возвращает true в случае успеха и использует соответствующий пароль.
bool try_entry(const char * entry)
{
    for (int i = 0; i < PASS_COUNT; i++)
        if (passwords[i].matches(entry))
            return passwords[i].use();
    return false;  // совпадение не найдено
}

Функция update_all_passwords() предназначена для вызова при каждом итерация loop(). Это может показаться лишним, так как пароль обновляется. всякий раз, когда вы пытаетесь его использовать. Однако без регулярного обновления использованный пароль можно было повторно использовать через 49,7 дней из-за millis() опрокидывание.

Теперь в вашей программе вам просто нужно:

  1. Поместите вызов update_all_passwords() в начале loop()
  2. Замените большое условие, проверяющее действительный пароль, на if (try_entry(readString.c_str()))
,

Хороший ответ! Я бы добавил, что использовать delay() не рекомендуется. Думаю, стоит упомянуть, что стиль кодирования из примера BlinkWithoutDelay намного лучше (который вы уже использовали в своем коде, а ОП — нет), и он особенно поможет при добавлении в код дополнительных функций., @chrisl