Использование MFRC522 вместе с другими входами (Bluetooth, клавиатура)

Я делаю небольшую парковку, которая включает в себя в основном открытие серводвигателя с помощью клавиатуры, Bluetooth (hc-05) и недавно добавленного Rfid (RC522). Я не могу получить данные из других источников, если хочу получить UID из RFID. это означает, что когда я добавил единственный фрагмент кода, который я нашел, который возвращает UID, кажется, что он блокирует весь цикл void(), поэтому все остальные входы/код не работают. Вот полный код:

#include <Servo.h>          //Серводвигатель
#include <SoftwareSerial.h>//Библиотека функций Bluetooth: HC05 ПРЕВОСХОДНО!
#include "TM1637.h"        //Библиотека функций 4-разрядного дисплея
#include <SPI.h>
#include <MFRC522.h>
// Кредит Бароряну

//авторское право (с)*/
const int rs = 38, en = 39, d4 = 36 ,d5 = 37, d6 = 41, d7 = 40;//Определение пинов LCD
const int DA=31, D0=30,D1=33,D2=32,D3=35;//Определение пинов данных КЛАВИАТУРЫ
const int servoPin=43,buzzer=42,rx=53,tx=52;//Определение (по порядку): servo pin, buzzer pin, 4DD pins и bluetooth pins(rx tx)
//контакт зуммера 36!
//,CLK=34,DIO=35

#define SS_PIN 45
#define RST_PIN 44
int count = 0;
int cnt=0;//это cnt используется позже, чтобы убедиться, что все 5 символов равны.
int cnt2=0;//используется для случая переключения, чтобы подсчитать, сколько символов уже было получено
int cnt3=0;
char c=0;//здесь размещаем полученный от пользователя char

char password[5] = {'8', '5', '2', '0', '#'};
char keysPressed[5] = "";
char keys[5]="";

byte customChar2[] = {
  B00000,
  B00000,
  B01010,
  B00000,
  B10001,
  B01110,
  B00000,
  B00000
};


byte customChar[] = {//Custom Char для ЖК-экрана, в данном случае; сердце.
  0x00,
  0x00,
  0x0A,
  0x1F,
  0x1F,
  0x0E,
  0x04,
  0x00
};
// #define DA 25 Используется для определения контактов клавиатуры и прочего с помощью #Define, который взаимодействует с процессором->
// #define D0 24 ->решено использовать вместо него const int.
// # определить D1 27
// # определить D2 26
// # определить D3 29
// # определить сервопин 37
// #определить зуммер 36
// # определить CLK 34
// # определить DIO 35
void lcdSetup();
void gateOpenSequence();
void returnKey(int key);
void wrongPassword();
void Beep();
SoftwareSerial Bluetooth(rx,tx);//инициализировать bluetooth для контактов
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);//инициализировать LCD на контакты
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Создать экземпляр MFRC522.
Servo servo;//инициализация сервопривода
byte nuidPICC[4];


void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

void setup()
{
  Serial.begin(9600);
  Bluetooth.begin(9600);
  SPI.begin();      // Инициируем шину SPI
  pinMode(DA ,INPUT);
  pinMode(D0 ,INPUT);
  pinMode(D1 ,INPUT);
  pinMode(D2,INPUT);
  pinMode(D3,INPUT);
  mfrc522.PCD_Init();   // Инициировать MFRC522
  lcd.begin(20,4);
  lcdSetup();//Самостоятельно созданная функция, которая превращает ЖК-дисплей в наш предпочтительный экран по умолчанию "Главный экран"
  servo.attach(servoPin);
  servo.write(5);
  pinMode(buzzer,OUTPUT);
  digitalWrite(buzzer, HIGH); 
  delay(200);          
  digitalWrite(buzzer, LOW);
  Bluetooth.print("Enter 1 to open the gate!");//Записываем пользователю инструкции по bluetooth-терминалу
  lcd.createChar(2, customChar2);
  lcd.createChar(1, customChar);
}

void loop()
{


  if (!mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  //Выбираем одну из карт
  if (!mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  // Показать UID на последовательном мониторе
  Serial.print("UID tag :");
  String content= "";
  byte letter;

  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "17 27 C7 A6" || "BA FA 21 28") // измените здесь UID карты/карт, которым вы хотите дать доступ
  {
    Serial.println("Authorized access");
    Serial.println();
    delay(3000);
  }
 
 else   {
    Serial.println(" Access denied");
    delay(3000);
  }
  
  char Data=Bluetooth.read();//Получает данные из bluetooth и помещает их в переменную 'Data'
  if(Data=='1'){//если данные от bluetooth равны 1(1, полученная от bluetooth, НЕ ЯВЛЯЕТСЯ целым числом, это символ.)
    gateOpenSequence();//Самостоятельно созданная функция, которая выполняет все действия, когда нужно открыть ворота.
  }
  while(digitalRead(DA)==1){         //При получении символов с клавиатуры.
    int key =digitalRead(D3)*8 + digitalRead(D2)*4 +digitalRead(D1)*2 + digitalRead(D0);//Определенная формула, используемая для расшифровки того, какая клавиша была нажата
    returnKey(key);//Самостоятельно созданная функция, которая переводит расшифрованную клавишу в раскладку клавиатуры. помещает нажатую клавишу в переменную 'c'
    Serial.print(c);
    if(c!='D') keys[cnt3]=c;
      
    switch(cnt2){
      case 0:
        if(c!='D'){
          lcd.clear();
          lcd.setCursor(9, 0);
          lcd.print(keys[cnt3]);
          ++cnt3;
          ++cnt2;
          Beep();
          break;
        }
        else break;
      case 1:
        if(c!='D'){
          lcd.setCursor(8,0);
          lcd.print("*");
          lcd.print(keys[cnt3]);
          ++cnt3;
          ++cnt2;
          Beep();
          break;
        }
        else{
          lcd.clear();
          --cnt3;
          --cnt2;
          break;
        }

      case 2:
        if(c!='D'){
          lcd.setCursor(8, 0);
          lcd.print("**");
          lcd.print(keys[cnt3]);
          ++cnt2;
          ++cnt3;
          Beep();
          break;
        }
        else{
          lcd.clear();
          lcd.setCursor(9,0);
          cnt3--;
          cnt2--;
          lcd.print(keys[cnt3-1]);
          
          
          break;
        }

      case 3:
        if(c!='D'){
          lcd.setCursor(8, 0);
          lcd.print("***");
          lcd.print(keys[cnt3]);
          ++cnt2;
          ++cnt3;
          Beep();
          break;
        }
        else{
          lcd.clear();
          lcd.setCursor(9,0);
          lcd.print("*");
          cnt3--;
          cnt2--;
          lcd.print(keys[cnt3-1]);
          break;
        }
      case 4:
        if(c!='D'){
          cnt2=0;
          cnt3=0;
        }
        else{
          lcd.clear();
          lcd.setCursor(9, 0);
          lcd.print("**");
          cnt2--;
          cnt3--;
          lcd.print(keys[cnt3-1]); 
        }
      break;
    }
    while(digitalRead(DA)==1);//убедимся, что мы не получим двойной ввод от одного нажатия, заставляя цикл оставаться там, пока нажата клавиша
    if(c!='D'){
      keysPressed[count] = c;//Помещаем нажатую клавишу в массив
      count++;//поднятие индекса массива
    }
    else{
      keysPressed[count]="";
      count--;      
     }
    if (count == 5)//когда count достигает 5, что означает, что массив заполнен, проверьте, равен ли «пароль» массива 5 ключам, которые только что ввел пользователь.
    {
      for (int i = 0; i < 5; i++)
      {
        if (password[i] == keysPressed[i])//если ключи одинаковые добавляем к cnt единицу, если cnt равно 5 значит все ключи были одинаковые
        {
          cnt++;
        }
      }
        if(cnt==5){
          gateOpenSequence();
          cnt=0;
        }
        else{
          wrongPassword();
          cnt=0;
        }
        }
      }
  }


void returnKey(int key)
{ 
  char arrkey[16]={ '1','2','3','A','4','5','6','B','7','8','9','C','*','0','#','D' };
  c=arrkey[key];
  
}

void lcdSetup(){
  lcd.setCursor(0,0);
  lcd.write(2);
  lcd.setCursor(1, 0);
  lcd.write(1);
  lcd.setCursor(18,0);
  lcd.write(1);
  lcd.setCursor(19,0);
  lcd.write(2);
  lcd.setCursor(2,0);
  lcd.print("----Welcome-----");
  lcd.setCursor(0,1);
  lcd.print("|  Enter password  |");
  lcd.setCursor(0,2);
  lcd.print("|and then press '#'|");
  lcd.setCursor(0, 3);
  lcd.print("|------------------|");
}
void gateOpenSequence(){
  int start = 0;
  int desired = 105;
  lcd.clear();
  lcd.setCursor(6,0);
  lcd.print("Welcome");
  lcd.setCursor(8,1);
  lcd.print("Home");
  count = 0;
  digitalWrite(buzzer,HIGH);
  while(start<desired){
  servo.write(++start);
  delay(10);
  }
  delay(1000);
  digitalWrite(buzzer,LOW);
  lcdSetup();
  while(start>5){
  servo.write(--start);
  delay(10);
  }


}
void wrongPassword(){
  lcd.clear();
  lcd.setCursor(7,0);
  lcd.print("Wrong");
  lcd.setCursor(6,1);
  lcd.print("Password");
  lcd.setCursor(4, 2);
  lcd.print("Achalta ota");
  count = 0;
  for(int jj=0;jj<3;jj++){
    Beep();
  }
  delay(2000);
  lcdSetup();

}

void Beep(){
  digitalWrite(buzzer,HIGH);
  delay(200);
  digitalWrite(buzzer,LOW);
  delay(200);
}

Я буду очень признателен за помощь, так как не могу найти никаких объяснений по поводу этих двух функций:

if (!mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  //Выбираем одну из карт
  if (!mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }

Заранее спасибо, Барзи.

, 👍2


1 ответ


0
mfrc522.PICC_IsNewCardPresent()

проверит, поднесена ли к считывателю новая RFID-карта/метка. Поэтому, если это возвращает true, вы можете прочитать карту.

mfrc522.PICC_ReadCardSerial()

фактически считывает данные с карты/тега, чтобы UUID был доступен через mfrc522.uid.


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

if (!mfrc522.PICC_IsNewCardPresent()) 
{
    return;
}
//Выбираем одну из карт
if (!mfrc522.PICC_ReadCardSerial()) 
{
    return;
}

Когда мы переводим первый оператор if на английский язык, мы получаем:

 If no new card is present restart the function `loop()`.

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

Вместо этого вы можете немного изменить структуру своего RFID-кода:

if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()){
    // Обработка всего RFID-кода здесь
    // Показать UID на последовательном мониторе
    Serial.print("UID tag :");
    String content= "";
    byte letter;

    for (byte i = 0; i < mfrc522.uid.size; i++) 
    {
        Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522.uid.uidByte[i], HEX);
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
    }
    Serial.println();
    Serial.print("Message : ");
    content.toUpperCase();
    if (content.substring(1) == "17 27 C7 A6" || "BA FA 21 28") // измените здесь UID карты/карт, которым вы хотите дать доступ
    {
        Serial.println("Authorized access");
        Serial.println();
        delay(3000);
    } else {
        Serial.println(" Access denied");
        delay(3000);
    }
}

Это выполнит код RFID, если новая карта может быть прочитана. В противном случае он просто продолжит работу с остальной частью кода.

Обратите внимание, что из-за вызова delay(3000) ваш код не будет реагировать ни на что в течение 3 секунд после того, как карта была поднесена к считывателю. Возможно, вы захотите отказаться от этой задержки в пользу лучшего отклика.

,