JRD-100 - UHF-RFID Arduino Модуль

Reading time: 5 minutes.

17 August 2021

О модуле

JRD-100 - это модуль беспроводного считывания меток сверхвысокой частоты (UHF).

Данное решение позволяет считывать сразу до 50 радиометок в секунду. Внутренний буфер рассчитан на 200 единиц. Конструкция модуля позволяет применять передатчик мощностью 100 мВт, что обеспечивает производительную, энергоэффективную работу в радиусе более 1.5 метра.

Спецификации JRD-100

  • Расстояние считывания тегов: 1-2,5 м
  • Расстояние записи: 10 см
  • Рабочее напряжение: 3,3 - 5 В
  • Диапазон рабочих частот: 840-960 МГц
  • Выходная мощность: 18-26 dBm
  • Интерфейс: TTL UART
  • Стабильное и чувствительное считывание меток
  • Поддержка протоколов беспроводного интерфейса
    • EPCglobal UHF Class 1 Gen 2
    • ISO 18000-6C.

Сферы применения

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

Распиновка JRD-100

Подключение UHF-RFID по UART

Подключается JRD-100 “Plug & Play” через UART-интерфейс. Управление передачей данных происходит при помощи набора AT-команд.

Подключите пин к 5V, а также установите пару конденсаторов на питание.

Код

В публичном доступе нет мануалов и примеров интеграции модуля, поэтому мы сами разработали интеграцию UHF-RFID JRD-100 и Arduino.

Код работает почти на любом микроконтроллере.

В начале задан массив команд, для управления модулем. В теле программы по индексу вызываются команды:

#include <Arduino.h>
#include <HardwareSerial.h>

HardwareSerial Serial2(PA3, PA2);
bool DEBUG = true;

const uint8_t RFID_cmdnub[39][26] =
{
  {0xBB, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, 0x7E,},       //0. Hardware version 
  {0xBB, 0x00, 0x03, 0x00, 0x01, 0x01, 0x05, 0x7E,},       //1. Software version 
  {0xBB, 0x00, 0x03, 0x00, 0x01, 0x02, 0x06, 0x7E,},       //2. manufacturers  
  {0xBB, 0x00, 0x22, 0x00, 0x00, 0x22, 0x7E,},             //3. Single polling instruction 
  {0xBB, 0x00, 0x27, 0x00, 0x03, 0x22, 0x27, 0x10, 0x83, 0x7E,}, //4. Multiple polling instructions 
  {0xBB, 0x00, 0x28, 0x00, 0x00, 0x28, 0x7E,},             //5. Stop multiple polling instructions 
  { 0xBB, 0x00, 0x0C, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x20,
    0x60, 0x00, 0x30, 0x75, 0x1F, 0xEB, 0x70, 0x5C, 0x59, 0x04,
    0xE3, 0xD5, 0x0D, 0x70, 0xAD, 0x7E,
  },                        //6. Set the SELECT parameter instruction 
  {0xBB, 0x00, 0x0B, 0x00, 0x00, 0x0B, 0x7E,},              //7. Get the SELECT parameter 
  {0xBB, 0x00, 0x12, 0x00, 0x01, 0x01, 0x14, 0x7E,},        //8. Set the SELECT mode 
  { 0xBB, 0x00, 0x39, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x03,
    0x00, 0x00, 0x00, 0x08, 0x4D, 0x7E,
  },                      //9. Read label data storage area 
  { 0xBB, 0x00, 0x49, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x03,
    0x00, 0x00, 0x00, 0x04, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x71, 0x7E
  },   //10. Write the label data store 
  { 0xBB, 0x00, 0x82, 0x00, 0x07, 0x00, 0x00, 0xFF,
    0xFF, 0x02, 0x00, 0x80, 0x09, 0x7E,
  },                       //11. Lock the LOCK label data store 
  { 0xBB, 0x00, 0x65, 0x00, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0x67,
    0x7E,
  },                                                //12. Inactivate the kill tag 
  {0xBB, 0x00, 0x11, 0x00, 0x02, 0x00, 0xC0, 0xD3, 0x7E,}, //13. Set communication baud rate 
  {0xBB, 0x00, 0x0D, 0x00, 0x00, 0x0D, 0x7E,},            //14. Get parameters related to the Query command 
  {0xBB, 0x00, 0x0E, 0x00, 0x02, 0x10, 0x20, 0x40, 0x7E,}, //15. Set the Query parameter 
  {0xBB, 0x00, 0x07, 0x00, 0x01, 0x01, 0x09, 0x7E,},      //16. Set up work area 
  {0xBB, 0x00, 0x08, 0x00, 0x00, 0x08, 0x7E,},            //17. Acquire work locations 
  {0xBB, 0x00, 0xAB, 0x00, 0x01, 0x01, 0xAC, 0x7E,},      //18. Set up working channel 
  {0xBB, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0x7E,},            //19. Get the working channel 
  {0xBB, 0x00, 0xAD, 0x00, 0x01, 0xFF, 0xAD, 0x7E,},      //20. Set to automatic frequency hopping mode
  { 0xBB, 0x00, 0xA9, 0x00, 0x06, 0x05, 0x01, 0x02,
    0x03, 0x04, 0x05, 0xC3, 0x7E,
  },                             //21. Insert the working channel 
  {0xBB, 0x00, 0xB7, 0x00, 0x00, 0xB7, 0x7E,},            //22. Acquire transmitting power 
  {0xBB, 0x00, 0xB6, 0x00, 0x02, 0x07, 0xD0, 0x8F, 0x7E,}, //23. Set the transmitting power 
  {0xBB, 0x00, 0xB0, 0x00, 0x01, 0xFF, 0xB0, 0x7E,},      //24. Set up transmitting continuous carrier 
  {0xBB, 0x00, 0xF1, 0x00, 0x00, 0xF1, 0x7E,},            //25. Gets the receiving demodulator parameters 
  {0xBB, 0x00, 0xF0, 0x00, 0x04, 0x03, 0x06, 0x01, 0xB0, 0xAE, 0x7E,}, //26. Set the receiving demodulator parameters 
  {0xBB, 0x00, 0xF2, 0x00, 0x00, 0xF2, 0x7E,},            //27. Test the RF input block signal 
  {0xBB, 0x00, 0xF3, 0x00, 0x00, 0xF3, 0x7E,},            //28. Test the RSSI signal at the RF input 
  {0x00},
  {0xBB, 0x00, 0x17, 0x00, 0x00, 0x17, 0x7E,},            //30. Module hibernation 
  {0xBB, 0x00, 0x1D, 0x00, 0x01, 0x02, 0x20, 0x7E,},      //31. Idle hibernation time of module
  {0xBB, 0x00, 0x04, 0x00, 0x03, 0x01, 0x01, 0x03, 0x0C, 0x7E,}, //32. The IDLE mode 
  {0xBB, 0x00, 0xE1, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xE4, 0x7E,}, //33.NXP G2X label supports ReadProtect/Reset ReadProtect command 
  {0xBB, 0x00, 0xE3, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xE7, 0x7E,}, //34. The NXP G2X label supports the CHANGE EAS directive 
  {0xBB, 0x00, 0xE4, 0x00, 0x00, 0xE4, 0x7E,},            //35. The NXP G2X tag supports the EAS_ALARM directive 
  {0xBB, 0x00, 0xE0, 0x00, 0x06, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xE4, 0x7E,}, //36.NXP G2X label 16bits config-word 
  { 0xBB, 0x00, 0xE5, 0x00, 0x08, 0x00, 0x00, 0xFF,
    0xFF, 0x01, 0x01, 0x40, 0x00, 0x2D, 0x7E,
  },                   //37.Impinj Monza 4 Qt tags support Qt instructions 
  { 0xBB, 0x00, 0xD3, 0x00, 0x0B, 0x00, 0x00, 0xFF,
    0xFF, 0x01, 0x03, 0x00, 0x00, 0x01, 0x07, 0x00, 0xE8, 0x7E,
  },   //38.The BlockPermalock directive permanently locks blocks of a user's Block 

};

void Sendcommand(uint8_t com_nub)
{
  uint8_t b = 0;
  while (RFID_cmdnub[com_nub][b] != 0x7E)
  {
    Serial2.write(RFID_cmdnub[com_nub][b]);
    if(DEBUG) {
      Serial.print(" 0x");
      Serial.print(RFID_cmdnub[com_nub][b], HEX);
    }
    b++;
  }
  Serial2.write(0x7E);
  Serial2.write("\n\r");
  Serial.println();
}
uint8_t DATA_I[256];

void Readcallback()
{
  uint8_t DATA_I_NUB = 0;
  while(!Serial2.available());
  while (Serial2.available())
  {
    delay(2);
    DATA_I[DATA_I_NUB] = Serial2.read();
    if (DEBUG == 1)
    {
      if(DATA_I[DATA_I_NUB] < 16) {
        Serial.print(" 0x0");
      } else {
        Serial.print(" 0x");
      }
      Serial.print(DATA_I[DATA_I_NUB], HEX);
    }
    DATA_I_NUB++;
  }
  Serial.println();
}
/* code */
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("begin of UHF-Reader");
  Serial2.begin(115200);

}

void loop() {
  // put your main code here, to run repeatedly:
  for (size_t i = 0; i < 10; i++) {
    Serial.println("Single polling:");
    Sendcommand(3);
    Serial.println("Recieving:");
    Readcallback();
    // Serial.println();
    Serial.println("Requesting data:");
    Sendcommand(9);
    Serial.println("Recieving data:");
    Readcallback();
    delay(3000);
    Serial.println();
  }
  // Serial.println("End of programm");
  // delay(5000); 
}