1

I am in serious need for help here. I have a rather small function that get's the number of files from within a given directory. Now, the directory name (that is the path) is stored in a char array within my main loop.

My problem is, I have no idea how to pass this char array to my function.

This is my code (it's of course just a subset but it's the part that is obviously wrong) and you can also see the complete program at the end:

In the setup() routine I define my current working directory:

char plrCurrentFolder[9];

In the main loop I want to get the number of files of a given directory (in the final program this directory name will come from an NFC tag):

String temp = "findorie";
temp.toCharArray(plrCurrentFolder, 9);
unsigned int numberOfFiles = countFiles(plrCurrentFolder);

This is the function to return the number of files:

unsigned int countFiles(File dir){
  unsigned int counter = 0;
  while (true){
    File entry = dir.openNextFile();
    if (!entry){
      // no more files
      break;
    }
    counter++;
    entry.close();
  }
  dir.close();
  return counter;
}

To be honest I have two issues with this. First, I don't really like to create a temp String variable to create the char array here as I would rather stick with the char array in itself to safe on memory and maybe this would also aid in performance (although I'm not sure about that).

Second, The way this whole thing is structured right now, it simply doesn't work. When building, the compiler correctly complains:

exit status 1
could not convert '(char*)(& plrCurrentFolder)' from 'char*' to 'SDLib::File'

Can anyone help me out and give me a code snippet how to make this work???

Kind regards to all,

Christian

--- below you may find the complete code as of now ---

/*
 * Fairytale Main program
 * 
 * This programm will read an nfc tag. It will check for a directory name and optional a filename 
 * and start playing this on the music maker shield.
 * 
 * Restrictions:
 * 1. All filenames mus be in the format  trackXXX.mp3  - where XXX is a numbering from 001 to 999
 * 2. All directory names must be exactly 8 chars long
 * 
 */

// make sure to change this to 0 before uploading in production as it turns on lots and lots of serial messages
#define DEBUG 1
// we only show light effects, in case this is set to 1
#define LIGHTEFFECTS 0
// we only use the nfc reader if this is set to 1
#define NFCREADER 0

//
// setup SPI, MP3 and SD libraries
//
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
// These are the pins used for the music maker shield
#define SHIELD_RESET  -1     // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)
#define CLK 13 // SPI Clock, shared with SD card
#define MISO 12 // Input data, from VS1053/SD card
#define MOSI 11 // Output data, to VS1053/SD card

// These are common pins between breakout and shield
#define CARDCS 4     // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

Adafruit_VS1053_FilePlayer musicPlayer = 
  // create shield-example object!
  Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);


//
// setup NFC Adapter 
//
#ifdef NFCREADER
/*
  #include <PN532_SPI.h>
  #include <PN532.h>
  #include <NfcAdapter.h>

  #define PN532_SCK (13) //changed from pin 2
  #define PN532_MISO (12) //changed from pin 5
  #define PN532_MOSI (11) //changed from pin 3
  #define PN532_SS (10) //changed from 4

  PN532_SPI pn532spi(SPI, PN532_SS);
  NfcAdapter nfc = NfcAdapter(pn532spi);
*/
#endif

// these variables are used for the light effects
int lightValue1, lightValue2, lightValue3;
const int redPin = 7;
const int greenPin = 8;
const int bluePin = 9;


// these are timing counters for the light effects
long time=0;
int periode = 20000;
int displace = 500;

// uptime counters
unsigned int runCounter = 0;
unsigned long startUpTime = 0;
const unsigned long maxUpTime = 120000; // 1800000L;  // 30 Minutes


// these are variables for the nfc card
boolean cardScanned = false;    // did we already scan the card?? using this to suppress reading in the card data while it is on the reader
char cardId[16];                // the uid of the card as read in through the nfc reader


// mp3 player variables
boolean plrIsPlaying = false;                         // is the mp3 player already playing?
char plrCurrentFile[13];                              // which track is the player playing?
char plrNextFile[13];                                 // which track is the player playing?
char plrPrevFile[13];                                 // which track is the player playing?
char plrCurrentFolder[9];                             // which directory is the player playing?
uint8_t plrCurrentPosition = 0;                       // on which position in seconds are we in the current track?
char currentTrackFileName[] = "/system/current.txt";  // a file we might use to store the last played track


// volume control variables for the analog poti
int volumePotPin = A0;        // the analog input pin that we use for the potentiometer
int sensorDrift = 7;          // difference to last received sensor value that must be exceeded to activate a change in the volume
int compareValue = 0;         // just a convenience variable to make comparison easier
int sensorValue = 0;          // read the value from the potentiometer
int lastSensorValue = 0;      // keeps the last read sensor value
uint8_t soundVolume = 0;      // the sound volume is derived via a map function from the sensor value

// other button settings
int btnLinePin = A1;         // pin on which the button line (4 buttons) is connected
int btnVal = 0;


// these are the prototypes for the nfc card reader
void getNfcCardData();


// these are the prototypes for the mp3 player controller
uint8_t getVolume(void);        // function that returns the volume setting based on the analog read
char plrNext(void);             // play next file in album
char plrPrev(void);             // play previous file in album
void plrPlayTrack(char, char);  // play a single track
void setupSound(void);          // initializes the sound system and plays the startup sound

// these are the prototypes to work on files
void printDirectory(File, int);   // print out the content of specified directory on serial console
unsigned int countFiles(File);    // return the number of files in a directory passed as a File descriptor
//unsigned int countFiles(char[]);    // return the number of files in a directory passed as a File descriptor


// these are the prototypes for the light effects
void fader(void);
void startuplight(void);
void highlight(int);
void flash(int);
void pulse(int);


void setup() {
  #ifdef DEBUG
    Serial.begin(115200);
  #endif

  plrCurrentFile[0] = 0; // we initialize the fiirst element of the array to 0 to later check if a current file was given.

  // initialise the music player
  if (! musicPlayer.begin()) { // initialise the music player
    #ifdef DEBUG
      Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    #endif
    while (1);
  }
  #ifdef DEBUG
    Serial.println(F("Music Maker Shield VS1053 found"));
  #endif

  //musicPlayer.sineTest(0x44, 500);    // Make a tone to indicate VS1053 is working

  if (!SD.begin(CARDCS)) {
    #ifdef DEBUG
      Serial.println(F("failed to detect the SD-Card"));
    #endif
    while (1);  // don't do anything more
  }
  #ifdef DEBUG
    Serial.println("SD found and operational");
  #endif

  // set the buttons as input
  pinMode(volumePotPin, INPUT);
  pinMode(btnLinePin, INPUT);

  // setup music maker shield and start playing startup file
  setupSound();

  #ifdef DEBUG
    // list files
    printDirectory(SD.open("/"), 0);
  #endif

/*
  // now as the last thing, start the nfc reader
  #ifdef DEBUG
    Serial.print("initializing NFC TAG reader ... "); 
  #endif
  nfc.begin();
  delay(1000); // wait some time for
*/

  // check our current time, so we know when to stop
  startUpTime = millis();
  #ifdef DEBUG
    Serial.println("we are up and running and ready to play audio"); 
  #endif
}


//
//      LL       OOOOOO    OOOOOO   PPPPPPP
//      LL      OO    OO  OO    OO  PP    PP
//      LL      OO    OO  OO    OO  PP    PP
//      LL      OO    OO  OO    OO  PPPPPP
//      LLLLLL   OOOOOO    OOOOOO   PP
void loop() {
  #ifdef LIGHTEFFECTS
    // turn off all the lights. we only want to have fading lights, while the playr is active
    //analogWrite(redPin, 0);
    //analogWrite(greenPin, 0);
    //analogWrite(bluePin, 0);
  #endif

  // NFC Tag reader functions
  // now we only do this, when an nfc tag is present
/*  
  if (nfc.tagPresent()){
    Serial.println("NFC tag Found!\n");
    NfcTag tag = nfc.read();
    Serial.print("Tag Type: ");
    Serial.println(tag.getTagType());
    Serial.print("UID: ");
    Serial.println(tag.getUidString());

    getNfcCardData();
*/  

    String temp = "findorie";
    temp.toCharArray(plrCurrentFolder, 9);


    // now let's get the number of files in the album directory
    //unsigned int numberOfFiles = 0;
    unsigned int numberOfFiles = countFiles(plrCurrentFolder);
    #ifdef DEBUG
      Serial.print("Directory ");Serial.print(plrCurrentFolder);Serial.print(" contains ");Serial.print(numberOfFiles);Serial.println(" files");
    #endif

    // if we did not get the current file from the tag, we are hardcoding it to track001.mp3
    if ((plrCurrentFile[0] == 0)) { 
      temp = "track001.mp3";
      temp.toCharArray(plrCurrentFile, 13);
    }

    #ifdef DEBUG
      Serial.print("currentFolder holds: ");Serial.print(plrCurrentFolder);Serial.print(" / currentFile contains: ");Serial.print(plrCurrentFile);
    #endif

    temp = "/";
    temp.concat(plrCurrentFolder);
    temp.concat("/");
    temp.concat(plrCurrentFile);
    char filename[temp.length() + 1];
    temp.toCharArray(filename, sizeof(filename));
    Serial.print(" / filename contains: ");Serial.println(filename);

    if (SD.exists(filename)) {
      Serial.print(filename);Serial.println(" exists.");

      // mp3 player functions playback
      // Start playing a file, then we can do stuff while waiting for it to finish
      if (! musicPlayer.startPlayingFile(filename)) {
        #ifdef DEBUG
          Serial.print("Could not open file ");Serial.println(filename);
        #endif
        while (1);
      }
      #ifdef DEBUG
        Serial.print(F("Start playing "));Serial.println(filename);
      #endif

      while (musicPlayer.playingMusic) {
        // file is now playing in the 'background' so now's a good time
        // to do something else like handling LEDs or buttons :)

        // play some nice light effects, if wanted
        #ifdef LIGHTEFFECTS
          //fader();
        #endif

        // volume control functions
        // read the input on analog pin 0 and check if we have a change in volume.
        sensorValue = analogRead(volumePotPin);
        if (lastSensorValue > sensorValue) {compareValue = lastSensorValue - sensorValue;} else {compareValue = sensorValue - lastSensorValue;}
        // If we have a high enough difference in the sensor reading, calculate it so we may set it on the player
        if (compareValue > sensorDrift){
          #ifdef DEBUG
            Serial.print("changing volume: ");
          #endif
          soundVolume = getVolume();
          musicPlayer.setVolume(soundVolume,soundVolume);
        }
      }
      #ifdef DEBUG
        Serial.println("Done playing ");Serial.println(filename);
      #endif
      #ifdef LIGHTEFFECTS
        //startuplight();
      #endif
    } else {
      Serial.print(filename);Serial.println(" does not exist.");
    } // end of file does not exist

  //} // end of tag found
} // end of loop


//
//        NN    NN  FFFFFF   CCCCCC
//        NNNN  NN  FF      CC
//        NN  N NN  FFFF    CC
//        NN  NNNN  FF      CC
//        NN    NN  FF       CCCCCC
//  BELOW THIS LINE THE NFC CONTROL IS DEFINED
//
void getNfcCardData(){
/*
  NfcTag tag = nfc.read();
  boolean usableContent = false;
  if (tag.hasNdefMessage()){
    NdefMessage message = tag.getNdefMessage();

    // If you have more than 1 Message then it wil cycle through them
    int recordCount = message.getRecordCount();
    for (int i = 0; i < recordCount; i++) {
      NdefRecord record = message.getRecord(i);

      int payloadLength = record.getPayloadLength();
      byte payload[payloadLength];
      record.getPayload(payload);

      String payloadAsString = ""; // Processes the message as a string vs as a HEX value
      for (int c = 0; c < payloadLength; c++) {
        payloadAsString += (char)payload[c];
      }

      String cleanString = payloadAsString;
      cleanString.remove(0,3);
      #ifdef DEBUG
        Serial.print("content element "); Serial.print(i); Serial.print(": "); Serial.println(cleanString);
      #endif

      // now populate the vars for the player
      int spacePosition = cleanString.indexOf(':');
      if (cleanString.charAt(spacePosition - 1) == 'A') {
        String contentString = cleanString.substring(3);
        #ifdef DEBUG
          Serial.print("Album info: ");Serial.println(contentString);
        #endif
      }
      if (cleanString.charAt(spacePosition - 1) == 'D') {
        usableContent = true;
        String contentString = cleanString.substring(3);
        plrCurrentFolder = contentString;
        #ifdef DEBUG
          Serial.print("Directory: ");Serial.println(contentString);
        #endif
      }
      if (cleanString.charAt(spacePosition - 1) == 'T') {
        String contentString = cleanString.substring(3);
        plrCurrentFile = contentString;
        #ifdef DEBUG
          Serial.print("Track: ");Serial.println(contentString);
        #endif
      }
      if (cleanString.charAt(spacePosition - 1) == 'P') {
        String contentString = cleanString.substring(3);
        plrCurrentPosition = contentString.toInt();
        #ifdef DEBUG
          Serial.print("Position: ");Serial.println(contentString);
        #endif
      }

      String uid = record.getId();
      if (uid != "") {
        #ifdef DEBUG
          Serial.print("  ID: ");
          Serial.println(uid);
        #endif
      }
    }
    if (!usableContent){
      #ifdef DEBUG
        Serial.println("THIS CARD DOES NOT HAVE THE NECESSARY MESSAGES FOR THE MP3 PLAYER");
      #endif
    }
  } else { // does the card have NDEF messages?
    #ifdef DEBUG
      Serial.println("THIS CARD DOES NOT HAVE MESSAGES AT ALL - NOT USABLE FOR THE MP3 PLAYER");
    #endif
  }
*/
}

//
//        MM      MM   PPPPPP   33333
//        MMMM  MMMM  PP    PP      33
//        MM  MM  MM  PP    PP    3333
//        MM      MM  PPPPPP        33
//        MM      MM  PP        33333
//  BELOW THIS LINE THE MP3 PLAYER CONTROL IS DEFINED
//
uint8_t getVolume(){
  soundVolume = map(sensorValue, 0, 1023, 0, 100); // map the sensor value to a sound volume

  #ifdef DEBUG
    Serial.print("last sensor value (if any) was ");Serial.print(lastSensorValue);Serial.print(" / new sensor value is ");Serial.print(sensorValue);Serial.print(" which is a volume of ");Serial.println(soundVolume);
  #endif
  lastSensorValue = sensorValue;
  return (soundVolume);
}

void plrPlayTrack(char dir, char file) {
  String temp = "/";
  temp.concat(dir);
  temp.concat("/");
  temp.concat(file);
  char myFile[temp.length() + 1];
  temp.toCharArray(myFile, sizeof(myFile));

  // mp3 player functions playback
  // Start playing a file, then we can do stuff while waiting for it to finish
  if (! musicPlayer.startPlayingFile(myFile)) {
    #ifdef DEBUG
      Serial.print("Could not open file ");Serial.println(myFile);
    #endif
    while (1);
  }
  #ifdef DEBUG
    Serial.print(F("Start playing "));Serial.println(myFile);
  #endif

  while (musicPlayer.playingMusic) {
    // file is now playing in the 'background' so now's a good time
    // to do something else like handling LEDs or buttons :)
    #ifdef DEBUG
      Serial.print(".");
    #endif
    #ifdef LIGHTEFFECTS
      //fader();
    #endif

  }
  #ifdef DEBUG
    Serial.println("Done playing ");Serial.println(myFile);
  #endif
}

char plrNext(void){
  char track[12] = "track003.mp3";
  #ifdef DEBUG
    Serial.println("plrNext toggled");
  #endif
  #ifdef LIGHTEFFECTS
    //pulse(bluePin);
  #endif

  return track;
}
char plrPrev(void){
  char track[12] = "track001.mp3";
  #ifdef DEBUG
    Serial.println("plrPrevious toggled");
  #endif
  #ifdef LIGHTEFFECTS
    //pulse(greenPin);
  #endif

  return track;
}

void setupSound(){
  // This option uses a pin interrupt. No timers required! But DREQ
  // must be on an interrupt pin. For Uno/Duemilanove/Diecimilla
  // that's Digital #2 or #3
  // See http://arduino.cc/en/Reference/attachInterrupt for other pins
  // *** This method is preferred
  if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) {
    #ifdef DEBUG
      Serial.println(F("DREQ pin is not an interrupt pin"));
    #endif
    while (1);
  }

  // Start playing a file, then we can do stuff while waiting for it to finish
  if (! musicPlayer.startPlayingFile("hello.mp3")) {
    #ifdef DEBUG
      Serial.println("Could not open file hello.mp3");
    #endif
  } else {
    #ifdef DEBUG
      Serial.print("playing welcome file hello.mp3 ");
    #endif
  }

  // now we play the welcome sound 
  startUpTime = millis();
  while (musicPlayer.playingMusic) {
    if (millis() - startUpTime > 500) {
      #ifdef DEBUG
        Serial.print(".");
      #endif
      startUpTime = millis();
    }
    // file is now playing in the 'background' so now's a good time
    // to do something else like handling LEDs or buttons :)
    #ifdef LIGHTEFFECTS
      //startuplight();
    #endif
  }
  #ifdef DEBUG
    Serial.println(" done");
  #endif
  getVolume();
  musicPlayer.setVolume(soundVolume,soundVolume);
}

//
//        FFFFFF  II  LL      EEEEEE
//        FF      II  LL      EE
//        FFFF    II  LL      EEEE
//        FF      II  LL      EE
//        FF      II  LLLLLL  EEEEEE
// BELOW THIS LINE THE FILE HELPER FUNCTIONS CAN BE FOUND
//
// counts the number of files in directory
//unsigned int countFiles(char dir[]){

unsigned int countFiles(File dir){
  unsigned int counter = 0;
  while (true){
    File entry = dir.openNextFile();
    if (!entry){
      // no more files
      break;
    }
    counter++;
    entry.close();
  }
  dir.close();
  return counter;
}


// store last played track
void rememberCurrentTrack(){

}

// read last played track
void getLastPlayedTrack(){

}

// File listing helper
void printDirectory(File dir, int numTabs) {
   while(true) {
     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');
     }
     Serial.print(entry.name());
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numTabs+1);
     } else {
       // files have sizes, directories do not
       Serial.print("\t\t");
       Serial.println(entry.size(), DEC);
     }
     entry.close();
   }
}


//
//        LL      EEEEEE  DDDDDD
//        LL      EE      DD    DD
//        LL      EEEE    DD    DD
//        LL      EE      DD    DD
//        LLLLLL  EEEEEE  DDDDDD
//  BELOW THIS LINE THE LIGHT EFFECTS ARE DEFINED
//
// fading organically
void fader(){
  time = millis();
  lightValue1 = 128+127*cos(2*PI/periode*time);
  lightValue2 = 128+127*cos(2*PI/periode*(displace-time));
  lightValue3 = 128+127*cos(2*PI/periode*(2*displace-time));
  analogWrite(redPin, lightValue1);           // sets the value (range from 0 to 255) 
  analogWrite(greenPin, lightValue2);        // sets the value (range from 0 to 255) 
  analogWrite(bluePin, lightValue3);         // sets the value (range from 0 to 255) 
}
// illuminate the 3 led with some fancy lightning during startup
void startuplight(){
  for (int i = 0; i<150; i++) {
    analogWrite(redPin, i);
    analogWrite(greenPin, i);
    analogWrite(bluePin, i);
    delay(10);
  }
  for (int i = 150; i>0; i--) {
    analogWrite(redPin, i);
    analogWrite(greenPin, i);
    analogWrite(bluePin, i);
    delay(10);
  }
  analogWrite(redPin, 0);
  analogWrite(greenPin, 0);
  analogWrite(bluePin, 0);
}
//turn on the desired pin for 5000 milliseconds
void highlight(int pin){
  time = millis();
  while (millis()<time+5000){
    analogWrite(pin, 255);
  }
  analogWrite(pin, 0);
}
//turn on the desired pin for 5000 milliseconds
void flash(int pin){
  time = millis();
  while (millis()<time+1000){
    analogWrite(pin, 255);
  }
  analogWrite(pin, 0);
}
//turn on the desired pin for 5000 milliseconds
void pulse(int pin){
  for (int i=0;i<3;i++){
    time = millis();
    while (millis()<time+2500){
      analogWrite(pin, 255);
    }
    analogWrite(pin, 0);
  }
}
  • 1
    You need to open the file then pass that file. Or have your function accept a char array and do the file opening itself. Either way, at some point, you will need to open the file. – Majenko Dec 28 '17 at 10:26
  • Actually that function does not open a file at all. It simply counts the number of files in a directory. But you have a point nonetheless. Maybe best would be to restructure the function and find a way to count files in a directory without the need to pass a File descriptor to the function. Would you have, by any chance an idea on how to count files in a directory where the directory name is past as a char array??? – siliconchris Dec 28 '17 at 10:38
  • 1
    As far as filesystems are concerned (in general) a directory is just another file. You just use special functions to read the contents of it. To do any operation on a directory you need to open it. Like a file. – Majenko Dec 28 '17 at 10:51
  • Thank you so very much. As posted below, I was really blindfolded here. Thanks for your help – siliconchris Dec 28 '17 at 10:54
1

OMG. I'm so sorry for posting such a stupid question. And I'm also sorry for not seeing the obvious even after Majenko pointed me to it.

Of course I need to call the function like this:

numberOfFiles = countFiles(SD.open(plrCurrentFolder));

That way, the directory get's opened and my function can operate on it.

I see I still have to learn a lot :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.