Note, a string of 224 WS2812B units takes about 6.7 ms to update: 224 units x 24 bits x 1.25 μs/bit. Each time you update your matrix of lights, the millis()
counter, timer0_millis
, will lose 5 or 6 ms because pixels.show()
runs with interrupts turned off. To compensate, you could add 5 to timer0_millis
after each update. To make the loss always be 5 ms instead of sometimes 5 and sometimes 6, add the following code just before pixels.show()
: unsigned long now=millis(); while (now==millis());
, which will stall until the end of the current millisecond. To see how to change timer0_millis
, see the "Better Alternative" section of my answer to "How to keep accurate millis() while using ADC_sleep mode?" my answer to "How to keep accurate millis() while using ADC_sleep mode?".
Note, a string of 224 WS2812B units takes about 6.7 ms to update: 224 units x 24 bits x 1.25 μs/bit. Each time you update your matrix of lights, the millis()
counter, timer0_millis
, will lose 5 or 6 ms because pixels.show()
runs with interrupts turned off. To compensate, you could add 5 to timer0_millis
after each update. To make the loss always be 5 ms instead of sometimes 5 and sometimes 6, add the following code just before pixels.show()
: unsigned long now=millis(); while (now==millis());
, which will stall until the end of the current millisecond. To see how to change timer0_millis
, see the "Better Alternative" section of my answer to "How to keep accurate millis() while using ADC_sleep mode?".
Note, a string of 224 WS2812B units takes about 6.7 ms to update: 224 units x 24 bits x 1.25 μs/bit. Each time you update your matrix of lights, the millis()
counter, timer0_millis
, will lose 5 or 6 ms because pixels.show()
runs with interrupts turned off. To compensate, you could add 5 to timer0_millis
after each update. To make the loss always be 5 ms instead of sometimes 5 and sometimes 6, add the following code just before pixels.show()
: unsigned long now=millis(); while (now==millis());
, which will stall until the end of the current millisecond. To see how to change timer0_millis
, see the "Better Alternative" section of my answer to "How to keep accurate millis() while using ADC_sleep mode?".
// Sketch that accepts a number k via serial input, and responds with
// the k-th set of numbers from among some sets of numbers stored in
// PROGMEM. This avoids copying the array data into RAM. jiw 31 Oct 2016
#include <Streaming.h> // Ref: http://arduiniana.org/libraries/streaming/
// Set up datatext in PROGMEM
const byte L1[] PROGMEM = { 102, 103, 112, 113, 116, 117, 146, 147, 148,
149, 160, 161, 28, 29, 58, 59, 72, 73, 0};
const byte R1[] PROGMEM = { 124, 125, 128, 129, 134, 135, 136, 137, 172,
173, 40, 41, 46, 47, 84, 85, 90, 91, 0};
const byte L2[] PROGMEM = { 152, 153, 156, 157, 158, 159, 160, 161, 144,
145, 118, 119, 104, 105, 102, 103, 68, 69, 64,
65, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0};
const byte R2[] PROGMEM = { 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52,
53, 80, 81, 92, 93, 90, 91, 132, 133, 130,
131, 168, 169, 170, 171, 172, 173, 140, 141, 0};
const void* Addrs[] = { L1, R1, L2, R2 };
enum { nAddrs = sizeof Addrs / sizeof Addrs[0] };
void prompt() {
Serial << endl << "Please enter item number from 1 to " << _DEC(nAddrs) << ": ";
}
void setup() {
Serial.begin(115200); // init serial port
prompt(); // Issue initial prompt
}
void loop() {
char c, d;
while (Serial.available()) { // Get characters
c = Serial.read();
if (c >= '0' && c <= '9') {
Serial << c << endl; // Echo the entered digit
d = c - '0' - 1;
if (d>=0 && d < nAddrs) {
byte k=0, t = pgm_read_byte(Addrs[d]);
Serial << "Set #" << _DEC(d+1) << ": ";
while (t) {
Serial << _HEX(t) << ' ';
t = pgm_read_byte(++k + Addrs[d]);
}
Serial << endl;
}
prompt(); // Issue prompt after any digit
}
}
}
// Sketch that accepts a number k via serial input, and responds with
// the k-th set of numbers from among some sets of numbers stored in
// PROGMEM. This avoids copying the array data into RAM. jiw 31 Oct 2016
#include <Streaming.h> // Ref: http://arduiniana.org/libraries/streaming/
// Set up datatext in PROGMEM
const byte L1[] PROGMEM = { 102, 103, 112, 113, 116, 117, 146, 147, 148,
149, 160, 161, 28, 29, 58, 59, 72, 73, 0};
const byte R1[] PROGMEM = { 124, 125, 128, 129, 134, 135, 136, 137, 172,
173, 40, 41, 46, 47, 84, 85, 90, 91, 0};
const byte L2[] PROGMEM = { 152, 153, 156, 157, 158, 159, 160, 161, 144,
145, 118, 119, 104, 105, 102, 103, 68, 69, 64,
65, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0};
const byte R2[] PROGMEM = { 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52,
53, 80, 81, 92, 93, 90, 91, 132, 133, 130,
131, 168, 169, 170, 171, 172, 173, 140, 141, 0};
const void* Addrs[] = { L1, R1, L2, R2 };
enum { nAddrs = sizeof Addrs / sizeof Addrs[0] };
void prompt() {
Serial << endl << "Please enter item number from 1 to " << _DEC(nAddrs) << ": ";
}
void setup() {
Serial.begin(115200); // init serial port
prompt(); // Issue initial prompt
}
void loop() {
char c, d;
while (Serial.available()) { // Get characters
c = Serial.read();
if (c >= '0' && c <= '9') {
Serial << c << endl; // Echo the entered digit
d = c - '0' - 1;
if (d>=0 && d < nAddrs) {
byte k=0, t = pgm_read_byte(Addrs[d]);
Serial << "Set #" << _DEC(d+1) << ": ";
while (t) {
Serial << _HEX(t) << ' ';
t = pgm_read_byte(++k + Addrs[d]);
}
Serial << endl;
}
prompt(); // Issue prompt after any digit
}
}
}
// Sketch that accepts a number k via serial input, and responds with
// the k-th set of numbers from among some sets of numbers stored in
// PROGMEM. This avoids copying the array data into RAM. jiw 31 Oct 2016
#include <Streaming.h> // Ref: http://arduiniana.org/libraries/streaming/
// Set up datatext in PROGMEM
const byte L1[] PROGMEM = { 102, 103, 112, 113, 116, 117, 146, 147, 148,
149, 160, 161, 28, 29, 58, 59, 72, 73, 0};
const byte R1[] PROGMEM = { 124, 125, 128, 129, 134, 135, 136, 137, 172,
173, 40, 41, 46, 47, 84, 85, 90, 91, 0};
const byte L2[] PROGMEM = { 152, 153, 156, 157, 158, 159, 160, 161, 144,
145, 118, 119, 104, 105, 102, 103, 68, 69, 64,
65, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0};
const byte R2[] PROGMEM = { 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52,
53, 80, 81, 92, 93, 90, 91, 132, 133, 130,
131, 168, 169, 170, 171, 172, 173, 140, 141, 0};
const void* Addrs[] = { L1, R1, L2, R2 };
enum { nAddrs = sizeof Addrs / sizeof Addrs[0] };
void prompt() {
Serial << endl << "Please enter item number from 1 to " << _DEC(nAddrs) << ": ";
}
void setup() {
Serial.begin(115200); // init serial port
prompt(); // Issue initial prompt
}
void loop() {
char c, d;
while (Serial.available()) { // Get characters
c = Serial.read();
if (c >= '0' && c <= '9') {
Serial << c << endl; // Echo the entered digit
d = c - '0' - 1;
if (d>=0 && d < nAddrs) {
byte k=0, t = pgm_read_byte(Addrs[d]);
Serial << "Set #" << _DEC(d+1) << ": ";
while (t) {
Serial << _HEX(t) << ' ';
t = pgm_read_byte(++k + Addrs[d]);
}
Serial << endl;
}
prompt(); // Issue prompt after any digit
}
}
}
- 8.9k
- 3
- 21
- 33
const byte L1[] = ({160, 161, 146, 147, 116, 117, 102, 103, 72, 73, 58, 59, 28, 29, 148,
149, 112, 113, 0)};
...
const byte R2[] = ({34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52, 53, 80, 81, 92, 93, 90,
91, 132, 133, 130, 131, 168, 169, 170, 171, 172, 173, 140, 141, 0)};
void loadDigit(byte *pixelList) {
for (byte j=0; pixelList[j]; ++j)
individualPixels[pixelList[j]] = 1;
}
...
loadDigit(L1); // Write a left 1
...
loadDigit(R2); // Write a right 2
const byte *digitsL[] = ({L0, L1, L2, L3, L4, L5, L6, L7, L8, L9)};
const byte *digitsR[] = ({R0, R1, R2, R3, R4, R5, R6, R7, R8, R9)};
...
if (num>9)
loadDigit(digitsL[num/10]); // Write tens digit
loadDigit(digitsR[num%10]); // Write units digit
A drawback to using const byte
arrays like L0 ... L9
and R0 ... R9
is that when your program starts they get copied from PROGMEM into RAM for access. It would make sense to declare them in PROGMEM, and use them directly from PROGMEM by appropriate changes. [Edit: See example program, below]
Following is an example program that illustrates storing a constant array of bytes in PROGMEM, and accessing its entries via pgm_read_byte()
calls.
// Sketch that accepts a number k via serial input, and responds with
// the k-th set of numbers from among some sets of numbers stored in
// PROGMEM. This avoids copying the array data into RAM. jiw 31 Oct 2016
#include <Streaming.h> // Ref: http://arduiniana.org/libraries/streaming/
// Set up datatext in PROGMEM
const byte L1[] PROGMEM = { 102, 103, 112, 113, 116, 117, 146, 147, 148,
149, 160, 161, 28, 29, 58, 59, 72, 73, 0};
const byte R1[] PROGMEM = { 124, 125, 128, 129, 134, 135, 136, 137, 172,
173, 40, 41, 46, 47, 84, 85, 90, 91, 0};
const byte L2[] PROGMEM = { 152, 153, 156, 157, 158, 159, 160, 161, 144,
145, 118, 119, 104, 105, 102, 103, 68, 69, 64,
65, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0};
const byte R2[] PROGMEM = { 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52,
53, 80, 81, 92, 93, 90, 91, 132, 133, 130,
131, 168, 169, 170, 171, 172, 173, 140, 141, 0};
const void* Addrs[] = { L1, R1, L2, R2 };
enum { nAddrs = sizeof Addrs / sizeof Addrs[0] };
void prompt() {
Serial << endl << "Please enter item number from 1 to " << _DEC(nAddrs) << ": ";
}
void setup() {
Serial.begin(115200); // init serial port
prompt(); // Issue initial prompt
}
void loop() {
char c, d;
while (Serial.available()) { // Get characters
c = Serial.read();
if (c >= '0' && c <= '9') {
Serial << c << endl; // Echo the entered digit
d = c - '0' - 1;
if (d>=0 && d < nAddrs) {
byte k=0, t = pgm_read_byte(Addrs[d]);
Serial << "Set #" << _DEC(d+1) << ": ";
while (t) {
Serial << _HEX(t) << ' ';
t = pgm_read_byte(++k + Addrs[d]);
}
Serial << endl;
}
prompt(); // Issue prompt after any digit
}
}
}
const byte L1[] = (160, 161, 146, 147, 116, 117, 102, 103, 72, 73, 58, 59, 28, 29, 148,
149, 112, 113, 0);
...
const byte R2[] = (34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52, 53, 80, 81, 92, 93, 90,
91, 132, 133, 130, 131, 168, 169, 170, 171, 172, 173, 140, 141, 0);
void loadDigit(byte *pixelList) {
for (byte j=0; pixelList[j]; ++j)
individualPixels[pixelList[j]] = 1;
}
...
loadDigit(L1); // Write a left 1
...
loadDigit(R2); // Write a right 2
const byte *digitsL[] = (L0, L1, L2, L3, L4, L5, L6, L7, L8, L9);
const byte *digitsR[] = (R0, R1, R2, R3, R4, R5, R6, R7, R8, R9);
...
if (num>9)
loadDigit(digitsL[num/10]); // Write tens digit
loadDigit(digitsR[num%10]); // Write units digit
A drawback to using const byte
arrays like L0 ... L9
and R0 ... R9
is that when your program starts they get copied from PROGMEM into RAM for access. It would make sense to declare them in PROGMEM, and use them directly from PROGMEM by appropriate changes.
const byte L1[] = {160, 161, 146, 147, 116, 117, 102, 103, 72, 73, 58, 59, 28, 29, 148,
149, 112, 113, 0};
...
const byte R2[] = {34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52, 53, 80, 81, 92, 93, 90,
91, 132, 133, 130, 131, 168, 169, 170, 171, 172, 173, 140, 141, 0};
void loadDigit(byte *pixelList) {
for (byte j=0; pixelList[j]; ++j)
individualPixels[pixelList[j]] = 1;
}
...
loadDigit(L1); // Write a left 1
...
loadDigit(R2); // Write a right 2
const byte *digitsL[] = {L0, L1, L2, L3, L4, L5, L6, L7, L8, L9};
const byte *digitsR[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9};
...
if (num>9)
loadDigit(digitsL[num/10]); // Write tens digit
loadDigit(digitsR[num%10]); // Write units digit
A drawback to using const byte
arrays like L0 ... L9
and R0 ... R9
is that when your program starts they get copied from PROGMEM into RAM for access. It would make sense to declare them in PROGMEM, and use them directly from PROGMEM by appropriate changes. [Edit: See example program, below]
Following is an example program that illustrates storing a constant array of bytes in PROGMEM, and accessing its entries via pgm_read_byte()
calls.
// Sketch that accepts a number k via serial input, and responds with
// the k-th set of numbers from among some sets of numbers stored in
// PROGMEM. This avoids copying the array data into RAM. jiw 31 Oct 2016
#include <Streaming.h> // Ref: http://arduiniana.org/libraries/streaming/
// Set up datatext in PROGMEM
const byte L1[] PROGMEM = { 102, 103, 112, 113, 116, 117, 146, 147, 148,
149, 160, 161, 28, 29, 58, 59, 72, 73, 0};
const byte R1[] PROGMEM = { 124, 125, 128, 129, 134, 135, 136, 137, 172,
173, 40, 41, 46, 47, 84, 85, 90, 91, 0};
const byte L2[] PROGMEM = { 152, 153, 156, 157, 158, 159, 160, 161, 144,
145, 118, 119, 104, 105, 102, 103, 68, 69, 64,
65, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0};
const byte R2[] PROGMEM = { 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 52,
53, 80, 81, 92, 93, 90, 91, 132, 133, 130,
131, 168, 169, 170, 171, 172, 173, 140, 141, 0};
const void* Addrs[] = { L1, R1, L2, R2 };
enum { nAddrs = sizeof Addrs / sizeof Addrs[0] };
void prompt() {
Serial << endl << "Please enter item number from 1 to " << _DEC(nAddrs) << ": ";
}
void setup() {
Serial.begin(115200); // init serial port
prompt(); // Issue initial prompt
}
void loop() {
char c, d;
while (Serial.available()) { // Get characters
c = Serial.read();
if (c >= '0' && c <= '9') {
Serial << c << endl; // Echo the entered digit
d = c - '0' - 1;
if (d>=0 && d < nAddrs) {
byte k=0, t = pgm_read_byte(Addrs[d]);
Serial << "Set #" << _DEC(d+1) << ": ";
while (t) {
Serial << _HEX(t) << ' ';
t = pgm_read_byte(++k + Addrs[d]);
}
Serial << endl;
}
prompt(); // Issue prompt after any digit
}
}
}