Получение редактируемых данных из памяти RFID (RC522)
- Войдите на сайт для отправки комментариев
Добрый день, уважаемые старожилы)
Вопрос наверное до безумия глупый, но бьюсь уже второй день с ним(
Исходные данные: Есть ридер RC552, куча меток-брелков к ней, горячее желание сделать что-то полезное и не особо понимающая как это сделать голова(
Цель: Есть куча меток, поднося которые к ридеру можно получить определенное количество баллов. Количество баллов записано в памяти метки.
Реализация: Используя библиотеку <MFRC522.h> и стандартные примеры в ней (rfid_read_personal_data.ino и rfid_write_personal_data.ino) записываем в память метки 4 числа, для примера 7010, где "7" - пароль, для того чтобы мы понимали что это наша метка используется (для исключения использования сторонними метками), а "010" это количество баллов на конкретной метке (будет от 000 до 999).
Используя пример rfid_write_personal_data.ino на запрос Name вводим через монитор порта "7010". Запись проходит. Хорошо, с этим мы справились)
Код примера записи (он стандартный в библиотеке):
#include <SPI.h> #include <MFRC522.h> #define RST_PIN 9 // Configurable, see typical pin layout above #define SS_PIN 10 // Configurable, see typical pin layout above MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance void setup() { Serial.begin(9600); // Initialize serial communications with the PC SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card Serial.println(F("Write personal data on a MIFARE PICC ")); } void loop() { // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory. MFRC522::MIFARE_Key key; for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF; // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return; } Serial.print(F("Card UID:")); //Dump UID 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.print(F(" PICC type: ")); // Dump PICC type MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); Serial.println(mfrc522.PICC_GetTypeName(piccType)); byte buffer[34]; byte block; MFRC522::StatusCode status; byte len; Serial.setTimeout(20000L) ; // wait until 20 seconds for input from serial // Ask personal data: Family name Serial.println(F("Type Family name, ending with #")); len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial for (byte i = len; i < 30; i++) buffer[i] = ' '; // pad with spaces block = 1; //Serial.println(F("Authenticating using key A...")); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("PCD_Authenticate() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } else Serial.println(F("PCD_Authenticate() success: ")); // Write block status = mfrc522.MIFARE_Write(block, buffer, 16); if (status != MFRC522::STATUS_OK) { Serial.print(F("MIFARE_Write() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } else Serial.println(F("MIFARE_Write() success: ")); block = 2; //Serial.println(F("Authenticating using key A...")); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("PCD_Authenticate() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // Write block status = mfrc522.MIFARE_Write(block, &buffer[16], 16); if (status != MFRC522::STATUS_OK) { Serial.print(F("MIFARE_Write() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } else Serial.println(F("MIFARE_Write() success: ")); // Ask personal data: First name Serial.println(F("Type First name, ending with #")); len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial for (byte i = len; i < 20; i++) buffer[i] = ' '; // pad with spaces block = 4; //Serial.println(F("Authenticating using key A...")); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("PCD_Authenticate() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // Write block status = mfrc522.MIFARE_Write(block, buffer, 16); if (status != MFRC522::STATUS_OK) { Serial.print(F("MIFARE_Write() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } else Serial.println(F("MIFARE_Write() success: ")); block = 5; //Serial.println(F("Authenticating using key A...")); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("PCD_Authenticate() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // Write block status = mfrc522.MIFARE_Write(block, &buffer[16], 16); if (status != MFRC522::STATUS_OK) { Serial.print(F("MIFARE_Write() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } else Serial.println(F("MIFARE_Write() success: ")); Serial.println(" "); mfrc522.PICC_HaltA(); // Halt PICC mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD }
Далее загружаем пример rfid_read_personal_data.ino считываем данные из метки и выводим в монитор порта заветное значение Name: 7010.
Код примера чтения:
#include <SPI.h> #include <MFRC522.h> #define RST_PIN 9 // Configurable, see typical pin layout above #define SS_PIN 10 // Configurable, see typical pin layout above MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance //*****************************************************************************************// void setup() { Serial.begin(9600); // Initialize serial communications with the PC SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card Serial.println(F("Read personal data on a MIFARE PICC:")); //shows in serial that it is ready to read } //*****************************************************************************************// void loop() { // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory. MFRC522::MIFARE_Key key; for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF; //some variables we need byte block; byte len; MFRC522::StatusCode status; //------------------------------------------- // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return; } Serial.println(F("**Card Detected:**")); //------------------------------------------- mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card //mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //uncomment this to see all blocks in hex //------------------------------------------- Serial.print(F("Name: ")); byte buffer1[18]; block = 4; len = 18; //------------------------------------------- GET FIRST NAME status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file if (status != MFRC522::STATUS_OK) { Serial.print(F("Authentication failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } status = mfrc522.MIFARE_Read(block, buffer1, &len); if (status != MFRC522::STATUS_OK) { Serial.print(F("Reading failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } //PRINT FIRST NAME for (uint8_t i = 0; i < 16; i++) { if (buffer1[i] != 32) { Serial.write(buffer1[i]); } } Serial.print(" "); //---------------------------------------- GET LAST NAME byte buffer2[18]; block = 1; status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834 if (status != MFRC522::STATUS_OK) { Serial.print(F("Authentication failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } status = mfrc522.MIFARE_Read(block, buffer2, &len); if (status != MFRC522::STATUS_OK) { Serial.print(F("Reading failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } //PRINT LAST NAME for (uint8_t i = 0; i < 16; i++) { Serial.write(buffer2[i] ); } //---------------------------------------- Serial.println(F("\n**End Reading**\n")); delay(1000); //change value if you want to read cards faster mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1(); }
Казалось бы победа, НО я вот честно не могу понять как мне перевести buffer1 и buffer2 в десятичные цифры. В мониторе порта отображается все верно, выводится мое число, но при присваивании любого из буфера хоть в переменную, хоть в массив побайтово - выходит какая то ахинея(
Я честно признаю что не могу понять как перевести и из-за этого стопорится все, мне же потом эти баллы суммировать надо в итоге, да и проверку по паролю первой цифры нужно провести...
Поэтому очень прошу помощи, как мне из этих буферов получить две цифры (первое число и 2-4)?
в первом примере вы записываете свое число не как число, а как строку - "7010". Cоответвенно и читаетеся обратно строка, где в первом символе - ваш пароль, а со второго - номер.
в первом примере вы записываете свое число не как число, а как строку - "7010". Cоответвенно и читаетеся обратно строка, где в первом символе - ваш пароль, а со второго - номер.
Хм... теперь стало понятнее, а каким образом мне можно из строки получить число?
читай за atoi()
Большое спасибо за наводку, все получилось!) Правда пришлось байтовый массив перевести в строчный, а потом уже перевести в цифры. Хоть и с костылями, но он работает!)
Правда пришлось байтовый массив перевести в строчный, а потом уже перевести в цифры. Хоть и с костылями, но он работает!)
лучше не в строчный (String), а в символьный - char[]. И не такой уж это костыль, а довольно типовое решение
Перевел!!!!) И даже все заработало!
Но теперь нужен обратный цикл, чтобы в команду на запись отправить число интовое, что я только не пытался делать - нифига не выходит(( При прочтении показывает абракадабру( То есть примером с терминала все хорошо записывается и читается, а когда пытаюсь с устройства записать интовое значение - не выходит.
Вот кусок из примера на запись, в buffer нужно загнать предыдущее значение z. Пните меня пожалуйста в нужном направлении) Потому что пробовал z разбивать на числа, присваивать символьной переменной, а ее через buffer[0]=(byte)buffer2[0]; присваивать буферу, на выходе какая то пакость(
Обратное к atoi - ltoa, ultoa
Попробовал, все равно абра-кадабра((
Выдает:
А что, в карту нужно строку писать? Я всегда число писал числом.
Да я бы с удовольствием)) Только не понимаю как((
numberR=0;
numberW=2022;
...write(..., (uint8_t*)&numberW, sizeof(numberW));
...read(..., (uint8_t*)&numberR, sizeof(numberR));
...print(numberR);
Считали из памяти N байт, начиная с адреса, по которому лежит numberW.
Записали в память N байт, начиная с адреса, по которому находится numberR.
Обе переменные должны быть одинакового типа.
Вроде как-то так.