モバイルアプリ経由で接続された 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 文字が失われます。
文字の損失は通常、文字列のさまざまな部分で発生しますが、連続する文字が読み違えるたびに発生します。また、後ろ向きのクエスチョン マークが表示されることもあります。どこで実装が間違っているのかわからないため、この問題を解決するための助けをいただければ幸いです。
ありがとう!