Portenta H7: Write to SD Card

Hi,

I would like to write to an Micro SD Card. I'm using the Pins 55, 57, 59, 61,63, 65 on the high density connector J1 (see appendix).
The example code TestSDCARD.ino is working well and I can list some directories on the SD Card.

Now I trying to use the FATFileSystem with fopen, fprintf and fclose, but I can't write to the SD Card. The red LED on the Portenta board starts flashing. The Serial output is:

Test
1

Which concludes that there is a error in line fprintf(fs,"test \r\n");

#include "FATFileSystem.h"
#include "mbed.h"
#include <string>

mbed::FATFileSystem fs("fs");

void setup() {
  // put your setup code here, to run once:
  delay(2000);
  Serial.begin(115200);
  Serial.println("Test");
 

    FILE *fp = fopen("/fs/test.txt", "w");
    Serial.println("1");
    fprintf(fp,"test \r\n");
    Serial.println("2");
    fclose(fp);
    
}

void loop() {
  // put your main code here, to run repeatedly:

}

What is wrong with this code? Is there some example code to write to a SD Card with the Protenta H7?
The SD Card is formatted to FAT32 (32GB, V30, U3)

Thanks a lot!

Unbenannt.JPG

Unbenannt.JPG

Ah, ok, i need to mount the filesystem... This is the solution:

#include "SDMMCBlockDevice.h"
#include "FATFileSystem.h"

SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");

void setup() {
  // put your setup code here, to run once:
  delay(2000);
  Serial.begin(115200);
  Serial.println("Test");
  int err =  fs.mount(&block_device);
  if (err) {
    // Reformat if we can't mount the filesystem
    // this should only happen on the first boot
    Serial.println("No filesystem found, formatting... ");
    fflush(stdout);
    err = fs.reformat(&block_device);
  }

  FILE *fp = fopen("/fs/test.txt", "a");
    Serial.println("1");
    fprintf(fp,"test \r\n");
    Serial.println("2");
    fclose(fp);
}

void loop() {
  // put your main code here, to run repeatedly:

}
1 Like

Thanks for this. I was able to write the constant string values to file with this.

The next step is how to write sensor values to sd card file. The fprintf function requires a 'const char' variable as input. I'm getting errors cannot convert convert Arduino::string to const char*.

This seems like a simple problem but I'm an amateur and I have been googling this for hours. Googling "Portenta write to SD card" yields your post first. To save others time I found a solution to write integer values to file.

I'm using the same code as you but removed your
fprintf(fp,"test \r\n");
with this into the loop() code.

const int analogInPin0 = A0; // Pin to read analog values from
int sensorValue0=0; // initialize sensor value
char string0[2]; // Array to store the string
sensorValue0 = analogRead(analogInPin0);
itoa(sensorValue0,string0,10); // converts int to char *
fprintf(fp,string0); // write data to file
fprintf(fp,"/r/n"); //new line
delay(500); // Wait 500ms before next loop

I'm able to print integers to file like this. Now to figure out how to do floats. I'll leave that for another day.

1 Like

Hi. Working on this today as well. Thanks for the starting setup.


/*
  Portenta - TestSDCARD

  The sketch shows how to mount an SDCARD and list its content.

  The circuit:
   - Portenta H7 + Vision Shield
   - Portenta H7 + Portenta Breakout

  This example code is in the public domain.
*/
#include "SDMMCBlockDevice.h"
#include "FATFileSystem.h"

SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");
FILE *myFile;

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("Mounting SDCARD...");
  int err =  fs.mount(&block_device);
  if (err) {
    // Reformat if we can't mount the filesystem
    // this should only happen on the first boot
    Serial.println("No filesystem found, please check on computer and mually format");
   // err = fs.reformat(&block_device);  // seriously don't want to format good data
  }
  if (err) {
     Serial.println("Error formatting SDCARD ");
     while(1);
  }
  
  DIR *dir;
  struct dirent *ent;
  int dirIndex = 0;

  Serial.println("List SDCARD content: ");
  if ((dir = opendir("/fs")) != NULL) {
    // Print all the files and directories within directory (not recursively)
    while ((ent = readdir (dir)) != NULL) {
      Serial.println(ent->d_name);
      dirIndex++;
    }
    closedir (dir);
  } else {
    // Could not open directory
    Serial.println("Error opening SDCARD\n");
    while(1);
  }
  if(dirIndex == 0) {
    Serial.println("Empty SDCARD");
  }
 Serial.println("------------------------- Done --------------------------------"); 
}

void loop() {

  int myTime = millis()/1000; // seconds since ???
  char myFileName[] = "fs/00000000.json";
  myFileName[3] = myTime/10000000 % 10 + '0';
  myFileName[4] = myTime/1000000 % 10 + '0';
  myFileName[5] = myTime/100000 % 10 + '0';
  myFileName[6] = myTime/10000 % 10 + '0';
  myFileName[7] = myTime/1000 % 10 + '0';
  myFileName[8] = myTime/100 % 10 + '0';
  myFileName[9] = myTime/10 % 10 + '0';
  myFileName[10] = myTime % 10 + '0';
  //const char *myFileName2 = myFileName;
  myFile = fopen(myFileName, "a");  // "a" for append or make it if file not there
    Serial.println(myFileName);

  //  fprintf(myFile,"test \r\n");
    fprintf(myFile,"{\"protected\":{\"ver\":\"v1\",\"alg\":\"none\",\"iat\":1603914126},");
    fprintf(myFile,"\"signature\":\"0\",\"payload\":{\"device_type\":\"TEST\",\"interval_ms\":10,");
    fprintf(myFile,"\"sensors\":[{\"name\":\"sensor1\",\"units\":\"N/A\"}],");
    fprintf(myFile,"\"values\":[234,423,534,654]}}\r\n");

  fclose(myFile);
  delay(30000);


}

@pert does Arduino have a file print procedure that takes a string? The following works fine, but using char arrays is a huge pain. Any Arduino file print procedures that take strings?

#include "SDMMCBlockDevice.h"
#include "FATFileSystem.h"


  char myFileName[] = "fs/00000000.json";
  char buffer0[30] = "I can be saved";
  myFile = fopen(myFileName, "a");  
  fprintf(myFile, buffer0);
  fclose(myFile);

Any other string options?

.
few days later

I made some .json and .csv sd card examples here for edge impulse uploading, but I also made a simple .txt file example

/*
  Portenta - TestSDCARD

  The sketch shows how to mount an SDCARD and list its content.
  then add a file.

  Note: SD Card seems finisky, takes a few times to load the filesystem

  The circuit:
   - Portenta H7 + Vision Shield
   or
   - Portenta H7 + Portenta Breakout

  This example code is in the public domain.
*/
#include "SDMMCBlockDevice.h"
#include "FATFileSystem.h"

SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");


void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  
  delay(5000); // time to connect serial
  Serial.println("Connect serial if needed");
  delay(5000);
  //while (!Serial);  // blocking call

  Serial.println("Mounting SDCARD...");
  int err =  fs.mount(&block_device);
  if (err) {
     Serial.println("No SD Card filesystem found, please check SD Card on computer and manually format if needed.");
     // int err = fs.reformat(&block_device);  // seriously don't want to format your good data
  }

}

void loop() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // flips LED on and off
  
  // Make a folder if needed
  mkdir("fs/myFolder2",0777);                     // 0777 full access permissions linux style 
   
  char myFileName[] = "fs/myFolder2/test2.txt";   // "fs/" needs to be there, think fileSystem
 
  FILE *myFile = fopen(myFileName, "w");          // "a" for append (add to file), "w" write, "r" read ??
 
     Serial.println(myFileName);
     fprintf(myFile,"Test how cool this is \r\n");
     fprintf(myFile,"Also this line \r\n");
   
  fclose(myFile);

  Serial.println("------------------------- Done Writing file --------------------------------");
  delay(10);
   
  unsigned char c; 
  FILE *fp = fopen(myFileName, "r");              // "r" read only
     while (!feof(fp)){                           // while not end of file
        c=fgetc(fp);                              // get a character/byte from the file
        //printf("Read from file %02x\n\r",c);    // and show it in hex format
        Serial.print((char)c);                    // show it as a text character
     }
  fclose(fp); 
  Serial.println("------------------------- Done Showing file --------------------------------");

  delay(10000);   // wait a bit
  
}

Just occurred to me, if you have the vision shield on the breakout board you have access to 2 SD cards. How do you identify which one is the correct sd card to access?