Почему я не могу выйти из цикла while, читая из serial?

Я пытаюсь работать с библиотеками FastLED и управляю светодиодным Stip через WEMOS D1 MINI на базе ESP8266, чего я пытаюсь добиться, так это перехода от анимации fastled к другой .. эти анимации находятся внутри цикла While, как показано в коде, поэтому я подумал: просто прочитайте еще раз из серийного номера, чтобы изменить целое число для выхода из цикла while, но по какой-то причине оно работает не так, как ожидалось. Кто-нибудь может помочь мне понять?

CRGB leds[NUM_LEDS];
int incomingByte = 0;
int exit = 0;
void setup() {
    Serial.begin(115200);
    delay( 1000 ); 
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
}

void loop() 
{
    while (Serial.available()>0) 
    {
      Serial.write("Serial.available");
       incomingByte = Serial.read();

       switch (incomingByte)
        {
          case '1':
            GreenYellow();
            break;

          case '2':
            Sparkle();
            break;
        }
    }
}


void Sparkle() {
    while(exit = 0){
        int Pixel = random(NUM_LEDS);
        setPixel(Pixel,random(255),random(255),random(255));
        FastLED.show();
        delay(50);
        setPixel(Pixel,0,0,0);
        if(Serial.available()>0){
            incomingByte = Serial.read();
            if(incomingByte != '2'){
                exit = 1;
            }
        }
    }
  }
}
void GreenYellow()
{
  for(int x =0; x< NUM_LEDS/2; x++){
    leds[x]= CRGB::Green;
  }
  
  for(int x =NUM_LEDS/2; x< NUM_LEDS; x++){
    leds[x]= CRGB::Yellow;
  }
  FastLED.show();
}


void setPixel(int Pixel, byte red, byte green, byte blue) 
{
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
   FastLED.show();
}
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

Бонусный вопрос: я читал, что на ESP2866 нет программирования потоков через Arduino IDE, я прав?

, 👍0


1 ответ


1

Проблема в том, что вы проверяете внутри двух функций Sparkle и GreenYellow наличие другого последовательного байта. Затем, когда он неравен, вы возвращаетесь к циклу while, где ждете следующего последовательного байта, но я думаю, что вам нужно использовать тот же самый байт, чтобы решить перейти к правильной функции, а не ждать следующего последовательного байта.

Вероятно, проще всего не читать serial в цикле while, а проверить глобальную переменную incomingByte (содержащую последний прочитанный байт и, например, 1 изначально), и ТОЛЬКО в двух функциях установить эту глобальную переменную. Затем, возвращаясь к циклу while, вы проверяете эту глобальную переменную, чтобы перейти к правильной функции.

Таким образом, вы создаете функцию установки, которая устанавливает глобальную переменную в 1 (или вы делаете это в самой инициализации):

int incomingByte = 1; // Начать с GreenYellow

Затем в функции цикла вы используете:

void loop() 
{
       switch (incomingByte)
        {
          case '1':
            GreenYellow();
            break;

          case '2':
            Sparkle();
            break;
        }
}

Если вы не хотите начинать ни с того, ни с другого, то используйте 3 значения (0, 1, 2) и ТОЛЬКО в функции цикла считывайте последовательный байт, но не считывайте его в функциях. Таким образом, он немного чище, так как отделяет функциональность светодиода от последовательной функциональности.

Результат (используя последний метод), приводит к следующему коду (компилируется, не проверяется).

Комментарии:

  • Использовал перечисление для режима

  • Разделение функций последовательных данных, обработка режимов и подпрограмм RGB

  • Я добавил некоторые строки инициализации (т.Е. константы), чтобы сделать его компилируемым.

    #include <FastLED.h>
    
    #define NUM_LEDS 60 // количество светодиодов, присутствующих в вашей ленте
    #define LED_PIN 6
    #define BRIGHTNESS 100
    
    enum EMode
    {
      ModeNone,
      ModeSparkle,
      ModeGreenYellow
    };
    
    CRGB leds[NUM_LEDS];
    EMode mode;
    
    void ParseSerialData();
    void ProcessMode();
    void GreenYellow();
    void Sparkle();
    void setPixel(int Pixel, byte red, byte green, byte blue);
    
    
    void setup() 
    {
        Serial.begin(115200);
        delay( 1000 ); 
        FastLED.addLeds<WS2811, LED_PIN, EOrder::RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
        FastLED.setBrightness(  BRIGHTNESS );
        mode = EMode::ModeNone;
    }
    
    void loop() 
    {
      ParseSerialData();
      ProcessMode();
    }
    
    void ParseSerialData()
    {
      while (Serial.available() > 0) 
      {
        Serial.write("Serial.available");
        char incomingByte = Serial.read();
    
        switch (incomingByte)
        {
        case '1':
          mode = EMode::ModeGreenYellow;
          break;
    
        case '2':
          mode = EMode::ModeSparkle;
          break;
    
        default:
          // Игнорировать
          break;
        }
      }
    }
    
    
    void ProcessMode()
    {
      switch (mode)
      {
      case EMode::ModeNone:
        // Ничего не делать
        break;
    
      case EMode::ModeGreenYellow:
        GreenYellow();
        break;
    
      case EMode::ModeSparkle:
        Sparkle();
        break;
    
      default:
        // Игнорировать
        break;
      }
    }
    
    
    void Sparkle() 
    {
        int Pixel = random(NUM_LEDS);
        setPixel(Pixel,random(255),random(255),random(255));
        FastLED.show();
        delay(50);
        setPixel(Pixel,0,0,0);
    }
    
    void GreenYellow()
    {
      for(int x =0; x< NUM_LEDS/2; x++)
      {
        leds[x]= CRGB::Green;
      }
    
      for(int x =NUM_LEDS/2; x< NUM_LEDS; x++)
      {
        leds[x]= CRGB::Yellow;
      }
      FastLED.show();
    }
    
    
    void setPixel(int Pixel, byte red, byte green, byte blue) 
    {
       leds[Pixel].r = red;
       leds[Pixel].g = green;
       leds[Pixel].b = blue;
       FastLED.show();
    }
    
    void setAll(byte red, byte green, byte blue) 
    {
      for(int i = 0; i < NUM_LEDS; i++ ) {
        setPixel(i, red, green, blue);
      }
      FastLED.show();
    }
    
,

спасибо за повтор, можете ли вы изменить мой фрагмент кода? Мне трудно понять ваше решение, так что, возможно, чтение кода поможет. Спасибо., @FabioEnne

Я бы пошел другим путем. Оставьте все последовательные чтения внутри функции цикл. Удалите цикл while внутри функции Sparkle. Сохраните текущий режим, который был выбран, в переменной. Затем в цикле вызовите функцию, основанную на текущем режиме., @Gerben

@Gerben Я тоже, но первое было самым "простым", а не самым чистым решением., @Michel Keijzers

Я попытался изменить код (он компилируется)... Я удалил код выхода и попытался навести порядок., @Michel Keijzers