RFIDのサンプルスケッチでの発見

RFIDのサンプルスケッチ

公開されているサンプルスケッチでNUIDの値を読んでみようと思って行った作業。
DumpInfoのスケッチではRFIDタグを近づけたり遠ざけたりするたびに値がシリアルモニタに出力されたのに、ReadNUIDのスケッチでは、電源を入れる前からRFIDタグくっつけていた時しか出力がなかったので、不思議に思って比べたり、ReadNUIDの改造をして出力できたという記録

参考にしたスケッチDumpInfoの抜粋にコメント追加

まずは「DumpInfo」はこちらのURLで本物を見てほしい。
https://github.com/miguelbalboa/rfid/blob/master/examples/DumpInfo/DumpInfo.ino
2つのスケッチを比べてほしいので引用して同じページに記載しているけれど、もともとのスケッチを参考にしてほしい。

# Pin位置がコメントに書いてあるのがうれしい。
 
/*
 * 
 * @license Released into the public domain.
 * 
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 */
 
# ヘッダーの読み込み
#include <SPI.h>
#include <MFRC522.h>
 
 
# RSTとSDA(SS)のPin番号を定数として。
constexpr uint8_t RST_PIN = 9;          // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;         // Configurable, see typical pin layout above
 
#インスタンス作成はコメント通り。setupやloopから外して、共通のオブジェクトとする…はず。
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
 
void setup() {
	Serial.begin(9600);		// Initialize serial communications with the PC
	while (!Serial);		// Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
	SPI.begin();			// Init SPI bus
	mfrc522.PCD_Init();		// Init MFRC522
	mfrc522.PCD_DumpVersionToSerial();	// Show details of PCD - MFRC522 Card Reader details
	Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}
 
void loop() {
	// Look for new cards
	if ( ! mfrc522.PICC_IsNewCardPresent()) {
		return;
	}
 
	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
		return;
	}
 
	// Dump debug info about the card; PICC_HaltA() is automatically called
	mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

これは、ずらずらっとすべてのデータが出てくれるスケッチ。書き込みはしないので安心して実行することができた。
近づけると何度もダンプされるので注意。

mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

これは、初期化しなくても呼ばれるたびに値が出てくるものらしい。

NUIDを読み取るスケッチ。ReadNUIDの抜粋

本物はこちら。バージョンも変わっているかもしれないので本物を見てほしい。
https://github.com/miguelbalboa/rfid/blob/master/examples/ReadNUID/ReadNUID.ino

 
#include <SPI.h>
#include <MFRC522.h>
 
constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above
 
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
 
MFRC522::MIFARE_Key key; 
 
// Init array that will store new NUID 
byte nuidPICC[4];
 
void setup() { 
  Serial.begin(9600);
  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522 
 
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
 
  Serial.println(F("This code scan the MIFARE Classsic NUID."));
  Serial.print(F("Using the following key:"));
  printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
}
 
void loop() {
 
  // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return;
 
  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return;
 
  Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  Serial.println(rfid.PICC_GetTypeName(piccType));
 
  // Check is the PICC of Classic MIFARE type
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println(F("Your tag is not of type MIFARE Classic."));
    return;
  }
 
  if (rfid.uid.uidByte[0] != nuidPICC[0] || 
    rfid.uid.uidByte[1] != nuidPICC[1] || 
    rfid.uid.uidByte[2] != nuidPICC[2] || 
    rfid.uid.uidByte[3] != nuidPICC[3] ) {
    Serial.println(F("A new card has been detected."));
 
    // Store NUID into nuidPICC array
    for (byte i = 0; i < 4; i++) {
      nuidPICC[i] = rfid.uid.uidByte[i];
    }
 
    Serial.println(F("The NUID tag is:"));
    Serial.print(F("In hex: "));
    printHex(rfid.uid.uidByte, rfid.uid.size);
    Serial.println();
    Serial.print(F("In dec: "));
    printDec(rfid.uid.uidByte, rfid.uid.size);
    Serial.println();
  }
  else Serial.println(F("Card read previously."));
 
  // Halt PICC
  rfid.PICC_HaltA();
 
  // Stop encryption on PCD
  rfid.PCD_StopCrypto1();
}
 
 
/**
 * Helper routine to dump a byte array as hex values to Serial. 
 */
void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}
 
/**
 * Helper routine to dump a byte array as dec values to Serial.
 */
void printDec(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], DEC);
  }
}

これは読み取ったNUIDを16進数と10進数で出力している。

これを最初に実行したときに、「あれ?でてこないなー」って何度もRFIDタグを近づけたり遠ざけたりしてたんだけれど、
どうやら1回切りらしいと気が付いて。loop()のなかで初期化をしていないからsetup()の1回を逃すとずっと出てこないというスケッチ。
のちに、この現象の正体がわかって自分で何度も出るようになるまで直してみたりした。

void loop() {
 
  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

これをloop()の直後に書くか、書かないかで最初の1回きりなのか、何度も何度も繰り返し判定に行くのかという点が違っていた。
Dumpはこんなことをしなくても読めるけれど、特定の値を読もうと思ったらこのkeyに0xFFを入れないとだめだった。