Получение редактируемых данных из памяти 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[]. И не такой уж это костыль, а довольно типовое решение
Перевел!!!!) И даже все заработало!
byte buffer2[18]; //Байтовая переменная чтобы записать информацию из памяти метки char buffer3[18]; //Символьная переменная чтобы записать информацию из байтовой status = mfrc522.MIFARE_Read(block, buffer2, &len); for (uint8_t i = 0; i < 16; i++) { Serial.write(buffer2[i]); buffer3[i] = buffer2[i];} lcd.setCursor(0,0); int z=atoi(buffer3); //Переводим строку в число, получаемНо теперь нужен обратный цикл, чтобы в команду на запись отправить число интовое, что я только не пытался делать - нифига не выходит(( При прочтении показывает абракадабру( То есть примером с терминала все хорошо записывается и читается, а когда пытаюсь с устройства записать интовое значение - не выходит.
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: "));Вот кусок из примера на запись, в buffer нужно загнать предыдущее значение z. Пните меня пожалуйста в нужном направлении) Потому что пробовал z разбивать на числа, присваивать символьной переменной, а ее через buffer[0]=(byte)buffer2[0]; присваивать буферу, на выходе какая то пакость(
Обратное к atoi - ltoa, ultoa
Попробовал, все равно абра-кадабра((
char buffer3[18]; byte buffer[34]; ltoa (5001, buffer3, 16); buffer[0]=buffer3[0]; buffer[1]=buffer3[1]; buffer[2]=buffer3[2]; buffer[3]=buffer3[3]; // 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: "));Выдает:
А что, в карту нужно строку писать? Я всегда число писал числом.
Да я бы с удовольствием)) Только не понимаю как((
numberR=0;
numberW=2022;
...write(..., (uint8_t*)&numberW, sizeof(numberW));
...read(..., (uint8_t*)&numberR, sizeof(numberR));
...print(numberR);
Считали из памяти N байт, начиная с адреса, по которому лежит numberW.
Записали в память N байт, начиная с адреса, по которому находится numberR.
Обе переменные должны быть одинакового типа.
Вроде как-то так.