Помогите избавиться от GOTO и бесконечных циклов в коде
- Войдите на сайт для отправки комментариев
Всем привет,
Переписываю скетч Гайвера для управления подсветкой Adalight под ESP8266. Столкнулся с тем, что коде обработки входящих данных используется GOTO и много замкнутых циклов - на время ожидания поступлениях данных на вход - чтение данных осуществляется по-байтово.
while (!Serial.available()) check_connection();; //пока нет данных идет отсчет таймера на автоотключение подсветки.
Пока лучшее что я придумал - добавить в этих циклах return - для выхода из функции. Алгоритм работает, но это рушит некоторые моменты типа включения\выключения подсветки.. Также есть риск пропустить что-либо во входящем буфере.
Приведу код оригинального скетча:
#include <FastLED.h> #define NUM_LEDS 176 // число светодиодов в ленте #define DI_PIN 14 // пин, к которому подключена лента #define OFF_TIME 10 // время (секунд), через которое лента выключится при пропадаании сигнала unsigned long off_timer; #define serialRate 115200 // скорость связи с ПК uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i; // кодовое слово Ada для связи CRGB leds[NUM_LEDS]; // создаём ленту boolean led_state = true; // флаг состояния ленты void setup() { FastLED.addLeds<WS2812, DI_PIN, GRB>(leds, NUM_LEDS); // инициализация светодиодов Serial.begin(serialRate); Serial.print("Ada\n"); // Связаться с компом } void loop() { if (!led_state) led_state = true; off_timer = millis(); for (i = 0; i < sizeof prefix; ++i) { waitLoop: while (!Serial.available()) check_connection();; //как тут избавиться от GOTO? i=-1? if (prefix[i] == Serial.read()) continue; i = 0; goto waitLoop; } while (!Serial.available()) check_connection();; hi = Serial.read(); while (!Serial.available()) check_connection();; lo = Serial.read(); while (!Serial.available()) check_connection();; chk = Serial.read(); if (chk != (hi ^ lo ^ 0x55)) { i = 0; goto waitLoop; } memset(leds, 0, NUM_LEDS * sizeof(struct CRGB)); for (uint8_t i = 0; i < NUM_LEDS; i++) { byte r, g, b; // читаем данные для каждого цвета while (!Serial.available()) check_connection(); r = Serial.read(); while (!Serial.available()) check_connection(); g = Serial.read(); while (!Serial.available()) check_connection(); b = Serial.read(); leds[i].r = r; leds[i].g = g; leds[i].b = b; } FastLED.show(); // записываем цвета в ленту } void check_connection() { if (led_state) { if (millis() - off_timer > (OFF_TIME * 1000)) { led_state = false; FastLED.clear(); FastLED.show(); } } }
пробовал расставлять Сириал принты в каждом цикле - они действительно срабатывают периодически, т.е. получается нельзя заменить все одной проверкой на Serial.available()
Всем привет,
Переписываю скетч Гайвера для ...
Вот это к нему
А причем тут он?) он выложил в открытый доступ "как есть", оно работает. А я уже пытаюсь допилить под свои нужды
ну можно поднапрячься и переписать в структурном стиле без ГОТО......
Вместо этого
пишем так:
вроде ничего не упустил
Выход из цикла без выхода из функции - break
вроде ничего не упустил
Там еще один вызов goto в строке 42 - как его лучше обойти? через флаг? типа
static boolean flag_goto=false; в начале функции
Затем обернуть все до "while (i<sizeof(prefix))" в if(!flag_goto){}
а на строке 42 делать flag_goto=true; return;
Или есть более правильное решение?
Там еще один вызов goto в строке 42
я только кусок с 26 по 31 строчку переписывал...
Там у гайвера прилично закручено... думать надо. В том коде. что я переписал - тоже не вполне логика сохранена... надо еще править.
ну можно поднапрячься и переписать в структурном стиле без ГОТО......
Вместо этого
пишем так:
вроде ничего не упустил
Ну изначально задача была убрать бесконечные циклы т.к. иначе при программа могла зависнуть внутри этого goto навсегда - в оригинальном проекте где кроме получения данных по Serial и управления лентой ничего и не надо - то для ESP-варианта нужно обеспечивать wifi соединение, проверять подключенных клиентов, обслуживать веб-сервер с настройками и т.п.
Ну и эстетическая составляющая - когда goto перенаправляет внутрь цикла For - это как-то ппц криво.
Вариант предложенный b707 - работает, дополнил его кодом указынным выше и алгоритм работает нормально, Спасибо. Привожу пример реальной функции:
Время на отрисовку 180лед по wifi не превышает 120мс, чаще 30-50;
Как-то управление по сериал отличается от wi-fi?
не совсем понял.. что значит управление?
Управление происходит программой AmbiBox, при подключении через сериал - она шлет данные напрямую в ком-порт устройства. По файваю Ambibox подключается к виртуальному ком-порту и шлет данные туда, а виртуальный ком-порт уже перекидывает данные на TCP сервер ESP, дальше все тоже самое, т.к. протокол данных задает Амбибокс.