Подвисает nano

Тема в разделе "Arduino & Shields", создана пользователем xsash, 12 сен 2016.

  1. xsash

    xsash Нерд

    Добрый!

    Недавно я создавал топик про параллельное отслеживание состояния геркона и считывание 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 порт данные в течение дня слать?)
     
    Последнее редактирование: 12 сен 2016
  2. Vad33

    Vad33 Капитан-оригинал

    Разобраться и включить watchdog
     
  3. Tomasina

    Tomasina Сушитель лампочек Модератор

    перед if(guardOn)
    вставь:
    Код (C++):
    unsigned long timestamp = millis() / 1000;
    Serial.println(timestamp);
    Хоть будет видно в какой момент происходит зависание.

    P.S. Почему в beep(...) нет завершающего noTone(...)?
     
  4. xsash

    xsash Нерд

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

    про noTone не знал, учту, спс