Adafruit NeoPixel 库在处理超过 7 个 LED 灯条时不起作用
Adafruit NeoPixel library doesn't work when addressing more than 7 LED strips
关于我关于 SO 的最后一个问题,我正在研究一个由 Arduino Mega 控制的交互式 14x14 LED table(有关设置和代码的更多信息,请查看 .
在解决了数据以错误的顺序到达 Arduino 的问题后,我现在面临这个问题:
为了使用 Adafruit 的 NeoPixel 库控制 LED table 上每个像素的颜色,我读取了一个 int[14][14][3] 形式的数组。这现在工作正常,但是当我尝试为超过 7 个 LED 灯带设置 RGB 值时,没有任何反应。我也有几个 Serial.println()
调用来检查读取了哪些数据,如果我 运行 超过 7 个 LED 条 0
打印每个可能的值。
控制 LED 的基本功能完美运行 - 只要我使用的灯带不超过 7 个,我也可以正确处理上述数据并将其输出到 LED 灯带。问题是,如果我在一个数组中声明多于这 7 个条带或拆分它们都没有关系。单独初始化它们也不像每次我想使用不同的条带时创建一个条带实例并为其重新分配引脚那样有效。
我的代码目前看起来像这样,我完全不知道这个问题可能是什么原因或我该如何解决。
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define PINROW0 0
#define PINROW1 1
#define PINROW2 2
#define PINROW3 3
#define PINROW4 4
#define PINROW5 5
#define PINROW6 6
#define PINROW7 7
#define PINROW8 8
#define PINROW9 26
#define PINROW10 28
#define PINROW11 30
#define PINROW12 32
#define PINROW13 34
#define NUMPIXELS 14 //Anzahl der Pixel pro Reihe
/*Adafruit_NeoPixel row0 = Adafruit_NeoPixel(NUMPIXELS, PINROW0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row1 = Adafruit_NeoPixel(NUMPIXELS, PINROW1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row2 = Adafruit_NeoPixel(NUMPIXELS, PINROW2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row3 = Adafruit_NeoPixel(NUMPIXELS, PINROW3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row4 = Adafruit_NeoPixel(NUMPIXELS, PINROW4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row5 = Adafruit_NeoPixel(NUMPIXELS, PINROW5, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row6 = Adafruit_NeoPixel(NUMPIXELS, PINROW6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row7 = Adafruit_NeoPixel(NUMPIXELS, PINROW7, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row8 = Adafruit_NeoPixel(NUMPIXELS, PINROW8, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row9 = Adafruit_NeoPixel(NUMPIXELS, PINROW9, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row10 = Adafruit_NeoPixel(NUMPIXELS, PINROW10, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row11 = Adafruit_NeoPixel(NUMPIXELS, PINROW11, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row12 = Adafruit_NeoPixel(NUMPIXELS, PINROW12, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row13 = Adafruit_NeoPixel(NUMPIXELS, PINROW13, NEO_GRB + NEO_KHZ800);
*/
//Adafruit_NeoPixel currentStrip = Adafruit_NeoPixel(NUMPIXELS, pins[0], NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row[] = { //Initialisieren des Arrays, das die addressierbaren LED Streifen im Adafruit Format enthält
Adafruit_NeoPixel(NUMPIXELS, PINROW0, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW1, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW2, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW3, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW4, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW5, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW6, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW7, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW8, NEO_GRB + NEO_KHZ800)/*,
Adafruit_NeoPixel(NUMPIXELS, PINROW9, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW10, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW11, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW12, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW13, NEO_GRB + NEO_KHZ800)*/
};
#define DELAY 1000 //Refresh Zyklus auf 10 Millisekunden setzen
#define NUMSTRIPS 9/*(sizeof(row)/sizeof(row[0]))*/ //Anzahl der verbundenen LED Streifen definieren
int values[14][14][3];
String matrixAsString = "";
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
/*Seriellen Port über den der Pi sich mit dem Arduino verbindet einrichten*/
Serial.begin(115200); //setzen der Bitrate auf 115200 Bit pro Sekunde
Serial.setTimeout(100000);
/*NeoPixel Library initialisieren*/
for (int i = 0; i < NUMSTRIPS; i++) {
row[i].begin();
row[i].show();
}
}
void process(String matrixAsString) {
DynamicJsonDocument doc(4372);
Serial.println(matrixAsString);
deserializeJson(doc, matrixAsString);
Serial.println((int)(doc[2][10][0]));
Serial.println((int)(doc[2][10][0]));
Serial.println((int)(doc[5][10][0]));
Serial.println((int)(doc[0][1][2]));
Serial.println((int)(doc[0][0][1]));
for (int i = 0; i < NUMSTRIPS; i++) {
for (int j = 0; j < NUMPIXELS; j++) {
for (int k = 0; k < 3; k++) {
values[i][j][k] = (int)(doc[i][j][k]);
}
}
}
}
void paint() {
int r = 0;
int g = 0;
int b = 0;
for (int i = 0; i < NUMSTRIPS; i++) {
for (int j = 0; j < NUMPIXELS; j++) {
r = values[i][j][0];
g = values[i][j][1];
b = values[i][j][2];
row[i].setPixelColor(j, row[i].Color(r, g, b));
row[i].show();
}
}
}
//infinite loop refreshing the matrix
void loop() {
while (Serial.available()) {
char c = Serial.read();
matrixAsString += c;
if (c == '\n') {
process(matrixAsString);
paint();
matrixAsString = "";
}
}
}
根据官方 Adafruit 文档,该库设计为连接 Arduino 能够支持的条带数量,因此必须有一个解决方案。
为了测试我的代码,我使用了这个数据,它是随机生成的 14x14 RGB 矩阵的字符串表示形式:
[[[0,0,0],[1,0,0],[1,1,0],[2,1,0],[2,2,0],[3,2,0],[3,3,0],[3,3,1],[3,3,2],[3,3,3],[4,3,3],[4,4,3],[5,4,3],[5,4,4]],[[6,4,4],[7,4,4],[7,5,4],[7,6,4],[7,7,4],[7,7,5],[7,7,6],[7,7,7],[7,7,8],[8,7,8],[8,8,8],[8,9,8],[8,10,8],[8,11,8]],[[8,11,9],[8,11,10],[9,11,10],[9,11,11],[9,12,11],[9,12,12],[9,13,12],[10,13,12],[10,13,13],[10,13,14],[10,13,15],[11,13,15],[11,14,15],[11,15,15]],[[12,15,15],[12,15,16],[12,15,17],[13,15,17],[13,16,17],[13,16,18],[14,16,18],[14,17,18],[15,17,18],[15,17,19],[15,18,19],[15,18,20],[15,19,20],[15,19,21]],[[15,20,21],[15,21,21],[16,21,21],[17,21,21],[17,22,21],[18,22,21],[19,22,21],[19,23,21],[20,23,21],[20,23,22],[20,23,23],[20,24,23],[20,25,23],[20,26,23]],[[21,26,23],[22,26,23],[22,27,23],[23,27,23],[23,27,24],[24,27,24],[24,27,25],[24,28,25],[24,28,26],[24,29,26],[24,29,27],[24,29,28],[24,30,28],[25,30,28]],[[25,30,29],[25,31,29],[25,31,30],[26,31,30],[27,31,30],[27,32,30],[27,32,31],[27,33,31],[27,34,31],[27,35,31],[27,35,32],[28,35,32],[28,36,32],[29,36,32]],[[29,37,32],[29,37,33],[29,38,33],[29,38,34],[30,38,34],[31,38,34],[32,38,34],[33,38,34],[33,39,34],[33,39,35],[33,39,36],[33,40,36],[33,40,37],[33,41,37]],[[33,42,37],[33,42,38],[33,42,39],[33,42,40],[33,43,40],[33,43,41],[33,43,42],[33,44,42],[33,45,42],[33,45,43],[33,46,43],[34,46,43],[34,47,43],[35,47,43]],[[36,47,43],[37,47,43],[38,47,43],[38,47,44],[39,47,44],[39,47,45],[39,48,45],[40,48,45],[40,48,46],[40,49,46],[41,49,46],[41,50,46],[41,51,46],[41,51,47]],[[42,51,47],[42,51,48],[43,51,48],[43,51,49],[43,52,49],[43,53,49],[43,54,49],[43,54,50],[44,54,50],[44,55,50],[45,55,50],[45,55,51],[46,55,51],[47,55,51]],[[48,55,51],[48,56,51],[48,57,51],[48,58,51],[48,58,52],[48,58,53],[48,59,53],[48,59,54],[48,60,54],[48,60,55],[48,60,56],[48,60,57],[49,60,57],[49,61,57]],[[49,62,57],[49,62,58],[49,63,58],[49,63,59],[50,63,59],[50,64,59],[50,65,59],[51,65,59],[52,65,59],[53,65,59],[54,65,59],[54,66,59],[54,66,60],[54,67,60]],[[55,67,60],[56,67,60],[57,67,60],[58,67,60],[59,67,60],[59,67,61],[59,68,61],[59,69,61],[60,69,61],[61,69,61],[61,69,62],[61,69,63],[61,70,63],[61,71,63]]]
提前感谢您的帮助,非常感谢您提供的任何提示或建议。
您只有 8kB 的 ram,并且您正在使用:
int values[14][14][3];
=> 此数组上的 1176 个字节(而不是一半,如果你使用 byte/uint8_t 而不是 int)
- 该死的
String matrixAsString = "";
和 +=
运算符。那会严重扰乱内存(就内存碎片而言)。
DynamicJsonDocument doc(4372);
分配另一个巨大的内存
- 更不用说,每个条带都有自己的像素内存,所以
values
数组有点无关紧要
- 也许可以使用相同的缓冲区来读取和 json 解析器?这可能会节省很多
所以根据那个,你一定是内存不足
无论如何,我会使用一些体面的 ARM 和 DMA 魔法(例如在 STM32 MCU 上同时使用 16 个通道)而无需 CPU 的太多交互来发送它。或者像 OctoWS2811 LED Library
这样的现有解决方案
关于我关于 SO 的最后一个问题,我正在研究一个由 Arduino Mega 控制的交互式 14x14 LED table(有关设置和代码的更多信息,请查看
为了使用 Adafruit 的 NeoPixel 库控制 LED table 上每个像素的颜色,我读取了一个 int[14][14][3] 形式的数组。这现在工作正常,但是当我尝试为超过 7 个 LED 灯带设置 RGB 值时,没有任何反应。我也有几个 Serial.println()
调用来检查读取了哪些数据,如果我 运行 超过 7 个 LED 条 0
打印每个可能的值。
控制 LED 的基本功能完美运行 - 只要我使用的灯带不超过 7 个,我也可以正确处理上述数据并将其输出到 LED 灯带。问题是,如果我在一个数组中声明多于这 7 个条带或拆分它们都没有关系。单独初始化它们也不像每次我想使用不同的条带时创建一个条带实例并为其重新分配引脚那样有效。
我的代码目前看起来像这样,我完全不知道这个问题可能是什么原因或我该如何解决。
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define PINROW0 0
#define PINROW1 1
#define PINROW2 2
#define PINROW3 3
#define PINROW4 4
#define PINROW5 5
#define PINROW6 6
#define PINROW7 7
#define PINROW8 8
#define PINROW9 26
#define PINROW10 28
#define PINROW11 30
#define PINROW12 32
#define PINROW13 34
#define NUMPIXELS 14 //Anzahl der Pixel pro Reihe
/*Adafruit_NeoPixel row0 = Adafruit_NeoPixel(NUMPIXELS, PINROW0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row1 = Adafruit_NeoPixel(NUMPIXELS, PINROW1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row2 = Adafruit_NeoPixel(NUMPIXELS, PINROW2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row3 = Adafruit_NeoPixel(NUMPIXELS, PINROW3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row4 = Adafruit_NeoPixel(NUMPIXELS, PINROW4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row5 = Adafruit_NeoPixel(NUMPIXELS, PINROW5, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row6 = Adafruit_NeoPixel(NUMPIXELS, PINROW6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row7 = Adafruit_NeoPixel(NUMPIXELS, PINROW7, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row8 = Adafruit_NeoPixel(NUMPIXELS, PINROW8, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row9 = Adafruit_NeoPixel(NUMPIXELS, PINROW9, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row10 = Adafruit_NeoPixel(NUMPIXELS, PINROW10, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row11 = Adafruit_NeoPixel(NUMPIXELS, PINROW11, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row12 = Adafruit_NeoPixel(NUMPIXELS, PINROW12, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row13 = Adafruit_NeoPixel(NUMPIXELS, PINROW13, NEO_GRB + NEO_KHZ800);
*/
//Adafruit_NeoPixel currentStrip = Adafruit_NeoPixel(NUMPIXELS, pins[0], NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel row[] = { //Initialisieren des Arrays, das die addressierbaren LED Streifen im Adafruit Format enthält
Adafruit_NeoPixel(NUMPIXELS, PINROW0, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW1, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW2, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW3, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW4, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW5, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW6, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW7, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW8, NEO_GRB + NEO_KHZ800)/*,
Adafruit_NeoPixel(NUMPIXELS, PINROW9, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW10, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW11, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW12, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUMPIXELS, PINROW13, NEO_GRB + NEO_KHZ800)*/
};
#define DELAY 1000 //Refresh Zyklus auf 10 Millisekunden setzen
#define NUMSTRIPS 9/*(sizeof(row)/sizeof(row[0]))*/ //Anzahl der verbundenen LED Streifen definieren
int values[14][14][3];
String matrixAsString = "";
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
/*Seriellen Port über den der Pi sich mit dem Arduino verbindet einrichten*/
Serial.begin(115200); //setzen der Bitrate auf 115200 Bit pro Sekunde
Serial.setTimeout(100000);
/*NeoPixel Library initialisieren*/
for (int i = 0; i < NUMSTRIPS; i++) {
row[i].begin();
row[i].show();
}
}
void process(String matrixAsString) {
DynamicJsonDocument doc(4372);
Serial.println(matrixAsString);
deserializeJson(doc, matrixAsString);
Serial.println((int)(doc[2][10][0]));
Serial.println((int)(doc[2][10][0]));
Serial.println((int)(doc[5][10][0]));
Serial.println((int)(doc[0][1][2]));
Serial.println((int)(doc[0][0][1]));
for (int i = 0; i < NUMSTRIPS; i++) {
for (int j = 0; j < NUMPIXELS; j++) {
for (int k = 0; k < 3; k++) {
values[i][j][k] = (int)(doc[i][j][k]);
}
}
}
}
void paint() {
int r = 0;
int g = 0;
int b = 0;
for (int i = 0; i < NUMSTRIPS; i++) {
for (int j = 0; j < NUMPIXELS; j++) {
r = values[i][j][0];
g = values[i][j][1];
b = values[i][j][2];
row[i].setPixelColor(j, row[i].Color(r, g, b));
row[i].show();
}
}
}
//infinite loop refreshing the matrix
void loop() {
while (Serial.available()) {
char c = Serial.read();
matrixAsString += c;
if (c == '\n') {
process(matrixAsString);
paint();
matrixAsString = "";
}
}
}
根据官方 Adafruit 文档,该库设计为连接 Arduino 能够支持的条带数量,因此必须有一个解决方案。
为了测试我的代码,我使用了这个数据,它是随机生成的 14x14 RGB 矩阵的字符串表示形式:
[[[0,0,0],[1,0,0],[1,1,0],[2,1,0],[2,2,0],[3,2,0],[3,3,0],[3,3,1],[3,3,2],[3,3,3],[4,3,3],[4,4,3],[5,4,3],[5,4,4]],[[6,4,4],[7,4,4],[7,5,4],[7,6,4],[7,7,4],[7,7,5],[7,7,6],[7,7,7],[7,7,8],[8,7,8],[8,8,8],[8,9,8],[8,10,8],[8,11,8]],[[8,11,9],[8,11,10],[9,11,10],[9,11,11],[9,12,11],[9,12,12],[9,13,12],[10,13,12],[10,13,13],[10,13,14],[10,13,15],[11,13,15],[11,14,15],[11,15,15]],[[12,15,15],[12,15,16],[12,15,17],[13,15,17],[13,16,17],[13,16,18],[14,16,18],[14,17,18],[15,17,18],[15,17,19],[15,18,19],[15,18,20],[15,19,20],[15,19,21]],[[15,20,21],[15,21,21],[16,21,21],[17,21,21],[17,22,21],[18,22,21],[19,22,21],[19,23,21],[20,23,21],[20,23,22],[20,23,23],[20,24,23],[20,25,23],[20,26,23]],[[21,26,23],[22,26,23],[22,27,23],[23,27,23],[23,27,24],[24,27,24],[24,27,25],[24,28,25],[24,28,26],[24,29,26],[24,29,27],[24,29,28],[24,30,28],[25,30,28]],[[25,30,29],[25,31,29],[25,31,30],[26,31,30],[27,31,30],[27,32,30],[27,32,31],[27,33,31],[27,34,31],[27,35,31],[27,35,32],[28,35,32],[28,36,32],[29,36,32]],[[29,37,32],[29,37,33],[29,38,33],[29,38,34],[30,38,34],[31,38,34],[32,38,34],[33,38,34],[33,39,34],[33,39,35],[33,39,36],[33,40,36],[33,40,37],[33,41,37]],[[33,42,37],[33,42,38],[33,42,39],[33,42,40],[33,43,40],[33,43,41],[33,43,42],[33,44,42],[33,45,42],[33,45,43],[33,46,43],[34,46,43],[34,47,43],[35,47,43]],[[36,47,43],[37,47,43],[38,47,43],[38,47,44],[39,47,44],[39,47,45],[39,48,45],[40,48,45],[40,48,46],[40,49,46],[41,49,46],[41,50,46],[41,51,46],[41,51,47]],[[42,51,47],[42,51,48],[43,51,48],[43,51,49],[43,52,49],[43,53,49],[43,54,49],[43,54,50],[44,54,50],[44,55,50],[45,55,50],[45,55,51],[46,55,51],[47,55,51]],[[48,55,51],[48,56,51],[48,57,51],[48,58,51],[48,58,52],[48,58,53],[48,59,53],[48,59,54],[48,60,54],[48,60,55],[48,60,56],[48,60,57],[49,60,57],[49,61,57]],[[49,62,57],[49,62,58],[49,63,58],[49,63,59],[50,63,59],[50,64,59],[50,65,59],[51,65,59],[52,65,59],[53,65,59],[54,65,59],[54,66,59],[54,66,60],[54,67,60]],[[55,67,60],[56,67,60],[57,67,60],[58,67,60],[59,67,60],[59,67,61],[59,68,61],[59,69,61],[60,69,61],[61,69,61],[61,69,62],[61,69,63],[61,70,63],[61,71,63]]]
提前感谢您的帮助,非常感谢您提供的任何提示或建议。
您只有 8kB 的 ram,并且您正在使用:
int values[14][14][3];
=> 此数组上的 1176 个字节(而不是一半,如果你使用 byte/uint8_t 而不是 int)- 该死的
String matrixAsString = "";
和+=
运算符。那会严重扰乱内存(就内存碎片而言)。 DynamicJsonDocument doc(4372);
分配另一个巨大的内存- 更不用说,每个条带都有自己的像素内存,所以
values
数组有点无关紧要 - 也许可以使用相同的缓冲区来读取和 json 解析器?这可能会节省很多
所以根据那个,你一定是内存不足
无论如何,我会使用一些体面的 ARM 和 DMA 魔法(例如在 STM32 MCU 上同时使用 16 个通道)而无需 CPU 的太多交互来发送它。或者像 OctoWS2811 LED Library
这样的现有解决方案