Цикл чтения RFID-карты кажется остановленным
Мне удалось запрограммировать считыватель RFID-карт на включение и выключение света при предъявлении любой RFID-карты. Я протестировал это, и оно работает, при этом индикаторы постоянно включаются и выключаются, если представлена какая-либо карта с поддержкой RFID.
Я попытался добавить команду, согласно которой при считывании двух определенных карт (идентифицируемых по их номерам UID) только эти карты будут сбрасывать индикаторы на "выключено" независимо от того, в каком состоянии они были в данный момент — как кнопка сброса.
Проблема заключается в том, что после предъявления одной из этих карт индикатор гаснет, но система перестает реагировать, а при предъявлении одной из других карт индикатор больше не включается и не выключается.
Я новичок в программировании Arduino, а также в технологии RFID, но мне кажется, что цикл не сбрасывается в начало должным образом, или мой оператор IF каким-то образом оставляет систему в состоянии, когда начальный код не может запустить.
Мой код ниже. Будем признательны за любые мысли.
`
#define r1 A0
int relay1 = LOW;
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Создать экземпляр MFRC522.
void setup()
{
pinMode(r1, OUTPUT);
Serial.begin(9600); // Инициируем последовательную связь
SPI.begin(); // Инициируем шину SPI
mfrc522.PCD_Init(); // Инициировать MFRC522
Serial.println("Approximate your card to the reader...");
Serial.println();
}
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) == "23 49 1F BE") || (content.substring(1) == "CB CB 2C E3")) // меняем здесь UID карты/карт которым вы хотите предоставить доступ
{
Serial.println("Staff access");
Serial.println();
relay1 = HIGH;
digitalWrite(r1, relay1);
delay(500);
}
else
{
Serial.println("Authorized access");
Serial.println();
relay1 = ~ relay1;
digitalWrite(r1, relay1);
delay(500);
}
}
`
@Christine, 👍1
Обсуждение1 ответ
Проблема заключается в неправильном использовании тильды (~) , которая является побитовым оператором НЕ, по отношению к переменной int
relay1
.
Кажется, что он работает правильно, когда реле 1 запускается с НИЗКИМ значением, которое имеет значение 0. То есть реле 1 имеет внутреннее значение 0b00000000000000000. Если теперь выполняется оператор relay1 = ~relay1
, внутреннее значение relay1 будет 0b1111111111111111. Это обрабатывается как HIGH в выражении digitalWrite(r1, relay1);
, поэтому кажется, что он работает правильно.
Если снова выполняется оператор relay1 = ~relay1
, внутреннее значение relay1 будет равно 0b00000000000000000. Это рассматривается как LOW в выражении digitalWrite(r1, relay1);
Так что это также будет работать непрерывно, включая и выключая реле.
Проблема возникает, когда вы явно устанавливаете relay1 в HIGH здесь: relay1 = HIGH;
. HIGH имеет значение 1, то есть реле1 теперь имеет внутреннее значение 0b00000000000000001, и снова это работает, однако следующее выполнение инструкции relay1 = ~relay1
дает реле1 внутреннее значение
0b1111111111111110, который также считается ВЫСОКИМ. Итак, с этого момента оператор relay1 = ~relay1
всегда будет приводить к тому, что relay1 будет иметь значение, которое интерпретируется как ВЫСОКОЕ. Таким образом, реле, похоже, застряло.
Решение, которое уже фигурирует в комментарии, состоит в том, чтобы изменить оператор int relay1 = LOW;
на bool relay1 = LOW;
и изменить этот оператор реле1 = ~ реле1;
в реле1 = ! реле1;
Большое спасибо за объяснение. Я не понимал, что будет внутреннее значение, отличное от нуля, и единица, связанная с НИЗКИМ и ВЫСОКИМ, поэтому не мог понять, как решение изменения оператора реле может помочь. Похоже, это решит проблему, и теперь у меня есть еще одна концепция, которую нужно изучить и понять больше :), @Christine
@Кристина, протокол заключается в том, чтобы отметить правильный ответ. :-), @Rohit Gupta
- rfid_default_keys проверить с помощью RC522
- Отправка данных из ESP8266 в PHP
- Как сделать динамическое меню с подменю ( Arduino mega или Arduino Uno)
- Я пытаюсь совместить автоматический дверной замок с RFID MFRC522 с программой IR REMOTE.
- Автопарковка на arduino
- Печать string and integer LCD
- Почему мои часы реального времени показывают неверное время с моего ПК?
- Arduino uno + cnc Shield v3 + драйвер шагового двигателя A4988 + AccelStepper?
Вы смотрите на последовательный вывод, когда это происходит? Вы видите сообщение «Доступ персонала»? а затем есть ли какие-либо другие признаки того, что он делает? Я бы добавил операторы печати в два места, куда вы возвращаетесь, таким образом вы сможете отслеживать состояние цикла и/или видеть, перестанет ли он работать и где последнее место, откуда он печатался., @Chad G
если первая карта, которую я представляю, является универсальной картой, последовательный монитор возвращает «авторизованный доступ» при каждом нажатии и продолжает включать и выключать свет. Если затем я представлю карту персонала, последовательный монитор вернет «доступ персонала», но индикаторы ничего не сделают, и после этого, если я снова коснусь общей карты, последовательный монитор вернет «разрешить доступ снова, но индикаторы больше не реагируют., @Christine
Эта операция с
int
нуждается в некотором объяснении:relay1 = ~ relay1;
. Есть ли другой способ достичь своей цели здесь?, @6v6gtДа, relay1 должен быть логическим, а затем используйте relay1=!relay1; для переключения состояний., @Chad G
relay1 = ~relay1 работал нормально, когда я использовал только один критерий для карт (это означает, что все были авторизованы). только когда я добавил критерий «Доступ персонала», он перестал работать. Есть ли особая причина, по которой !relay1 будет работать лучше, чем ~relay1 ?, @Christine
Оператор C++ тильда (~) является побитовым оператором NOT. То есть он изменяет каждый 0 на 1 и каждую 1 на 0. Он почти никогда не подходит для использования с числами со знаком, такими как
int
, где бит старшего разряда является битом знака. Обычно он используется для управления отдельными битами переменной, а не для логических операций., @6v6gtСпасибо, и совет принят, но не думаете ли вы, что это проблема, из-за которой цикл не работает? Как я уже сказал, раньше он работал, меняя состояние от низкого к высокому, когда его активировала любая карта. Почему код больше не запускает событие освещения теперь, когда есть два набора карт доступа для оценки? Я чувствую, что может быть что-то не так с оператором if или с тем, как он заканчивается., @Christine