RFID + millis

DaeRiuS
DaeRiuS аватар
Offline
Зарегистрирован: 28.08.2018

Здравствуйте, жители форума. Недавно начал изучать millis и уже написал код считывания показаний датчика с помощью millis (просто сам до этого решил дойти), но когда приступил к RFID-метке, возникла проблема.

Все, что у меня получилось, это написать код, в котором присутсвуют:

1) Функция возрвращения uid приложенной карты

2) И в loop'е сравнивает его, при вызове функции, с нужным, после чего должны последовать действия(например - вкл светодиод).

Но у меня не получается реализовать это с millis

Когда я прикладываю карту, у меня просто быстро начинает вкл-выкл светодиод. И так пока держу карту.

Надеюсь код будет понятен и вы сможете мне помочь.

#include <MFRC522.h>
//---------------------------------------------------------//
#define BUTTON_PIN A1   // Сенсорная кнопка
#define LIGHT_LINE 46 // Светодиодная лента на входе

boolean button_state = false;
boolean light_state = false;
boolean button_flag = false;
boolean card_flag = false;

unsigned long real_time;

MFRC522 mfrc522(53, 5);  // SS_PIN and RST_PIN
//---------------------------------------------------------//
void setup() {
  pinMode(BUTTON_PIN, INPUT);

  SPI.begin();
  mfrc522.PCD_Init();
  Serial.begin(9600);
}

void loop() {
  real_time = millis();

  if (getID() == 911266) {  // 911266 - uid моей карты
    if (card_flag == false) {
      card_flag = true;
      light_state = !light_state;
      real_time = millis();
    }
    if (card_flag == true && (millis() - real_time) < 1000) {
      card_flag = false;
    }
  }
  digitalWrite(LIGHT_LINE, light_state);
}

unsigned long getID() { // ----- Функция, возращающая uid приложеной карты ----- //
  unsigned long uidDec, uidDecTemp;
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return 0;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return 0;
  }
  uidDec = 0;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    uidDecTemp = mfrc522.uid.uidByte[i];
    uidDec = uidDec * 256 + uidDecTemp;
  }
  return uidDec;
}

 

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

Конечный автомат мы принципиально не применяем? Мол Аллах запретил. Но хоть по ночам, когда Аллах "не видит" поизучайте немного.

DaeRiuS
DaeRiuS аватар
Offline
Зарегистрирован: 28.08.2018

Мистер qwone, а что Вы в данном случае имеете ввиду под "конечный автомат". Если Вы про действие, которое должно произойти с помощью RFID-метки, то я написал, что должен загореться светодиод

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

Конечный автомат это внятные последовательности действия . А просто прилипить флаг и сказать что все ОК не выйдет. Поймите что при переходе из одного состояния в другое должна произходить выдержка времени организованая на millis а потом уже повторное считывание.

DaeRiuS
DaeRiuS аватар
Offline
Зарегистрирован: 28.08.2018

Хорошо, спасибо. Теперь понял, попробую реализовать

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А Вы можете внятно, нормальными русскими словами, которые Вы понимаете, объяснить что делаетеся в строках №№ 26-35. По мне. так там бред, но, возможно, я ошибаюсь. Объясните, пожалуйста.

DaeRiuS
DaeRiuS аватар
Offline
Зарегистрирован: 28.08.2018

if (getID() == 911266) {

на 26 строке мы вызываем функцию считывания uid карты, которую мы прикладываем, после чего сравниваем с uid нужной нам карты и выполнеем(или не выполняем) последующие действия

if (card_flag == false) {
	      card_flag = true;
	      light_state = !light_state;
	      real_time = millis();
	    }

В строках 27-31 мы делаем следующее:

   если специальный флаг карты == false, то мы:

   1) меняем его состояние на true

   2) меняем значение переменной состояния светодиода на противоположное ему

   3) обновляем значение переменной, хранящее аппартное время платы

if (card_flag == true && (millis() - real_time) < 1000) {
	      card_flag = false;
	    }

Строки 32-34:

   1) если флаг карты == true (т.е. предыдущий if выполнился), то меняем его состояние на false

   2) Если все-таки флаг карты == true, то должно еще и пройти время(1 секунда), чтобы действия выполнились

digitalWrite(LIGHT_LINE, light_state);

Подаем(HIGH)/Не подаем(LOW) питание на светодиод, в зависимости от значения переменной light_state

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
#define LIGHT_LINE 46 // Светодиодная лента на входе

unsigned long past;
boolean card_flag = false;
void set( bool f) {
  past = millis();
  card_flag = f;
  if (f) {
    light_state = true;
  }
  else {
    light_state = false;
  }
  digitalWrite(LIGHT_LINE, light_state);
}

void setup() {
  pinMode(LIGHT_LINE, OUTPUT);
  set(false);
}

void loop() {
  uint32_t tmp = getID();
  if (f) { // если включено
    if (millis() - past >= 1000) { // если прошло время
      if (tmp = 911266)// если карточка совпала
        set(false);// то выключить
    }
  };
  else {  // если выключено
    if (millis() - past >= 1000) { // если прошло время
      if (tmp = 911266)// если карточка совпала
        set(true);// то включить
    };
  }
}

ПС: дальше жевать эту ботву не буду.

DaeRiuS
DaeRiuS аватар
Offline
Зарегистрирован: 28.08.2018

Хорошо, спасибо. Сейчас буду разбирать Ваш код и пробовать

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DaeRiuS пишет:

Хорошо, спасибо. Сейчас буду разбирать Ваш код и пробовать

Очень плохая идея. Разбирать надо свой код.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DaeRiuS пишет:

В строках 27-31 мы делаем следующее:...

Ну, я же просил Вас смотреть на строки и писать что они делают. А Вы мне что написали? Вы написали, что он по Вашей задумке должны были бы делать.

Давайте я прокомментирую Ваш loop

void loop() {
  real_time = millis(); // нафиг ненужная операция, т.к. если правильную карту не поднесли,
  								// то real_time никак не используется, а если поднесли, то ей
  								// безусловно присваивается новое значение

  if (getID() == 911266) {  // Если это правильная карта, то
  	// сюда мы попадаем только тогда, когда поднесли правильную карту
    if (card_flag == false) {// Это условие истинно ВСЕГДА (см. ниже), поэтому оно лишнее
      card_flag = true;	// Это ЕДИНСТВЕННОЕ место в программе, где card_flag становится true.
      						// кроме как здесь он true стать не может
      light_state = !light_state;  // Изменяем light_state на противоположное
      real_time = millis();  // real_time делаем равным текущему millis
    }
    // Условие в следующей строке истинно ВСЕГДА, поэтому оно лишнее.
    // 	Действительно card_flag мы ТОЛЬКО ЧТО сделали true, real_time ТОЛЬКО ЧТО сделали 
    // 	равным текущему millis
    if (card_flag == true && (millis() - real_time) < 1000) {
      card_flag = false;	// здесь мы возвращаем card_flag значение false, обеспечивая 
      							// вечную истинность условия в строке №7 выше "if (card_flag == false)"
    }
  }
  digitalWrite(LIGHT_LINE, light_state); // независимо ни от чего устанавливаем LIGHT_LINE в значение light_state
}

Надеюсь, Вы согласны с моими комментариями?

Теперь давайте повыбрасываем вечно истинные условия и бессмысленное манипулирование card_flag
  и millis, и поймём, что Ваш код ПОЛНСТЬЮ эквивалентен вот такому.

void loop() {
  if (getID() == 911266) {  // Если это правильная карта, то
    // сюда мы попадаем только тогда, когда поднесли правильную карту
    light_state = !light_state;  // Изменяем light_state на противоположное
  }
  digitalWrite(LIGHT_LINE, light_state); // независимо ни от чего устанавливаем LIGHT_LINE в значение light_state
}

Вот и всё. Больше у Вас ничего не делается. Поднесли карту - на пине LIGHT_LINE сигнал поменялся на противоположный. Поднесли ещё раз - поменялся "взад". Так она себя ведёт? Собственно, как написано, так и ведёт.