Светодиод не хочет выходить из цикла мигания

Тема в разделе "Arduino & Shields", создана пользователем Suyano, 6 окт 2018.

  1. Suyano

    Suyano Нерд

    Доброе утро!

    Задача: моргать светодиодом в разных режимах (горение, быстрое моргание, долгое моргание, несколько морганий и др.)

    Код (C++):
    #define BTN_LED 6

    int req;
    // Light
    int bblink; // Режим мерцания кнопки
    int bled; // Запись состояния Button LED (HIGH / LOW)
    unsigned long timer; // Таймер Blink Button
    int tb; // Счетчик включений
    bool block; // Блокировка в цикле режима кнопки #5 (защита от флуда в Serial)



    void ledbtn_mode(int sd) { // 1 - свечение / 2 - выключение / 3 - blink mode / 4 - error blink mode
        switch (sd) {
        case 1:
            // Включение светодиода кнопки
            if(bblink != 1) {
                digitalWrite(BTN_LED, HIGH); // Включаем светодиод
                bblink = 1; // Записываем режим
            }
            break;
        case 2:
            // Выключение светодиода кнопки
            if(bblink != 2) {
                digitalWrite(BTN_LED, LOW); // Выключаем светодиод
                bblink = 2; // Записываем режим
            }
            break;
        case 3:
            // Blink Mode
            if(bblink != 3) {
                tb = 0;
                timer = millis(); // Записываем текущее время
                bblink = 3; // Запускаем режим мерцания
            }
            break;
        case 4:
            // Error Blink Mode
            if(bblink != 4) {
                tb = 0;
                timer = millis();
                bblink = 4;
            }
            break;
        case 5:
            // Кнопка зажата, моргнем несколько раз
            if(bblink != 5) {
                block = false; // Сброс блокировки
                tb = 0;
                timer = millis();
                bblink = 5; // Запуск режима
            }
            break;
        case 6:
            // Постоянное моргание
            if(bblink != 6) {
                tb = 0;
                timer = millis();
                bblink = 6;
            }
            break;
        }
    }

    void setup() {
        Serial.begin(115200);
        pinMode(BTN_LED, OUTPUT);
        pinMode(13, OUTPUT);
        digitalWrite(BTN_LED, HIGH);
        delay(500);
        digitalWrite(BTN_LED, LOW);
        delay(500);
        digitalWrite(BTN_LED, HIGH);
        digitalWrite(13, LOW);
    }

    void loop() {
        if(Serial.available() > 0) {
            req = Serial.parseInt();
        }
        if(req == 10) {
            //digitalWrite(BTN_LED, LOW);
            ledbtn_mode(1);
        } else if(req == 15) {
            //digitalWrite(BTN_LED, HIGH);
            ledbtn_mode(2);
        } else if(req == 20) {
            ledbtn_mode(3);
        } else if(req == 25) {
            ledbtn_mode(4); // Проблемный режим
        } else if(req == 30) {
            ledbtn_mode(5); // Проблемный режим
        } else if(req == 35) {
            ledbtn_mode(6);
        }

        if(bblink == 5) {
            digitalWrite(13, HIGH);
        } else {
            digitalWrite(13, LOW);
        }

    // Btn Blink Mode (#3) - Все ок
        if(bblink == 3) {
            if((millis() - timer) >= 500) {
                if(digitalRead(BTN_LED) == HIGH) {
                    bled = LOW;
                } else {
                    bled = HIGH;
                }
                digitalWrite(BTN_LED, bled);
                timer = millis();
            }
        }

        // Error Blink Mode Btn (#4) - Проблема со сбросом режима
        if(bblink == 4) {
            // Моргнем три раза
            if(tb <= 6 && (millis() - timer) >= 150) {
                if(digitalRead(BTN_LED) == HIGH) {
                    bled = LOW;
                } else {
                    bled = HIGH;
                }
                digitalWrite(BTN_LED, bled);
                tb++;
                timer = millis();
            } else if(tb >= 6) {
                digitalWrite(BTN_LED, HIGH);
            }
        }

        // Blink Mode (#5) - Проблема со сбросом режима
        if(bblink == 5) {
            // Моргнем три раза
            if(tb < 6 && (millis() - timer) >= 500) {
                if(digitalRead(BTN_LED) == HIGH) {
                    bled = LOW;
                } else {
                    bled = HIGH;
                }
                digitalWrite(BTN_LED, bled);
                tb++;
                timer = millis();
            } else if(tb >= 6 && block == false) {
                Serial.println("<320>");
                if(digitalRead(BTN_LED) == LOW) {
                    digitalWrite(BTN_LED, HIGH);
                }
                block = true;
            }
        }

        // Постоянное моргание
        if(bblink == 6) {
            if((millis() - timer) >= 1500) {
                if(digitalRead(BTN_LED) == HIGH) {
                    bled = LOW;
                } else {
                    bled = HIGH;
                }
                digitalWrite(BTN_LED, bled);
                timer = millis();
            }
        }

    }

    Я отправляю определенное число в Serial (10 / 15 / 20 / 25 / 30 / 35) и в соответствии с ним запускается нужный режим работы светодиода. Проблемы возникли в двух режимах (Режим №4 - Число 25 и Режим №5 - Число 30). В этих режимах светодиод должен моргнуть несколько раз (до переполнения счетчика) и после встать в обычный режим горения. Это работает, но ровно 1 раз. Если я повторно введу число вызова любого из этих режимов - ничего не произойдет. Это означает, что после переполнения счетчика переменная bblink не выходит из своего режима.

    Пример:
    - Ввожу в Serial число 30 - светодиод моргнет пару раз. Вроде все хорошо.
    - Пробую ввести снова число 30 - ничего не происходит.

    Но. Если после срабатывания режима я запущу другой, то этот режим снова можно будет запустить. Это означает, что переменная bblink сброшена.

    Я попробовал по окончанию цикла моргания сбросить переменную bblink, отвечающую за номер режима:

    Код (C++):
        // Blink Mode (#5) - Проблема со сбросом режима
        if(bblink == 5) {
            // Моргнем три раза
            if(tb < 6 && (millis() - timer) >= 500) {
                if(digitalRead(BTN_LED) == HIGH) {
                    bled = LOW;
                } else {
                    bled = HIGH;
                }
                digitalWrite(BTN_LED, bled);
                tb++;
                timer = millis();
            } else if(tb >= 6 && block == false) {
                Serial.println("<320>");
                if(digitalRead(BTN_LED) == LOW) {
                    digitalWrite(BTN_LED, HIGH);
                }
                bblink = 0;
                block = true;
            }
        }
    Код (C++):
    bblink = 0;

    Теперь светодиод моргает постоянно. В чем ошибка?
     
  2. Daniil

    Daniil Гуру

    Не понял. Куда вы вставили сброс bblink? Кажется, что не в окончание цикла, а просто после кода, который отвечает за цикл.
     
  3. Suyano

    Suyano Нерд

    Daniil,

    4 строка снизу. Внутри условия, где счетчик tb >= 6
     
  4. Daniil

    Daniil Гуру

    а что этот кусок кода делает, вне всех циклов?
    Мне кажется, что после case нет смысла проверять bblink if-ом. Вы тут задаёте начальные условия для цикла.
    Скажите, что делает block? Это избыточно, у вас и так есть проверка tb (счетчик горения).
    Так как у вас tb инкрементируется независимо от состояния светодиода, то миганий получается 3, да? прочитал коментарии)
    Какому режиму соответсвует bblink=0? Может, приравнять 1?
    Прошу, выложите, пожалуйста, код после правок (если они будут и не помогут) ещё раз целиком.
     
  5. Daniil

    Daniil Гуру

    Я бы порекомендовал ещё не играть с bblink-ом вне процедуры ledbtn_mode, т.е. если нужно переключить режим мерцания, то вызывать процедуру ledbtn_mode с другим режимом. Она задает нач. положения переменных, о которых вы можете забыть