RFIDの識別にUIDを使おうと思いArduino側のEEPROMへの読み書きにて実装したこと

RFIDの識別にUIDを使おうと思いArduino側のEEPROMへの読み書きにて実装したこと

これは、最初に実装したスケッチなんだけれど、「さーて、開いたり閉じたりできたから、RFIDタグを複製するか」と次の段階に移ろうとしたらUID部分が複製不可能(高価なRFIDタグならできる)ということが分かったので没にしたもの。

EEPROMというのはArduinoが持っている領域で、プログラムを書き込むのとは違うところ。
読み書き込みできるスケッチを別途用意して、Arduinoの領域にOKなRFIDのUIDを書き込んでみた。
よく考えれば、UIDを書き換えるたびにArduinoのスケッチを書き換えないとだめなので、最初から実装に無理あったかも

/* シリアル出力を抑制
 * --------------------------------------------------------------------------------------------------------------------
 * Example sketch/program showing how to read new NUID from a PICC to serial.
 * --------------------------------------------------------------------------------------------------------------------
 * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
 * 
 * Example sketch/program showing how to the read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
 * Reader on the Arduino SPI interface.
 * 
 * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
 * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
 * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
 * will show the type, and the NUID if a new card has been detected. Note: you may see "Timeout in communication" messages
 * when removing the PICC from reading distance too early.
 * 
 * @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>
#include <EEPROM.h>
#include <Servo.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
constexpr uint8_t SV_PIN = 3;     // Configurable, see typical pin layout above
 
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
 
struct MyObject {
  byte field1;
  byte field2;
  byte field3;
  byte field4;
};
 
MyObject customVar; //Variable to store custom object read from EEPROM.
// 
int pos = 0;    // variable to store the servo position
Servo myservo;  // create servo object to control a servo
 
// 
//unsigned long opentime = 300000; //
//unsigned long opentime   = 30000; // 30秒
unsigned long opentime   = 1800000; // 30分
unsigned long unlocktime = 0; // 開錠した時間
unsigned long checktime  = 0; // 経過秒数
int           servodegree = 180; // 自動電源OFFのために電力調節
int           servodegree_pulse = 180; // 自動電源OFFのために電力調節 開錠時の一時角度
int           pulse_count = 0;   // 自動電源OFFのために電力調節
boolean       close_flag  = true;   // 閉めたことを記録 true = 閉めた。false = 開いた
 
// 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 
 
 
  //Serial.println(F("This code scan the MIFARE Classsic NUID."));
  //Serial.print(F("Using the following key:"));
 
  int eeAddress = 0; 
  EEPROM.get(eeAddress, customVar);
 
  myservo.attach(SV_PIN);      // attaches the servo
  myservo.write(servodegree);  // deglee 180 is lock
 
}
 
void loop() {
 
  MFRC522::MIFARE_Key key; 
 
  // 開いて一定時間で自動施錠
  checktime = millis();
  if (unlocktime != 0 && unlocktime < checktime ){
      //Serial.println(unlocktime);
      //Serial.println(checktime);
      servodegree = 180;
      myservo.write(servodegree);       // deglee 180 is lock
      close_flag  = true; // 閉めたら1      
  }
 
  pulse_count = pulse_count + 1;
  //Serial.println(servodegree_pulse);
 
  // 一定時間でサーボモータに電力消費を促す(0.2s * 20 = 4秒)
  if ( ! rfid.PICC_IsNewCardPresent() || ! rfid.PICC_ReadCardSerial()){
    delay(200);
    if ( pulse_count > 20 && close_flag == false){
      servodegree_pulse = 75;
      myservo.write(servodegree_pulse);
      pulse_count = 0;
      delay(500);
    } else {
      myservo.write(servodegree);
      delay(500);
    }
    return;
 }
 
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
 
  // 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] != customVar.field1 || 
    rfid.uid.uidByte[1] != customVar.field2 || 
    rfid.uid.uidByte[2] != customVar.field3 || 
    rfid.uid.uidByte[3] != customVar.field4 ) {
    // 
    //Serial.println(F("A new card has been detected."));
 
    //Serial.println(F("The NUID tag is:"));
    //Serial.print(F("In hex: "));
    //Serial.println();
  }
  else {
    servodegree = 80;
    myservo.write(servodegree); // deglee 90 is UNlock deglee 80 is UNlock sor Osoyoo SG90
    unlocktime = millis() + opentime;
    close_flag  = false; // 開けたらfalse
    //Serial.print(F("unlocktime:"));
    //Serial.println(unlocktime);
  }
 
  // Halt PICC
  rfid.PICC_HaltA();
 
  // Stop encryption on PCD
  rfid.PCD_StopCrypto1();
 
  delay(1000); //change value if you want to read cards faster
 
}

初期化するところでEEPROMから読み込み

 
void setup() { 
  //Serial.begin(9600); // デバッグ用
  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522 
 
 
  //Serial.println(F("This code scan the MIFARE Classsic NUID."));
  //Serial.print(F("Using the following key:"));
 
  int eeAddress = 0; 
  EEPROM.get(eeAddress, customVar);
 
  myservo.attach(SV_PIN);      // attaches the servo
  myservo.write(servodegree);  // deglee 180 is lock
 
}

判定はこの部分。

  if (rfid.uid.uidByte[0] != customVar.field1 || 
    rfid.uid.uidByte[1] != customVar.field2 || 
    rfid.uid.uidByte[2] != customVar.field3 || 
    rfid.uid.uidByte[3] != customVar.field4 ) {

EEPROMを書き換えるスケッチ

/***
    eeprom_put example.
 
    This shows how to use the EEPROM.put() method.
    Also, this sketch will pre-set the EEPROM data for the
    example sketch eeprom_get.
 
    Note, unlike the single byte version EEPROM.write(),
    the put method will use update semantics. As in a byte
    will only be written to the EEPROM if the data is actually
    different.
 
    Written by Christopher Andrews 2015
    Released under MIT licence.
***/
 
#include <EEPROM.h>
 
struct MyObject {
  byte field1;
  byte field2;
  byte field3;
  byte field4;
};
 
void setup() {
 
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
 
  int eeAddress = 0;   //Location we want the data to be put.
 
  /** Put is designed for use with custom structures also. **/
 
  //Data to store.
  MyObject customVar = {
    0x90,
    0xCF,
    0x39,
    0x83
  };
 
  EEPROM.put(eeAddress, customVar);
  Serial.print("Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!");
}
 
void loop() {
  /* Empty loop */
}

このMyObject customVarの値を書き換えて実行するというもの。

EEPROMを読みだすスケッチ

/***
    eeprom_get example.
 
    This shows how to use the EEPROM.get() method.
 
    To pre-set the EEPROM data, run the example sketch eeprom_put.
    This sketch will run without it, however, the values shown
    will be shown from what ever is already on the EEPROM.
 
    This may cause the serial object to print out a large string
    of garbage if there is no null character inside one of the strings
    loaded.
 
    Written by Christopher Andrews 2015
    Released under MIT licence.
***/
 
#include <EEPROM.h>
 
void setup() {
 
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Read float from EEPROM: ");
 
  /***
    As get also returns a reference to 'f', you can use it inline.
    E.g: Serial.print( EEPROM.get( eeAddress, f ) );
  ***/
 
  /***
    Get can be used with custom structures too.
    I have separated this into an extra function.
  ***/
 
  secondTest(); //Run the next test.
}
 
struct MyObject {
  byte field1;
  byte field2;
  byte field3;
  byte field4;
};
 
void secondTest() {
  int eeAddress = 0; 
 
  MyObject customVar; //Variable to store custom object read from EEPROM.
  EEPROM.get(eeAddress, customVar);
 
  Serial.println("Read custom object from EEPROM: ");
  Serial.print(customVar.field1,HEX);
  Serial.print(customVar.field2,HEX);
  Serial.print(customVar.field3,HEX);
  Serial.print(customVar.field4,HEX);
}
 
void loop() {
  /* Empty loop */
}

説明いらないと思うけれど、EEPROMの領域を読みだすっていうもの。