// https://forum.arduino.cc/t/flag-led-matrix/1180853/
#include <FastLED.h>
#include <avr/pgmspace.h> // for PROGMEM
#define ROWS 16 // rows of Neopixels
#define COLS 32 // columns per row
#define NUMPIX (ROWS * COLS)
#define MATRIX_PIN 2
#define MAXBRIGHT 255
int INTENSITY[] = {255, 127, 63}; // RIDGE (bright), NODE (middle), TROUGH (dim)
CRGB led[NUMPIX];
const PROGMEM char flagUS[] = { // sizeof() = 257
"________________" // 0 - off
"#-#-#-#@@@@@@@@@" // 1 - blu/wht/red
"-#-#-#----------" // 2
"#-#-#-#@@@@@@@@@" // 3
"-#-#-#----------" // 4
"#-#-#-#@@@@@@@@@" // 5
"-#-#-#----------" // 6
"#-#-#-#@@@@@@@@@" // 7
"----------------" // 8 - wht
"@@@@@@@@@@@@@@@@" // 9 - red
"----------------" // 10
"@@@@@@@@@@@@@@@@" // 11
"----------------" // 12
"@@@@@@@@@@@@@@@@" // 13
"________________" // 14
"________________" // 15
};
const PROGMEM char poppy[] = {
"%_______________" // 0 - off / grn test
"______@@@@______" // 1 - red
"____@@@@@@@@____" // 2
"___&@@@@@@@@&___" // 3
"__@@&@@@@@@&@@__" // 4
"__@@@&@$$@&@@@__" // 5 - red/dark
"_@@@@@$$$$@@@@@_" // 6
"_@@@@@$$$$@@@@@_" // 7
"_@@@@@$$$$@@@@@_" // 8
"__@@@&@$$@&@@@__" // 9
"__@@&@@@@@@&@@__" // 10
"___&@@@@@@@@&___" // 11
"____@@@@@@@@____" // 12
"______@@@@______" // 13
"________________" // 14
"_______________%" // 15 - grn test
};
void setup() {
FastLED.addLeds<WS2812B, MATRIX_PIN, GRB>(led, NUMPIX);
FastLED.setBrightness(MAXBRIGHT); // Adjust the brightness value as needed
FastLED.clear(); // clear pixel buffer
FastLED.show(); // display cleared buffer
randomSeed(analogRead(A0)); // increase randomness - not needed
Serial.begin(9600); // debugging - not needed
// These functions are stand-alone.
showFlags(); // in work - combining showIS and showUS
// waveFlags(); // in work - only changing one column takes a long time lighting.
// showUS(); // show US flag
// showIS(); // show IS flag
// flagcorners(); // flag corners
// fourcorners(); // pixel matrix corners
// serial(); // output PROGMEM to serial monitor
serialSideBySide(); // output PROGMEM to serial monitor side by side
FastLED.show(); // last function called for pixels to be displayed
}
void loop() {
// randomPixels(); FastLED.show(); // random pixel in random color
}
void showFlags() { // show both flags
int asciiChar; // the data read from PROGMEM
for (int flag = 0; flag < 2; flag++) { // 0 = US, 1 = IS
int row = 0, column = 0;
for (int i = 0; i < 257; i++) { // strlen(flagXX) = 257
if (!flag) // select which flag to display
asciiChar = pgm_read_byte_near(flagUS + i); // flagXX is a contiguous line of text
else
asciiChar = pgm_read_byte_near(poppy + i);
if (asciiChar == '-')
led[(15 - row) * COLS + column + flag * 16] = CRGB(INTENSITY[1], INTENSITY[1], INTENSITY[1]); // WHITE
if (asciiChar == '#')
led[(15 - row) * COLS + column + flag * 16] = CRGB(0, 0, INTENSITY[1]); // BLUE
if (asciiChar == '@')
led[(15 - row) * COLS + column + flag * 16] = CRGB(INTENSITY[1], 0, 0); // RED
if (asciiChar == '&')
led[(15 - row) * COLS + column + flag * 16] = CRGB(15, 0, 0); // "light" red
if (asciiChar == '$')
led[(15 - row) * COLS + column + flag * 16] = CRGB(0, 0, 15); // "dark" blue
if (asciiChar == '%') { // test character
led[(15 - row) * COLS + column + flag * 16] = CRGB(0, 255, 0); // GREEN - test % placement
Serial.print("grn @ i:"); Serial.print(i); Serial.print(" ");
Serial.print("row:"); Serial.print(row); Serial.print(" ");
Serial.print("col:"); Serial.println(column);
}
column++; // move right one column
if (column % 16 == 0) { // indicates 16 columns have been counted
row++; // at the end of a column, move down one row
column = 0; // at the end of a column, reset to first column
}
}
}
}
void showUS() { // US flag in neopixels
int column = 0, row = 0, flag = 0;
flag = flag * 16; // 0 = US, 16 = IS
for (int i = 0; i < strlen(flagUS); i++) {
int asciiChar = pgm_read_byte_near(flagUS + i);
if (asciiChar == '-') // white
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[1], INTENSITY[1], INTENSITY[1]); // WHITE
if (asciiChar == '#') // blue
led[(15 - row) * COLS + column + flag] = CRGB(0, 0, INTENSITY[1]); // BLUE
if (asciiChar == '@') // red
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[1], 0, 0); // RED
if (asciiChar == '%') { // green
led[(15 - row) * COLS + column + flag] = CRGB(0, 255, 0); // testi % placement
Serial.print("i:"); Serial.print(i); Serial.print(" ");
Serial.print("row:"); Serial.print(row); Serial.print(" ");
Serial.print("col:"); Serial.println(column);
}
column++;
if (column % 16 == 0) {
row++;
column = 0;
}
}
}
void showIS() { // IS flag in neopixels
int column = 0, row = 0, flag = 1;
flag = flag * 16; // 0 = US, 16 = IS
for (int i = 0; i < strlen(poppy); i++) {
int asciiChar = pgm_read_byte_near(poppy + i);
if (asciiChar == '-')
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[1], INTENSITY[1], INTENSITY[1]); // WHITE
if (asciiChar == '#')
led[(15 - row) * COLS + column + flag] = CRGB(0, 0, INTENSITY[1]); // BLUE
if (asciiChar == '@')
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[1], 0, 0); // RED
if (asciiChar == '%') { // test character
led[(15 - row) * COLS + column + flag] = CRGB(0, 255, 0); // GREEN - for testing where % is placed
Serial.print("i:"); Serial.print(i); Serial.print(" ");
Serial.print("row:"); Serial.print(row); Serial.print(" ");
Serial.print("col:"); Serial.println(column);
}
column++;
if (column % 16 == 0) {
row++;
column = 0;
}
}
}
void waveFlags() { // change intensity in columns for waving flag
int wave = 0, column = 0, row = 0, flag = 0;
flag = flag * 16; // 0 = US, 16 = IS
showUS(); FastLED.show(); // display flag
delay(500); // Pause
for (int i = 0; i < strlen(flagUS); i++) { // read through PROGMEM
if (i % 16 == 4) { // identify the column
int asciiChar = pgm_read_byte_near(flagUS + i);
// change intensity to high
if (asciiChar == '-') // WHITE - Compare character to color
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[2], INTENSITY[2], INTENSITY[2]); // set pixel intensity
if (asciiChar == '#')
led[(15 - row) * COLS + column + flag] = CRGB(0, 0, INTENSITY[2]); // BLUE
if (asciiChar == '@')
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[2], 0, 0); // RED
if (asciiChar == '%') { // test character
led[(15 - row) * COLS + column + flag] = CRGB(0, 255, 0); // GREEN - for testing where % is placed
Serial.print(i); Serial.print(" "); Serial.print(row); Serial.print(" "); Serial.println(column);
}
FastLED.show(); delay(500);
// change intensity to middle
if (asciiChar == '-') // WHITE - Compare character to color
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[1], INTENSITY[1], INTENSITY[1]); // set pixel intensity
if (asciiChar == '#')
led[(15 - row) * COLS + column + flag] = CRGB(0, 0, INTENSITY[1]); // BLUE
if (asciiChar == '@')
led[(15 - row) * COLS + column + flag] = CRGB(INTENSITY[1], 0, 0); // RED
if (asciiChar == '%') { // test character
led[(15 - row) * COLS + column + flag] = CRGB(0, 255, 0); // GREEN - for testing where % is placed
Serial.print(i); Serial.print(" "); Serial.print(row); Serial.print(" "); Serial.println(column);
}
FastLED.show(); delay(500);
}
column++;
if (column % 16 == 0) {
row++;
column = 0;
}
}
// TO DO on flagWave()
// Read column X (column pixels increas by 16: 0, 16, 32, 48, ... 240)
// Set cX to ridge
// Hard-code the SECOND column to 191 (int node = 191).
// Find the pattern in the pseudo-code pseudo-formula (above)
// Use the formula to loop the FIRST column from "trough" to "node" to "ridge" to "node"
// Code a pixel step from column 1 to column 32 on row 0 (from 0 to 31)
// Code a pixel step from column 2 to column 32 on row 1 (this one goes from 64 to 32)
// Make them both move.
// Use the "wave" on 8 and 9.
}
void serial() { // show flags in serial monitor
for (int i = 0; i < strlen(flagUS); i++) {
if (i % 16 == 0)
Serial.println();
int us = pgm_read_byte_near(flagUS + i);
Serial.write(us);
}
for (int i = 0; i < strlen(poppy); i++) {
if (i % 16 == 0)
Serial.println();
int is = pgm_read_byte_near(poppy + i);
Serial.write(is);
}
}
void serialSideBySide() { // show flags in serial monitor, side by side
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
Serial.write(pgm_read_byte_near(flagUS + j + i * 16));
}
Serial.print(" ");
for (int j = 0; j < 16; j++) {
Serial.write(pgm_read_byte_near(poppy + j + i * 16));
}
Serial.println();
}
}
/*
15*32+0+f 15*32+31+f
led[480] led[511]
+--------------------------------+
|15 |
| |
| PROGMEM ASCII to PIXEL |
| PIX = row * COLS + col + FLAG |
| |
+0_____________________________31+
led[0] led[31]
0 * 32 + 0 0 * 32 + 31
*/
void flagcorners() { // show the four corners of the neopixels
led[ 0 * 32 + 0] = CRGB(255, 0, 255); // first flag, first row, first column
led[ 0 * 32 + 15] = CRGB(255, 128, 0); // first flag, first row, last column
led[ 0 * 32 + 16] = CRGB(255, 255, 0); // second flag, first row, first column
led[ 0 * 32 + 31] = CRGB(0, 255, 255); // second flag, first row, last column
led[15 * 32 + 0] = CRGB(255, 0, 255); // first flag, last row, first column
led[15 * 32 + 15] = CRGB(255, 128, 0); // first flag, last row, last column
led[15 * 32 + 16] = CRGB(255, 255, 0); // second flag, last row, first column
led[15 * 32 + 31] = CRGB(0, 255, 255); // second flag, last row, last column
}
void fourcorners() {
led[0] = CRGB(255, 000, 000); // bottom, left
led[31] = CRGB(000, 000, 255); // bottom, right
led[480] = CRGB(255, 255, 000); // top, left
led[511] = CRGB(000, 255, 000); // top, right
}
void randomPixels() { // random pixel in random PRIMARY and SECONDARY color on ROWS x COLS matrix
led[random(ROWS) * random(COLS)] = CRGB((random(2) * 255), (random(2) * 255), (random(2) * 255));
}