Arduino:RFID RC522および

この記事では、Arduinoを使用して子供のテレビを見る時間を制限する方法について説明します。



しばらくの間、彼らは学校で私の子供の成績に反対し始めました。 パスワードはタブレットとスマートフォンで設定され、PCでの使用時間は制限されていましたが、テレビは残りました。 私は毎日ケーブルを隠すのにうんざりしているが、彼が自分でケーブルを買っていないのは事実ではない。 その結果、テレビを見る時間を制限するデバイスを作ることにしました。 220Vをオフにします。



彼のアイデアを実装するために、彼は以下を使用しました。



1.二重側面プロトタイプPCBは普遍的な回路盤2x8 cm 20mmx80mm FR4を錫メッキしました:

画像



PIC AVR DSP ARM MCU Arduino用の2.5V One 1チャネルリレーモジュールボードシールド:

画像



3. Arduino用USB Nano V3.0 ATmega328 16M 5VマイクロコントローラーCH340Gボード:

画像



4. Mifare RC522カード読み取りアンテナRFモジュールRFIDリーダーICカード近接モジュール:

画像



5. Arduino用の白色3-5V 0.96 "SPIシリアル128X64 OLED LCD LEDディスプレイモジュール:

画像



デバイスの電源を入れると、記録されたカードの存在についてEEPROMから情報を読み取ります(カードの最大数を6枚に制限しました)。 EEPROMは、10進形式に変換されたカードUIDの最後の4バイトを保存します。 EEPROMの読み取りと書き込みには、ライブラリEEPROM2.hを使用しました



コード
cardPresent = readCards(); boolean readCards() { cardPresent = false; for(int k = 0; k <6; k++) { EEPROM_read(k*6+4, time[k]); if(time[k] >= 0) { cardPresent = true; EEPROM_read(k*6, cards[k]); } } return cardPresent; }
      
      







モジュールMFRC522を使用するには、ライブラリMFRC522.hを使用しました 。 次のようにカードを読み取ります。



コード
 MFRC522 mfrc522(SS_PIN, RST_PIN); void setup() { SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 void loop() { // Look for new cards if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return; } String s = dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); mfrc522.PICC_HaltA(); //           (  dump_byte_array    ,      ). Serial.println(s); }
      
      







EEPROMにカードがない場合、最初に接続されたカードがウィザードによって割り当てられ、セル0に記録されます。



コード
  if(!cardPresent) { //  ,      short master = 0; EEPROM_write(0, uiddec); EEPROM_write(4, master); message = "NEW MASTER"; cardPresent = true; readCards(); }
      
      







モニターにメッセージを表示します。 HCuOLED.hライブラリを使用しました



コード
 /* Create an instance of the library (uncomment one of the lines below) */ //HCuOLED HCuOLED(SSD1307, SS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052) HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI); // For SH1106 displays (HCMODU0058 & HCMODU0059) void setup() { HCuOLED.Reset(); } void drawUid(char *s) { HCuOLED.Erase(0,16,120,32); HCuOLED.SetFont(MedProp_11pt); HCuOLED.Cursor(0,16); HCuOLED.Print(s); HCuOLED.Refresh(); } void drawLong(long uid) { HCuOLED.Erase(0,33,120,48); HCuOLED.SetFont(MedProp_11pt); HCuOLED.Cursor(0,33); HCuOLED.Print(uid); HCuOLED.Refresh(); } void drawCardTime(String s) { char mess[12]; s.toCharArray(mess, 12); HCuOLED.Erase(0,49,120,80); HCuOLED.SetFont(MedProp_11pt); HCuOLED.Cursor(0,49); HCuOLED.Print(mess); HCuOLED.Refresh(); }
      
      







次に、文字列dump_byte_array関数のコード(byte * buffer、byte bufferSize)を示します。 カードを読み取った後に呼び出されます。 デバイスの操作は次のように実装されます。



1.最後の4バイトを10進形式に変換し、両方の形式でuidカードを表示し、uidとEEPROMから読み取ったものとの一致を探します。



コード
  String s; unsigned long uiddec = 0; unsigned long temp; char uid[8]; for (byte m = (bufferSize > 4 ? (bufferSize - 4) : 0); m < bufferSize; m++) { //   4       unsigned long p = 1; for(int k = 0; k < bufferSize-m-1; k++) { p = p*256; } uiddec += p*buffer[m]; s = s + (buffer[m] < 0x10 ? "0" : ""); s = s + String(buffer[m], HEX); } s.toCharArray(uid, 8); drawUid(uid); drawLong(uiddec); message = "unknow"; short currentCard = -1; for(int k = 0; k <6; k++) { //  uid        if((time[k] >=0) && (cards[k] == uiddec)) { currentCard = k; } }
      
      







2.次は、デバイスロジックが実装されるコードです。 カードが既知であるがマスターではない場合、onRelay(Relay、currentCard)関数が呼び出され、オンにするのに十分な時間が経過したかどうかがチェックされます。



文字列onRelay(int relayPin、ショートカード)
  String onRelay(int relayPin, short card) { String messa; if(time[card] == 0) { //  offAllCards(); //   messa = "master ON"; digitalWrite(relayPin, LOW); //  } else { if(!isOn[card]) { //    unsigned long lastOn = (lastTime[card] == NULL ? 0 : lastTime[card]); //   if((millis()-lastOn)/60000 > (freqOn - 1)) { //    ,     messa = "time:" + String(time[card]); lastTime[card] = someCardsIsOn() + time[card]*60000; //          +   isOn[card] = true; //       digitalWrite(relayPin, LOW); //  } else { //      short waitminutes = freqOn - (millis()-lastOn)/60000; //      messa = "Wait:" + String(waitminutes/60) + "h" + String(waitminutes%60)+ "m"; //messa = String(waitminutes); } } else { messa = "Allready ON"; } } return messa; } void offAllCards() { for(int k = 0; k < 10; k++) { isOn[k] = false; } } unsigned long someCardsIsOn() { // -   ,          unsigned long maxtime = millis(); for(int k = 0; k <6; k++) { if(isOn[k]&&(lastTime[k] > maxtime)) { maxtime = lastTime[k]; } } return maxtime; }
      
      







コード
  if(currentCard > 0) { // ,     message = onRelay(Relay, currentCard); } else { if(currentCard == 0) { // ,     ,     EEPROM,  ,     if(!masterPresent) { newCard = false; masterPresent = true; message = "master in"; onRelay(Relay, currentCard); } else { if(newCard) { for(int k = 1; k < 6; k++) { if(time[k] < 0) { writeNewCard(newCardUid,k); //Serial.println("new card write to " + String(k)); newCard = false; message = "card added"; break; } } } else { masterPresent=false; offRelay(Relay); message = "master out"; } } } else { //   0,   ,   ,  ,    ,    if(masterPresent) { newCard = true; newCardUid = uiddec; message = "confirm?"; } else {message = "unknow";} } } if(!cardPresent) { //  ,      short master = 0; EEPROM_write(0, uiddec); EEPROM_write(4, master); message = "NEW MASTER"; cardPresent = true; readCards(); } if(uiddec == 696374757) { //      eraseCards(); cardPresent = readCards(); message = "ERASED"; } drawCardTime(message); } void eraseCards() { short master = -1; for(int t = 0; t < 40; t++) { EEPROM_write(t*2, master);} readCards(); //Serial.println("Cards erased"); } void writeNewCard(unsigned long uid, int k) { short time = 30; EEPROM_write(k*6, uid); EEPROM_write(k*6+4, time); readCards(); }
      
      







タイムアウトが発生したときにデバイスを切断することを忘れないでください。このため、ループ()関数の最初に次のコードを追加します。



コード
  if((millis()/10000)%2 ^ i) { //check each 10 seconds i = !i; if(!masterPresent) { if(millis() > (someCardsIsOn()-1000)) { offRelay(Relay); message = "Time over"; } else { message = "Remain:" + String((someCardsIsOn() - millis())/60000+1); Serial.println(message); } drawCardTime(message); HCuOLED.Refresh(); } }
      
      







全体としてのコードのスケッチ:



スケッチコード全体
 /* * Typical pin layout used: * ----------------------------------------------------------------------------------------- * MFRC522 Arduino Arduino Arduino Arduino Arduino * Reader/PCD Uno 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 <HCuOLED.h> #include <EEPROM2.h> #define RST_PIN 6 // #define SS_PIN 7 // /* Digital pin number for the displays chip select pin */ #define CS_DI 10 /* Digital pin number for the displays data/command pin */ #define DC_DI 9 /* Digital pin number for the displays reset pin */ #define RST_DI 8 #define Relay 3 #define freqOn 300 //      unsigned long cards[6]; //uids    eeprom unsigned long newCardUid; //     boolean i = false; short time[6]; //        ,   eeprom unsigned long lastTime[6]; //    boolean isOn[6]; //      boolean cardPresent; //       eeprom boolean masterPresent = false; //   boolean newCard = false; //    String message; /* Create an instance of the library (uncomment one of the lines below) */ //HCuOLED HCuOLED(SSD1307, SS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052) HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI); // For SH1106 displays (HCMODU0058 & HCMODU0059) 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) pinMode(Relay, OUTPUT); digitalWrite(Relay, HIGH); SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 ShowReaderDetails(); // Show details of PCD - MFRC522 Card Reader details //Serial.println(F("Scan PICC to see UID, type, and data blocks...")); HCuOLED.Reset(); //HCuOLED.SetFont(MedProp_11pt); //HCuOLED.Cursor(40,0); //HCuOLED.Print("Uid:"); //eraseCards(); cardPresent = readCards(); } void loop() { if((millis()/10000)%2 ^ i) { //check each 10 seconds i = !i; if(!masterPresent) { if(millis() > (someCardsIsOn()-1000)) { offRelay(Relay); message = "Time over"; } else { message = "Remain:" + String((someCardsIsOn() - millis())/60000+1); Serial.println(message); } drawCardTime(message); HCuOLED.Refresh(); } } // Look for new cards if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return; } String s = dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); mfrc522.PICC_HaltA(); Serial.println(s); } void ShowReaderDetails() { // Get the MFRC522 software version byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); Serial.print(F("MFRC522 Software Version: 0x")); Serial.print(v, HEX); if (v == 0x91) Serial.print(F(" = v1.0")); else if (v == 0x92) Serial.print(F(" = v2.0")); else Serial.print(F(" (unknown)")); Serial.println(""); // When 0x00 or 0xFF is returned, communication probably failed if ((v == 0x00) || (v == 0xFF)) { Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?")); } } String dump_byte_array(byte *buffer, byte bufferSize) { String s; unsigned long uiddec = 0; unsigned long temp; char uid[8]; for (byte m = (bufferSize > 4 ? (bufferSize - 4) : 0); m < bufferSize; m++) { //   4       unsigned long p = 1; for(int k = 0; k < bufferSize-m-1; k++) { p = p*256; } uiddec += p*buffer[m]; s = s + (buffer[m] < 0x10 ? "0" : ""); s = s + String(buffer[m], HEX); } s.toCharArray(uid, 8); drawUid(uid); drawLong(uiddec); message = "unknow"; short currentCard = -1; for(int k = 0; k <6; k++) { //  uid        if((time[k] >=0) && (cards[k] == uiddec)) { currentCard = k; } } if(currentCard > 0) { // ,     message = onRelay(Relay, currentCard); } else { if(currentCard == 0) { // ,     ,     EEPROM,  ,     if(!masterPresent) { newCard = false; masterPresent = true; message = "master in"; onRelay(Relay, currentCard); } else { if(newCard) { for(int k = 1; k < 6; k++) { if(time[k] < 0) { writeNewCard(newCardUid,k); //Serial.println("new card write to " + String(k)); newCard = false; message = "card added"; break; } } } else { masterPresent=false; offRelay(Relay); message = "master out"; } } } else { //   0,   ,   ,  ,    ,    if(masterPresent) { newCard = true; newCardUid = uiddec; message = "confirm?"; } else {message = "unknow";} } } if(!cardPresent) { //  ,      short master = 0; EEPROM_write(0, uiddec); EEPROM_write(4, master); message = "NEW MASTER"; cardPresent = true; readCards(); } if(uiddec == 696374757) { eraseCards(); cardPresent = readCards(); message = "ERASED"; } drawCardTime(message); return s; } void drawUid(char *s) { HCuOLED.Erase(0,16,120,32); HCuOLED.SetFont(MedProp_11pt); HCuOLED.Cursor(0,16); HCuOLED.Print(s); HCuOLED.Refresh(); } void drawLong(long uid) { HCuOLED.Erase(0,33,120,48); HCuOLED.SetFont(MedProp_11pt); HCuOLED.Cursor(0,33); HCuOLED.Print(uid); HCuOLED.Refresh(); } void drawCardTime(String s) { char mess[12]; s.toCharArray(mess, 12); HCuOLED.Erase(0,49,120,80); HCuOLED.SetFont(MedProp_11pt); HCuOLED.Cursor(0,49); HCuOLED.Print(mess); HCuOLED.Refresh(); } void eraseCards() { short master = -1; for(int t = 0; t < 40; t++) { EEPROM_write(t*2, master);} readCards(); //Serial.println("Cards erased"); } boolean readCards() { cardPresent = false; for(int k = 0; k <6; k++) { EEPROM_read(k*6+4, time[k]); if(time[k] >= 0) { cardPresent = true; EEPROM_read(k*6, cards[k]); //Serial.print(cards[k]); //Serial.print(" - "); //Serial.println(time[k]); } } return cardPresent; } void writeNewCard(unsigned long uid, int k) { short time = 30; EEPROM_write(k*6, uid); EEPROM_write(k*6+4, time); readCards(); } String onRelay(int relayPin, short card) { String messa; if(time[card] == 0) { //  offAllCards(); //   messa = "master ON"; digitalWrite(relayPin, LOW); //  } else { if(!isOn[card]) { //    unsigned long lastOn = (lastTime[card] == NULL ? 0 : lastTime[card]); //   if((millis()-lastOn)/60000 > (freqOn - 1)) { //    ,     messa = "time:" + String(time[card]); lastTime[card] = someCardsIsOn() + time[card]*60000; //          +   isOn[card] = true; //       digitalWrite(relayPin, LOW); //  } else { //      short waitminutes = freqOn - (millis()-lastOn)/60000; //      messa = "Wait:" + String(waitminutes/60) + "h" + String(waitminutes%60)+ "m"; //messa = String(waitminutes); } } else { messa = "Allready ON"; } } return messa; } void offRelay(int relayPin) { offAllCards(); digitalWrite(relayPin, HIGH); } void offAllCards() { for(int k = 0; k < 10; k++) { isOn[k] = false; } } unsigned long someCardsIsOn() { unsigned long maxtime = millis(); for(int k = 0; k <6; k++) { if(isOn[k]&&(lastTime[k] > maxtime)) { maxtime = lastTime[k]; } } return maxtime; }
      
      







配線図:



画像





スケッチリンク



仕事のデモンストレーション:







変更/追加したいもの:



1.デバイスをカードに使用する時間を変更して削除できるようにします(ウィザードを数回適用することにより、時間を変更します:30、45、60、90、120、-1)。

2.デバイスをリセットできるボタンを回路に追加します。



All Articles