Добрый! Недавно я создавал топик про параллельное отслеживание состояния геркона и считывание rfid. Спасибо за подсказки и векторы поиска. В итоге наткнулся на разные реализации многопоточности и остановился на библиотеке "Timer" версии 2.1 Задача - создать очередную sms сигнализацию, но с оговоркой - датчик считывания RFID стоит внутри квартиры. Вот такая вот оговорка. Алгоритм - прикладываем ключ, дается N секунд на выход, после чего система ставится на охрану. Когда пришли, срабатывает датчик (геркон), дается N секунд приложить ключ (снять с охраны), иначе отправляется СМС. Что получилось в итоге: Arduino Nano, к ней подключены 3 светодиода (зеленый/красный - состояние охраны, желтый - индикатор отсчета N секунд, спикер от системника для озвучки, геркон и собственно RFID-RC522). Пока нет sim модуля, выводим информацию просто в com порт. Если потребуется отрисовать схему - добавлю, но вроде все просто. В целом все работает, но при длительном тесте (больше 2-3-4 часов работы) система зависает. Индикаторы горят, но метка уже не считывается. Плата подключена к компьютеру, компьютер просто включен (браузер, тв...). Вот сейчас опять ардуинка "задумалась", запустил arduino ide, на порт прилетело "Start system" (плата ребутнулась) Сам код Код (C++): #include <SPI.h> #include <MFRC522.h> #include <Event.h> #include <Timer.h> #define RST_PIN 9 #define SS_PIN 10 /*************************************************/ MFRC522 mfrc522(SS_PIN, RST_PIN); Timer t; // для отображения номера карточки в десятичном формате unsigned long idKey, idKeyTemp; unsigned long ticketNumber; /* Массив ключей */ char* myKeys[] = {"3714368928", "1854873968"}; /* Переменные Pin */ int pinLedRed = 6; int pinLedYellow = 7; int pinLedGreen = 8; int pinBeep = 5; //спикер int pinDoor = 2; //геркон int checkAlarmEvent; int LedYellowEvent; int sendSMSEvent; bool greenLight = true; bool redLight = false; int openDoor = 0; //Дверь закрыта int waitExit = 20; //** секунд на выход; int waitEnter = 20; //** секунд на вход; /* Логические переменные */ bool guardOn = false; //система при старте не работает bool guardOnTmp = false; bool alarm = false; //тревога выключена bool access = true; //доступ разрешен /* Текстовые переменные */ String txtKey = ""; /*************************************************/ void setup() { Serial.begin(9600); while (!Serial); // инициализация SPI SPI.begin(); // инициализация MFRC522 mfrc522.PCD_Init(); pinMode(pinLedRed, OUTPUT); pinMode(pinLedYellow, OUTPUT); pinMode(pinLedGreen, OUTPUT); pinMode(pinBeep, OUTPUT); pinMode(pinDoor, INPUT); Serial.println("Start system"); digitalWrite(pinLedRed, redLight); digitalWrite(pinLedGreen, greenLight); // каждую секунду пытаемся считать ключ t.every(1000, readKey, (void*)0); // каждую секунду проверяем состояние датчика/датчиков t.every(1000, checkSensor, (void*)0); // каждую секунду проверяем активировано ли состояние "постановка на охрану" checkAlarmEvent = t.every(1000, checkAlarm, (void*)0); } void loop() { t.update(); } //спикер void beep(int ton, int time) { tone(pinBeep, ton, time); delay(time + 20); Serial.println("beep"); } void readKey(void *context) { // Поиск новой карточки if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Выбор карточки if ( ! mfrc522.PICC_ReadCardSerial()) { return; } idKey = 0; Serial.println("Read card:"); for (byte i = 0; i < mfrc522.uid.size; i++) { idKeyTemp = mfrc522.uid.uidByte[i]; idKey = idKey*256+idKeyTemp; } txtKey = String(idKey); Serial.println(txtKey); if (checkKey(txtKey)) { //если карта принята access = true; Serial.println("Key accept!"); beep(1500, 350); beep(1500, 350); //определяем входит или выходит человек if (guardOnTmp) { //если входит - отключаем сигнализацию, останавливаем мигающий желтый индикатор Serial.println("I am enter!"); guardOn = false; t.stop(LedYellowEvent); digitalWrite(pinLedYellow, LOW); } else { //если выходит - ставим на охрану через waitExit секунд, мигаем желтым индикатором Serial.println("I am exit!"); guardOn = true; LedYellowEvent = t.oscillate(pinLedYellow, 500, HIGH); t.after(waitExit*1000, guard, (void*)0); } //меняем состояние вход/выход человека, и зеленый/красный индикатор guardOnTmp = !guardOnTmp; redLight = !redLight; greenLight = !greenLight; } else { //ключ не определен access = false; Serial.println("Key not found!"); beep(150, 1000); } // Halt PICC mfrc522.PICC_HaltA(); digitalWrite(pinLedRed, redLight); digitalWrite(pinLedGreen, greenLight); } //проверка ключа bool checkKey(String txt) { boolean validKey = false; for (int i = 0; i < 2; i++) { if ((txtKey == myKeys[i]) && (!validKey)) { validKey = true; } } if (validKey) { return true; //ключ найден в массиве } else { return false; //ключ не найден в массиве } } //активация состояние охраны void guard(void *context) { guardOn = true; t.stop(LedYellowEvent); } //проверка датчика/датчиков void checkSensor(void *context) { if (guardOn) { openDoor = digitalRead(pinDoor); if (openDoor == 1) { alarm = true; //включение тревоги // Serial.println("Attention! Alarm ON!"); } } } //проверка активации датчика void checkAlarm(void *context) { if (alarm) { //если датчик активирован - включаем желтый индикатор и одижаем waitEnter секунд (см. ниже) LedYellowEvent = t.oscillate(pinLedYellow, 100, HIGH); sendSMSEvent = t.after(waitEnter*1000, sendSMS, (void*)0); t.stop(checkAlarmEvent); } else { alarm = false; //выключение тревоги, мы уже запустили функцию sendSMSEvent выше } } void sendSMS(void *context) { if (alarm) { //если в течение waitEnter секунд ключ не опознан - отправляем смс beep(550, 1000); Serial.println("SMS send"); } else { //иначе останавливается световая индикация t.stop(LedYellowEvent); Serial.println("Hello frend!"); } } Повторюсь, сам в принципе код рабочий, но в какой-то момент его клинит. Вероятно есть какие-то лимиты у счетчиков... Подскажите, что обнулять, куда копать, да и как хоть отладить подобное (тупо на com порт данные в течение дня слать?)
перед if(guardOn) вставь: Код (C++): unsigned long timestamp = millis() / 1000; Serial.println(timestamp); Хоть будет видно в какой момент происходит зависание. P.S. Почему в beep(...) нет завершающего noTone(...)?
немного переписал логику, упростив ненужные проверки. да, уже почти так и мониторю с выводом в порт про noTone не знал, учту, спс