Storing SD card values into SRAM

Hey guys,

I'm working on a project with an E-ink display. I wanna get the pictures for the display from an SD card using a SD card reader module. I can read an write from and to the card without any issue. The problem is that I want to load the picture into the SRAM by using a variable, maybe an array, so that I can feed it to the display. I can display the data onto the serial monitor, but no more than that.

The display uses this function to display data:

void PIC_display(const unsigned char* picData_old, const unsigned char* picData_new)
{
  unsigned int i;
  EPD_W21_WriteCMD(0x10);        //Transfer old data
  for (i = 0; i < 15000; i++)
  {
    EPD_W21_WriteDATA(pgm_read_byte(&picData_old[i]));
  }

  EPD_W21_WriteCMD(0x13);        //Transfer new data
  for (i = 0; i < 15000; i++)
  {
    EPD_W21_WriteDATA(pgm_read_byte(&picData_new[i]));
  }
}

It uses two layers "old and new" that overlap to create a whole picture. It is reading this data from the program memory. It's being read from the .h file.

This is the code I wrote:

#include <SPI.h>
#include <SD.h>

File myFile;

int picdata[150];

void setup()  // in the setup the program will check if there is a SD card installed
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  delay(1000);
  Serial.println("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(4))
  {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

void loop() //this loop will read the SD card and put it into the SRAM
{
  myFile = SD.open("test.txt");
  // Put the data into SRAM
  int i = 0;
  while (myFile.available())
  {
    picdata[i] = myFile.read();
    i ++;
    Serial.println(picdata[i]); //show the data that is stored in picdata
  }
}

Maybe i'm not even approaching this the right way, looking at the function of the E-ink display. Maybe I should read this byte by byte? Some advice for this noob would be amazing!

Wrong type (should be uint8_t/byte) and ridiculous small.
Your PIC_display uses 15000 bytes for the picture.

So you probably don't have enough RAM to hold the picture in RAM,
maybe you can transfer the data chunk after chunk.

If you had only mentioned what type or Arduino you are using, I could be more specific.

File probably also has a function to read a bunch of bytes at a time, there is no reason
to read the bytes one by one.

I forgot about that... Stupid. I used a Arduino Uno, then switched to an QTPY (samd21) and then to a raspberry pi Pico. I can get alle three to work, but the Pico is the only one with more than enough SRAM.

Then get the file size, allocate a buffer of that size, and read the data.

How should I do that?
I have seen something like myFile.read(buf,len) but i'm not sure how that works. Also, I don't think that 15000 will be constant. Pictures can change in size.
I really tried to code it, but i'm missing something (probably easy)

  • find out, how you can get the size of the file that you want to display,
    then call that function saving its result
  • allocate a buffer of the saved size
  • open the file and read its content into the buffer, again using the saved size
  • close the file
  • display the picture by passing the buffer (and probably the length) to the display function
  • free the buffer

I can not look into the documentation of your unspecified SD library.

I'm using the standard Arduino SD card library. Nothing special.

So that library supports a

?

yes it does. just the regular sd library supports Raspberry pi Pico

So you should be able to solve your problem, as described.

I will not spoon-feed a solution.

I have been trying to create a code this is what I came up with:

 myFile = SD.open("pic.txt");
  int filesize = myFile.size();
  int inputValues [filesize]; //store data in an array (buffer)
  for (i = 0; i < filesize; i++)
  {
    myFile.seek(i); //select byte (selects byte after byte)
    value = myFile.read(1, 1); //read the first byte and store that byte.
    inputValues[i] = value; // array with all the values of the read bytes. Should be passed to E-ink write function.
  }
  myFile.close();
  for (i = 0; i < 15000; i++)
  {
    EPD_W21_WriteDATA(inputValues[i]);
    //   EPD_W21_WriteDATA(pgm_read_byte(&picData_old[i])); <- the old code, by manufacturer 
  }

Do you have some feedback on it? And I dont need spoon-fed solutions. It's just that some of the functions of Arduino feel very unnatural to me, even though I have some programming experience. I could go a lot further if some things could be clarified, sadly not everything is well documented.

You did not read or understand the documentation of File::read().

read()

Read from the file.

read() inherits from the Stream utility class.
Syntax

file.read() file.read(buf, len)
Parameters

file: an instance of the File class (returned by SD.open())

buf: an array of characters or bytes

len: the number of elements in buf
Returns

The next byte (or character), or -1 if none is available. 

Just use myFile.read(inpuValues, filesize); instead of

  for (i = 0; i < filesize; i++)
  {
    myFile.seek(i); //select byte (selects byte after byte)
    value = myFile.read(1, 1); //read the first byte and store that byte.
    inputValues[i] = value; // array with all the values of the read bytes. Should be passed to E-ink write function.
  }
int inputValues [filesize]; 

This is the wrong datatype, use uint8_t.

for (i = 0; i < 15000; i++)

So filesize mutated to 15000?

Well I didn't solve my problem but I used someone else his code for now. I found this topic that happend to discribe my exact problem. I can now read from my SD card and display it on the screen. Maybe when I become better at this, I will try again.

Sure, if there is a function to display SD images, and you want to save the file anyway
drawBitmapFromSD is a solution, if you change the pixel format to Bitmap.