Правильный способ завершения цикла при необходимости?

Я новичок в Arduinos. В настоящее время я пытаюсь изменить скрипт здесь, который в данный момент просто включает или выключает светодиод в зависимости от того, какой HTTP-запрос GET он получает. Однако я хочу изменить это так, чтобы светодиод модулировал включение/выключение при получении запроса On HTTP GET, а затем просто выключался полностью при получении запроса Off HTTP GET. Однако я нашел два противоречивых метода, которые позволяют этого добиться; первый из них:

int value = LOW;
    if (request.indexOf("/LED=ON") != -1)  {
      value = HIGH;
      do
      {
      digitalWrite(ledPin, HIGH);
      delay(3000);
      digitalWrite(ledPin, LOW);
      delay(5000);
      value = HIGH;
      } while (value = HIGH);
    }
    if (request.indexOf("/LED=OFF") != -1)  {
      digitalWrite(ledPin, LOW);
      value = LOW;
    }

В то время как другой:

  int value = LOW;
    if (request.indexOf("/LED=ON") != -1)  {
      value = HIGH;
      void loop() {
      digitalWrite(ledPin, HIGH);
      delay(3000);
      digitalWrite(ledPin, LOW);
      delay(5000);
      value = HIGH;
      }
    }
    if (request.indexOf("/LED=OFF") != -1)  {
      digitalWrite(ledPin, LOW);
      value = LOW;
    }

Как вы можете видеть, первый использует do...while, а второй использует loop(). У меня есть ощущение, что первый из двух скриптов был бы более подходящим, так как он должен выключаться, как только value устанавливается в LOW (т. е. когда запрашивается выключение)

Однако я был бы очень признателен, если бы кто-нибудь мог просмотреть оба скрипта и сказать мне, какой из них является правильным способом добиться такого рода отключения при запросе HTTP GET Off (если хотя бы один из них является правильным способом сделать это!).

Заранее спасибо за помощь,

С наилучшими пожеланиями, Том

, 👍3


1 ответ


Лучший ответ:

3

Как отметили Игнасио Васкес-Абрамс и jsotola, вам нужно использовать конечный автомат, как в Мигание без задержки Учебник по Arduino. Ваш будет немного сложнее, потому что вы нужен способ включать и выключать его, и поскольку вы используете разные кнопки включения и выключения периоды выключения. Вот пример кода, который абстрагирует логику мигания на три функции:

  • update_led() отвечает за мигание, и его нужно вызывать довольно часто, чтобы добиться плавного мигания
  • start_blinking() и stop_blinking(), как следует из их названий, являются используется для включения и выключения мигающего конечного автомата.
const uint32_t ON_TIME  = 3000;
const uint32_t OFF_TIME = 5000;

bool led_blinking;     // мигаем ли мы светодиодом?
bool led_on;           // светодиод в данный момент горит?
uint32_t last_toggle;  // последний раз переключался во время мигания

void update_led() {
    if (!led_blinking) return;
    uint32_t now = millis();
    if (led_on && now - last_toggle >= ON_TIME) {
        digitalWrite(ledPin, LOW);
        led_on = false;
        last_toggle = now;
    }
    if (!led_on && now - last_toggle >= OFF_TIME) {
        digitalWrite(ledPin, HIGH);
        led_on = true;
        last_toggle = now;
    }
}

void start_blinking() {
    digitalWrite(ledPin, HIGH);
    led_blinking = true;
    led_on = true;
    last_toggle = millis();
}

void stop_blinking() {
    digitalWrite(ledPin, LOW);
    led_blinking = false;
    led_on = false;
}

Затем вам нужно вызвать эти функции из loop() следующим образом:

void loop() {
    // При необходимости оставьте светодиод мигать.
    update_led();
    ...
    if (request.indexOf("/LED=ON") != -1)  {
        start_blinking();
    }
    if (request.indexOf("/LED=OFF") != -1)  {
        stop_blinking();
    }
    ...
}

Изменить, в ответ на комментарии jsotola:

Отвечая на вопрос, я изначально хотел сделать BlinkingLed класс, с функциями в качестве его открытого интерфейса и переменные частные. Я сопротивлялся искушению на том основании, что, учитывая очевидный уровень знаний C++ у OP, который может оказаться хорошим над его головой. Вместо этого я использовал документацию как неформальный способ разделение публичного и личного: вы должны использовать только что документировано, т.е. функции. Вы не «срезаете путь» ваша программа и очистите led_blinking напрямую”.

Вы, конечно, можете сделать переменную led_blinking частью публичный интерфейс. Это может быть даже хорошим упрощением, так как вы не больше не нужна функция старт/стоп. Но тогда вы теряете контроль над начальная фаза мигания. Это может и не быть проблемой, но если вы хотите, чтобы светодиод включился сразу после установки led_blinking в значение true, то вам придется сделать что-то вроде

void update_led() {
    uint32_t now = millis();
    if (!led_blinking) {
        digitalWrite(ledPin, LOW);
        led_on = false;
        last_toggle = now - OFF_TIME;  // исправить начальную фазу
        return;
    }
    ...
}

Обратите внимание, что вычитание может привести к переполнению, но это не проблема, потому что он следует правилам модульной арифметики.

Мне на самом деле нравится этот вариант, вся логика в одном функция. Таким образом, переменные led_on и last_toggle могут быть сделаны статический локальный по отношению к функции, который обеспечивает настоящую инкапсуляцию без класс. Однако, с педагогической точки зрения, я думаю, что мой первоначальный предложение легче понять.

,