SD Card Espressif ESP32C and library conflicts

I'm deliberately not including code in this post!

I'd been chasing my tail for multiple days and I think I've discovered the issue, plus some of the problems others might have seen then given up.

When we add includes into the sketch like:

#include <SD.h>

The IDE tries to resolve and find the library. It may include information about the specific board. In my case an XIAO ESP32C3, the board library might be the Espressif version... might is the key. The reason for the no code will be obivous shortly!

I've two versions of the Ardunio IDE, a 1.8.x version and the newer 2.x.x version (downloaded last week). I have TWO large SSD drives the I install to - one on the C drive and one on D drive.

After chasing my tail, one issue is that the IDE doesn't necessarily install the board information and libraries to the correct drive. Worse yet it looks like some of the board libraries - like the one for the ESP32 from Espressif include some of their own "special libraries" for things like the SD card.

Seems reasonable - that should give a better optimization -- right? Nope, the ESP32 3.x.x library for SD cards from Espressif does not have the complete FAT structure available in it that the SD.h from the generic arduino library. The "#include SD.h" used depends on the board selected! That means sometimes a board will compile correctly and run on one instance - but will fail if a different board is selected.

For example compiling with the XIAO ESP32C3 the library path is:

'XIAO_ESP32C3' from platform in folder: C:\Users\dennish\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.0.0

That used SD.h from Espressif looks like:
'

// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SD_H_
#define _SD_H_

#include "FS.h"
#include "SPI.h"
#include "sd_defines.h"

namespace fs {

class SDFS : public FS {
protected:
  uint8_t _pdrv;

public:
  SDFS(FSImplPtr impl);
  bool begin(
    uint8_t ssPin = SS, SPIClass &spi = SPI, uint32_t frequency = 4000000, const char *mountpoint = "/sd", uint8_t max_files = 5, bool format_if_empty = false
  );
  void end();
  sdcard_type_t cardType();
  uint64_t cardSize();
  size_t numSectors();
  size_t sectorSize();
  uint64_t totalBytes();
  uint64_t usedBytes();
  bool readRAW(uint8_t *buffer, uint32_t sector);
  bool writeRAW(uint8_t *buffer, uint32_t sector);
};

}  // namespace fs

extern fs::SDFS SD;

using namespace fs;
typedef fs::File SDFile;
typedef fs::SDFS SDFileSystemClass;
#define SDFileSystem SD

#endif /* _SD_H_ */'

When you chase your tail and look for the FAT structure - the ESP32 library by Espressif - doesn't include the structure..

That makes it difficult to write code to set the date & time for a file as it is created with their library.

Whereas other SD libraries do indeed include the FAT structure. For example:

SD - a slightly more friendly wrapper for sdfatlib

This library aims to expose a subset of SD card functionality
in the form of a higher level "wrapper" object.

License: GNU General Public License V3
          (Because sdfatlib is licensed with this.)

  (C) Copyright 2010 SparkFun Electronics

*/

#ifndef __SD_H__
#define __SD_H__

#include <Arduino.h>

#include "utility/SdFat.h"
#include "utility/SdFatUtil.h"

#define FILE_READ O_READ
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)

namespace SDLib {

  class File : public Stream {
    private:
      char _name[13]; // our name
      SdFile *_file;  // underlying file pointer

    public:
      File(SdFile f, const char *name);     // wraps an underlying SdFile
      File(void);      // 'empty' constructor
      virtual size_t write(uint8_t);
      virtual size_t write(const uint8_t *buf, size_t size);
      virtual int availableForWrite();
      virtual int read();
      virtual int peek();
      virtual int available();
      virtual void flush();
      int read(void *buf, uint16_t nbyte);
      boolean seek(uint32_t pos);
      uint32_t position();
      uint32_t size();
      void close();
      operator bool();
      char * name();

      boolean isDirectory(void);
      File openNextFile(uint8_t mode = O_RDONLY);
      void rewindDirectory(void);

      using Print::write;
  };

  class SDClass {

    private:
      // These are required for initialisation and use of sdfatlib
      Sd2Card card;
      SdVolume volume;
      SdFile root;

      // my quick&dirty iterator, should be replaced
      SdFile getParentDir(const char *filepath, int *indx);
    public:
      // This needs to be called to set up the connection to the SD card
      // before other methods are used.
      boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);
      boolean begin(uint32_t clock, uint8_t csPin);

      //call this when a card is removed. It will allow you to insert and initialise a new card.
      void end();

      // Open the specified file/directory with the supplied mode (e.g. read or
      // write, etc). Returns a File object for interacting with the file.
      // Note that currently only one file can be open at a time.
      File open(const char *filename, uint8_t mode = FILE_READ);
      File open(const String &filename, uint8_t mode = FILE_READ) {
        return open(filename.c_str(), mode);
      }

      // Methods to determine if the requested file path exists.
      boolean exists(const char *filepath);
      boolean exists(const String &filepath) {
        return exists(filepath.c_str());
      }

      // Create the requested directory heirarchy--if intermediate directories
      // do not exist they will be created.
      boolean mkdir(const char *filepath);
      boolean mkdir(const String &filepath) {
        return mkdir(filepath.c_str());
      }

      // Delete the file.
      boolean remove(const char *filepath);
      boolean remove(const String &filepath) {
        return remove(filepath.c_str());
      }

      boolean rmdir(const char *filepath);
      boolean rmdir(const String &filepath) {
        return rmdir(filepath.c_str());
      }

    private:

      // This is used to determine the mode used to open a file
      // it's here because it's the easiest place to pass the
      // information through the directory walking function. But
      // it's probably not the best place for it.
      // It shouldn't be set directly--it is set via the parameters to `open`.
      int fileOpenMode;

      friend class File;
      friend boolean callback_openPath(SdFile&, const char *, boolean, void *);
  };

  extern SDClass SD;'
 rest left off..

I've run into several other problems with the Espressif ESP32 board definitions which cause template errors to pop up.

Has anyone else seen this? What is the better way to select SD.h, when the sketch might be on drive C or drive D. The preference in the arduino IDE doesn't let you to redefine the library search order.

Is there an Arduino reference document which helps with the switches that I can add during the compile to capture issues like this.

I can't imagine the nightmares some of the new Arduino users might go through when their sketches become more complicated.

Far too many of the libraries lack decent documentation - and reading their source is the only solution.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.