wtorek, 30 maja 2017

[31] Arduino - Układ RFID RC522, sterowanie przekaźnikami

W tym poście chciałbym opisać projekt sterowania układem przekaźnikami za pomocą kart Mifare odczytywanych przez moduł z układem RC522. Pozwala on na odczytywanie jak i zapisywanie danych na kartę na częstotliwości 13,56 MHz. Komunikacja z nim odbywa się przez interfejs SPI. Układ zasilany jest napięciem 3.3V. Nie ma problemów z podłączeniem go do Arduino Uno, zasilanego z 5V.

Podłączenie:


Układ został podłączony do płytki w następujący sposób:

Przekaźniki:
  • Przekaźnik 1 - pin 7 Arduino
  • Przekaźnik 2 - pin 8 Arduino

Moduł MF RC522:
  • SPI MOSI - pin 11 Arduino
  • SPI MISO - pin 12 Arduino
  • SPI SCK - pin 13 Arduino
  • RST - pin 9 Arduino
  • SPI SS PIN(SDA)  - pin 10 Arduino

Program:


Na początku w programie można ustawić tryb pracy (zmienna workMode). Pierwszy z nich pozwala przy pierwszym przyłożeniu na załączenie jednego przekaźnika. Ponowne przyłożenia karty powoduje odłączenie przekaźnika.

Drugi tryb pracy załącza przekaźnik i po około 10 sekundach następuje jego odłączenie. Obliczenia są wykonywane za pomocą zwykłej funkcji opóźniające, wobec tego może występować pewne odchylenie od zakładanej wartości. Może on być dynamicznie zmieniany za pomocą komend poprzez interfejs UART. W celu ulepszenia programu można dołożyć zapis tego parametru do pamięci nieulotnej. 

Do obsługi układu RC522 wykorzystuje bibliotekę MFRC522 stworzoną przez GithubCommunity w wersji 1.3.6. Można ją w bardzo łatwy sposób pobrać poprzez Menedżer bibliotek.

  1. /*
  2.  * Relay control test program
  3.  * Communication from UART to open or close
  4.  * two relays
  5.  * control HIGH state - turn off relay
  6.  * control LOW state - turn on relay
  7.  *  Connection:
  8.  *  * RST/Reset   RST          9            
  9.  *    SPI SS      SDA(SS)      10            
  10.  *    SPI MOSI    MOSI         11 / ICSP-4  
  11.  *    SPI MISO    MISO         12 / ICSP-1  
  12.  *    SPI SCK     SCK          13 / ICSP-3
  13.  */
  14. #include <SPI.h>
  15. #include <MFRC522.h>
  16. //--------------------------------------------------------------------------------------------
  17. #define RST_PIN         9   /* Rst pin for RC522 */
  18. #define SS_PIN          10  /* SS pin for RC522 */      
  19. //--------------------------------------------------------------------------------------------
  20. #define RELAY1          7 /* Relay 1 connect to pin 10 */
  21. #define RELAY2          8 /* Relay 2 connect to pin 11 */
  22. //--------------------------------------------------------------------------------------------
  23. /* Number from my tags */
  24. /* Card data, small tag: UID: 46, 75, D5, 8F */
  25. /* Card data, small tag: UID: 91, B8, E8, 09 */
  26. //--------------------------------------------------------------------------------------------
  27. /* Variables for relay control */
  28. String receiveData = "";
  29. bool relayState1 = true; /* State for relay one */
  30. bool relayState2 = true; /* State for relay one */
  31. //--------------------------------------------------------------------------------------------
  32. /* Variables for RC522 */
  33. byte serialNumberFromTag[4];
  34. byte decodeFlag = 0;
  35. /* table variable that keeps my card numbers, to read other card you just need to put your to
  36.     rfid module, that will be print on serial port*/
  37. byte tagSerialNumber[2][4] = {{0x460x730xD50x8F},
  38.                               {0x910xB80xE80x09}} ;
  39. //--------------------------------------------------------------------------------------------
  40. byte workMode=2;  /* Work mode can be set before compilation or using UART */
  41. //--------------------------------------------------------------------------------------------
  42. MFRC522 mfrc522(SS_PIN, RST_PIN);  /* Create instance for MFRC522 */
  43. //--------------------------------------------------------------------------------------------
  44. /* Functions */
  45. void comPortInit(void);
  46. void initPins(void);
  47. void relayControl(String msg);
  48. void relayControlCardNumber(byte cardNumber[4]);
  49. uint8_t getCardNumber();
  50. void checkRelaysWorkMode2();
  51. //--------------------------------------------------------------------------------------------
  52. void setup() {
  53.   /* Set comPort */
  54.   comPortInit();
  55.   initPins();
  56. }
  57. void loop() {
  58.   if(Serial.available() > 0){
  59.     receiveData = Serial.readStringUntil('\n');     /* if data receive by uart */
  60.     relayControl(receiveData);
  61.    
  62.     /* Clear data buffer */
  63.     receiveData = "";
  64.     if ( ! mfrc522.PICC_IsNewCardPresent()) {
  65.       return;
  66.     }
  67.     /* Select one of the cards */
  68.     if ( ! mfrc522.PICC_ReadCardSerial()) {
  69.       return;
  70.     }
  71.   }
  72.   getCardNumber();
  73.   if(workMode == 2){
  74.     checkRelaysWorkMode2();
  75.   }
  76. }
  77. //--------------------------------------------------------------------------------------------
  78. void comPortInit(void){
  79.   Serial.begin(115200, SERIAL_8N1);
  80.   while (!Serial);
  81.   Serial.println("Com Port ON");
  82. }
  83. //--------------------------------------------------------------------------------------------
  84. void initPins(void){
  85.   /* Set relay pins as output */
  86.   pinMode(RELAY1, OUTPUT);
  87.   pinMode(RELAY2, OUTPUT);
  88.   /* Set default state */
  89.   digitalWrite(RELAY1, HIGH);
  90.   digitalWrite(RELAY2, HIGH);
  91.   SPI.begin();  
  92.   mfrc522.PCD_Init();
  93.   /* Read firmvare version */
  94.   byte firmwareVersion = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
  95.   if(firmwareVersion == 0){
  96.     Serial.println("Error while checking RC522 module, check connection");
  97.   }
  98.   else{
  99.     Serial.print("Module find succesfully. Firmware version 0x");
  100.     Serial.print(firmwareVersion, HEX);
  101.    
  102.     if(firmwareVersion == 0x91){
  103.       Serial.println(" - Version 1.0");
  104.     }
  105.     else if(firmwareVersion == 0x92){
  106.       Serial.println(" - Version 1.0");
  107.     }
  108.     else{
  109.       Serial.println(" - Version ????");
  110.     }
  111.   }
  112.   Serial.println("Set pins, spi finish! You can enter data now");
  113. }
  114. //--------------------------------------------------------------------------------------------
  115. void relayControl(String msg){
  116.     if(msg == "relay1") /* open or close relay 1 */
  117.     {
  118.       /* Turn on/off relay 1*/
  119.        relayState1=!relayState1;
  120.        digitalWrite(RELAY1, relayState1);
  121.        if(relayState1 == true){
  122.           Serial.println("Realy 1 OFF");
  123.        }
  124.        else{
  125.           Serial.println("Realy 1 ON");
  126.        }
  127.     }
  128.     else if(msg == "relay2") /* open or close relay 2 */
  129.     {
  130.         /* Turn on/off relay 2*/
  131.         relayState2=!relayState2;
  132.         digitalWrite(RELAY2, relayState2);
  133.         if(relayState2 == true){
  134.            Serial.println("Realy 2 OFF");
  135.         }
  136.         else{
  137.            Serial.println("Realy 2 ON");
  138.         }
  139.     }
  140.     else if(msg == "workmode_1")  /* set workmode as 1 */
  141.     {
  142.         /* Set work mode to 1 */
  143.         if(workMode == 1){
  144.           Serial.println("Work mode already set to 1");
  145.         }
  146.         else{
  147.           workMode = 1;
  148.           Serial.println("Work mode set to 1");
  149.         }
  150.     }
  151.     else if(msg == "workmode_2")  /* set workmode as 2 */
  152.     {
  153.         /* Set work mode to 2 */
  154.         if(workMode == 2){
  155.           Serial.println("Work mode already set to 2");
  156.         }
  157.         else{
  158.           workMode = 2;
  159.           Serial.println("Work mode set to 2");
  160.         }
  161.     }
  162.     else if(msg == "workmode_?")  /* check workmode */
  163.     {
  164.         /* Check workMode value*/
  165.         Serial.print("Work mode value: ");
  166.         Serial.println(workMode);
  167.     }
  168.     else
  169.     {
  170.         Serial.println("Wrong message to Arduino!");
  171.     }
  172. }
  173. //--------------------------------------------------------------------------------------------
  174. void relayControlCardNumber(byte cardNumber[4])
  175. {
  176.   if((cardNumber[0] == tagSerialNumber[1][0]) && (cardNumber[1] == tagSerialNumber[1][1]) &&
  177.       (cardNumber[2] == tagSerialNumber[1][2]) && (cardNumber[3] == tagSerialNumber[1][3]))
  178.   {
  179.     decodeFlag = 1;
  180.     if((workMode == 1) || ((workMode == 2) && relayState1 == true)){
  181.       relayControl("relay1");
  182.     }
  183.   }
  184.   else if((cardNumber[0] == tagSerialNumber[0][0]) && (cardNumber[1] == tagSerialNumber[0][1]) &&
  185.      (cardNumber[2] == tagSerialNumber[0][2]) && (cardNumber[3] == tagSerialNumber[0][3]))
  186.   {
  187.     decodeFlag = 2;
  188.     if((workMode == 1) || ((workMode == 2) && relayState2 == true)){
  189.       relayControl("relay2");
  190.     }
  191.   }
  192.   else
  193.   {
  194.       Serial.println("Wrong card number!");
  195.   }
  196. }
  197. //--------------------------------------------------------------------------------------------
  198. uint8_t getCardNumber() {
  199.   // Getting ready for Reading PICCs
  200.   if ( ! mfrc522.PICC_IsNewCardPresent()) { /* If a new PICC placed to RFID reader continue */
  201.     return 0;
  202.   }
  203.   if ( ! mfrc522.PICC_ReadCardSerial()) {   /* Since a PICC placed get Serial and continue */
  204.     return 0;
  205.   }
  206.   /* Write card number into variable, and print it on the screen */
  207.   for (uint8_t i = 0; i < 4; i++)
  208.   {
  209.     serialNumberFromTag[i] = mfrc522.uid.uidByte[i];
  210.     Serial.print(serialNumberFromTag[i], HEX);
  211.   }
  212.   Serial.println("");
  213.   mfrc522.PICC_HaltA();
  214.   /* Go to relay control function */
  215.   relayControlCardNumber(serialNumberFromTag);
  216.   return 1;
  217. }
  218. //--------------------------------------------------------------------------------------------
  219. void checkRelaysWorkMode2()
  220. {
  221.   static uint16_t relayOneCount;
  222.   static uint16_t relayTwoCount;
  223.   /* If relay 1 is open */
  224.   if(decodeFlag==1){
  225.     relayOneCount+=1;
  226.     if(relayOneCount == 300){
  227.       relayOneCount=0;
  228.       decodeFlag = 0;
  229.       relayControl("relay1");
  230.     }
  231.     delay(10);
  232.   }
  233.   /* If relay 2 is open */
  234.   if(decodeFlag==2){
  235.     relayTwoCount+=1;
  236.     if(relayTwoCount == 300){
  237.       relayTwoCount=0;
  238.       decodeFlag = 0;
  239.       relayControl("relay2");
  240.     }
  241.     delay(10);
  242.   }
  243. }
  244. //--------------------------------------------------------------------------------------------

Jako dodatkowe usprawnienie można dołożyć zapamiętywanie wcześniejszego nr karty i wykonać brak reakcji na ponowne przyłożenie tej samej karty do czytnika, zanim zostanie przyłożona inna karta. Taki mechanizm jest często stosowany w systemach kontroli dostępu. Można go wykonać poprzez dodanie dodatkowej zmiennej w formacie byte lub dodatkowego wiersza w zmiennej tagSerialNumber.