我有一个arduino接受串行输入并打开LED指示灯。代码如下。
我有一个奇怪的问题,当我发送120x字节的倍数时,例如240,480,最后的120个字节永远不会被完全读取。
如果我发送480字节的数据,我在串行监视器120 120 120 81上看到。谁能指出错误?
#include "FastLED.h"
#define DATA_PIN 6
#define NUM_LEDS 40
byte colors[120];
CRGB leds[NUM_LEDS];
void setup(){
FastLED.addLeds<NEOPIXEL, DATA_PIN, RGB>(leds, NUM_LEDS);
Serial.begin(115200);
}
void loop(){
if (Serial.available()){
int i =0;
char incomingByte;
while(1) {
incomingByte = Serial.readBytes((char *)colors,120);
break;
}
Serial.print(incomingByte);
for(i=0;i<NUM_LEDS ;i++){
leds[i].green = colors[i];
leds[i].red = colors[i+1];
leds[i].blue = colors[i+2];
}
if(incomingByte==0x78){
FastLED.show();
}
}
}
答案 0 :(得分:0)
你的代码以不同的方式存在缺陷。
首先,请删除无用的while(1) {…; break;}
,它只是增加了开销,并且不会为您的算法添加任何内容。
否则,您的代码运行不正常,因为,我想,在某些时候,串行通信中发生了导致读取超时的延迟。我们来看看源代码。
首先,您使用readBytes()
功能。它所做的就是:
size_t Stream::readBytes(char *buffer, size_t length)
{
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0) break;
*buffer++ = (char)c;
count++;
}
return count;
}
即。它在阻塞读取函数上迭代length
次。但如果函数的返回值小于零,则返回小于length
个字节。因此,为了获得低于length
而发生的事情,让我们来看看timedRead()
:
int Stream::timedRead()
{
int c;
_startMillis = millis();
do {
c = read();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
这里发生的是,如果读取成功,则返回读取值,否则它将循环直到超时,并返回-1,它将立即结束readBytes
。超时的默认值为1000ms,但您可以在Serial.setTimeout(5000);
函数中使用setup()
来提高该值。
虽然使用阻止readBytes()
功能无法获得任何收益。因此,您最好编写循环,以便读取值,并在读取所有值后触发事件:
#define NB_COLORS 120
void loop() {
static byte colors[NB_COLORS];
static int colors_index=0;
if (colors_index < NB_COLORS) {
// let's read only one byte
colors[colors_index] = Serial.read();
// if a byte has been read, increment the index
if (colors[colors_index] != -1)
++colors_index;
} else {
// reset the index to start over
colors_index = 0;
// should'nt you iterate 3 by 3, i.e. having i=i+3 instead of i++ ?
for(i=0;i<NUM_LEDS ;i++){
leds[i].green = colors[i];
leds[i].red = colors[i+1];
leds[i].blue = colors[i+2];
}
FastLED.show();
}
}
HTH