Правильный способ завершения цикла при необходимости?
Я новичок в 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 (если хотя бы один из них является правильным способом сделать это!).
Заранее спасибо за помощь,
С наилучшими пожеланиями, Том
@Tom, 👍3
1 ответ
Лучший ответ:
Как отметили Игнасио Васкес-Абрамс и 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
могут быть сделаны
статический локальный по отношению к функции, который обеспечивает настоящую инкапсуляцию без
класс. Однако, с педагогической точки зрения, я думаю, что мой первоначальный
предложение легче понять.
- Метод HTTP PUT на NodeMCU/ESP8266
- Http-запрос в прерывании esp8266 не работает
- Как определить размер Flash?
- WebSocketsServer.h: No such file or directory
- Как публиковать запросы HTTP POST на моем веб-сайте?
- В ESP-12E NodeMCU, какой выход PIN A0?
- Преобразование byte* в int в Arduino
- Каково использование зарезервированных контактов и контактов SDD2, SDD3 NodeMCU?