Как работать с несколькими RFID-ридерами RC522?

Тема в разделе "Arduino & Shields", создана пользователем Vittorio, 23 мар 2015.

  1. Vittorio

    Vittorio Нуб

    Можно ли одним МК рулить несколькими ридерами? В примерах такого не нашел, а по схеме подключения непонятно как задействовать еще несколько.
    Замок один, а ридеров надо три (два по обеим сторонам двери и третий у пульта охраны). Расстояние от МК не более 2 метров до каждого.
     
  2. M0ln1a

    M0ln1a Гик

    Посмотри этот обзор, может поможет... (Обзор от Амперки)
     
  3. M0ln1a

    M0ln1a Гик

    Несколько карточек - Один ридер
     
  4. Unixon

    Unixon Оракул Модератор

    Оно работает по SPI, значит SCK, MISO, MOSI - общие для всех, а SS - у каждого свой. Если расстояние между ридерами большое, тогда лучше к каждому свой контроллер, а связь по RS485.
     
    Roon Booh нравится это.
  5. Tomasina

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

    а ему надо несколько ридеров и несколько карточек.
     
  6. Vittorio

    Vittorio Нуб

    А вот и не получается :(
    Видимо, адрес у них одинаковый, при подключении двух RC522 (SS - у каждого свой пин), карточки не читаются.
    Как еще можно их использовать одновременно? Искать i2c вариант?
    Или подключать программно (только один одновременно), читать, затем переключаться на следующий? Тогда как? Отрывание ноги 3,3 В не помогает (паразитное питание с линий данных). Помогает лишь отрывание GND (на платке индикатор питания начинает мерцать, мне это не нравится).
     
  7. geher

    geher Гуру

    "Адрес одинаковый" тут точно ни при чем. В управлении по SPI "адрсация" идет при помощи пина SS (HIGH - отключено, LOW - включено).
    Тут могут быть другие причины.
    1. Требуется "руками" выставлять состояние на пинах SS.
    2. Элементарно не хватает питания на оба ридера одновременно.
    3. Библиотека (если она, конечно, вообще есть) "криво" написана. Тут возможны свои варианты: SS прибит гвоздями, должен быть конкретный пин, библиотека не позволяет одновременно сосуществовать нескольким экземплярам устройства одновременно, используется какой-то ресурс (вроде таймера для периодической проверки), который не получается разделить на два устройства (например, инициируем второе устройство - теряется таймер для первого). Тут надо смотреть реализацию библиотеки, чтобы понять.
    4. "Кривая" железная реализация: состояние SS пина вообще не учитывается, ридеры всегда активны (встречал такое у других устройств).

    Может еще какая экзотическая причина, вроде взаимовлияния устройств за счет утечек тока через линии SPI. Но это скорее вроде из серии "диких идей", которые приходят в голову, когда все стандартное перепробовано не один раз.

    А рубить можно все ноги (6 шт, начиная с данных), хотя это порождает избыточные элементы в схеме.
    Только если имеет место пункт 1 в варианте невозможности одновременного сосуществования двух устройств, то может и не помочь.
     
    Последнее редактирование: 29 мар 2015
  8. Vittorio

    Vittorio Нуб

    вот мой код, где сделано переключение SS перед чтением:
    Код (Text):
    //YWROBOT
    //Compatible with the Arduino IDE 1.0
    //Library version:1.1

    #if defined(ARDUINO) && ARDUINO >= 100
    #define printByte(args)  write(args);
    #else
    #define printByte(args)  print(args,BYTE);
    #endif

    /*
    * MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
    * The library file MFRC522.h has a wealth of useful info. Please read it.
    http://mac86project.altervista.org/
    ----------------------------------------------------------------------------- Nicola Coppola
    * Typical pin layout used:
    * -----------------------------------------------------------------------------------------
    *            MFRC522      Arduino      Arduino  Arduino    Arduino          Arduino
    *            Reader/PCD  Uno          Mega      Nano v3    Leonardo/Micro  Pro Micro
    * Signal      Pin          Pin          Pin      Pin        Pin              Pin
    * -----------------------------------------------------------------------------------------
    * RST/Reset  RST          9            5        D9        RESET/ICSP-5    RST
    * SPI SS      SDA(SS)      10            53        D10        10              10
    * SPI MOSI    MOSI        11 / ICSP-4  51        D11        ICSP-4          16
    * SPI MISO    MISO        12 / ICSP-1  50        D12        ICSP-1          14
    * SPI SCK    SCK          13 / ICSP-3  52        D13        ICSP-3          15
    *
    * The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com.
    */

    #include <SPI.h>
    #include <MFRC522.h>

    /* Set your new UID here! */
    #define NEW_UID {0xDE, 0xAD, 0xBE, 0xEF}
    byte SS_PIN = 10;
    #define RST_PIN 9

    MFRC522 mfrc522(SS_PIN, RST_PIN);        // Create MFRC522 instance.
    MFRC522::MIFARE_Key key;

    void setup(){
      Serial.begin(9600);        // Initialize serial communications with the PC
      pinMode(4, OUTPUT);    // SS для первого считывателя
      pinMode(10, OUTPUT);   // SS для второго считывателя
      while (!Serial);          // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
      SPI.begin();              // Init SPI bus
      mfrc522.PCD_Init();        // Init MFRC522 card
      Serial.println(F("Warning: this example overwrites the UID of your UID changeable card, use with care!"));

      // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
      for (byte i = 0; i < 6; i++) {
        key.keyByte[i] = 0xFF;
      }
      delay(3000);
      Serial.println("Ready...");
    }


    // But of course this is a more proper approach
    void loop() {
      // Look for new cards, and select one if present
      if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
        delay(50);
        return;
      }

      // Now a card is selected. The UID and SAK is in mfrc522.uid.

      // Dump UID
      Serial.print(F("Card ID:"));
      for (byte i = 0; i < mfrc522.uid.size; i++) {
        Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522.uid.uidByte[i], HEX);
      }
      Serial.println();

      delay(1000);

      // Подключение нескольких устройств по SPI
      // Да все ясно SCK MISO MOSI паралельно, а CS отдельно. Просто нужно перед обращением к устройству дергать его  CS (установив на всех 1 на нужном 0).
      // http://arduino.ru/forum/obshchii/podklyuchenie-neskolkikh-ustroistv-po-spi#comment-35811
      digitalWrite(SS_PIN, HIGH);
      if (SS_PIN != 4) SS_PIN = 4;
      else SS_PIN = 10;
      digitalWrite(SS_PIN, LOW);
    }
    При отключении любого из считывателей все работает, вместе не хотят.
     
  9. geher

    geher Гуру

    А если попробовать объявить несколько экземпляров класса для ридера?
    Примерно так:
    #define RST_PIN 9
    #define SS_PIN 10
    #define SS_PIN2 4
    MFRC522 mfrc522(SS_PIN, RST_PIN);
    MFRC522 mfrc522_2(SS_PIN2, RST_PIN);

    Естественно, в сетапе надо для каждого сделать инициализацию.
    mfrc522.PCD_Init();
    mfrc522_2.PCD_Init();
    а потом читать по очереди, обращаясь к разным экземплярам класса.
    Если библиотека написана правильно, должно прокатить.
    Правда еще вопрос с RST_PIN. Для чего он вообще, и можно ли использовать общий для двух ридеров?
     
  10. Vittorio

    Vittorio Нуб

    Код (Text):
    //YWROBOT
    //Compatible with the Arduino IDE 1.0
    //Library version:1.1

    #if defined(ARDUINO) && ARDUINO >= 100
    #define printByte(args)  write(args);
    #else
    #define printByte(args)  print(args,BYTE);
    #endif

    /*
    * MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
    * The library file MFRC522.h has a wealth of useful info. Please read it.
    <a href="http://mac86project.altervista.org/" rel="nofollow">http://mac86project.altervista.org/</a>
    ----------------------------------------------------------------------------- Nicola Coppola
    * Typical pin layout used:
    * -----------------------------------------------------------------------------------------
    *            MFRC522      Arduino      Arduino  Arduino    Arduino          Arduino
    *            Reader/PCD  Uno          Mega      Nano v3    Leonardo/Micro  Pro Micro
    * Signal      Pin          Pin          Pin      Pin        Pin              Pin
    * -----------------------------------------------------------------------------------------
    * RST/Reset  RST          9            5        D9        RESET/ICSP-5    RST
    * SPI SS      SDA(SS)      10            53        D10        10              10
    * SPI MOSI    MOSI        11 / ICSP-4  51        D11        ICSP-4          16
    * SPI MISO    MISO        12 / ICSP-1  50        D12        ICSP-1          14
    * SPI SCK    SCK          13 / ICSP-3  52        D13        ICSP-3          15
    *
    * The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com.
    */

    #include <SPI.h>
    #include <MFRC522.h>

    /* Set your new UID here! */
    #define NEW_UID {0xDE, 0xAD, 0xBE, 0xEF}
    #define SS1_PIN 4
    #define SS2_PIN 10
    #define RST_PIN 9

    MFRC522 mfrc522_1(SS1_PIN, RST_PIN);        // Create MFRC522 instance.
    MFRC522 mfrc522_2(SS2_PIN, RST_PIN);        // Create MFRC522 instance.
    MFRC522::MIFARE_Key key1;
    MFRC522::MIFARE_Key key2;

    void setup(){
      Serial.begin(9600);        // Initialize serial communications with the PC
      pinMode(4, OUTPUT);    // SS для первого считывателя
      pinMode(10, OUTPUT);  // SS для второго считывателя
      while (!Serial);          // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
      SPI.begin();              // Init SPI bus
      mfrc522_1.PCD_Init();        // Init MFRC522 card
      mfrc522_2.PCD_Init();        // Init MFRC522 card
      Serial.println(F("Warning: this example overwrites the UID of your UID changeable card, use with care!"));

      // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
      for (byte i = 0; i < 6; i++) {
        key1.keyByte[i] = 0xFF;
        key2.keyByte[i] = 0xFF;
      }
      delay(3000);
      Serial.println("Ready...");
    }


    // But of course this is a more proper approach
    void loop() {
      // Look for new cards, and select one if present
      if ( ! mfrc522_1.PICC_IsNewCardPresent() || ! mfrc522_1.PICC_ReadCardSerial() || ! mfrc522_2.PICC_IsNewCardPresent() || ! mfrc522_2.PICC_ReadCardSerial() ) {
        delay(50);
        return;
      }

      // Now a card is selected. The UID and SAK is in mfrc522.uid.

      // Dump UID
      Serial.print(F("Card1 ID:"));
      for (byte i = 0; i < mfrc522_1.uid.size; i++) {
        Serial.print(mfrc522_1.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522_1.uid.uidByte[i], HEX);
      }
      Serial.println();

      Serial.print(F("Card2 ID:"));
      for (byte i = 0; i < mfrc522_2.uid.size; i++) {
        Serial.print(mfrc522_2.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522_2.uid.uidByte[i], HEX);
      }
      Serial.println();

      delay(1000);

    /*
      // Подключение нескольких устройств по SPI
      // Да все ясно SCK MISO MOSI паралельно, а CS отдельно. Просто нужно перед обращением к устройству дергать его  CS (установив на всех 1 на нужном 0).
      // <a href="http://arduino.ru/forum/obshchii/podklyuchenie-neskolkikh-ustroistv-po-spi#comment-35811" rel="nofollow">http://arduino.ru/forum/obshchii/podklyuchenie-neskolkikh-ustroistv-po-spi#comment-35811</a>
      digitalWrite(SS_PIN, HIGH);
      if (SS_PIN != 4) SS_PIN = 4;
      else SS_PIN = 10;
      digitalWrite(SS_PIN, LOW);
      */
    }
    Никакой реакции :( Теперь даже один подключенный считыватель не работает. Видимо, эти имена жестко заданы в библиотеке и менять их нельзя.
     
    Последнее редактирование: 29 мар 2015
  11. ostrov

    ostrov Гуру

    Тоже попробовал прицепить несколько RFID ридеров к одной Меге, а если точнее, то три. С наскоку победить не удалось. Смотрел что происходит анализатором: ножки SS Мега дергает у каждого ридера по очереди, как и положено, но несмотря на это отвечают все одновременно. Удалив два из трех и посмотрев что происходит, я убедился в том, что правил приличий у ридера нет совсем, он действительно отвечает на любой запрос MOSI вне зависимости от того его SS теребится в данный момент или нет.

    Думаю, что проблема аппаратная, любо в прошивке ридеров, рыться в библиотеке бесполезно. Как исправить в домашних условиях не представляю. Есть идея отключать их по очереди от земли (так как от питания отключать бесполезно, они питаются паразитно от SPI), таким образом затыкая ненужные в данный момент. Не знаю только насколько быстро это можно делать не повредив модули и сколько времени занимает запуск каждого. Ну или подключать каждый ридер к отдельному МК, что несомненно усложнит конструкцию.
     
  12. Unixon

    Unixon Оракул Модератор

    Берете одну или несколько 74HC405x и мультиплексируете ими весь SPI.
     
  13. ostrov

    ostrov Гуру

    В идеале бы взять правильные ридеры, которые отвечают на SPI только когда их спрашивают, но наверное таких не достать. Мультеплексировать SPI желанием не горю, но видно придется. Или делать свой МК к каждому ридеру.
     
  14. Andrey_K

    Andrey_K Нуб

    На чем остановились все таки? Сейчас тоже столкнулся с проблемой подключения двух и более RFID модулей к меге.
    Очень хотелось бы получить совет от Вас.
     
  15. ostrov

    ostrov Гуру

    Пока остановился на том, что для каждого ридера делаю устройство с Атмегой8 (ориентировочную схему см. ниже), в ней уже происходит сравнение и выдача результатов на Мегу. К сожалению, работать по очереди ридеры так и не хотят, наверное потому что китайские и сделаны не совсем так как задумывалось изначально. В итоге хочу попробовать и переходить на ридеры использующие UART.

    [​IMG]
     
  16. Ed209

    Ed209 Нуб

    Rc522 работает по spi, i2c и uart. Обычно у китайских братьев платы разведены под spi. Я сразу ориентировался использовать uart через rs485 для увеличения дальности. Несколько на одну шину было не критично, но желательно, подумал если работает по i2c то наверняка имеет какой либо адрес, и может его можно будет сменить и повесить несколько на одну шину. Но когда я им занялся и сразу перевел на работу через uart, обломался. Запрос ведется сразу к регистрам без указания какого либо адреса устройства. Придется покурить спецификацию еще тщательнее, может тут кто чего подскажет.
     
  17. Ed209

    Ed209 Нуб

    В итоге решил на каждый rc522 использовать отдельную пару драйверов rs485, а у контроллера все их запараллелить и включать по отдельности тот с которым надо поговорить в данный момент времени. Получится схема типа звезда, хотя ранее я предполагал последовательное подключение, но для меня это не критично. Покурив на ночь спецификацию, выяснил что адресация разных устройств возможна только по i2c, с назначением каждому своего адреса, но на относительно большие расстояния этот вариант не очень подходит, т.к. я уже давно заказал драйвера rs485.
     
  18. Roon Booh

    Roon Booh Нерд

    Привет ребята, помните поговорку - "Дело было не в бабине?"
    Я решил вашу проблему!

    Вот что надо:

    1- подойти к зеркалу.
    2- посмотреть в зеркало на свое отражение.
    3- осознать что в зеркале вы видите ленивую жопу, не желающую думать.
    4- открыть самоучитель по C++.
    5- прочитать эту книгу.
    6- посмотреть мой пример.
    7- понять в чем ваша ошибка.
    8- повторить п1 п2,
    9- понять что вы теперь не ленивая жопа.
    10 - осознать что мир стал лучше.
    *11 - заказать у меня гаджет =) (по желанию)

    пример кода
    Код (C++):

    #include <SPI.h>
    #include <RFID.h>

    #define SS_PIN 53
    #define RST_PIN 5

    RFID rfid_1(SS_PIN, RST_PIN);
    RFID rfid_2(48, RST_PIN);
    RFID rfid_3(49, RST_PIN);

    // Setup variables:
        int serNum0;
        int serNum1;
        int serNum2;
        int serNum3;
        int serNum4;

    void setup()
    {
      Serial.begin(9600);
      SPI.begin();
      rfid_1.init();
      rfid_2.init();
      rfid_3.init();

    }

    void loop()
    {
     
        // Если обнаружена карта
        if (rfid_1.isCard()) {
            // Считываем адрес
            if (rfid_1.readCardSerial()) {
              // Выводим его в порт в десятичном представлении
              Serial.println("Card number:");
              Serial.print(rfid_1.serNum[0],DEC);
              Serial.print(", ");
            Serial.print(rfid_1.serNum[1],DEC);
              Serial.print(", ");
            Serial.print(rfid_1.serNum[2],DEC);
              Serial.print(", ");
            Serial.print(rfid_1.serNum[3],DEC);
              Serial.print(", ");
            Serial.print(rfid_1.serNum[4],DEC);
              Serial.println(" ");
            }    
        }
        rfid_1.halt();
     
        // Если обнаружена карта
        if (rfid_2.isCard()) {
            // Считываем адрес
            if (rfid_2.readCardSerial()) {
              // Выводим его в порт в десятичном представлении
              Serial.println("Card number:");
              Serial.print(rfid_2.serNum[0],DEC);
              Serial.print(", ");
            Serial.print(rfid_2.serNum[1],DEC);
              Serial.print(", ");
            Serial.print(rfid_2.serNum[2],DEC);
              Serial.print(", ");
            Serial.print(rfid_2.serNum[3],DEC);
              Serial.print(", ");
            Serial.print(rfid_2.serNum[4],DEC);
              Serial.println(" ");
            }    
        }
        rfid_2.halt();
     
        // Если обнаружена карта
        if (rfid_3.isCard()) {
            // Считываем адрес
            if (rfid_3.readCardSerial()) {
              // Выводим его в порт в десятичном представлении
              Serial.println("Card number:");
              Serial.print(rfid_3.serNum[0],DEC);
              Serial.print(", ");
            Serial.print(rfid_3.serNum[1],DEC);
              Serial.print(", ");
            Serial.print(rfid_3.serNum[2],DEC);
              Serial.print(", ");
            Serial.print(rfid_3.serNum[3],DEC);
              Serial.print(", ");
            Serial.print(rfid_3.serNum[4],DEC);
              Serial.println(" ");
            }    
        }
        rfid_3.halt();
    }
     
     
    ostrov, noevile, ИгорьК и ещё 1-му нравится это.
  19. ИгорьК

    ИгорьК Гуру

    Уникальный тезис. Просто открытие. Не все до него доходят, поверьте.
     
    noevile и Roon Booh нравится это.
  20. ostrov

    ostrov Гуру

    Если жопа действительно не ленивая, то хорошо бы переписать программу так, чтобы все три (или больше если надо) ридера считывались в цикле, а не трижды повторять одинаковый по сути код. Надо лишь создать массив экземпляров класса RFID, что несомненно описано в самоучителе С++. А пока налицо только эйфория от освоения готовой библиотеки RFID.h, что к знанию С++ имеет опосредованное отношение.

    Да, и еще неприятность. Не все ридеры реально поддерживают активацию на ноге SS. У меня вот из четырех партий за всю историю так работали только из одной. Кроме того, не все ридеры, даже поддерживающие SS-активацию, работают стабильно в цепочке числом более 5. Во всяком случае те, что сделаны дядюшкой Ляо (99.9% из доступных у нас). Было бы хорошо, если было бы так просто, проблема решилась бы еще полгода назад.

    И вот это в программе вашей явно лишнее:
    Код (C++):
        int serNum0;
        int serNum1;
        int serNum2;
        int serNum3;
        int serNum4;
     
    Последнее редактирование: 3 май 2016