1

モバイルアプリ経由で接続された 80 の LED ストリップを制御するプロジェクトがあります。使用したコンポーネントは次のとおりです。

  • Arduinoナノボード
  • HM-10 ブルートゥースモジュール
  • WS2812b LED ストリップ

アプリで、ユーザーは色 (最大 5 つ)、アニメーション (オプション)、アニメーションの速度、明るさを選択します。選択した構成は、特定のスロットルとデバウンスで BLE モジュールに送信されます。色 (アプリのカラー ホイールで選択) と明るさは問題なく正常に送信されます。

私たちが遭遇する問題は、特定のアニメーションがアクティブなときに、ユーザーがアプリを介してアニメーションの速度を変更すると、arduino の部分がロックされ、それ以上のコマンドを受け付けなくなることです。

アニメーションで構成を有効にするには、次のようにアプリから arduino にデータを送信します。

<l255180200,240135068:089;04200>

形式は次のとおりです。 < [モード] [色 (',')] : [明るさ] ; [animationCode(2桁)] [animationSpeed] >

最初は、連続したデータとの不一致があったため、データ取得のために次のように実装しました。

void loop()
{
  // Read all serial data available, as fast as possible
  while (bleSerial.available() > 0)
  {
    char inChar = bleSerial.read();
    if (inChar == SOP)
    {
      index = 0;
      inData[index] = '\0';
      started = true;
      ended = false;
    }
    else if (inChar == EOP)
    {
      ended = true;
      break;
    }
    else
    {
      if (index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if (started && ended)
  {
    // The end of packet marker arrived. Process the packet

    Serial.println(inData);
    Serial.println(inData[0]);
    char mode = inData[0];

    if (mode == 'p')
    {
      togglePower(inData);
      finalizeRead();
      return;
    }

    if (mode == 'b')
    {
      changeBrightness(inData);
      finalizeRead();
      return;
    }
    if (mode == 't')
    {
      char *themeNo = strtok(NULL, ";");
      int themeCode = valueFromString(themeNo, 0, 2);
      theme(themeCode);
    }

    //    if (mode == 'e') {
    //      sound();
    //      return;
    //    }

    char *colorsWithBrightness = strtok(inData, ";");
    char *animation = strtok(NULL, ";");

    char *colors = strtok(colorsWithBrightness, ":");
    char *brightness = strtok(NULL, ":");

    custom(colors, brightness, animation);

    finalizeRead();
  }
}

void finalizeRead()
{
  // Reset for the next packet
  started = false;
  ended = false;
  index = 0;
  inData[index] = '\0';
}

int valueFromString(char *string, int start, int width)
{
  int value = 0;
  for (int n = 0; n < width; n++)
    value = value * 10 + string[start + n] - '0';

  return value;
}

したがって、カスタム関数はモード == 'l' のときに呼び出されます。カスタム関数では、次のように実行します。

void custom(char *colors, char *brightness, char *animation)
{
  char *trueColors = strtok(colors, "l");
  char *colorsSplit = strtok(trueColors, ",");
  int colorCount = 0;
  uint32_t colorArray[5] = {};
  while (colorsSplit != NULL)
  {
    int r = valueFromString(colorsSplit, 0, 3);
    int g = valueFromString(colorsSplit, 3, 3);
    int b = valueFromString(colorsSplit, 6, 3);

    colorArray[colorCount] = strip.Color(r, g, b);
    colorCount++;
    colorsSplit = strtok(NULL, ",");
  }

  int ledsPerSegment = ledCount / colorCount;

  for (int n = 0; n < colorCount; n++)
  {
    int currentSegment = (n + 1) * ledsPerSegment;
    Serial.println(currentSegment);
    for (int z = n * ledsPerSegment; z < (n + 1) * ledsPerSegment; z++)
    {
      strip.setPixelColor(z, colorArray[n]);
    }
  }

  strip.setBrightness(atoi(brightness));
  strip.show();
  Serial.println("Done");

  if (animation)
  {
    int animationCode = valueFromString(animation, 0, 2);
    int animationSpeed = valueFromString(animation, 2, 3);
    Serial.println(animationSpeed);
    if (animationCode == 1)
      breath(animationSpeed, atoi(brightness));
    else if (animationCode == 7)
      pulse(animationSpeed, colorArray, colorCount);
  }
}

この問題は、次のようなパルス アニメーションで発生します。

void pulse(int wait, uint32_t colorArray[], int colorCount)
{
  black();
  while (bleSerial.available() <= 0)
  {
    for (i = 0; i < colorCount && bleSerial.available() <= 0; i++)
    {
      for (j = 0; j < ledCount / 2 && bleSerial.available() <= 0; j++)
      {
        strip.setPixelColor(39 - j, colorArray[i]);
        strip.setPixelColor(40 + j, colorArray[i]);
        strip.show();
        delay(wait);
      }
      black();
    }
  }
}

以下を使用して、問題なくアニメーションを初期化します。

<l255180200,240135068:089;04200>

アプリからアニメーション速度を調整するとすぐに、1 秒あたり約 2 つの新しい構成を送信します。これは上記と同じですが、速度が異なるだけです (「>」の前の最後の 3 文字)。arduino の部分がランダムにデータを誤って受信し、<l2551800,240135068:089;04200> のように 2 ~ 3 文字が失われます。

文字の損失は通常、文字列のさまざまな部分で発生しますが、連続する文字が読み違えるたびに発生します。また、後ろ向きのクエスチョン マークが表示されることもあります。どこで実装が間違っているのかわからないため、この問題を解決するための助けをいただければ幸いです。

ありがとう!

4

0 に答える 0