I am using an Adafruit RP2040 as an Arduino. It has 264K of ram and 16mb of qspi flash. The matrix I want to store is too big to fit in ram, but I don't know how to put into flash. (I am not very experienced with Arduino programming). The matrix can be read only, and is populated from a file on an SD card. The file contains a large number of RGB values.
I know PROGMEM is probably the answer, but I think the matrix has to be declared as a const, in which case I can't write values to it in a loop? Any help would be greatly appreciated. Code is below;
#include "Adafruit_NeoPixel.h"
#include "SdFat.h"
#define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 20 // Number of NeoPixels
#define SD_CS_PIN 23 // CS pin for SD card
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
SdFat sd;
File32 myFile;
int Wide = 0;
const int MAX_WIDTH = 100; // Maximum width of matrix
byte matrix[360][650]; // Define matrix as a global variable
int dT = -3;
int F = 0; //starting y position to read neopixel values from matrix
int sensorPin = A0; // select the input pin for the potentiometer
void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!sd.begin(SD_CS_PIN)) {
Serial.println("Initialization failed!");
return;
}
Serial.println("Initialization done.");
myFile.open("colors.txt");
if (myFile) {
Serial.println("colors.txt:");
const int Width = myFile.parseInt() * 3;
Wide = Width;
const int Height = myFile.parseInt();
Serial.print("width = :");
Serial.println(Width);
Serial.print("Height = :");
Serial.println(Height);
// Read from the file and populate matrix
for (int i = 0; i < Height; i++) {
for (int j = 0; j < Width; j++) {
if (myFile.available()) {
matrix[j][i] = myFile.parseInt(); // Read a number from the file
Serial.print(matrix[j][i]);
Serial.print(" ");
}
}
Serial.println();
}
strip.begin();
strip.show();
myFile.close();
} else {
Serial.println("Error opening colors.txt");
}
}
void loop() {
F = map(analogRead(sensorPin),0,1023,0,80);
dT = dT + 3;
if (dT > (Wide - 3)) dT = 0;
// Serial.print(Wide);
// Serial.print(", ");
// Serial.println(dT);
// Loop and assign neopixel values
for (int i = F; i < (F + PIXEL_COUNT); i++) {
int R = matrix[dT][i];
int G = matrix[dT+1][i];
int B = matrix[dT+2][i];
strip.setPixelColor(i - F,strip.Color(R ,G ,B ));
// Serial.print(R);
// Serial.print(", ");
// Serial.print(G);
// Serial.print(", ");
// Serial.println(B);
}
strip.show();
delay (1000/30);
}
How would I assign 10,000 values from a text file to a "const byte matrix [] [n] PROGMEM" array so it is stored in flash? Some kind of char variable that has the proper format in it? Like "char content = "{{1,2,3....},{4,5,6,....}, etc }""?
Exactly like that. An editor with some sort of keyboard macro capability is useful, if you data is currently text. If they're not numbers, it'll look something like
So hard code the numbers into the Arduino code file? I can do this by modifying the program that preps the data from a .jpg image so it produces a text file like;
{
{1,2,3,...},{2,3,4...},
{5,5,6...},{7,8,2}
}
Then copy and paste.
Is there a limit on the line length in the Arduino code file?
if PROGMEM is not needed, then can I access the data in the matrix in the normal way?
I tried the hard code method, and that actually worked! Thanks for all your help on this one. The "const" function was enough for the RP2040 to put the matrix in flash (although I included PROGMEM), and I could read the values back in the normal way x = matrix [4] [23];
To be used, the data must be read byte-by-byte from the SD card and put somewhere. That somewhere is likely RAM (I don't know if it's possible to read from SD and write to Flash at run-time). If the application and contents of the array is such that the whole thing must be accessible during program execution, then the whole thing must be read into RAM. But:
on an ESP32 or RP2040 the flash memory is mapped into the program space so you can read it just like it's in RAM, it will be a bit slower but faster than reading from an SD card
Understood. But my point was (responding to @jimLee's quetion), if the data is stored on SD Card, it must be copied somewhere at run-time to be used as an array by the code. Can that that "somewhere" be Flash?
OK, but littleFS (like SD) is just a file system. It's not an array. How does OP's code access the data as an array (or "Matrix", per the title of this thread)?
My solution (with your suggestions) got rid of the need for the SD card. I can't read directly from the SD during execution, because I need random access and speed. I wrote an external program in XOJO that processes the .jpg file, extracts the pixel colors, and formats the output so it is a simple cut and paste into the arduino code.
Interestingly, the first time the code runs, it takes about 5 seconds to load the numbers and get to "loop {;". The second time it is almost instantaneous, so it seems like it doesn't need to reload the matrix into flash again.
indeed - it's just faster than SD because in flash
if you store binary structures into a file system then accessing a structure at a given index is seeking to an easy to calculate position and read in enough bytes to fill in the structure if you want to bring that in RAM