Помогите решить проблему с RFID

skyfoll
Offline
Зарегистрирован: 22.11.2017

Есть RFID считыватель. Задача такая: нужно, чтобы при поднесении карты с одним номером начинался цикл while и при повторном поднесении этой же карты он прекращался. Как это осуществить?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015
bool onCicle = false;

void loop()
{
   if(rfid.CardPresent())
   {
       onCicle = !onCicle;
       if(onCicle) echo "work";
       else echo "idle";
   }
}

Псевдокод, для демонстрации подхода.

skyfoll
Offline
Зарегистрирован: 22.11.2017

Понял. А как мне зафиксировать значение? В сериал выводит поочередно ON и OFF

boolean tinker_flag = false;
#include <SoftwareSerial.h>
#include <SPI.h>
#include <MFRC522.h> // библиотека "RFID".
#define SS_PIN 10
#define RST_PIN 9
unsigned long uidDec, uidDecTemp;  // для храниения номера метки в десятичном формате
MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
  pinMode(8, OUTPUT);
  Serial.begin(9600);
  Serial.println("Waiting for card...");
  SPI.begin();  //  инициализация SPI / Init SPI bus.
  mfrc522.PCD_Init();     // инициализация MFRC522 / Init MFRC522 card.

}

void loop() {

  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // Выбор метки
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
  uidDec = 0;
  // Выдача серийного номера метки.
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    uidDecTemp = mfrc522.uid.uidByte[i];
    uidDec = uidDec * 256 + uidDecTemp;
  }
  Serial.println("Card UID: ");
  Serial.println(uidDec);
  
  if (uidDec == 3237618307) {
    tinker_flag = !tinker_flag;
    if (tinker_flag) {
      digitalWrite(8, 1);
      Serial.println("ON");
    }
    else if (!tinker_flag){
       digitalWrite(8, 0);
      Serial.println("OFF");
    }

  }
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

skyfoll пишет:

Понял. А как мне зафиксировать значение? В сериал выводит поочередно ON и OFF

Фиксируйте карту и время её приложения. Т.е. - приложили карту, вы смотрите флаг - эта карта уже была приложена на крайнем проходе loop? Если нет - инвертируете флаг работы, запоминаете, что карта приложена. Если да - ничего не делаете. Как только считыватель скажет, что карты нет на нём - сбрасываете флаг приложенной карты. Псевдокод:

bool onWork = false;
bool ourCard = false;

void loop()
{
   if(!rfid.cardPresent()) {ourCard = false; return;}

  if(card == ...)
  {
     if(ourCard) return;
     ourCard = true;
     onWork = !onWork;
     if(onWork) echo "work";
     else echo "idle";
  }
}

 

skyfoll
Offline
Зарегистрирован: 22.11.2017
Где ошибка? Включает, но не выключает
boolean onWork = false;
boolean ourCard = false;
#include <SoftwareSerial.h>
#include <SPI.h>
#include <MFRC522.h> // библиотека "RFID".
#define SS_PIN 10
#define RST_PIN 9
unsigned long uidDec, uidDecTemp;  // для храниения номера метки в десятичном формате
MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
  pinMode(8, OUTPUT);
  Serial.begin(9600);
  Serial.println("Waiting for card...");
  SPI.begin();  //  инициализация SPI / Init SPI bus.
  mfrc522.PCD_Init();     // инициализация MFRC522 / Init MFRC522 card.

}

void loop() {

  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // Выбор метки
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
  uidDec = 0;
  // Выдача серийного номера метки.
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    uidDecTemp = mfrc522.uid.uidByte[i];
    uidDec = uidDec * 256 + uidDecTemp;
  }
  Serial.println("Card UID: ");
  Serial.println(uidDec);
  if (!uidDec == 3237618307) {
    ourCard = false;
    return;
  }
  if (uidDec == 3237618307) {
    if (ourCard) {
      return;
    }
    ourCard = true;
    onWork = !onWork;
    if (onWork) {
      digitalWrite(8, 1);
    }
    else {
      digitalWrite(8, 0);
    }
  }
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

skyfoll пишет:

Где ошибка? Включает, но не выключает
boolean onWork = false;
boolean ourCard = false;
#include <SoftwareSerial.h>
#include <SPI.h>
#include <MFRC522.h> // библиотека "RFID".
#define SS_PIN 10
#define RST_PIN 9
unsigned long uidDec, uidDecTemp;  // для храниения номера метки в десятичном формате
MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
  pinMode(8, OUTPUT);
  Serial.begin(9600);
  Serial.println("Waiting for card...");
  SPI.begin();  //  инициализация SPI / Init SPI bus.
  mfrc522.PCD_Init();     // инициализация MFRC522 / Init MFRC522 card.

}

void loop() {

  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // Выбор метки
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
  uidDec = 0;
  // Выдача серийного номера метки.
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    uidDecTemp = mfrc522.uid.uidByte[i];
    uidDec = uidDec * 256 + uidDecTemp;
  }
  Serial.println("Card UID: ");
  Serial.println(uidDec);
  if (!uidDec == 3237618307) {
    ourCard = false;
    return;
  }
  if (uidDec == 3237618307) {
    if (ourCard) {
      return;
    }
    ourCard = true;
    onWork = !onWork;
    if (onWork) {
      digitalWrite(8, 1);
    }
    else {
      digitalWrite(8, 0);
    }
  }
}

 

Вы невнимательно читали мой пример. Перед 23 строкой вставьте сброс флага, когда карты нету.

skyfoll
Offline
Зарегистрирован: 22.11.2017

Получается так, что снова поочередно выводит ON и OFF. Объясните мне на пальцах, как это работает? У меня в голове эти флажки не укладываются

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

skyfoll пишет:

Получается так, что снова поочередно выводит ON и OFF. Объясните мне на пальцах, как это работает? У меня в голове эти флажки не укладываются

Давайте на примере: вам надо, чтобы при первом приложении ключа к считывателю - мотор закрутился (например), при втором приложении ключа к считывателю - остановился. Считыватель необязателен, это может быть кнопка, геркон и т.п. - важен принцип работы.

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

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

Вот тут и нужны разные флаги, с помощью которых мы можем манипулировать состоянием системы. Есть ещё один подход - конечный автомат, я сознательно не стал его приводить, т.к. он сложнее в понимании. Но он также прекрасно демонстрирует управление ветками программного кода. Смотрите ниже псевдокод:

typedef enum
{
  msWaitForCardPresent, // ждём карты на считывателе
  msWaitForCardReleased, // ждём, когда карду уберут со считывателя
} MachineState;

MachineState machineState;
bool motorRunning;

void loop()
{
  switch(machineState)
  {
    case msWaitForCardPresent:
    {
      if(rfid.CardPresent())
      {
        if(rfid.getCardNumber() == 123456)
        {
          echo "Found our card, switch motor state!";
          
          motorRunning = !motorRunning;
          
          if(motorRunning)
            echo "work";
          else
            echo "idle";
            
          echo "Wait for card released...";
          machineState = msWaitForCardReleased;
        }
      }
    }
    break;
    
    case msWaitForCardReleased:
    {
      if(!rfid.CardPresent())
      {
        machineState = msWaitForCardPresent;
        echo "card released, switch to wait mode...";
      }
    }
    break;
  }
}

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

Не запутал?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Процессор не может стоять (в нормальных услових). Процессор всегда в секунду выполняет определеное количество команд. Но пользователю хватает только определеное количество. Остальные процессор делает в холостую. И важно что бы в холостую процессор что-то сделал не так. Дальше у процессора нет памяти , а та память что есть это скорее записная книжка. Вот по ней процессор и сверяется что делать. Процессор обнаружил что есть карточка. А раньше была? Если была то идем на новый круг. А если не была. То она появилась. Надо что то сделать. А что сделать? Если в книжке написана-"лампочка погашена" , то включить и записать в книжку "лампочка включена". А если иначе то сделать на оборот. 

  И так два флага- 1 это состоние наличия карточки раньше - Есть/Нет 2 - состояние лампочки - Погашена/Включена. 

ПС: В общем  считайте что процессор это Колобок Коллега из этого. https://www.youtube.com/watch?v=tIWbdsbHZN8

 

skyfoll
Offline
Зарегистрирован: 22.11.2017

Нет, спасибо) Буду разбираться дальше. Если что - отпишусь.

skyfoll
Offline
Зарегистрирован: 22.11.2017

qwone пишет:

Процессор не может стоять (в нормальных услових). Процессор всегда в секунду выполняет определеное количество команд. Но пользователю хватает только определеное количество. Остальные процессор делает в холостую. И важно что бы в холостую процессор что-то сделал не так. Дальше у процессора нет памяти , а та память что есть это скорее записная книжка. Вот по ней процессор и сверяется что делать. Процессор обнаружил что есть карточка. А раньше была? Если была то идем на новый круг. А если не была. То она появилась. Надо что то сделать. А что сделать? Если в книжке написана-"лампочка погашена" , то включить и записать в книжку "лампочка включена". А если иначе то сделать на оборот. 

  И так два флага- 1 это состоние наличия карточки раньше - Есть/Нет 2 - состояние лампочки - Погашена/Включена. 

ПС: В общем  считайте что процессор это Колобок Коллега из этого. https://www.youtube.com/watch?v=tIWbdsbHZN8

 

Спасибо))