Замок на RFID

Тема в разделе "Arduino & Shields", создана пользователем DIYMan, 8 авг 2016.

  1. DIYMan

    DIYMan Guest

    Предисловие: чем меньше люди будут разбираться в теме - тем больше у меня будет работы :D

    Задача: вывалить практически готовый скетч, чтобы махом решить две проблемы: первая - вынесена в предисловие, вторая - чтобы унять жажду быстрого результата у источников первой проблемы :D

    Железо: ардуина + RFID RDM6300, тот, который выплёвывает данные поднесённого ключа в UART и прост в общении, как рубь с полтиной.

    Реализация (комментарии присутствуют, на случай - а ну вдруг кто-то всё-таки захочет вкурить, как оно работает? :D):

    Код (C++):
    #include <SoftwareSerial.h>

    // на каких пинах подключен RFID-считыватель
    SoftwareSerial sSerial(8,9);

    // тестовый пин, на котором будем включать светодиод, говорящий о том, что система закрыта/открыта
    const int ledPin = 13;

    // флаг, что юзер залогинен
    bool isUserLoggedIn = false;

    // длина ключа RFID-метки
    const byte RFID_TAG_LENGTH = 14;

    // сюда будем читать ключ
    byte enteredKey[RFID_TAG_LENGTH] = {0};
    // здесь будем хранить информацию о последнем сравненном ключе, чтобы избежать повторного выполнения кода
    byte lastKey[RFID_TAG_LENGTH] = {0};

    // массив ключей, которые нам известны
    byte knownKeys[][RFID_TAG_LENGTH]=
    {
      { 0x02, 0x30, 0x39, 0x30, 0x30, 0x34, 0x46, 0x35, 0x33, 0x46, 0x33, 0x45, 0x36, 0x03 }
    , { 0x02, 0x30, 0x46, 0x30, 0x30, 0x36, 0x31, 0x42, 0x46, 0x39, 0x32, 0x34, 0x33, 0x03 }
    // сюда дописывать ключи
    , {0,0,0,0,0,0,0,0,0,0,0,0,0,0} // заглушка, признак окончания массива ключей  
    };

    byte writePos = 0; // позиция записи
    unsigned long eraseKeyTimer = 0; // таймер присутствия ключа в считывателе
    const unsigned int waitEraseInterval = 1000; // через сколько миллисекунд можно повторно приложить ключ

    void setup()
    {
      Serial.begin(57600);
      sSerial.begin(9600);

      pinMode(ledPin,OUTPUT);
      digitalWrite(ledPin,LOW);

      Serial.println(F("System ready, locked."));

    }
    // сравниваем ключи на совпадение
    bool sameKey(byte* k1, byte* k2)
    {
      return !memcmp(k1,k2,RFID_TAG_LENGTH);
    }
    // проверяем - известен ли нам ключ
    bool isKnownKey(byte* key)
    {
      byte pos = 0;
      while(1)
      {
        if(!memcmp(knownKeys[pos],key,RFID_TAG_LENGTH)) // ключ совпал
        {
          return true;
        }
       
        if(knownKeys[pos][0] == 0) // дошли до конца массива известных ключей
          break;
        pos++;
      }
      return false;
    }
    void loop()
    {

       
        while(sSerial.available())
        {
         // есть данные от ключа, считываем их
           enteredKey[writePos++] = sSerial.read();
           if(writePos >= RFID_TAG_LENGTH)
           {
             // прочитали весь ключ, проверяем его
             writePos = 0;
             if(isKnownKey(enteredKey)) // ключ известен
             {
                if(!sameKey(enteredKey,lastKey)) // если только его не продолжают держать у считывателя
                {
                  // пишем, что мы узнали ключ
                  Serial.println(F("Key known :)))"));

                  // меняем статус системы
                  isUserLoggedIn = !isUserLoggedIn;
                  digitalWrite(ledPin,isUserLoggedIn ? HIGH: LOW);
                  Serial.println(isUserLoggedIn ? F("System unlocked.") : F("System locked."));
                }
             }
             else // ключ неизвестен
             {
              // если только ключ не тот же, т.е. если его не держат на считывателе
              if(!sameKey(enteredKey,lastKey))
                Serial.println(F("Key unknown :("));
             }
             // запоминаем, какой ключ на считывателе
             memcpy(lastKey,enteredKey,RFID_TAG_LENGTH);

            // обновляем таймер присутствия ключа в считывателе
             eraseKeyTimer = millis();
           } // if(writePos >= RFID_TAG_LENGTH)
         
        } // while
       

      // если ключ отсутствует больше N секунд - стираем информацию о последнем введённом ключе
      if(millis() - eraseKeyTimer > waitEraseInterval)
      {
         memset(lastKey,0,RFID_TAG_LENGTH);
      }
     
     
      /*
       // тестовый код для считывания поднесённых ключей
      if(sSerial.available())
      {
        while(sSerial.available())
        {
          char ch = sSerial.read();
          Serial.print("0x");
          if(ch < 16)
            Serial.print('0');
          Serial.print(ch, 16);
          Serial.print(' ');
         
        }

        Serial.println();
      }
      */


    }
     
    Пользуйтесь, никогда не жалко поделиться набросками ;)
     
    Ermine882, vvr, Vetrinus и 3 другим нравится это.
  2. Airbus

    Airbus Радиохулиган Модератор

    Хорошо сделано!Респект!Надо попробовать сделать на RFID RDM6300.Раньше делал на RC522
     
  3. ostrov

    ostrov Гуру

    Этот ридер действительно прост как огурец (не соленый), особенно в сравнении с RC522. Плюет ключи в виде строки в сериал порт и все. Если экзотики от ридера не нужно, например хранения данных в брелоках, то он даже лучше. Можно просто сравнивать как текст с эталоном с помощью какого нибудь string.compareTo(), благо громадной скорости от этой процедуры не требуется.

    Вот единственное, что мне не понравилось в нем по сравнению с RC522 - хрупкость. Нужно как можно быстрее зафиксировать его на рабочей поверхности пока проводки не отвалились. А то что радиус обнаружения метки мал, так этом в каком то смысле даже плюс.
     
  4. ostrov

    ostrov Гуру

    Зачем плодить сущности, у гугла полно примеров на эту тему.
     
  5. babajaga

    babajaga Нуб

    А, скетч-то не рабочий. Повторил - не работает, хотя комплимируется.
     
  6. b707

    b707 Гуру

    и чего все тащатся от скрипок ... я попробовал поиграть - звук ужасный...
     
    Feofan, DetSimen, Vovka и ещё 1-му нравится это.
  7. babajaga

    babajaga Нуб

    Если можешь - помоги (со скетчем).Скрипку больше не бери, попробуй барабаны!
     
  8. b707

    b707 Гуру

    это
    DIYMan,
    его критиковать нельзя