我们有一个控制 80 条 LED 灯条的项目,通过移动应用程序连接。我们使用的组件如下:
- Arduino纳米板
- HM-10蓝牙模块
- WS2812b 灯带
在应用程序上,用户可以选择颜色(最多 5 种)、动画(可选)、动画速度和亮度。选择的配置通过一定的节流和去抖动传输到 BLE 模块。颜色(在应用程序的色轮上选择)和亮度传输良好,没有任何问题。
我们遇到的问题是,当某些动画处于活动状态时,如果用户通过应用程序更改动画速度,arduino 部分会自行锁定,不再接受任何命令。
要使用动画激活配置,我们将数据从应用程序发送到 arduino,如下所示:
<l255180200,240135068:089;04200>
格式为:< [mode] [colors(with ',')] : [brightness] ; [动画代码(2位)] [动画速度] >
起初,我们对连续数据有一些不一致的地方,所以我们实现了以下数据采集:
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>
一旦我们从应用程序调整动画速度,我们每秒发送大约 2 个新配置,这与上面相同,只是速度不同('>' 之前的最后 3 个字符)。arduino部分随机接收数据不正确,丢失2-3个字符,如<l2551800,240135068:089;04200>
字符丢失通常发生在字符串的不同部分,但每次都会发生连续字符被误读的情况。此外,有时我们会得到一个倒退的问号。我们不确定我们在哪里实施了错误,因此对于解决此问题的任何帮助表示赞赏。
谢谢!