0

I want to open a .wav file in bytes from the sd card connected to esp32. My code is based in this question

I just want upload a file from my sd card to a server but by the moment I can't read the file despites the file exists in the sd card:

Look this lines of code:

 char *fname = "/sdcard/test.wav";
  FILE *fp = fopen(fname, "rb"); // read in bytes
   
  if(!fp) {
    Serial.println("File doens't exist");
  }

I don't understand why it File file = SD.open("/test.wav") works but the above code not. According to my reference I should read this file in bytes and not in a normal manner like this => File file = SD.open("/test.wav").

I would like know how I can see the full path of my sd card because the original code uses this:

char *fname = "/sdcard/test_text.txt";
  FILE *fp = fopen(fname, "rb"); 

why that uses this path /sdcard/test_text.txt I don't know exactly. If I try to open by using:

File file = SD.open("/test.wav") 

will works but some lines of code after this will throws errors because the file should be read in bytes.

I would like to see your advices guys I will appreciate any idea to fix this problem.

this is the entire code:

#include "Arduino.h"
#include "WiFi.h"
#include "SD.h"
#include "FS.h"
#include "HTTPClient.h"
//SD CARD MODULE
#define SD_CS          5
#define SPI_MOSI      23
#define SPI_MISO      19
#define SPI_SCK       18

// Wifi Credentials
const char* ssid     = "XXX";
const char* password = "XXX";

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("MY IP address: ");
  Serial.println(WiFi.localIP());

  
  if (!SD.begin(SD_CS)) {
    Serial.println("SD init failed!");
    return;
  }
   Serial.println("SD init successfull!");

  
}

void loop()
{
  WiFiClient client;
  Serial.println("starting file upload");
  IPAddress host(192, 168, 18, 8); //server ip
  int port = 80;
  if (!client.connect(host, port))
  { // check connection to host if untrue internet connection could be down
    Serial.println("couldn't connect to host");
  }
  Serial.println("Connect to host!");

  HTTPClient http;
  const char* serverName = "http://192.168.18.8/upload/upload.php";
  http.begin(client, serverName);

  char *fname = "/sdcard/test.wav";
  FILE *fp = fopen(fname, "rb"); // read in bytes
   
  if(!fp) {
    Serial.println("File doens't exist");
  }

  //get file size
  fseek(fp, 0, SEEK_END); //send file pointer to end of file 
  int file_size = ftell(fp); //get end position of file
  fseek(fp, 0, SEEK_SET); //send pointer back to start

  int max_upload_size = 10; // array size, larger = less uploads but too large can cause memory issues
  int num_of_uploads = file_size / max_upload_size; // figure out how many evenly sized upload chunks we need
  int num_of_uploads_mod = file_size % max_upload_size; //find out size of remaining upload chunk if needed
  int i;
  //upload file in even chunks    
  if (num_of_uploads > 0)
  {
    char buff1[max_upload_size+1] = {}; // array to save file too. add 1 for end of array symbol '\n'
    for (i = 0; i < num_of_uploads; i++)
    {
      fread(buff1, sizeof(buff1)-1, 1, fp); // -1 as don't want to count the '\n'
      http.addHeader("file_name", "file_name"); //header to say what the file name is
      int httpResponseCode = http.POST((uint8_t *)buff1, sizeof(buff1)-1); //send data. Datatype is (uint8_t *)
    }
  }
  //upload any remaining data
  if (num_of_uploads_mod > 0)
  {
    int remainder = file_size - num_of_uploads * max_upload_size;
    uint8_t buff2[remainder] = {};
    fread(buff2, sizeof *buff2, sizeof buff2 / sizeof *buff2, fp);
    http.addHeader("file_name", "file_name");
    http.addHeader("Content-Type", "application/octet-stream");
    int httpResponseCode = http.POST(buff2, sizeof(buff2));
  }
  http.end(); // Close connection
  delay(10 * 1000);
} 

thanks so much.

2 Answers2

0

Unfortunately, this isn't straight-forward. You can either use the SD component directly or mount the correct file system driver (typically FatFs for an SD card). To use fopen, you need to register the correct driver first, hints can be found here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/fatfs.html#using-fatfs-with-vfs-and-sd-cards

I haven't tried this myself yet, but the magic function seems to be esp_vfs_fat_sdspi_mount that should enable the use of fopen with the SD card over SPI. The official documentation lacks a real-world example, but you might find something in this thread or via your preferred search engine. For further help, you might want to ask a question on arduino.se instead, where a number of experienced ESP32 experts are present.

PMF
  • 14,535
  • 3
  • 23
  • 49
0

I struggled myself with using SD Cards (fat32) on my ESP32. When trying to open my file using

std::ofstream dataFile("/sdcard/data.json", std::ofstream::out);

It wouldn't create my file. a sys/stat would thus give a -1. Turned out that you really need to use the 8.3 naming convention for FAT32. There's no "MS windows-magic" That abbreviates the file to: sdcard.j~1 etc. So just use a correct file name. not "/sdcard/mylomgfilename.exotic_extention" but just a "/mpoint/12345678.123" filename like "/sdcard/data.txt".

Robin van Leeuwen
  • 2,625
  • 3
  • 24
  • 35