Авторизация
Зарегистрироваться

Считыватель карточек RFID RC522 в домашнем хозяйстве


В какой-то момент мне снова стало скучно, и я, как мне показалось, придумал хорошую причину для покупки считывателя карточек. Концепция была такова: карточку приклеиваем на дно ноутбука, а считыватель ставим в то место, где компьютер обычно заряжается.

Результат: когда кладем ноутбук на «зарядку», то автоматически включается розетка с его зарядным устройством. А в остальное время розетка, понятно, выключена. Не сказать, что особо полезно, но — развлечение.

Но, как обычно, что-то пошло не так. То есть, вместо ударного труда на ниве розеток я в первую очередь зачем-то научился узнавать, сколько поездок осталось на моем билете местного метрополитена.

Для понимания: этот считыватель — не законченное устройство, а периферия для контроллера или компьютера. По этой причине для использования потребуется некоторое количество усилий. Готовых рецептов «из коробки» как бы нет, зато все остальное зависит от фантазии и способностей.

Что обычно делают? Чаще всего — замки с открытием по карточке, учет рабочего времени, СКД для домашних животных (допуск к корму, например).



Для экспериментов я выбирал недорогой и более-менее универсальный считыватель. RFID в названии этой штуки означает технологию радиоидентификации, то есть ничего конкретно не означает. Зато из спецификаций следует, что железка совместима с распространенными RFID карточками с протоколом MIFARE.

Скорее всего, вы неоднократно встречались с такими карточками. Чаще всего — в виде офисного пропуска. Другой яркий пример — бесконтактные билеты для прохода в метро.

Базовый принцип действия довольно прост для понимания. В карточке и в считывателе есть антенны, при этом сигнал считывающего устройства (суть электромагнитное поле) одновременно служит источником питания для карточки. Т.е. и в части энергетики, и в части передачи данных это очень похоже на ставшие сверхпопулярными беспроводные зарядки.

Сами же карточки, в зависимости от модификации, могут нести в себе от нескольких десятков байт до нескольких килобайт данных (в том числе — уникальный серийный номер). Также, в зависимости от модификации, карточка может быть укомплектована криптографической защитой информации.

. гребенок в комплекте было две, но одну (угловую) я, простите уже запаял. Поэтому вида платы без гребенок нет


Этот комплект включает в себя считыватель, гребенку для простого макетирования и даже монтажа на «материнскую» плату и два идентификатора: карточку MIFARE 1K и аналогичный по возможностям брелок. То есть, вполне достаточно для экспериментов.

.


.


.


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

. с батарейкой ААА


Т.е. можно не мучить себя компромиссом между удобством и универсальностью (гребенкой) и экономией места в расчете на встраивание (прямой пайкой проводов).



Среди прочего на плате также есть красный светодиод, который, увы, совершенно неинформативен. Суть в том, что он горит даже при оторванном питании — очевидно, достаточно уровней на SPI-интерфейсе. Да и на карточки он никак не реагирует.

Одним словом — горит, когда считыватель хоть как-то подключен к Arduino, что не гарантирует его работоспособности.

Что касается дальности срабатывания, то субъективно порог находится на расстоянии 2 см от поверхности платы. В пределах 2 — 2.5 см — область неуверенного срабатывания.

Характеристики (от продавца):

— Напряжение: 3.3В

— Потребляемый ток в активном состоянии:13-26 мА

— Потребляемый ток в состоянии ожидания: 10-13 мА

— Ток в режиме сна: менее 80 мкА

— Пиковое потребление: менее 30 мА

— Рабочая частота: 13.56 МГц

— Поддержвиаемые типы карт: MIFARE S50, MIFARE S70, MIFARE UltraLight, MIFARE Pro, MIFARE DESfire

— Интерфейс: SPI

— Размеры: 40х60 мм

Из приведенного выше видно, что отличился я дважды. Во-первых, не посмотрел на напряжение питания. А 3.3В, между прочим, означает, что проще всего использовать эту плату с Arduino Uno, Mega и прочими (или аналогичными платами), оснащенными регуляторами напряжения и выходом 3.3В. Благо максимальный потребляемый ток не выходит за пределы возможностей платформы.

В противном случае необходимо либо использовать единое питание 3.3В, либо дополнительный регулятор/стабилизатор/преобразователь напряжения.

Во-вторых, интерфейс SPI в требует 5 (!) проводов для подключения. Т.е. в сумме к считывателю подходит шлейф из 7 проводников, а это довольно расточительно. Для экономии имело смысл ориентироваться на I2C, но где я и где этот смысл?!

Подключение
Я бы хотел разделить подключение на софт и хард, но все так тесно переплелось — и вылилось в не очень интересную проблему.

Одним словом, все знают самую распространенную библиотеку RFID для RC522. Но почему-то никто не задается вопросом, почему в ридми, приложенном к библиотеке и в табличке в одном из ее примеров совершенно разная «распиновка» подключения считывателя.

Полагаю, это как раз одна из причин вечных проблем с этой библиотекой. Вторая причина в том, что подключение для Arduino Uno и Mega производится к разным пинам. Это связано с особенностью платформ.

Наконец, третья причина — два пина (SS и RST) допускают произвольное подключение и конфигурируются в коде. При этом по умолчанию в коде примера забита конфигурация для Arduino Uno, а если у вас Mega и вы подключали по агитке из ридми или таблички в начале примера, то, разумеется, промахнетесь.

Но фишка в том, что третья причина довольно очевидна, и ее я более-менее обошел, сразу задав свои пины, потому что у меня под руками была плата Arduino Mega. Поэтому же, кстати, меня обошла и вторая беда.

А вот первая — подключение пинов SPI помучила меня вдоволь. Я же и предположить не мог, что человек, сделавший успешную библиотеку, мог так накосячить в банальном подключении трех проводочков.

Иными словами, подключение ни по первому, ни по второму варианту, указанному в описании библиотеки, не помогло. Сначала я подумал, что у меня «мертвая плата». Поэтому, несмотря на позднее время, взял себя в руки и распаял гребенку на вторую (я запасливый и купил сразу три). Результат оказался аналогичным, несмотря на то, что я неоднократно проверял подключение по имеющимся на руках «распиновкам».

Даже не спрашивайте, почему я не пошел на Arduino.cc, чтобы посмотреть, как разведен SPI на Mega. По-моему, это случилось какое-то помутнение.

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

И обе платы заработали.

Чтобы очистить совесть — загрузил пример с «проблемной» библиотекой, и он оказался рабочим тоже.

. вот такими карточками я мучил считыватель. Слева направо: карточка из комплекта, карточка с буквой N, билет метро MIFARE UltraLight, карточка РЖД


. а это — как примерно выглядит дамп содержимого и вообще распознавание карточек с библиотекой RFID и ее же примером DumpInfo


Резюме по мучениям: распиновка от упомянутого товарища совпадает с распиновкой на сайте Arduino.cc и, что удивительно, совпадает с распиновкой в ридми библиотеки RFID. Учитывая последнее, могу предположить, что либо я ночью все же перепутал пины и с этого начались все мои несчастья, либо родная китайская библиотека как-то хитро инициализирует считыватель, после чего он начинает работать.

Отсюда рекомендация: если библиотека RFID не запустится при подключении с распиновкой с сайта Arduino.cc, то имеет смысл попробовать китайскую библиотеку.

В завершение правильная распиновка для китайской библиотеки и Mega, к которой я подключался:

Mega RC522
3.3V VCC
GND GND
RESET RST

50 MISO
51 MOSI
52 SCK
53 NSS

И для Uno (ее не проверял):

Uno RC522
3.3V VCC
GND GND
5 RST

12 MISO
11 MOSI
13 SCK
10 NSS

. вместе с большой сестрой


.


.


В результате простых испытаний, которые я все-таки выполнил, также выяснилось, что считыватель нормально записывает (вот такая игра слов) карты MIFARE 1K из тех, что были с ним в комплекте.

Вторая особенность в том, что эта штука адекватно реагирует, если к нему одновременно поднести несколько карт. Я подносил две карты, опять же, из тех, что были в комплекте. При этом пример DumpInfo из библиотеки RFID по порядку выводит содержимое обеих карт. Т.е. сначала — содержимое одной карты, а следом за ней — второй.

И шашечки, и ехать
Итак, подключили, полюбовались на дамп содержимого памяти карточек MIFARE 1K. Что дальше? А дальше мне было немного лень возиться с розеткой, и я вспомнил, что карточки метро, вроде бы, работают по тому же протоколу.

Сходил, взял свою, приложил, полюбовался на ее содержимое. Как и обещали: MIFARE UltraLight, 64 байта памяти и не очень понятно, где там поездки, где срок действия, ну и вообще не очень понятно.

Гугление на тему использования Arduino с этими карточками не дало ничего особо полезного. Чаще всего карточки метро, как выяснилось, используют в качестве ультрадешевых (т.е. бесплатных) NFC-меток во всяких самодельных системах вроде замков, исполнения сценариев и прочего, где достаточно знать серийный номер карты для идентификации. А вот готовых библиотек и решений для вывода информации о поездках я почему-то не нашел: то ли так спать хотел, то ли их действительно нет (см. синдром «Неуловимого Джо»).

Зато я нашел замечательный и очень романтичный текст авторства Александра «Dark Simpson» Симонова под заголовком "Взлом метро", опубликованный, судя по всему, в каком-то из номеров Хакера. Несмотря на любопытную природу текста, в нем есть масса полезной информации о структуре хранения данных, в том числе на интересующих меня билетах.

. значащая часть билета — номер — проверяемая визуально


Так что на следующий день я постарался переборость свое отвращение к HEX и полез разбираться. Вот такой дамп билета я получил с помощью библиотеки RFID:

Card UID: 04 6F 25 62 04 33 82
PICC type: MIFARE Ultralight or Ultralight C

Page 0 1 2 3
0 04 6F 25 C6
1 62 04 33 82
2 D7 48 F0 00
3 00 07 FF FC
4 45 DA 21 06
5 D0 E5 3D 00
6 1F E8 00 00
7 1F E8 00 00
8 1F 8F 5A 00
9 40 19 2E D2
10 19 91 59 7C
11 1F AB 91 C8
12 1F 8F 5A 00
13 40 19 2E D2
14 19 91 59 7C
15 1F AB 91 C8

Здесь Card UID — уникальный идентификатор карты (суть серийный номер), а остальное — 16 страниц памяти, каждая из которых содержит по 4 байта. Вместе — 64 байта.

Из чтения текста про билеты метро отметил наиболее полезные моменты:

1) Номер билета (который отпечатан на нем) зашит в 32 битах, начиная с 21 бита на странице 4: 10 6D 0E 53;

2) Дата выдачи билета в днях, прошедших с 01.01.1992 г. — первые два байта странице 8: 1F 8F;

3) Срок действия в днях — третий байт на странице 8: 5А.

4) Наконец, количество оставшихся поездок — второй байт на странице 9: 19.

С этим уже можно было работать.

Немного поковырялся в примере DumpInfo из библиотеки RFID, в ее же коде, чтобы понять, какие функции за что отвечают и чем могут быть полезны, в форумах Arduino, чтобы посмотреть реализацию вычисления даты (вообще, можно на любом языке смотреть, но мне было проще искать ближе к целевой платформе).

В итоге на свет появился монстр. То есть, скетч скроен из лоскутов, местами результат подогнан под ответ, но в целом все более-менее соответствует реальности. Поэтому нечего стрелять в пианиста, который играет, как умеет. Там, между прочим, даже базовая обработка ошибок есть: скетч предупредит о неподдерживаемой карте или о невозможности чтения.

МОНСТР
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 53
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);	// объект MFRC522
unsigned long uidDec, uidDecTemp; // для отображения номера карточки в десятичном формате
byte bCounter, readBit;
unsigned long ticketNumber;


void setup() {
	Serial.begin(9600);	
	SPI.begin();		// инициализация SPI
	mfrc522.PCD_Init();	// инициализация MFRC522
	Serial.println("Waiting for card...");
}

void loop() {
	// Поиск новой карточки
	if ( ! mfrc522.PICC_IsNewCardPresent()) {
		return;
	}

	// Выбор карточки
	if ( ! mfrc522.PICC_ReadCardSerial()) {
          	return;
	}

        uidDec = 0;

        // Выдача серийного номера карточки
        Serial.print("Card 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);
                uidDecTemp=mfrc522.uid.uidByte[i];
                uidDec=uidDec*256+uidDecTemp;
        } 
        Serial.println(uidDec);
        Serial.println();

        // Выдача типа карты
        byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); // запрос типа
        Serial.print("Card type: ");
        Serial.println(mfrc522.PICC_GetTypeName(piccType)); // трансляция типа в читаемый вид
        if (piccType != MFRC522::PICC_TYPE_MIFARE_UL) { // если не билетная карта
                Serial.print("Not a valid card: "); // так и говорим
                Serial.println(piccType);				
        	// Halt PICC
                mfrc522.PICC_HaltA();			// остановка чипа
                return;
        }

// сюда мы приедем, если чип правильный

	byte status;
	byte byteCount;
	byte buffer[18]; // длина массива (16 байт + 2 байта контрольная сумма) 
	byte pages[2]={4, 8}; // страницы с данными
	byte pageByte; // счетчик байтов страницы
	
	byteCount = sizeof(buffer);
        byte bCount=0;
        	

	for (byte i=0; i<2; i++) { // начинаем читать страницы
	status = mfrc522.MIFARE_Read(pages[i], buffer, &byteCount);
	
	if (status != MFRC522::STATUS_OK) {
		Serial.print("Read error: ");
		Serial.println(mfrc522.GetStatusCodeName(status));}
		else {
                      if (pages[i] == 4) {
				bCounter = 0; // 32-битный счетчик для номера
				
				// биты 0-3
				for (bCount=0; bCount<4; bCount++) {
					readBit = bitRead(buffer[6], (bCount+4));
					setBitsForGood(readBit);
				}

				// биты 4 - 27
				for (pageByte=5; pageByte > 2; pageByte--) {
					for (bCount=0; bCount<8; bCount++) {
						readBit = bitRead(buffer[pageByte], bCount);
						setBitsForGood(readBit);
					}
				}

				// биты 28-31
				for (bCount=0; bCount<4; bCount++) {
					readBit = bitRead(buffer[2], bCount);
					setBitsForGood(readBit);
				}

                                Serial.print("Ticket number: ");
                            	Serial.println(ticketNumber, DEC);
                         }
			
                          if (pages[i] == 8) { // читаем дату выдачи

				Serial.print("Issued: ");
				unsigned int issueDate = buffer[0] * 256 + buffer[1]; // количество дней с 01.01.1992 в десятичном формате, 256 - сдвиг на 8 бит
				printIssueDate(issueDate);

				Serial.print("Good for (days): "); // срок действия
				Serial.print(buffer[2], DEC);								
				Serial.println();				
			
				Serial.print("Trip reminder: "); // количество оставшихся поездок
				Serial.print(buffer[5], DEC);								
				Serial.println();	
			}
			
			
		}
        }

		
		
	// Halt PICC
    mfrc522.PICC_HaltA();			
	
}

void printIssueDate(unsigned int incoming) {

boolean isLeap = true; // признак високосного года
int days[]={0,31,59,90,120,151,181,212,243,273,304,334}; // последний по порядку день месяца для обычного года
byte dayOfMonth, monthCounter;
unsigned int yearCount;

incoming = incoming+1; // подогнал под ответ, но возможно это как раз необходимая коррекция, потому что начало отсчета - 01.01.1992, а не 00.01.1992

for (yearCount = 1992; incoming >366; yearCount++) { // считаем год и количество дней, прошедших с выдачи билета

	if ((yearCount % 4 == 0 && yearCount % 100 != 0) ||  yearCount % 400 == 0) {
		incoming = incoming - 366;
		isLeap = true;
          } else {
		incoming = incoming - 365;
		isLeap = false;
		}
	}

for (monthCounter = 0; incoming > days[monthCounter]; monthCounter++) { // узнаем номер месяца
}

// считаем день месяца

if (isLeap == true) { // если високосный год
  if (days[monthCounter-1]>31) { // если не первый месяц, то добавляем к последнему дню месяца единицы
  dayOfMonth = incoming - (days[monthCounter-1]+ 1);
  } else {
    dayOfMonth = incoming - (days[monthCounter-1]); // если первый - ничего не добавляем, потому что сдвиг начинается с февраля
  }
} else {
  dayOfMonth = incoming - (days[monthCounter-1]); // если не високосный год
}

Serial.print(dayOfMonth);
Serial.print(".");
Serial.print(monthCounter);
Serial.print(".");
Serial.print(yearCount);
Serial.println();

	

}




void setBitsForGood(byte daBeat) {


  
	if (daBeat == 1) {
		bitSet(ticketNumber, bCounter);
		bCounter=bCounter+1;
		}
	else {
		bitClear(ticketNumber, bCounter);
		bCounter=bCounter+1;
	}
}



Что мне дает этот скетч? Ну, во-первых, небольшую тренировку головы — приходилось, знаете, думать, когда разбирался со считывателем и кодом. Во-вторых, я всегда могу узнать, сколько осталось поездок, и когда закончится карточка. С учетом того, что у меня в смартфоне NFC нет, получается довольно удобно.

. результат работы монстра


Разумеется, в данном случае даже речь не идет о том, чтобы сделать «копию» билета. Это исключительно информационная функция, дублирующая терминал в вестибюле метро.

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

Итак, розетка, которая включается, когда нужна. Здесь карта (любая поддерживаемая считывателем и подходящая для размещения в целевом устройстве) используется исключительно как пропуск, то есть интересует только ее серийный номер.

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

РОЗЕТОЧНЫЙ МОНСТР
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 53
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);	// Create MFRC522 instance.
unsigned long uidDec, uidDecTemp;


#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

boolean switchOn = false;
boolean cardRead = false;

void setup() {
	Serial.begin(9600);	// Initialize serial communications with the PC
	SPI.begin();			// Init SPI bus
	mfrc522.PCD_Init();	// Init MFRC522 card
        mySwitch.enableTransmit(8);
	Serial.println("Waiting for card...");
}

void loop() {
	byte status;
	byte byteCount;
	byte buffer[2]; // длина массива (16 байт + 2 байта контрольная сумма) 
	
	byteCount = sizeof(buffer);
        uidDec = 0;
        status = mfrc522.PICC_RequestA(buffer, &byteCount); 
          if (mfrc522.PICC_ReadCardSerial()) {
                  for (byte i = 0; i < mfrc522.uid.size; i++) {  
                     uidDecTemp=mfrc522.uid.uidByte[i];
                     uidDec=uidDec*256+uidDecTemp;
                  }
                  if ((uidDec==2218415941) && (switchOn == false)) {
                    mySwitch.sendTriState("00110000F000");
                    switchOn = true;
                    // Serial.println("Switched On");
                  }                          
                  mfrc522.PICC_ReadCardSerial();
                  
        } else {
          if (switchOn == true) {
            mySwitch.sendTriState("001100000000");
            // Serial.println("Switched Off");
            switchOn = false;
          }
        }
 }



Аналогичным образом, используя карту как триггер, можно выполнять и различные сценарии домашней автоматизации. Например, положить карточку в электронную книгу, а на прикроватной тумбе разместить считыватель.

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

. вот так работает розеточный монстр


Подводя итог: недорого, просто, довольно удобно и стимулирует фантазию.

ps. Я уверен, что вы можете лучше, и что я ничего не понимаю в Arduino и программировании.

Ссылочки всякие
Библиотека RFID
Дружеский опыт
Распиновка Arduino Uno
Распиновка Arduino Mega
Описание системы контроля проезда в метрополитене (Взлом метро, Хакер)
Планирую купить +104 Добавить в избранное +67 +173
свернуть развернуть
Комментарии (193)
RSS
+
avatar
  • elf2978
  • 18 марта 2014, 10:12
+17
в начале обзора я еще что-то понимал...)))
супер обзор!
+
avatar
+5
магнит с герконом? не вариант? Но тогда не было бы всей остальной истории, и все закончилось бы ноутбуком на зарядке
+
avatar
  • spc
  • 19 марта 2014, 10:06
+2
Да, мне уже предложили ) Это такая хитрая деформация: когда начинаешь думать о микроконтроллерах, забываешь о простых решениях.
+
avatar
  • dEFLASH
  • 06 октября 2016, 16:42
0
Сложное ТЗ
замутить шахматы с распознаванием фигур над клеткой…
Как быть ?)
+
avatar
  • spc
  • 06 октября 2016, 21:21
0
Если серьезно, то я бы поставил в каждую клетку по разъему (два контакта достаточно) и получил бы таким образом матрицу 8х8. А в каждую фигуру — по штекеру с индивидуальным сопротивлением.

Это, по-моему, более реально.
+
avatar
+1
1. Open View
2. «Турок» — как остроумное надувательство — ТЗ же не запрещает прямо?)
3. «Турок» же, плюс несколько HMC5883L

Во всех случаях, внешний интеллект потребуется:)

PS. Для диплома настоящего работающего решения не потребуется, достаточно будет предъявить какие-нибудь элементы.
+
avatar
  • weiss
  • 18 марта 2014, 10:21
0
красавчик!
+
avatar
  • Mixnsk
  • 18 марта 2014, 10:23
+1
Розетки по акции из ЧипДип? =)
+
avatar
  • spc
  • 18 марта 2014, 10:31
0
Ага, они самые )
+
avatar
0
а что за акция? =)
+
avatar
  • spc
  • 19 марта 2014, 10:07
0
Они продавали радиорозетки (без пульта, только радиорозетки) по 100 рублей за штуку.
+
avatar
  • sgureev
  • 18 марта 2014, 10:45
+1
После утопления смартфона в стиральной машине (забыл вытащить из куртки), появилась идея закрепить брелок или карточку на телефоне, а считыватель установить на люке стиралки. Так и не реализовал идею, ввиду малого радиуса действия подобных устройств. Может кто нибудь сталкивался с возможностью увеличения радиуса чувствительности таких считывателей или чего нибудь похожего?
+
avatar
  • spc
  • 18 марта 2014, 10:53
+1
Эти штуки незря упоминаются в категории NFC (near field communication). Т.е. помимо специфики, обуславливающей довольно слабую энергетику, небольшой радиус действия также является преимуществом в смысле безопасности. Взять тот же офис. Кому нужен замок, который будет открываться, если сотрудник болтается в радиусе пяти метров от двери?

Поэтому иногда лучше проверять карманы перед стиркой. Ну и вообще проверять свои карманы — довольно полезное занятие. Глядишь, и чего интересное найдется.

В целом же обычно аналогичную проблему решают всякими «непотеряйками». Существуют и вещи вроде брелок-приемник или просто Bluetooth-сигнализация. Но у них тоже особенность: сигналят, когда охраняемый объект покидает зону действия, т.е. особого интеллекта вроде бы как и нет. Да и у Bluetooth радиус действия, как правило, не меньше нескольких метров, поэтому в целевую нишу (30-40 см) тоже не особо попадает.
+
avatar
  • sgureev
  • 18 марта 2014, 11:23
0
Спасибо.
+
avatar
  • spc
  • 18 марта 2014, 12:37
0
Поспыаю голову пеплом. Оказывается, есть более-менее «мощные» считыватели на разумную дистанцию. И с учетом обстоятельств (не самая дешевая фирма), по вполне приемлемой цене.
+
avatar
  • sgureev
  • 18 марта 2014, 13:32
0
Спасибо огромное за отзывчивость.
+
avatar
  • varrt
  • 18 марта 2014, 14:07
-1
заезжая на работу карточку-пропуск на расстоянии 2-2.5 метра считывает штука закреплённая на шлагбауме контролерина с датчиком. Даже через стекло.
Единственное направлять-ориентировать её всё-таки как-то надо
+
avatar
  • spc
  • 18 марта 2014, 14:45
0
А вы уверены, что эта система работает по стандарту/протоколу MIFARE?
+
avatar
0
контролерина, заезжая на работу, считывает карточку

руская езыка есть осень слозная, насяльника!
+
avatar
  • zaleks
  • 18 марта 2014, 10:55
0
Обрати внимание на считыватели, которые стоят в магазине. Например в «МВидео» (у нас стоят, у вас не знаю). Там тоже RFID считыватели и метки (на товар наклеивают). Думаю в интернете есть информация по ним. А дальше думать как реализовать на стиралке.
+
avatar
  • sgureev
  • 18 марта 2014, 11:22
0
Спасибо. Я эту идею тоже прорабатывал. Только готового портативного для бытового использования на просторах ибея не видел. А самому проводить исследования и эксперименты времени и возможности мало имею.
+
avatar
  • spc
  • 18 марта 2014, 11:38
0
Там энергетика бешеная совершенно. Ну, по крайней мере, в некоторых моделях. У меня рядом с такими турникетами магнитный зажим для денег вибрировать начинал. Все же не для дома вещи.
+
avatar
  • JhaoDa
  • 18 марта 2014, 18:03
0
Там обычные радиочастотные, магнитные или акустомагнитные метки, про RFID в качестве антикражной защиты никогда не слышал, ибо дорого это.
+
avatar
  • nedobog
  • 18 марта 2014, 11:24
0
зачем такие костыли? или у вас 15 мобильных телефонов? :)
+
avatar
  • sgureev
  • 18 марта 2014, 13:31
0
В том то и дело, что не 15. Было бы 15 не парился бы с этой идеей, топи их себе на здоровье, ещё много останется… А может и впрямь не стоит овчинка выделки, нужно попросту проверять карманы. Просто хотелось внести элемент новизны в имеющуюся бытовую технику.
Утопленный телефон попросту послужил инициатором идеи, суть которой была в том, чтоб обезопасить лишний раз себя и близких от подобной неприятности не только с мобильником, но и возможностью постирать важный документ (паспорт, студенческий билет и т.п.). Вот вроде без костылей. К стати можно присмотреться к ссылке предложенной SPС.
+
avatar
  • TpuPyku
  • 18 марта 2014, 12:57
0
Если так принципиально, то у считывателей на 125KHz дальность поболее, а если ещё и антенну вокруг окна загрузки намотать самостоятельно… :D
+
avatar
  • SerjNSK
  • 18 марта 2014, 20:41
+3
Можно немного изменить условие. Кладете телефон с меткой на считыватель и только тогда розетка стиралки активируется и держится в активном состоянии N часов. Есть конечно недостатки у методы, но их можно обойти.
+
avatar
  • gogabig
  • 18 марта 2014, 21:40
0
:-) Отличная идейка, можно развить — пока считыватель не считает ВСЕ метки со ВСЕХ ваших:
1) телефонов;
2) паспортов:
3) карточек, пропусков и т.д.;
4) котов;
5) маленьких детишек;



ХХ) нужное добавьте сами.
КОРОЧЕ стиралку ХРЕН включишь!!!
+
avatar
  • strange
  • 19 марта 2014, 07:42
0
… а после приложить палец для сканирования отпечатка,
и глаз — пусть стиралка еще отсканирует сетчатку,
Анализатор ДНК чтоб 100% идентифицировать пользователя.
И в довершении нужно громко и четко назвать ФИО и дату рождения.
И будет «Счастье» носки начнут стираться!
+
avatar
  • spc
  • 19 марта 2014, 10:12
0
Я не возражаю ) Особенно, если учесть, что это никак не меняет функциональное ядро. Т.е., к примеру, скетч, который реагирует на карту, можно использовать для чего угодно, поскольку в нем сейчас и особых условий нет: ведь включение розетки это только простейший пример, для чего используется «триггер».

Иными словами, вместо включения/выключения розетки можно подставлять что душе угодно. И можно по желанию использовать любое событие (появление/пропадание метки) по отдельности.
+
avatar
  • niked70
  • 18 марта 2014, 10:49
0
Скорее всего, вы неоднократно встречались с такими карточками. Чаще всего — в виде офисного пропуска. Другой яркий пример — бесконтактные билеты для прохода в метро.
я думаю большинство читателей не относятся к офисному «планктону», а уж тем более не проживают в Москве и Санкт-Петербурге — где распространены эл.билеты в метро.
+
avatar
  • spc
  • 18 марта 2014, 11:40
+1
карточки MIFARE продаются совершенно свободно, стоят — копейки. То, что я упоминал пропуска или билеты метро — так только потому, что это ближе всего ко мне.

Но они, эти пропуска и билеты, — суть обычная карточка MIFARE, и приведенный код будет работать с любой другой подходящего стандарта.
+
avatar
  • stels
  • 18 марта 2014, 10:50
+1
есть версии не только для считывания, но и для программирования карт и брелков?
+
avatar
  • spc
  • 18 марта 2014, 10:55
0
Формально библиотека RFID умеет и читать, и писать. Запись я не пробовал, но судя по всему, проблем быть не должно.
+
avatar
  • stels
  • 19 марта 2014, 08:03
0
вроде как есть разные версии, для считывания и для считывания/записи
+
avatar
  • spc
  • 19 марта 2014, 10:31
0
Честно говоря, не уверен в том, что есть разные версии RC522 для чтения и записи. По крайней мере, в даташите на RC522 указаны и запись, и чтение.

Возможно, есть какие-то программные особенности, конечно. И, разумеется, надо иметь в виду, что некоторые карты нельзя перезаписывать (установлен запрет в карте), вне зависимости от того, какой тип считывателя используется.

Но если очень интересно — постараюсь взять себя в руки и попробовать на своем считывателе запись.
+
avatar
  • stels
  • 19 марта 2014, 12:06
0
вот собственно возможность перезаписи меня и интересовала.

не боитесь ставить ноут на такую катушку?
+
avatar
  • spc
  • 19 марта 2014, 12:30
+1
если вечером соберусь с силами — проверю.

На такую катушку, конечно, не боюсь. Вы же не боитесь класть телефон на ноутбук, правда? А телефон гораздо более суровая вещь.
+
avatar
  • spc
  • 19 марта 2014, 23:20
+1
на карточку в комплекте MIFARE 1K пишет без вопросов
+
avatar
  • stels
  • 20 марта 2014, 08:58
0
огромная благодарность
+
avatar
  • zaleks
  • 18 марта 2014, 10:51
0
1) Номер билета (который отпечатан на нем) зашит в 32 битах, начиная с 21 бита на странице 4: 10 6D 0E 53;
Вот тут косяк: Вы перешли на другую систему счисления — «бит». Собственно бит это более мелкая единица (1байт — 8 бит). Тогда каждая страница это 32 бита и не совсем понятно почему 21 бит на 4 странице. Кроме того весь номер карты тогда поместится в 1 страницу. Если ошибка и там должно быть «байт», то опять же несоответствие ссылки «на 4 странице: 10 6D 0E 53;» и вышеприведенного дампа карты. Прочитал что написал и ужаснулся, но вроде понятно о чем я. :)))
+
avatar
  • spc
  • 18 марта 2014, 12:30
+1
Мне кажется, что косяков быть не должно, я два раза проверял ) Давайте смотреть.

Изначально читается «в 32 битах, начиная… на странице 4». Т.е. я указал начало, но про конец ничего не говорил — его легко посчитать, зная количество бит. Т.е. я не утверждал, что весь номер сидит на 4-й странице.

«Начиная с 21 бита». Считаем по фрагменту дампа:

«4 45 DA 21 06
5 D0 E5 3D 00»

45 — байт, DA — байт. Вместе — 16 бит. А еще у нас есть половинка байта 21 («2»). Это еще 4 бита. Т.е. в сумме уже 20 бит. А номер начинается с 21-го бита. Т.е. с «1». Возможно, беда в том, что здесь совпал номер стартового бита и HEX-значение байта. Это действительно может сбить с толку, но случай частный.

Надеюсь, я тоже понятно выразился :)
+
avatar
  • zaleks
  • 18 марта 2014, 13:19
0
Все, пропустил момент. Все встало на свои места и нашел кусок дампа. Надо было начинать считать с половины байта.
+
avatar
  • arhimed
  • 18 марта 2014, 10:51
0
действительно монстр))
+
avatar
  • mans
  • 18 марта 2014, 10:52
-1
А получится ли сделать «вечный» билет на метро?
+
avatar
  • spc
  • 18 марта 2014, 10:55
0
Нет, конечно.
+
avatar
  • zaleks
  • 18 марта 2014, 10:59
0
Даже если и клонируешь, будет момент когда турникет работать будет в On-Line режиме. В таком случае при несовпадении данных с карты с базой карта тю-тю (ЕМНИП), останется в турникете. А может и нет, давно на метро в МСК не был.
+
avatar
  • mans
  • 18 марта 2014, 11:05
-1
А если клонировать билет на одну поездку, даже если заглотит не жалко.
+
avatar
  • djvan
  • 18 марта 2014, 11:07
+1
так вроде в метро карта приклыдывается снаружи — и ни как не заглотит :) Хотя могу ошибаться — на метро уже лет 6 не ездил…
+
avatar
  • Rzzz
  • 20 марта 2014, 01:53
0
поездка все равно одна останется. Хоть двадцать карт наклонируй. Читайте статью.
+
avatar
0
1. По большому секрету — есть метрошные карты типа «безлимит», у которых есть срок действия и нет учёта количества поездок. (их и клонируют все умельцы)

2. Турникеты постоянно работают в режиме «On-line», именно поэтому по одной социальной карте пропускает только через 5-7-10 минут после прохода. Именно поэтому при проходе двух человек по одной карте (через два соседних турникета) списываются две поездки.

3. Что может остаться в турникете, при использовании бесконтактной карты, прикладываемой к считывателю снаружи?
Впрочем вопрос риторический, ответа не требуется.
+
avatar
  • GDragon
  • 18 марта 2014, 12:12
0
Если только для почти одновременного прохода на разных станциях метро :) В противном случае в течении 15мин(при синхронизации) он отключится в базе…
+
avatar
+1
При попытке поставить плюсов выдает:
Внимание
Вы уже голосовали за этот топик!

За это мало одного плюса!!! Достойный обзор не просто товара, но и реализации в устаройствах. Спасибо Автор.
+
avatar
  • spc
  • 18 марта 2014, 11:41
0
Спасибо )
+
avatar
  • djvan
  • 18 марта 2014, 11:06
0
Пока только осваиваю ардуино — тоже со стартовым комплектом мучался — карту считывает — показывает ее серийный номер в терминале, а вот синюю метку брелок подношу — не срабатывает, т.е. видит только карту :(
+
avatar
  • TpuPyku
  • 18 марта 2014, 11:27
+1
Возможно брелок у вас на частоте 125КГц работает (Em-Marine)
+
avatar
  • spc
  • 18 марта 2014, 11:42
0
Странно. Я в видео брелки не использовал, но проверял оба типа меток — оба работали. Вечером еще раз проверю на всякий случай.

Как вариант (к тому, что ниже сказали) — китайцы могли попутать брелки.
+
avatar
  • djvan
  • 18 марта 2014, 12:56
0
интересно — на даче где то валяется считыватель с 50 шт брелками — надо будет их попробовать… А то я уже намучался с этим — вроде с картой работает а с брелком нет… Кстати — еще вопрос — а ключи таблетки металлические от домофона считать чем можно? Там другой модуль уже должен быть?
+
avatar
  • TpuPyku
  • 18 марта 2014, 13:02
+1
robocraft.ru/blog/arduino/118.html типа так, т.е. с ардуиной никаких модулей не надо.
+
avatar
  • mofa
  • 18 марта 2014, 11:35
0
Месье знает толк… плюс однозначно!)
+
avatar
  • Sanja
  • 18 марта 2014, 11:38
+2
Есть дома такой. Ребёнок играет с кучей пустых билетов от метро.

Важные вещи, которые стоило бы упомянуть в обзоре — * читает только Mifare. Офисные пропуски HID, карты «Тройка» и прочеее — не читает, там другая частота RFID.

* на просторах интернет шопов есть 2 модификации — которая работает как серийное устройство (RX, TX) — и под неё море библиотек и примеров — и такая, как у вас и у меня, с интерфейсом SPI. Поскольку SPI капризнее, на плате Уно, Леонардо и Мега распаян в разных местах — это добавляет геморроя.
+
avatar
  • spc
  • 18 марта 2014, 11:50
0
По поводу MIFARE я упомянул — это в характеристиках указано. Офисные пропуски — все на совести того, кто делает. Может быть и EM-Marin, и никто не мешает использовать MIFARE.

Странно, что у Тройки другая частота. Или у нас в метро стоят «двухдиапазонные» ридеры? Почитаю еще на эту тему — пока только встречался с тем, что товарищи, которые пишут софт для Android, говорили, что читают обычные UltraLight и не могут прочитать Тройку, потому что там другая структура хранения данных.

Про модификации ридера я тоже упоминал, правда, про I2C (или это и есть «RX, TX»?). А основной геморрой, это, как по мне, так — немереное количество проводов у SPI. Других капризов пока не обнаружил.

Но, разумеется, примечания — по делу.
+
avatar
  • Sanja
  • 18 марта 2014, 13:01
0
Не, вроде как ещё проще — более распространённая модификация работает как серийное устройство (как древний модем или мышка с COM-портом — один провод на приём, другой на отправку. Указываете в коде скорость порта, подсоединились и работаем).
+
avatar
  • Prol
  • 30 ноября 2015, 19:37
0
из 5 карт «от метро», читаются только 2, возможно в чем-то несовместимость есть.
+
avatar
0
«Тройка» скорее всего не реализована в библиотеке, а так это Mifare Plus, сам чип имеет поддержку.

The MFRC522 supports all variants of the MIFARE Mini, MIFARE 1K,
MIFARE 4K, MIFARE Ultralight, MIFARE DESFire EV1 and MIFARE Plus RF
identification protocols.
+
avatar
  • bazis13
  • 18 марта 2014, 11:53
0
Отличный обзор!
«недорого, просто,» для зарядки ноутбука — это геркон, а не rfid-считыватель )
У меня сейчас 2 считывателя — такой же как в обзоре, и в 4 раза дороже на pn532. Никак не могу снова найти статью, где написано чем они отличаются. Только количеством интерфейсов?
Еще хочу спросить у какого-нибудь умного человека, как можно сделать внешнюю антенну к этому модулю?
Обязательно или отрезать антенну на плате и использовать экранированный кабель для подключения внешней антенны?
+
avatar
  • spc
  • 18 марта 2014, 12:23
0
Спасибо! И… да, что-то я заигрался. Ведь, действительно, геркона вполне достаточно )

Простым поиском нашелся PDF, в котором описаны возможности ридеров. Но это не столько сравнение, сколько именно что документация, т.е. таблички характеристик вручную сравнивать придется.
+
avatar
  • gogabig
  • 18 марта 2014, 11:58
0
Спасиб за интересный обзор, тоже «принюхивался» к этим считывателям, но моей фантазии не хватило придумать куда их мне присабачить. Читая Ваши посты здесь и на Хабре вижу что фонтан идей у Вас бъёт толстой струёй :-), успехов и новых обзоров ждём`с.
+
avatar
  • spc
  • 18 марта 2014, 12:46
0
Да, со струей пока, кажется, все в порядке :) Спасибо!
+
avatar
  • Duchich
  • 18 марта 2014, 12:43
0
Извините, если невнимательно проштудировал обзор на наличие интересующей меня информации.

Что за желтая плата подключена?
+
avatar
  • spc
  • 18 марта 2014, 12:46
+1
Это передатчик, который в данном случае используется для управления радиорозеткой. Я не акцентировал на нем внимание только по той причине, что прямого отношения к считывателю карточек он не имеет.
+
avatar
  • sledur
  • 18 марта 2014, 12:44
0
Однозначно плюс, пытливость приветствуется.
+
avatar
  • Dimmi
  • 18 марта 2014, 13:43
0
А что будет если поднести два ключа к считывателю? Будет работать с первым и игнорировать второй?
Есть идея сделать полочку/ёмкость для ключей и выполнять некоторые действия по приходу домой, после ухода. Как в отелях когда всё электричество включается/выключается в номере по карточке/брелку.
+
avatar
  • spc
  • 18 марта 2014, 14:05
0
Везде пишут, что по стандарту допускается нахождение нескольких карт в зоне действия считывателя. Считыватель при этом может выбрать нужную карту (по сериному номеру, подозреваю), она становится активной, а остальные — переводятся в пассив до следующего цикла поиска карт поблизости.

Я не проверял, что будет с несколькими картами у считывателя.
+
avatar
  • spc
  • 22 марта 2014, 00:04
0
Попробовал с двумя входящими в комплект картами и с простым стандартным примером DumpInfo из библиотеки RFID. При поднесении двух карт по очереди выводится содержимое обеих.

Т.е. сначала содержимое одной карты, потом — другой.

Причем порядок вывода не меняется, вне зависимости от того, какая карта сверху, а какая снизу. И также не играет роли, сколько раз этот сэндвич подносить. Порядок за пять раз был одним и тем же. Субъективно — сначала выводится содержимое карты с меньшим серийным номером, но не факт, что это правило.
+
avatar
  • Dimmi
  • 22 марта 2014, 22:11
0
Спасибо!
+
avatar
  • gord
  • 17 января 2015, 04:38
0
Интересует, будет ли работать при количестве более 10 в «бутерброде»/куче.
Не могли бы Вы проверить с максимальным количеством имеющихся меток?
Спасибо!
+
avatar
  • spc
  • 17 января 2015, 16:32
+1
У меня 4 метки. Будет время — проверю.
+
avatar
  • spc
  • 18 января 2015, 01:05
+1
В общем, это я думал, что у меня 4 метки. На самом деле три карточки и три брелка. Но брелки работают только по одному. Причина явления мне непонятна. А карточки — две читаются по очереди, а три — не читается ни одна (это в «сэндвиче», если подносить одновременно).

Это поведение с библиотекой MFRC522.
+
avatar
  • Prol
  • 30 ноября 2015, 19:46
0
у меня если поднести 2 карточки, ни одна не считывается.
+
avatar
  • Earnest
  • 18 марта 2014, 15:08
0
Спасибо. Интересно!
+
avatar
-1
адайте инвайт. хотя может не угадал)
+
avatar
0
SPI на меге и уно разведен отдельной 6-и пиновой колодкой. Назначения пинов гуглица по Atmel SPI pinout
+
avatar
  • spc
  • 19 марта 2014, 10:33
0
Разумеется. Только мне приходилось исходить из своей специфики: макетные провода покупал для подключения периферии к контроллеру. Поэтому провода типа папа-мама. А чтобы подключить ридер к колодке SPI, необходимы (если ничего не резать и не паять дополнительно) провода мама-мама.

Покупать здесь по конским ценам желания не было, ждать месяц из Китая — тоже. Поэтому подключился к пинам-дублерам.
+
avatar
  • dts
  • 18 марта 2014, 22:16
0
СКД для домашних животных
а как кота заставить прикладывать карту?
+
avatar
+1
выдавать еду по факту успешного прикладывания
жрать захочет — научится
+
avatar
  • spc
  • 19 марта 2014, 10:34
0
обычно вешают брелок на ошейник, и этим решают вопрос с прикладыванием
+
avatar
  • IVA2
  • 19 марта 2014, 23:22
0
Спасибо за обзор. Как раз присмативался к Ардуинкам и РФИДам.
+
avatar
0
Огромное спасибо за отличный обзор.
+
avatar
  • mu3
  • 29 марта 2014, 23:03
0
Нечто похожее, но с USB (примерно по той же цене). Заказал себе на потестить.
+
avatar
0
Он совместим только с картами EM-Marin, там другая частота, нет поддержки ISO14443
+
avatar
0
а дайте пожалуйста ссылочку на такую плату I2C? Обыскался, не нашёл такую, думаю уже такую же как у вас заказывать.
Как сделать читалку карт подальше от самой адруины? Можно как-нибудь вывести подлиннее антенну или удлинять сами провода SPI?
+
avatar
  • spc
  • 19 апреля 2014, 02:18
+1
Например, ищите по сочетанию «PN532» — это, судя по всему универсальная плата с SPI и I2C на борту. Не уверен, что можно удлиннить подводку к антенне: во-первых, по затуханию сигнала, во-вторых, потому, что антенна банально разведена на плате и ее оттуда не достать, а новую антенну еще надо постараться сделать. Но если верить интернету, то длина самой шины I2C может достигать нескольких метров (упоминается от 3 м до 100 м, но, очевидно, в зависимости от типа применяемого кабеля). Также упоминается, что длина шины данных упирается в ее максимальную емкость, которая для I2C указывается в пределах 400-500 пФ. Однако на сайте i2c-bus.org также говорится, что крайне желательна минимальная длина шины.

Опять же, речь идет про шину. А вот определиться с питанием считывателя придется отдельно, поскольку на больших дистанциях напряжение может заметно проседать, и если его считывателю не хватит, работать ничего не будет, даже если длина самой шины данных не выходит за пределы ограничений.
+
avatar
+1
всё что могу найти по pn532 в 4-5 раз дороже этой
питание-то я без проблем сделаю, вопрос только в данных
взял 522
+
avatar
0
RC522 умеет I2C, UART, SPI, распиновка есть в даташите на чип

Supported host interfaces
 SPI up to 10 Mbit/s
 I2C-bus interface up to 400 kBd in Fast mode, up to 3400 kBd in High-speed mode
 RS232 Serial UART up to 1228.8 kBd, with voltage levels dependant on pin
voltage supply
+
avatar
  • Ratio
  • 02 июня 2017, 23:17
0
Только плата распаяна под spi, чтобы превратить ее в i2c нужно:
1. Оторвать ногу 1 от — и приделать к + (например к соседней ноге 2)
2. Ноги 25-28 и пины MOSI и SCK приделать к -/+ в зависимости от необходимого адреса (возможно будет работать и без этого)
3. SCL шины i2c воткнуть в MISO
+
avatar
0
Более интересно эмулировать любую MIFARE карту с помощью RC522, по идее сам чип так должен уметь.

PS сам чип имеет на борту сразу все интерфейсы, I2C, UART, SPI. Выбор происходит автоматически, подробнее есть информация в даташите на RC522
+
avatar
  • oldman
  • 20 августа 2014, 18:36
0
… читаю несколько месяцев всякие описания RFID на базе RC-522 и недоумеваю — у всех все работает!!! :) Купил и себе это китайское чудо ( два комплекта синие). Бился пару месяцев изучая чужой опыт. Результат нулевой. Многозначительные намеки на ошибки в библиотеках и распиновках и советы не помогли. Купил у другого продавца — пришли платы не совсем похожие на первые и маркировка
на чипе 07 04 во второй строчке в отличие от первого 12 02 и разводка немного по другому выполнена. Все похоже на издевательство. Может кто нибудь по шагам описать как это чудо запустиь хотябы на считывание? Какие библиотеки использывались? Примеры все которые в поисковиках попробовал ни один не работает :((( библиотеки перебрал все что нашел. Не дайте сойти с ума… В интернете кочуют описания как две капли похожие друг на друга, слово в слово. Есть реальные люди кто это запустил?
+
avatar
  • spc
  • 20 августа 2014, 23:30
0
Наверное, я не очень хорошо понимаю суть вопроса, поскольку в тексте выше:

а) по шагам расписан запуск этого чуда именно что на чтение
б) использованные библиотеки
в) примеры кода
г) видеодемонстрация работы (к вопросу о реальных людях — там даже моя рука видна)

Что касается намеков по распиновке, то это, может, в моем исполнении — намеки, а по факту надо просто следовать документации на Arduino, и все.
+
avatar
  • oldman
  • 21 августа 2014, 07:42
0
Здравствуйте. Мой комментарий на самом деле выглядит наверно сумбурно. Простите. Я ни кого не хочу обидит просто хочу понять как это у всех работает и почему у меня нет даже намека на работу. Теперь по порядку:
-если я вас правильно понял библиотеки вы использовали megelBalboa? «Библиотека RFID». О чем идет речь: Отсюда рекомендация: если библиотека RFID не запустится при подключении с распиновкой с сайта Arduino.cc, то имеет смысл попробовать китайскую библиотеку. Это какую???
— вы пишите о И для Uno (ее не проверял):
Uno RC522
3.3V VCC
GND GND
5 RST

12 MISO
11 MOSI
13 SCK
10 NSS
это правильная распиновка ???
— путаница с выводом RST все таки куда он куда его подключать к «RESET», 5 или 9 ??? и опять в меге RESET это какой вывод??? если скетче написан явно вывод типа #define RST_PIN 9 и он так и подключен физически к 9 это неправильно???
-вывод SDA на модуле соответствует NSS ???
— SPI SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). These pins support SPI communication using the SPI library. В чем ошибка??? Где в скетче или в библиотеке?
— не в вашей статье читал к сожалению не могу привести ссылку что есть разница между чипами разных годов выпуска это так?
Можно Вас просить ответить на все вопросы если Вас это не затруднит. Спасибо за ранее.
+
avatar
  • spc
  • 21 августа 2014, 11:12
0
Честно говоря, прекрасно вас понимаю. Сам пребывал в несколько расстроенном состоянии, когда не смог с первого раза добиться работы считывателя. Даже подумал, что получил неисправный. Но так как заказал сразу несколько, то попробовал второй, а когда и там получил тот же (нерабочий) результат, то подумал, что с высокой долей вероятности имею дело с проблемой подключения, поскольку хоть это и китайцы, но в нескольких аналогичных устройствах обязательно находится исправное.

Теперь по пунктам.

Ссылка на опыт с китайским кодом есть в тексте ) Правда, автор немного поменял структуру сайта, но по оригинальной ссылке все равно показывается правильная ссылка. И прямая ссылка на китайский скетч.

Аналогично, официальная «распиновка» Arduino Uno доступна на сайте Arduino.cc. По понятным причинам ссылку на него я не приводил.

Путаницы с выводом RST нет, поскольку он, как я понимаю, не входит в используемый протокол SPI, и, соответственно, может подключаться к любому свободному цифровому пину Arduino. Поэтому он и задается в скетче (в отличие от жестко закрепленных в железе пинов SPI).

Когда я разбирался с подключением, то в целом гугление привело к выводу, что SS Эквивалентно NSS, а в случае с данным конкретным чипом RC522, этот сигнал или линия (не знаю, что правильнее) доступен на выводе, промаркированном SDA.

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

Распиновка, соответственно, по моему мнению — верная.

По поводу различий между версиями чипов ничего полезного сообщить не могу: этим вопросом не интересовался, поскольку добился работоспособности считывателя, и на этом остановился.
+
avatar
  • oldman
  • 21 августа 2014, 12:23
0
… еще раз внимательно все проверил распиновку… скетч китайский… не работает %(((( может в версии IDE дело? Откатить на старую попробовать… уже просто денег жалко честно говоря и времени ждать посылки… я в шоке. Может в KIT-е придет правильный, одна надежда осталась. Спасибо за помощь
+
avatar
  • spc
  • 21 августа 2014, 12:52
0
Сложно предполагать, что именно. Нюансы везде свои.
+
avatar
  • Graft
  • 31 августа 2014, 22:15
0
Здравствуйте. Купил такой же модуль, но пока ни могу понять, карту московского метро читает без проблем, но карточку и брелок которые шли в комплекте не читает. Не подскажите в чём может быть проблема?
+
avatar
  • spc
  • 01 сентября 2014, 11:25
0
Добрый день, поведение довольно странное, поскольку, если все верно, то карточка и брелок в комплекте должны быть того же стандарта, что и карта метро. Однако похоже, что у вас или неисправные комплектные брелки/карточки, что маловероятно, либо они другого стандарта (например, китайцы перепутали при комплектации).

Других вариантов, если карточки метро читаются, я придумать не могу.
+
avatar
  • Graft
  • 01 сентября 2014, 14:04
0
А различить, я так понимаю нет возможности?
+
avatar
  • spc
  • 01 сентября 2014, 23:12
0
Я сейчас посмотрел на брелки — по ним действительно не понять, что за стандарт. По крайней мере, я бы не стал ручаться.
+
avatar
  • Cobe
  • 12 ноября 2014, 03:14
0
Здравствуйте. Не могу понять, карточку и брелок которые шли в комплекте читает без проблема. Но билеты от Московского метрополитена пробовал, пробовал — никак не читает. Подскажите пожалуйста в чём может быть проблема ? ( Arduino Uno r3 + RC522 )
+
avatar
  • spc
  • 12 ноября 2014, 11:06
0
Добрый день. Честно говоря, идей не так уж много. Некоторые билеты действительно не читаются, причем я не знаю, почему. По крайней мере несколько раз было так, что билеты с нулевым количеством поездок не читались. А вот если на билете еще оставалась пара поездок — то читались.

Так что, возможно, имеет смысл или собрать больше использованных, или попробовать с билетом, на котором еще есть поездки.
+
avatar
0
Скажите, а есть ли возможность подключить несколько таких устройств к одной ардуине? SPI, на сколько я понял позволяет. Загвоздка в библиотеке.?
+
avatar
  • spc
  • 16 декабря 2014, 00:45
0
Библиотека, возможно, тоже позволяет. Это, правда, теоретическое заключение, основанное на том, что для начала работы со считывателем создается объект (в примере это «MFRC522 mfrc522(SS_PIN, RST_PIN);»).

Соответственно, ничто не мешает сделать несколько объектов. Вопрос правда в том, как выбирать нужный. Т.е. достаточно ли методов mfrc522.PCD_Init(); и mfrc522.PICC_HaltA();, или же есть дополнительный метод, который управляет сигналом SS.
+
avatar
+1
эксперимент показал что несколько устройств прекрасно работают с одной ардуиной. Более того для чтения карты ресет пин можно не подключать. Т.е. к уно можно подключить пять кардридеров. Но на практике я подключил два (больше под рукой не нашлось)
+
avatar
  • spc
  • 17 декабря 2014, 14:20
0
Спасибо за информацию! А покажете, как это в коде реализуется?
+
avatar
+1
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define SS_PIN1 5
MFRC522 mfrc522(SS_PIN, 0); // Create MFRC522 instance.
MFRC522 mfrc523(SS_PIN1, 0); // Create MFRC523 instance.
unsigned long uidDec, uidDecTemp;

boolean Red1 = false;
boolean Red2 = false;
boolean Blue1 = false;
boolean Blue2 = false;

void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
mfrc523.PCD_Init(); // Init MFRC523 card
Serial.println(«Waiting for card...»);
}

void loop() {
byte status;
byte byteCount;
byte buffer[2]; // длина массива (16 байт + 2 байта контрольная сумма)
byteCount = sizeof(buffer);
uidDec = 0;

status = mfrc522.PICC_RequestA(buffer, &byteCount);
if (mfrc522.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
uidDecTemp=mfrc522.uid.uidByte[i];
uidDec=uidDec*256+uidDecTemp;
}
if ((uidDec==46015106) && (Red1==false)){
Serial.println(«Red Card logged on Rider 1»);
Red1=true;
Red2=false;
}
if ((uidDec==3546663646) && (Blue1==false)){
Serial.println(«Blue Card logged on Rider 1»);
Blue1=true;
Blue2=false;
}
}
status = mfrc523.PICC_RequestA(buffer, &byteCount);
if (mfrc523.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc523.uid.size; i++) {
uidDecTemp=mfrc523.uid.uidByte[i];
uidDec=uidDec*256+uidDecTemp;
}
if ((uidDec==46015106) && (Red2==false)){
Serial.println(«Red Card logged on Rider 2»);
Red2=true;
Red1=false;
}
if ((uidDec==3546663646) && (Blue2==false)){
Serial.println(«Blue Card logged on Rider 2»);
Blue2=true;
Blue1=false;
}
}
}
+
avatar
  • spc
  • 19 декабря 2014, 00:18
0
И еще раз спасибо!
+
avatar
0
if (Если не умерла еще тема) {
Блин, у меня тоже проблема — не читаются карты единых билетов… То есть родные брелок и карточка идут на ура, с разными библиотеками и скетчами, из этого сайта и многих других, пробовал MFRC522-master, MFRC522, RFID. А вот больше- ничего. Ни карты единых билетов (30шт.), ни карты тройки, ни социальная карта, ни банковская, ни пропуск, ни брелок от домофона… Такое впечатление, что диапазон не тот. Хотя покупал как 13,56 МГц. Тут по просторам паутины встречаются заявления о частоте 150КГц. Как бы это выяснить точно, 1. на какой частоте все-таки работают единые билеты? 2. Возможна ли подстройка частоты модуля программно? 3. Может там есть каналы, как у блютуса? 4. А может у меня 150КГц, ну, типа, продавец перепутал, как ,s простыми средствами определить частоту?
Народ! Если кто ткнет носом, куда копать, буду благодарен!
}
+
avatar
  • spc
  • 29 января 2015, 11:23
0
Копать, очевидно, во-первых, в направлении даташита MFRC522, где однозначно (насколько я понял) указано, что для данного чипа несущая частота 13.56 МГц и других вариантов не предусмотрено.

Во-вторых, в сторону производителя билетов метро. Кто их делает я, если честно, не в курсе. Теоретически Микрон хвалился этим безумным достижением. Однако потом я читал, что кто-то потрошил билеты, и нашел на чипе маркировку совсем не Микрона. Но это лишь мои туманные воспоминания.

Что касается самого интернета, то он на все сто уверен, что билеты метро предназначены для систем 13.56 МГц.

А «не читается» — это ридер вообще карты не видит, или же библиотека не может вывести содержимое?
+
avatar
0
Спасибо за отклик. Не читается — не реагирует вообще, словно и не подносишь ничего. Кст. брал у друга радиосканер, проверил частоту — действительно, 13,56 точнее занимает полосу от 13,55 до 13,57 так что к продавцу вопросов нет, ничего не перепутал… Хотя, может бывают какие модификации или предустановки, действительно, надо даташит почитать…
+
avatar
+1
Вот, добавлю информацию, может кому поможет. Вобщем речь у меня шла о считывателе таком-же, но из ебея. И я подумав заказал еще один у продавца из шапки. И вот вчера получил. Блин, прочел все 30 моих полностью использованных карточек метро. Пробовал сначала на коротком скетче из примера с rfid библиотекой, затем 1й монстр из статьи с mfrc522 соответственно. Все работает. Попробовал домучить первый считыватель, появилась мысль что может питания не хватает — попробовал 3,3В от мощного стабилизатора — не помогло, поднял напряжение до 3,7В — не помогло, отключил 3,3В полностью — не помогло, хотя продолжает считывать брелки и даже светодиод горит, потеха… Наверное надо делать вывод о некондиционном экземпляре. Вот.
+
avatar
  • spc
  • 18 февраля 2015, 11:38
0
Спасибо за информацию!
+
avatar
  • droncs46
  • 10 февраля 2015, 22:39
0
Можно ли увеличить радиус считывания?
+
avatar
  • spc
  • 11 февраля 2015, 09:51
0
Вот об этом я не в курсе.
+
avatar
0
Когда я игрался со своим модулем, пробовал разные библиотеки и заметил, что одни читают увереннее, другие хуже. Мне больше всего понравилась RFID — радиус около 3-4 см. Для большего радиуса думаю нужны внешние антенны. Видел в продаже модули, к ним нужно самому лепить антенну — катушку провода. при этом радиус зависит от размера катушки и достигает 0,5м.
+
avatar
  • Cobe
  • 11 апреля 2015, 23:22
0
Спасибо за информацию нику geg_nuxmo. Я тоже купил 2 шт. у продавца из шапки. 30 использованных карточек метро, один прочитал
20 шт. а тарой 15 шт.,. Но поводом карточки и брелки которые шли в комплекте, карточки читает а брелки нет.
+
avatar
  • Cobe
  • 13 апреля 2015, 01:18
0
Добавлю еще о считывателе таком-же о котором я раньше писал, куплен в Москве карточку и брелок которые шли комплекте читает без проблема, а тоже считыватели с aliexpressа. Карточки и брелки из этих двух комплекта с aliexpressа первый считывател не читает. Почему?
+
avatar
0
Прочитав вашу статью собрал такой прибор. govnodav-1990.livejournal.com/2741.html
Не подскажите, нету ли библиотек под mfrc522, которые поддерживают тройку?
Ведь на сколько мне известно из даташита, mfrc 522 совместим с тройкой. Хотя так как тройка это Mifare Plus SL1 (в режиме совместимости с 1k) ардуина будет видеть ее как mifare 1k.
+
avatar
  • spc
  • 23 апреля 2015, 09:32
0
Я, если честно, сначала не встречал, а потом не искал — когда где-то прочитал, что Тройка этим считывателем не распознается.
+
avatar
0
Понятно, придется покупать пн532
+
avatar
  • vint_x
  • 30 апреля 2015, 16:00
0
Спасибо автору за обзор. Мне недавно пришел подобный модуль и тоже, читает лишь карточки формата mifare 1k. Остальные — ноль реакции, уже и библиотеку всю перекопал и даташит на предмет конфигурации чипа, но везде утыкаюсь, что должен он читать и все тут.
Можете прислать точное название на чипа вплоть до каждой закорючки? У меня последнее подозрение, что разные модификации чипов.
+
avatar
  • spc
  • 30 апреля 2015, 22:01
+1
+
avatar
  • vint_x
  • 07 мая 2015, 11:02
0
Спасибо за фото. Видно, что разные серии, но все равно никак не пойму, почему так. в даташите пишут что все работать должно, а на деле нет
+
avatar
0
А сможет ли кто-нибудь объяснить для какой цели используется контакт rst на считывателе rc522?
Дело в том, что если его оставить неподключенным, то считыватель прекрасно работает на чтение и без него. На запись не пробовал.
Я подключил 4 считывателя к одной UNO. Работают. Но иногда(раз в сутки) возникают странные зависания случайного считывателя. Вот у меня возникла мысль, а не из за того ли это, что у меня никуда не притянут rst…
+
avatar
  • spc
  • 03 июня 2015, 13:54
0
Если почитать текст библиотеки, то становится ясно, что по крайней мере при инициализации чипа эта линия нужна для аппаратной перезагрузки. Целиком я текст не читал, но смысл, RST, думаю, понятен.

void MFRC522::PCD_Init() {
	if (digitalRead(_resetPowerDownPin) == LOW) {	//The MFRC522 chip is in power down mode.
		digitalWrite(_resetPowerDownPin, HIGH);		// Exit power down mode. This triggers a hard reset.
		// Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74�s. Let us be generous: 50ms.
		delay(50);
+
avatar
0
ну да. тоже увидел теперь. работать должно только при высоком уровне в rst контакте. у меня он висит в воздухе. почему же оно вообще у меня работает?
+
avatar
  • spc
  • 03 июня 2015, 14:31
0
Формально из кода не следует, что «работать должно при высоком уровне». Из кода следует, что если на этой линии низкий уровень, то ее следует перевести в высокий. Но это — со стороны управляющего контроллера, а не со стороны ридера.

Собственно, я лишь хотел сказать, что линия RST нужна для принудительного сброса ридера при его инициализации. И, возможно, в каких-то других случаях. Если же она не подключена, то в библиотеке, если я не путаю, есть еще программный сброс, но, вероятно, его бывает недостаточно для приведения ридера в чувство.

Опять же, так как я библиотеку целиком не вычитывал, то не уверен, что аппаратный сброс через RST используется где-то еще кроме инициализации ридера.
+
avatar
0
Из кода следует, что если на этой линии низкий уровень, то ее следует перевести в высокий. Но это — со стороны управляющего контроллера, а не со стороны ридера.
Вероятнее всего, сам ридер сообщает — низким уровнем на ноге, что находится в режиме сна, и чтоб его разбудить необходимо на ногу подать «1». Это написано в библиотеке, в комменте.

Правда вот и с моим ридером тоже есть проблема, программный сброс наглухо вешает сам ридер, но как то странно, версию чипа я могу узнать, усиление антенны могу узнать, а вот при инициализации самотеста, все — «висяк», и висяк происходит именно при программном сбросе (в процедуре сброса есть цикл с условием, что пока ридер не отдаст в регисрте значение, цикл повторять).

Заметил еще такую непонятку, я заказал 10 карточек, первый ридер версии 2.0 читает только 3-4, остальные не видит (я уж было расстроился, что карточки мертвые), а вот другой ридер версии 1.0 прочитал все на ура. В версии 2.0 не получается читать стопку карточек, в 1.0 все без проблем. Разница во внешнем виде ридеров заключается в типе кварца, если он с ножками, то версия 2.0, если с контактами для поверхностного монтажа то версия 1.0, но это моя догадка, из 3 ридеров — 2шт. версии 2.0 (кварц с ногами) один версии 1.0, и на сайтах кит. продавцов тоже разные фотки.
+
avatar
  • Ratio
  • 02 июня 2017, 23:37
0
Согласно спеке этот пин работает только на вход. Следовательно код включает ридер, если он еще не включен.
Если оба пина работают на выход с разной полярностью, то это попахиват кз.
+
avatar
  • kityan
  • 26 июля 2015, 00:12
0
Спасибо за статью. Пробую и вот что странно.
Брелок в комплекте не читается — ну и фиг с ним. Может дефект, а может положили 125 кГц-овый.
Но вот карта в комплекте — читается нормально. И также на NFC Shield (Seeedstudio).
А вот метрошные карты (красные), которые прекрасно читаются на шиелде, этим модулем — не всегда.
Несколько карт купленных в июле 2015. Напросвет видно, что конфигурация в месте подсоединения антенны к чипу — разная. То есть карты различаются… Вот так.
+
avatar
  • spc
  • 26 июля 2015, 21:19
0
С одной стороны да, карты могут быть разные, с другой — ридеры в метро ведь не менялись, а это значит, что с высокой долей вероятности поменялись протоколы обмена. Почему не частота? Мне кажется, что с учетом далеко не одномоментной замены синих на красные были бы проблемы с частотой (можно, конечно, предположить, что ридер сканирует в нескольких диапазонах, но это же прямое влияние на цену железки).

Если думать о протоколе, я даже не знаю, что тут можно придумать.
+
avatar
  • tipgeroi
  • 19 сентября 2015, 23:42
0
А можно спросить может кто знает как реализовать такое?
по суnи радиоудлители ИК пультов есть и RFID 125kHz не как не найду
во вложении схема.Сразу спасибо за любую инфу.
yadi.sk/i/cvx-wXqPjC7TQ
+
avatar
  • MiG
  • 26 сентября 2015, 22:37
0
Обзор вроде весь перечитал, но кое-что так и осталось для меня не ясно. В обзоре написано, что данный считыватель отлично и записывает информацию, но как это реализовано нигде не нашел. Т.е. ну купил я данный считыватель, ну расключил на ардуинке, ну скачал библиотеку и запустил скетч, поднес ключ считал коды. А как будет вестись запись, в какой моммент и есть ли для этого уже готовы скетч?
+
avatar
  • spc
  • 27 сентября 2015, 21:27
0
В библиотеке для работы со считывателем есть функции записи, так что записывать можете, когда пожелаете. Но имейте в виду, что я описывал запись данных в прилагаемую карту Mifare, и запись данных, насколько я понимаю, еще не означает клонирование.
+
avatar
0
У меня тое какая то проблема с этим модулем, ключи из комплекта не читает, других нету, DumpInfo.ino останавливается на выводе версии ридера v2.0, firmware_check.ino дальше Performing test… не заходит, у вас тоже так?
Раз читает версию делаю вывод что подключил правильно но застрявание на firmware_check заставляет усомниться в его работоспособности. Если где то в коде вызвать PCD_Reset() то программа из while (PCD_ReadRegister(CommandReg) & (1<<4)) {} не выходит никогда.
Пробовал читать разные регистры, в суть их значения не вникал ну приходят не 0 и значения постоянные.
Также ggrfid.ino тоже не работает.

Пациент мертв или еще есть надежда?
+
avatar
  • spc
  • 02 ноября 2015, 22:56
0
К сожалению, уже вечность не пользовался ридерами, поэтому много чего успел забыть. Сейчас пересмотрел видео (в обзоре) — там вообще нет вывода версии ридера, только информация с карты. Вы точно пробовали библиотеки, которыми пользовался я?
+
avatar
0
Разные пробывал и та что вы полььзовались тоже.
в примере github.com/miguelbalboa/rfid/blob/master/examples/DumpInfo/DumpInfo.ino есть вывод версии.
+
avatar
+1
Проблема была в дефектном ридере, с другим все заработало
+
avatar
  • spc
  • 07 ноября 2015, 23:33
0
Спасибо! Учту на случай, если у кого-то будет аналогичная ситуация.
+
avatar
0
Помогите зделать дубликатор ключес Отпишитесь плиз на Mindezek@gmail.com
+
avatar
  • spc
  • 08 января 2016, 20:55
+1
Простите, я не умею.
+
avatar
  • YurOl
  • 29 апреля 2016, 03:07
0
В результате простых испытаний, которые я все-таки выполнил, также выяснилось, что считыватель нормально записывает (вот такая игра слов) карты MIFARE 1K из тех, что были с ним в комплекте.

САМИ пишите, что считыватель нормально ЗАПИСЫВАЕТ!!!, а потом говорите что не умеете… Вы как-то определитесь ) Человек именно об этом Вас и спрашивал, ибо в комплекте идут «пустые» брелок и карточка, все описывают как прописать карты метро в данном проекте, но никто не упоминает как например скопировать UID — идентификатор уже использованной карты метрополитена на эти новые чистые заготовки, что идут в комплекте.
+
avatar
0
День добрый, нет ли у вас сборочного чертежа этой платки, вместе с отверстиями под крепеж? Могучий гугл не помогает, а пока плата из Китая дойдет…
+
avatar
  • spc
  • 15 апреля 2016, 21:52
0
Добрый! К сожалению, такой штуки нет. У меня только сами платы.
+
avatar
  • Tomasina
  • 11 октября 2016, 23:45
0
для чего нужна переменная status, если она потом нигде не задействована?

И основное:
uidDec=uidDec*256+uidDecTemp; < — это мне понятно, из нескольких блоков формируем единое число, так с ним проще работать.

а вот как потом сделать обратное — из этого числа восстановить числа в блоках?
Т.е. из uidDec=2218415941 обратно получить номер метки в виде 0xAA, 0xBB, 0xCC, 0DD.
+
avatar
  • spc
  • 12 октября 2016, 10:37
0
Переменная status — наследие прошлой версии кода, здесь она действительно лишняя.

Я пробежался по верхам, поэтому прошу прощения, если вдруг ошибусь.

Исходные: UID бывают 4-байтовыми и 7-байтовыми. Если судить по одному из номеров, которые есть на видео в обзоре, то мне попались 4-байтовые.

Экспериментировать будем с UID 1644442498, благо в том же тексте есть и дамп карты, где виден UID:

Card UID: 04 6F 25 62 04 33 82
PICC type: MIFARE Ultralight or Ultralight C

Page 0 1 2 3
0 04 6F 25 C6
1 62 04 33 82
Сразу очевидный вопрос: почему так получается, что сверху написан UID из 7 байтов, а я считаю, что он состоит из 4? Мне пришлось сделать такое допущение, потому что UID в десятичной системе соответствует 4 байтам, а никак не семи.

В данном случае 1644442498 соответствует 62 04 33 82. Ну и для меня самый простой способ вернуть все как было — использовать битовые операции. Т.е. читаем по байту из десятичного UID, каждый байт соответствует «блоку» в шестнадцатиричном UID.

Вот такой тестовый код нормально развернул десятиричный UID в четыре блока HEX (условно, конечно — для отображения HEX я использовал форматирование при выводе):

#define uid 1644442498

byte tempByte = 0;
int bitCount = 31;

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
 while (bitCount > 0) {
  for (byte i = 0; i < 7; i++) {
    if (bitRead(uid, bitCount-i) == 1) {
      bitSet(tempByte, 7-i);
    }
  }
  bitCount = bitCount - 8;
  Serial.print(tempByte, HEX);
  Serial.print(" ");
  tempByte = 0;
  }

}

void loop() {
  // put your main code here, to run repeatedly:

}
+
avatar
  • don27
  • 05 ноября 2016, 17:32
0
При компиляции «монстра» выдается сообщение:
invalid conversion from 'byte {aka unsigned char}' to 'MFRC522::StatusCode' [-fpermissive]
выделенная строка скетча:
Serial.println(mfrc522.GetStatusCodeName(status));
Что-то не так с форматированием при выводе? Помогите пож. разобраться и запустить «монстра».
Сейчас я закомментировал эту строку и выдается только UID карточки. Хочется чтобы работал весь функционал «монстра».
+
avatar
  • spc
  • 05 ноября 2016, 23:15
0
попробуйте в коде заменить

byte status;


на

MFRC522::StatusCode status;
+
avatar
  • don27
  • 05 ноября 2016, 23:52
0
Теперь пишет:
invalid conversion from 'byte {aka unsigned char}' to 'MFRC522::PICC_Type' [-fpermissive]
+
avatar
  • spc
  • 06 ноября 2016, 00:02
0
Тогда надо найти строку

piccType  = mfrc522.PICC_GetType(mfrc522.uid.sak); // запрос типа


и заменить на

MFRC522::PICC_Type piccType  = mfrc522.PICC_GetType(mfrc522.uid.sak); // запрос типа
+
avatar
  • don27
  • 06 ноября 2016, 00:29
0
Теперь ошибок нет. Карту из комплекта и соцкарту распознает как:
MIFARE 1KB, пишет: Card type: Not a valid card:4
и привет.
+
avatar
  • don27
  • 06 ноября 2016, 00:51
0
Привет — в смысле завершения работы программы. Что такое MIFARE 1KB и 4? В вашем списке поддерживаемых карт такой нет.
+
avatar
  • spc
  • 06 ноября 2016, 01:19
0
Вопрос в другом: а что именно вы ждете от «монстра»? Этот код написан для работы с картами Ultralight, которые используются в московском метро.

Т.е. это совсем частный случай. Если вы хотите чего-то другого, то и код будет другой.
+
avatar
  • don27
  • 06 ноября 2016, 01:50
0
Большое спасибо за помощь. У меня нет карт метро. В принципе мне достаточно номера карты для моих целей.
+
avatar
  • spc
  • 06 ноября 2016, 09:29
0
Рад, что удалось помочь. В таком случае то, как я понимаю ситуацию.

Mifare — один из видов беспроводных карт (еще, к примеру, есть EM-Marin, но с ним ридер несовместим).

1K — это объем памяти карты. То есть, там килобайт памяти для данных пользователя.

4 — это тип то ли по классификации Mifare, то ли по мнению автора библиотеки MFRC522.

Что касается применения, то имейте в виду, что с расчетом на карты метро в «монстре» много лишнего — то же чтение даты выпуска/годности вместе с вычислением високосного года.

Плюс то же вычисление идентификатора в десятичном виде. Для карт метро это удобно, потому что на них напечатан именно десятичный номер.

Если же у карты нет такого «серийного» номера, а на напечатан ее UID (тоже какой-то уникальный номер (или вообще не напечатан), то все, что сделано для метро — лишнее.

Собственно, я к чему. У Mifare 1K (из комплекта ридера), как я помню, вот этого самого десятичного номера нет.
+
avatar
  • arbatjc
  • 07 января 2018, 12:17
0
Для тех, кто захочет как я, побаловаться с китайскими клонами Уно/Нано…
MFRC522 UNO/Nano v3
RST -> D9
SDA(SS) -> D10
MOSI -> D11
MISO -> D12
SCK -> D13
3V3 -> 3v3
GND -> GND
— В скетче автора исправить вмеcто #define SS_PIN 53, на (#define SS_PIN 10).
В противном случае, в таком случае(без исправления) работать с Нано/Уно, не будет. Скорость порта терминала — строго 9600.
Хотелось бы теперь разжиться скетчем, для записи и клонирования(записи) любой из разновидности карт, есть потребность, может у автора есть наработки?
+
avatar
  • spc
  • 07 января 2018, 12:41
0
Честно говоря, я так распиновку и написал в тексте, никакого открытия Америки здесь нет. И точно так же она приведена в описании библиотеки, которая действительно изначально сконфигурирована для Mega.

Китайский клон, или оригинал — роли не играет. Ну хотя бы потому, что у меня ни одной оригинальной платы нет.

Нет, я не занимался клонированием карт, и даже не интересовался этим вопросом.
+
avatar
  • arbatjc
  • 08 января 2018, 10:11
0
Вы о моей «Америке», или о вашей?
Я почитав ваш отчёт, захотел запустить на более простых клонах из доступных у меня. Не получилось. И о распиновке было «не оч», мутно. Да и в скетче оптимизация под вашу доску. Есть такое дело? Обидок, полагаю нет?
Результат порадовал, запустилось, работает о чем и благодарю, но указываю нюансы на будущее таким же как я. Ну или вам, скажем на развитие.
Да, билетики, как проверка даты и поездок работает, отлично. Я просто дальше пошёл, хотел не трогая их, перезаписать штатную 1кб карточку идущую в комплекте со считывателем.
Суть то моих желаний проста, для клонирования или записи дубликата пропускной системы. Сами же знаете, школьные, студенческие и на многих предприятиях подобное… Вот и понадобилось, на случай утери/порчи. Вдруг у вас наработка была/есть…
+
avatar
  • spc
  • 08 января 2018, 10:32
0
Да вообще о любой америке, поскольку все мои проблемы случились не от того, что не знал или не было написано. А просто от невнимательности, которая от уровня знаний не зависит никак. Ну, то есть, я сам себе буратина. В общем, прошу прощения, что недостаточно четко указал различия подключения для разных плат.

Перезаписью я не занимался по трем причинам: у меня не было таких задач (и не предвидится), судя по описанию, копирование будет заметно сложнее (если есть защита) просто чтения, и не хотелось прямо вот здесь создавать некий задел с прицелом на потенциально противоправные действия (потому что кому надо — и так сделает, а остальным не имеет смысла просто так себя подставлять).
+
avatar
  • arbatjc
  • 08 января 2018, 12:36
0
Спасибо. Я понимаю, буратины — они такие, я сам такой… :-)
Да я ни о какой противоправности и в помине не имел, даже если вам так показалось. Объясню просто и на пальцах. Смотрите, в комплекте со считывателем идет «болванка» PICC type: MIFARE 1KB. Вот и хотел её попробовать пустить в дело, благо есть куда. Теперь о том «куда»…

Есть несколько пропускных пунктов посредством таких карт. Устанавливала её «под ключ» сторонняя организация. Потерял/сломал ключ, попасть никак и надо к ним на поклон ехать, делать дубликат за денежку. Нужно коллегам/родственникам (второе место) попасть, никак — только оставлять свою. И не дай Бог чего… Опять тупик. Эти карты работают как ключ от домофона, реально. Вот по-этому и задался практическим вопросом.

Третий вариант, потерянный сломанный пропуск в учебное заведение. Нужно знать хорошо детей, что бы понимать, сколько за один учебный год, они их теряют. Каждый новый, помимо объяснительных, стоит 300 рублей. Какие тут заделы на противоправность?

Я же не говорю вам о всяких пре-пеид картах транспорта и все такое, ясно, что нафиг нужно! Кстати попробовал ради интереса тройку, не читает сколько осталось поездок и срок. Ну этот так, к слову.
Ладно, я вас услышал, отстаю…
+
avatar
  • Cobe
  • 31 января 2018, 17:21
0
Здравствуйте.Билеты на Московское метро (2014,2015,2016 г.) ваш скетч читал правильно а сейчас нет (2017,2018 г.).Как я понял что сейчас данные записываються в других сектора.Помогите пожалуйста, переделайте ваш скетч.Заранее спасибо.
Фото: 1-Dumpinfo, Фото: 2 ваш скетч (поездок осталось 6 шт.срок действия 90 дней) по 02.01.2018.
Фото: 3 Dumpinfo, Фото: 4 ваш скетч(поездок осталось 1 шт.срок действия 90 дней) по 18.06.2017.
Фото: 5 Dumpinfo хороший (поездок осталось 23шт. 90 дней) по 17.03. 2016
+
avatar
  • Cobe
  • 31 января 2018, 17:29
0
+
avatar
  • spc
  • 01 февраля 2018, 11:03
0
Теоретически могу попробовать, когда будет время. Но от вас — несколько подряд дампов одного и того же билета после каждой поездки. Т.е. прошли через турникет один раз — дамп, прошли еще раз — дамп. Лучше не меньше трех — пяти.

Судя по всему, вообще поменялся формат данных, потому что в новых дампах отсутствует значение 5A (90 в десятичной системе), то есть не виден срок действия. Вероятно, его показывают по другому — или в зашифрованном виде, или в виде количества оставшихся дней.

Результат не гарантирую, как и то, что сделаю в ближайшее время. Поэтому решать вам — нужна вам эта суета с дампами, или нет.
+
avatar
  • Cobe
  • 07 февраля 2018, 00:54
0
Билет на много поездок сейчас мне не нужен, купил на 2 поездки (срок действия 5 дней)
Фото:1- без поездки
Фото:2- первая поездка на метро
Фото:3- вторая поездка на метро





+
avatar
  • spc
  • 07 февраля 2018, 09:23
0
А даты покупки и поездок помните? Пока могу сказать, что этот билет подтверждает часть формата, понятного из предыдущего: количество поездок на странице 8 в первых двух байтах. Так что пока не поменяется формат, по крайней мере можно будет видеть число поездок.
+
avatar
  • spc
  • 07 февраля 2018, 11:46
0
Если воображение мне не отказывает, билет был куплен 2 или 3 февраля.
+
avatar
  • Cobe
  • 07 февраля 2018, 13:41
0
Билет был куплен 2 февраля, а дата поездок 6 февраля.
+
avatar
  • spc
  • 07 февраля 2018, 21:45
0
К слову сказать, подобрал пару билетов на одну поездку этого года. У них старый формат, дата выдачи, количество поездок — все показывается верно. Получается, сейчас в ходу оба формата.
+
avatar
  • Cobe
  • 08 февраля 2018, 22:37
0
В 2017 я покупал много раз на 20 поездок и несколько раз на 2
В этом году только на 2. Дату выдачи и количество поездок на всех показывает неправильно.
Как я понял, что билет на 1 поездку старого формата, а на 2/20/40/60 нового.
+
avatar
  • spc
  • 09 февраля 2018, 12:11
0
Я в отсутствие подходящих билетов поправил код, как мне это пока кажется более-менее правильным. Не уверен, что правильно, но прямо сейчас проверить не смогу.
Монстр 2016

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

#define SS_PIN 53
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);       // объект MFRC522
unsigned long uidDec, uidDecTemp; // для отображения номера карточки в десятичном формате
byte bCounter, readBit;
unsigned long ticketNumber;


void setup() {
        Serial.begin(9600);     
        SPI.begin();            // инициализация SPI
        mfrc522.PCD_Init();     // инициализация MFRC522
        Serial.println("Waiting for card...");
}

void loop() {
        // Поиск новой карточки
        if ( ! mfrc522.PICC_IsNewCardPresent()) {
                return;
        }

        // Выбор карточки
        if ( ! mfrc522.PICC_ReadCardSerial()) {
                return;
        }

        uidDec = 0;

        // Выдача серийного номера карточки
        Serial.print("Card 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);
                uidDecTemp=mfrc522.uid.uidByte[i];
                uidDec=uidDec*256+uidDecTemp;
        } 
        Serial.println(uidDec);
        Serial.println();

        // Выдача типа карты
        byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); // запрос типа
        Serial.print("Card type: ");
        Serial.println(mfrc522.PICC_GetTypeName(piccType)); // трансляция типа в читаемый вид
        if (piccType != MFRC522::PICC_TYPE_MIFARE_UL) { // если не билетная карта
                Serial.print("Not a valid card: "); // так и говорим
                Serial.println(piccType);                               
                // Halt PICC
                mfrc522.PICC_HaltA();                   // остановка чипа
                return;
        }

// сюда мы приедем, если чип правильный

        byte status;
        byte byteCount;
        byte buffer[18]; // длина массива (16 байт + 2 байта контрольная сумма) 
        byte pages[3]={4, 6, 8}; // страницы с данными
        byte pageByte; // счетчик байтов страницы
        
        byteCount = sizeof(buffer);
        byte bCount=0;
                

        for (byte i=0; i<3; i++) { // начинаем читать страницы
        status = mfrc522.MIFARE_Read(pages[i], buffer, &byteCount);
        
        if (status != MFRC522::STATUS_OK) {
                Serial.print("Read error: ");
                Serial.println(mfrc522.GetStatusCodeName(status));}
                else {
                      if (pages[i] == 4) {
                                bCounter = 0; // 32-битный счетчик для номера
                                
                                // биты 0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[6], (bCount+4));
                                        setBitsForGood(readBit);
                                }

                                // биты 4 - 27
                                for (pageByte=5; pageByte > 2; pageByte--) {
                                        for (bCount=0; bCount<8; bCount++) {
                                                readBit = bitRead(buffer[pageByte], bCount);
                                                setBitsForGood(readBit);
                                        }
                                }

                                // биты 28-31
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[2], bCount);
                                        setBitsForGood(readBit);
                                }

                                Serial.print("Ticket number: ");
                                Serial.println(ticketNumber, DEC);
                         }

                          // получение даты
                          if (pages[i] == 6) {
                                bCounter = 0; // 32-битный счетчик для номера
                                
                                0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[1], bCount+4);
                                        setBitsForGood(readBit);
                                }

                                // биты 4-11
                                for (bCount=0; bCount<8; bCount++) {
                                        readBit = bitRead(buffer[0], bCount);
                                        setBitsForGood(readBit);
                                }

                                Serial.print("RAW date");
                                Serial.println(ticketNumber, DEC);
                                rawDate = ticketNumber; // просто чтобы не запутаться, хоть ticketNumber уже и не нужен толком
printIssueDate(rawDate);
                         }

                         // получение количества поездок
                          if (pages[i] == 8) {                            
                        
                                Serial.print("Trip reminder: "); // количество оставшихся поездок
                                Serial.print(buffer[0], DEC);                                                           
                                Serial.println();       
                        }
                        
                        
                }
        }

                
                
        // Halt PICC
    mfrc522.PICC_HaltA();                       
        
}

void printIssueDate(unsigned int incoming) {

boolean isLeap = true; // признак високосного года
int days[]={0,31,59,90,120,151,181,212,243,273,304,334}; // последний по порядку день месяца для обычного года
byte dayOfMonth, monthCounter;
unsigned int yearCount;

incoming = incoming+1; // подогнал под ответ, но возможно это как раз необходимая коррекция, потому что начало отсчета - 01.01.1992, а не 00.01.1992

for (yearCount = 2016; incoming >366; yearCount++) { // считаем год и количество дней, прошедших с выдачи билета

        if ((yearCount % 4 == 0 && yearCount % 100 != 0) ||  yearCount % 400 == 0) {
                incoming = incoming - 366;
                isLeap = true;
          } else {
                incoming = incoming - 365;
                isLeap = false;
                }
        }

for (monthCounter = 0; incoming > days[monthCounter]; monthCounter++) { // узнаем номер месяца
}

// считаем день месяца

if (isLeap == true) { // если високосный год
  if (days[monthCounter-1]>31) { // если не первый месяц, то добавляем к последнему дню месяца единицы
  dayOfMonth = incoming - (days[monthCounter-1]+ 1);
  } else {
    dayOfMonth = incoming - (days[monthCounter-1]); // если первый - ничего не добавляем, потому что сдвиг начинается с февраля
  }
} else {
  dayOfMonth = incoming - (days[monthCounter-1]); // если не високосный год
}

Serial.print(dayOfMonth);
Serial.print(".");
Serial.print(monthCounter);
Serial.print(".");
Serial.print(yearCount);
Serial.println();

        

}




void setBitsForGood(byte daBeat) {


  
        if (daBeat == 1) {
                bitSet(ticketNumber, bCounter);
                bCounter=bCounter+1;
                }
        else {
                bitClear(ticketNumber, bCounter);
                bCounter=bCounter+1;
        }
}

+
avatar
  • Cobe
  • 09 февраля 2018, 22:35
0
Ошибка, не могу загрузить скетч.
+
avatar
  • spc
  • 09 февраля 2018, 23:53
0
Удалите строчку, где 0-3, она выше курсора на скриншоте.
+
avatar
  • Cobe
  • 10 февраля 2018, 02:40
0
Удалил строчку 0-3 и новая ошибка
+
avatar
  • spc
  • 10 февраля 2018, 22:27
0
В начале замените
unsigned long ticketNumber;

на

unsigned long ticketNumber, rawDate;
+
avatar
  • Cobe
  • 10 февраля 2018, 23:52
0
Вот что получается.
+
avatar
  • spc
  • 12 февраля 2018, 21:38
0
Вот

Дополнительная информация
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 53
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);       // объект MFRC522
unsigned long uidDec, uidDecTemp; // для отображения номера карточки в десятичном формате
byte bCounter, readBit;
unsigned long ticketNumber, rawDate;


void printIssueDate(unsigned int incoming) {

boolean isLeap = true; // признак високосного года
int days[]={0,31,59,90,120,151,181,212,243,273,304,334}; // последний по порядку день месяца для обычного года
byte dayOfMonth, monthCounter;
unsigned int yearCount;

for (yearCount = 2016; incoming >366; yearCount++) { // считаем год и количество дней, прошедших с выдачи билета

        if ((yearCount % 4 == 0 && yearCount % 100 != 0) ||  yearCount % 400 == 0) {
                incoming = incoming - 366;
                isLeap = true;
          } else {
                incoming = incoming - 365;
                isLeap = false;
                }
        }

for (monthCounter = 0; incoming > days[monthCounter]; monthCounter++) { // узнаем номер месяца
}

// считаем день месяца

if (isLeap == true) { // если високосный год
  if (days[monthCounter-1]>31) { // если не первый месяц, то добавляем к последнему дню месяца единицы
  dayOfMonth = incoming - (days[monthCounter-1]+ 1);
  } else {
    dayOfMonth = incoming - (days[monthCounter-1]); // если первый - ничего не добавляем, потому что сдвиг начинается с февраля
  }
} else {
  dayOfMonth = incoming - (days[monthCounter-1]); // если не високосный год
}

Serial.print(dayOfMonth);
Serial.print(".");
Serial.print(monthCounter);
Serial.print(".");
Serial.print(yearCount);
Serial.println();

        

}




void setBitsForGood(byte daBeat) {


  
        if (daBeat == 1) {
                bitSet(ticketNumber, bCounter);
                bCounter=bCounter+1;
                }
        else {
                bitClear(ticketNumber, bCounter);
                bCounter=bCounter+1;
        }
}

void setup() {
        Serial.begin(9600);     
        SPI.begin();            // инициализация SPI
        mfrc522.PCD_Init();     // инициализация MFRC522
        Serial.println("Waiting for card...");
}

void loop() {
        // Поиск новой карточки
        if ( ! mfrc522.PICC_IsNewCardPresent()) {
                return;
        }

        // Выбор карточки
        if ( ! mfrc522.PICC_ReadCardSerial()) {
                return;
        }

        uidDec = 0;

        // Выдача серийного номера карточки
        Serial.print("Card 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);
                uidDecTemp=mfrc522.uid.uidByte[i];
                uidDec=uidDec*256+uidDecTemp;
        } 
        Serial.println(uidDec);
        Serial.println();

        // Выдача типа карты
        byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); // запрос типа
        Serial.print("Card type: ");
        Serial.println(mfrc522.PICC_GetTypeName(piccType)); // трансляция типа в читаемый вид
        if (piccType != MFRC522::PICC_TYPE_MIFARE_UL) { // если не билетная карта
                Serial.print("Not a valid card: "); // так и говорим
                Serial.println(piccType);                               
                // Halt PICC
                mfrc522.PICC_HaltA();                   // остановка чипа
                return;
        }

// сюда мы приедем, если чип правильный

        byte status;
        byte byteCount;
        byte buffer[18]; // длина массива (16 байт + 2 байта контрольная сумма) 
        byte pages[3]={4, 6, 8}; // страницы с данными
        byte pageByte; // счетчик байтов страницы
        
        byteCount = sizeof(buffer);
        byte bCount=0;
                

        for (byte i=0; i<3; i++) { // начинаем читать страницы
        status = mfrc522.MIFARE_Read(pages[i], buffer, &byteCount);
        
        if (status != MFRC522::STATUS_OK) {
                Serial.print("Read error: ");
                Serial.println(mfrc522.GetStatusCodeName(status));}
                else {
                      if (pages[i] == 4) {
                                bCounter = 0; // 32-битный счетчик для номера
                                
                                // биты 0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[6], (bCount+4));
                                        setBitsForGood(readBit);
                                }

                                // биты 4 - 27
                                for (pageByte=5; pageByte > 2; pageByte--) {
                                        for (bCount=0; bCount<8; bCount++) {
                                                readBit = bitRead(buffer[pageByte], bCount);
                                                setBitsForGood(readBit);
                                        }
                                }

                                // биты 28-31
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[2], bCount);
                                        setBitsForGood(readBit);
                                }

                                Serial.print("Ticket number: ");
                                Serial.println(ticketNumber, DEC);
                                ticketNumber = 0;
                         }

                          // получение даты
                          if (pages[i] == 6) {
                                bCounter = 0; // 32-битный счетчик для номера
                                
                                // 0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[1], bCount+4);
                                        setBitsForGood(readBit);
                                }

                                // биты 4-11
                                for (bCount=0; bCount<8; bCount++) {
                                        readBit = bitRead(buffer[0], bCount);
                                        setBitsForGood(readBit);
                                }

                                Serial.print("Issued on: "); 
                                printIssueDate(ticketNumber);
                         }

                         // получение количества поездок
                          if (pages[i] == 8) {                            
                        
                                Serial.print("Trip reminder: "); // количество оставшихся поездок
                                Serial.print(buffer[0], DEC);                                                           
                                Serial.println();       
                        }
                        
                        
                }
        }

                
                
        // Halt PICC
    mfrc522.PICC_HaltA();                       
        
}

+
avatar
  • Cobe
  • 13 февраля 2018, 00:14
0
Все работает, показывает всё правильно,«молодец, умница». Спасибо Вам огромное за помощь.
+
avatar
  • Cobe
  • 13 февраля 2018, 01:18
0
Ещё бы сделать срок действия билета как раньше, если не трудно и есть желание.Спасибо.
+
avatar
  • spc
  • 13 февраля 2018, 18:55
0
Со сроком сложнее. Я пока не увидел однозначного указания на срок действия, поэтому у меня две версии: либо он определяется по типу билета, либо определяется по базе данных метрополитена.

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

В двух словах: я могу это сделать так, как умозрительно представляю сейчас, но не гарантирую, что это будет на сто процентов правильно, потому что для уверенности слишком мало исходных данных.

В общем, сделаю, а там сами решайте — можно полагаться, или нет.
+
avatar
  • spc
  • 13 февраля 2018, 22:48
0
Это весьма условная подгонка под условия задачи под имеющиеся образцы билетов (Единый на 2 поездки и Единый на неизвестное мне количество поездок).

Дополнительная информация

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

#define SS_PIN 53
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);       // объект MFRC522
unsigned long uidDec, uidDecTemp; // для отображения номера карточки в десятичном формате
byte bCounter, readBit;
unsigned long ticketNumber, issueDate;


void printIssueDate(unsigned int incoming) {

boolean isLeap = true; // признак високосного года
int days[]={0,31,59,90,120,151,181,212,243,273,304,334}; // последний по порядку день месяца для обычного года
byte dayOfMonth, monthCounter;
unsigned int yearCount;

for (yearCount = 2016; incoming >366; yearCount++) { // считаем год и количество дней, прошедших с выдачи билета

        if ((yearCount % 4 == 0 && yearCount % 100 != 0) ||  yearCount % 400 == 0) {
                incoming = incoming - 366;
                isLeap = true;
          } else {
                incoming = incoming - 365;
                isLeap = false;
                }
        }

for (monthCounter = 0; incoming > days[monthCounter]; monthCounter++) { // узнаем номер месяца
}

// считаем день месяца

if (isLeap == true) { // если високосный год
  if (days[monthCounter-1]>31) { // если не первый месяц, то добавляем к последнему дню месяца единицы
  dayOfMonth = incoming - (days[monthCounter-1]+ 1);
  } else {
    dayOfMonth = incoming - (days[monthCounter-1]); // если первый - ничего не добавляем, потому что сдвиг начинается с февраля
  }
} else {
  dayOfMonth = incoming - (days[monthCounter-1]); // если не високосный год
}

Serial.print(dayOfMonth);
Serial.print(".");
Serial.print(monthCounter);
Serial.print(".");
Serial.print(yearCount);
Serial.println();

        

}




void setBitsForGood(byte daBeat) {


  
        if (daBeat == 1) {
                bitSet(ticketNumber, bCounter);
                bCounter=bCounter+1;
                }
        else {
                bitClear(ticketNumber, bCounter);
                bCounter=bCounter+1;
        }
}

void setup() {
        Serial.begin(9600);     
        SPI.begin();            // инициализация SPI
        mfrc522.PCD_Init();     // инициализация MFRC522
        Serial.println("Waiting for card...");
}

void loop() {
        // Поиск новой карточки
        if ( ! mfrc522.PICC_IsNewCardPresent()) {
                return;
        }

        // Выбор карточки
        if ( ! mfrc522.PICC_ReadCardSerial()) {
                return;
        }

        uidDec = 0;

        // Выдача серийного номера карточки
        Serial.print("Card 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);
                uidDecTemp=mfrc522.uid.uidByte[i];
                uidDec=uidDec*256+uidDecTemp;
        } 
        Serial.println(uidDec);
        Serial.println();

        // Выдача типа карты
        byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); // запрос типа
        Serial.print("Card type: ");
        Serial.println(mfrc522.PICC_GetTypeName(piccType)); // трансляция типа в читаемый вид
        if (piccType != MFRC522::PICC_TYPE_MIFARE_UL) { // если не билетная карта
                Serial.print("Not a valid card: "); // так и говорим
                Serial.println(piccType);                               
                // Halt PICC
                mfrc522.PICC_HaltA();                   // остановка чипа
                return;
        }

// сюда мы приедем, если чип правильный

        byte status;
        byte byteCount;
        byte buffer[18]; // длина массива (16 байт + 2 байта контрольная сумма) 
        byte pages[3]={4, 6, 8}; // страницы с данными
        byte pageByte; // счетчик байтов страницы
        
        byteCount = sizeof(buffer);
        byte bCount=0;
                

        for (byte i=0; i<3; i++) { // начинаем читать страницы
        status = mfrc522.MIFARE_Read(pages[i], buffer, &byteCount);
        
        if (status != MFRC522::STATUS_OK) {
                Serial.print("Read error: ");
                Serial.println(mfrc522.GetStatusCodeName(status));}
                else {
                      if (pages[i] == 4) {
                                bCounter = 0; // 32-битный счетчик для номера
                                
                                // биты 0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[6], (bCount+4));
                                        setBitsForGood(readBit);
                                }

                                // биты 4 - 27
                                for (pageByte=5; pageByte > 2; pageByte--) {
                                        for (bCount=0; bCount<8; bCount++) {
                                                readBit = bitRead(buffer[pageByte], bCount);
                                                setBitsForGood(readBit);
                                        }
                                }

                                // биты 28-31
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[2], bCount);
                                        setBitsForGood(readBit);
                                }

                                Serial.print("Ticket number: ");
                                Serial.println(ticketNumber, DEC);
                                ticketNumber = 0;
                         }

                          // получение даты
                          if (pages[i] == 6) {
                                bCounter = 0; // 32-битный счетчик для номера
                                
                                // 0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[1], bCount+4);
                                        setBitsForGood(readBit);
                                }

                                // биты 4-11
                                for (bCount=0; bCount<8; bCount++) {
                                        readBit = bitRead(buffer[0], bCount);
                                        setBitsForGood(readBit);
                                }

                                

                                Serial.print("Issued on: "); 
                                printIssueDate(ticketNumber);
                                issueDate = ticketNumber;

                                ticketNumber = 0;
                                bCounter = 0;
    
                            // биты 16 - 31
                                for (pageByte=3; pageByte > 1; pageByte--) {
                                        for (bCount=0; bCount<8; bCount++) {
                                                readBit = bitRead(buffer[pageByte], bCount);
                                                setBitsForGood(readBit);
                                        }
                                }


                                if (ticketNumber == 14400) {
                                  Serial.println("Ticket valid for 5 days");
                                  Serial.print("Valid till: ");
                                  printIssueDate(issueDate+4);
                                } else {
                                  if (ticketNumber == 62592) {
                                  Serial.print("Ticket valid for 90 days");
                                  Serial.println("Valid till: ");
                                  printIssueDate(issueDate+89);                                    
                                  }
                                }
                                

                                
                         }

                         // получение количества поездок
                          if (pages[i] == 8) {                            
                        
                                Serial.print("Trip reminder: "); // количество оставшихся поездок
                                Serial.print(buffer[0], DEC);                                                           
                                Serial.println();       
                        }
                        
                        
                }
        }

                
                
        // Halt PICC
    mfrc522.PICC_HaltA();                       
        
}
+
avatar
  • Cobe
  • 14 февраля 2018, 03:53
0
Сделали Вы все, как надо, все отлично! За труд, за отличную работу Вам «Спасибо!».
За мастерство, за уменье и прекрасный результат от души благодарю.
+
avatar
  • Lakomich
  • 09 августа 2018, 15:48
0
Уважаемый spc, можно ли использовать ваш скетч с другим rfid? У меня arduino nano, pn532,…
Библиотеки совместимы?
+
avatar
  • spc
  • 09 августа 2018, 16:01
0
Нет, нельзя — библиотеки несовместимы.

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.