открытие замка сервомотором при последовательном приложении FRID меток.

Тема в разделе "Arduino & Shields", создана пользователем BlackWizard, 30 май 2017.

  1. BlackWizard

    BlackWizard Нуб

    Приветствую, я начал заниматься ардуино совсем недавно, решил сделать программу, которая открывает замок (поворачивает сервомотор) при последовательном правильном приложении к сенсору меток. получился вот такой код (большую часть взял отсюда http://arduino.ru/forum/proekty/rfid-zamok)
    Код (C++):
    01
    #include <Servo.h> // библиотека сервомотора
    02
    #include <SPI.h>
    03
    #include <MFRC522.h> // библиотека "RFID".
    04
    #define SS_PIN 10
    05
    #define RST_PIN 9
    06
    MFRC522 mfrc522(SS_PIN, RST_PIN);
    07
    unsigned long uidDec, uidDecTemp;  // для храниения номера метки в десятичном формате
    08
    Servo servo;
    09
    int counter = 0; // добавляем счётчик
    10
    void setup()
    11
    {
    12
      Serial.begin(9600);
    13
      Serial.println("Waiting for card...");
    14
      SPI.begin();  //  инициализация SPI / Init SPI bus.
    15
      mfrc522.PCD_Init();     // инициализация MFRC522 / Init MFRC522 card.
    16
      servo.attach(6);
    17
      servo.write(0);  // устанавливаем серву в закрытое сосотояние
    18
    }
    19
    void loop()
    20
    {
    21
        // Поиск новой метки
    22
      if ( ! mfrc522.PICC_IsNewCardPresent())
    23
      {
    24
        return;
    25
      }
    26
      // Выбор метки
    27
      if ( ! mfrc522.PICC_ReadCardSerial())
    28
      {
    29
        return;
    30
      }
    31
      uidDec = 0;
    32
      // Выдача серийного номера метки.
    33
      for (byte i = 0; i < mfrc522.uid.size; i++)
    34
      {
    35
        uidDecTemp = mfrc522.uid.uidByte[i];
    36
        uidDec = uidDec * 256 + uidDecTemp;
    37
      }
    38
      Serial.println("Card UID: ");
    39
      Serial.println(uidDec); // Выводим UID метки в консоль.
    40
      delay(1000);
    41
    if (uidDec == 3491476559) // Сравниваем Uid метки, если он равен заданому то увеличиваем счётчик на 1, если нет, то сбрасываем
    42
      {
    43
        if (counter == 0)
    44
        {
    45
          counter++;
    46
          Serial.println( counter);
    47
        }
    48
        else
    49
        {
    50
          counter =0;
    51
          Serial.println("couner reset1");
    52
        }
    53
      }
    54
      if (uidDec == 4210874628) // Сравниваем Uid метки, если он равен заданому то увеличиваем счётчик на 1, если нет, то сбрасываем
    55
      {
    56
        if (counter == 1)
    57
        {
    58
          counter++;
    59
          Serial.println( counter);
    60
        }
    61
        else
    62
        {
    63
          counter =0;
    64
          Serial.println("couner reset2");
    65
        }
    66
      }
    67
    if (counter == 2) // если счётчик равен заданному значению работает мотор
    68
      {
    69
          tone(5, 200, 500); // Делаем звуковой сигнал, Открытие
    70
          servo.write(90); // Поворациваем серву на угол 90 градусов(Отпираем какой либо механизм: задвижку, поворациваем ключ и т.д.)
    71
          delay(3000); // пауза 3 сек
    72
          tone(5, 500, 500); // Делаем звуковой сигнал,  Закрытие
    73
          servo.write(0); // механизм запирается.
    74
          counter = 0; // сбрасываем счётчик
    75
          Serial.println("couner reset3");
    76
      }
    77
    }
     
    ещё я хочу добавить таймер, который будет включаться после первого приложения метки и сбрасывать счётчик если в течении 5 секунд не приложить вторую метку, но не смог понять как это сделать.

    Очень прошу вашей помощи в этом вопросе
     
  2. rkit

    rkit Гуру

    Запоминаете время с помощью millis(). Когда нужно, получаете опять, и считаете сколько прошло.
     
  3. BlackWizard

    BlackWizard Нуб

    но millis начинает считать от начала работы программы, а есть ли метод чтобы начать отчёт от момента приложения первой метки, и если не приложить вторую. то сбросить счётчик?
     
  4. rkit

    rkit Гуру

    Есть. Описан в учебнике математики за второй класс.
     
  5. BlackWizard

    BlackWizard Нуб

    можно поконктетнее?
     
  6. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    вечер добрый. Я тоже начинающий и RFID метки еще не освоил. но в вашем случае это видится так
    Код (C++):
    uint32_t ms, ms1 = 0; //переменные для фиксации времени

    void loop() {


       ms = millis(); // после того что там у вас произошло запоминаете время
    //
       if( ( ms - ms1 ) > 5000 || ms < ms1 )
    {
           ms1 = ms;
    // сбрасываете ваш счетчик
       }
    как то так. (наверное)
     
  7. BlackWizard

    BlackWizard Нуб

    спасибо, попробую
     
  8. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    Код (C++):

    unsigned long ms1 =0;
    unsigned long ms;

    void setup() {


    }

    void loop() {
    if (   ) // произошло событие какое либо
    {
     

    ms = millis();
    if((ms - ms1)>5000)
    {
    // что то сделать
    ms1 = ms;
    }
    }
    скорее всего так правильнее
     
    Последнее редактирование: 30 май 2017
  9. Tomasina

    Tomasina Сушитель лампочек Модератор

    почти так.
    Код (C++):
    const unsigned long validID1 = 12345678; // ID первой карты
    const unsigned long validID2 = 13245678; // ID второй карты
    const unsigned int cardTimeout = 5000;   // время до сброса состояния
    byte state = 0; // текущее состояние
    // 0 - исходное состояние, ждем любую карту,
    // 1 - первая карта приложена, ждем следующую карту (не дольше cardTimeout)
    // 2 - вторая карта приложена, ждем следующую карту (не дольше cardTimeout)
    // 6 - неверная комбинация ID (пароль)
    // 7 - правильная комбинация ID (пароль)

    void setup()
    {
      Serial.begin(9600);
    }

    void loop()
    {
      static unsigned long msStart = 0;
      unsigned long msCurrent = 0;
      if (   ) // карта приложена (любая)
      {
        msStart = millis(); // запоминаем время
      }

      msCurrent = millis(); // смотрим текущее время
      if ((msCurrent - msStart) > cardTimeout) // превышен интервал ожидания
      {
        Serial.println("Timeout!"); // ворчим
        state = 0; // сбрасываем систему
      }

      switch (state) // конечный автомат состояний
      {
        case 0:
          break;

        case 1: // проверяем ID (пароль)
          if (ID == validID1)
          {
            state = 2; // карта опознана как правильная, ждем вторую карту
          }
          else state = 6;
          break;

        case 2: // проверяем ID (пароль)
          if (ID == validID2)
          {
            state = 7; // карта опознана как правильная
          }
          else state = 6;
          break;

        case 6:
          Serial.println("Invalid card."); // ругаемся
          state = 0; // сбрасываем систему
          break;

        case 7:
          Serial.println("Bingo!"); // хвалим
          // тут открываем замок
          state = 0; // сбрасываем систему
          break;
      }
    }
     
  10. qwone

    qwone Гик

    Код (C++):
    /*Servo_lock.ino
      серва  -> 5 (servo_pin)

       RFID_RC522 RST -> 9 (RST_pin)
            SDA(SS)-> 10 (SDA_pin)
            MOSI   -> 11 (MOSI_pin)
            MISO   -> 12 (MISO_pin)
            SCK    -> 13 (SCK_pin)
            3,3В   -> 3,3В
            GND    -> GND
    */

    //--------------------class Cl_Servo_lock------------------------
    #include <Servo.h> // библиотека сервомотора
    const byte angleOFF = 0;// угол закрытой сервы
    const byte angleON = 90;// угол открытой сервы
    const uint32_t lock_time = 2000; // максим время между 1 и 2  проверками
    const uint32_t ON_time = 3000; //  время в которое серва будет в состоянии ON
    class Cl_Servo_lock {
        byte pin;// нога
        Servo *myServo;// указатель на серву
        byte stat ; // состояние сервы 0 закрыта /1 первая проверка/ 2 открыта
        uint32_t past = 0;
      public:
        // указатель на следующий элемент
        Cl_Servo_lock *pnt;
        // конструктор
        Cl_Servo_lock(byte _pin): pin(_pin), pnt(NULL) {}
        // setup()
        void setup() {
          if (this->pnt != NULL) this->pnt->setup();
          myServo = new Servo;
          myServo->attach(pin);
          myServo->write(angleOFF);
          stat = 0;
        }
        // loop()
        void loop() {
          if (this->pnt != NULL) this->pnt->loop();
          if (stat == 1 && millis() - past > lock_time) stat = 0;
          if (stat == 2 && millis() - past > ON_time) {
            stat = 0;
            myServo->write(angleOFF);
          }
        }
        void ON1() {  // прошла 1 проверка
          past = millis();
          stat = 1;
        }
        void ON2() {
          if ((stat == 1) && (millis() - past <= lock_time)) { // если прошли проверку то открыть
            stat = 2;
            past = millis();
            myServo->write(angleON);
          }
        }
        void Break() {
          stat = 0;
        }
    };
    //--------------------class Cl_rfid------------------------
    #include <SPI.h>
    #include <MFRC522.h> // библиотека "RFID".
    class Cl_rfid {
        byte SS_pin;
        byte RST_pin;
        MFRC522 *Device;// указатель на устройство
        void (*Do1)(), (*Do2)(), (*Do3)();
        uint32_t com1, com2;
        uint32_t past = 0;
      public:
        // указатель на следующий элемент
        Cl_rfid *pnt;
        // конструктор
        Cl_rfid(byte SS, byte RST, uint32_t _com1, void (*_Do1)(), uint32_t _com2, void (*_Do2)(), void (*_Do3)())
          : SS_pin(SS), RST_pin(RST), com1(_com1), Do1(_Do1), com2(_com2), Do2(_Do2), Do3(_Do3), pnt(NULL) {}
        // setup()
        void setup() {
          if (this->pnt != NULL) this->pnt->setup();
          SPI.begin();  //  инициализация SPI / Init SPI bus.
          Device = new MFRC522(SS_pin, RST_pin);
          Device->PCD_Init(); // инициализация MFRC522 / Init MFRC522 card.
        }
        // loop()
        void loop() {
          if (this->pnt != NULL) this->pnt->loop();
          if (millis() - past >= 100) {
            past = millis();
            if (Device->PICC_IsNewCardPresent() && Device->PICC_ReadCardSerial()) {
              uint32_t uidDec, uidDecTemp;
              for (byte i = 0; i < Device->uid.size; i++) {
                uidDecTemp = Device->uid.uidByte[i];
                uidDec = uidDec * 256 + uidDecTemp;
              }
              Serial.println("Card UID: ");
              Serial.println(uidDec); // Выводим UID метки в консоль.
              if (uidDec ==  com1) Do1();
              else if (uidDec ==  com2) Do2();
              else Do3();
            }
          }
        }
    };
    //-----------------class Cl_sys---------------------------
    class Cl_sys {
        Cl_Servo_lock *Start_Servo = NULL;
        Cl_rfid *Start_rfid = NULL;
      public:
        Cl_sys() {}
        void Plug(Cl_Servo_lock * obj) {
          obj->pnt = Start_Servo;
          Start_Servo = obj;
        }
        void Plug(Cl_rfid * obj) {
          obj->pnt = Start_rfid;
          Start_rfid = obj;
        }
        void setup() {
          Start_Servo->setup();
          Start_rfid->setup();
        }
        void loop() {
          Start_Servo->loop();
          Start_rfid->loop();
        }
    } Sys;
    //--------------------------------------------
    Cl_Servo_lock Servo(/*пин*/5);// подключить серву-замок

    void Do_rfid1() {
      Servo.ON1();
    }
    void Do_rfid2() {
      Servo.ON2();
    }
    void Do_rfid3() {
      Servo.Break();
    }
    Cl_rfid rfid(/*SS_pin*/10,/*RST_pin*/9,
                           /*метка*/3491476559,/*обработчик*/ Do_rfid1,   //<-- тут вы впишете свои метки
                           /*метка*/4210874628,/*обработчик*/ Do_rfid2,   //<-- тут вы впишете свои метки
                           /* error_обработчик*/ Do_rfid3);      // подключить модуль
    void setup() {
      Serial.begin(9600);
      Sys.Plug(&Servo);
      Sys.Plug(&rfid);

      Sys.setup();
    }
    void loop() {
      Sys.loop();
    }
     
  11. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    Здравствуйте. пользуюсь случаем задать вопрос. что дает static в данном случае? переменная берет один раз значение у millis(); и больше не изменяется?
     
  12. DetSimen

    DetSimen Guest

    static переменные сохраняются между вызовами функции, т.е имеют последнее заданное значение, тогда как обычные локальные переменные функции имеют неопределенное значение при её вызове.
    Можно рассматривать ее как глобальную переменную, которую никто не видит, кроме функции в которой она обьявлена.
     
    CYITEP_BAC9I нравится это.
  13. Tomasina

    Tomasina Сушитель лампочек Модератор

    msStart нужна только внутри loop, поэтому нет смысла делать ее глобальной. Это позволяет нужный функционал (блок кода) перенести в другой проект простым копированием, без дробления на инициацизацию, setup и пр.

    Префикс static запрещает компилятору уничтожать содержимое этой переменной при окончании цикла loop.
     
    CYITEP_BAC9I нравится это.