Glediator SD Card, Name of files

Evening!

I have just completed creating a large WS2811 Matrix which is currently hung on my wall displaying cool patterns. I have attached a picture for those interested.

A lot of you might have seen these around but I loved the idea of using pinpong balls as diffusers.

Anyway, lets cut to the question I have. I read the data from an SD card, this data was captured from Glediator and with some messing around and scrating my head a lot got working, even with the bugs. (If some people have been experiencing the bug of the led format youll notice that you can save the raw output from the serial buffer; noticing glediator adds an ‘empty’ byte of data. I simply read and discard this).

Currently all my file names are 1.dat,2.dat,3.dat…n.dat. I can then try and read these right at the start with a simple while loop to find how many data files I have.

I now want to name my animations so i can identfy them at a later stage so i can modify/delete them. In my head this seemed like an easy idea, i read a file and see if its got ‘.dat’ at the end and then use something like ‘left’ with the file name which can be stored in string/character array of somesort.

I have struggled to find a way where i can do this and was wondering if anyone had experience in this area?

Find my current method below.

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

#define NUM_LEDS 286
#define DATA_PIN 12
#define SD_CS 53 //check for mega.
#define IR_recv 2//check for mega.

#define code1

IRrecv irrecv(IR_recv);
decode_results IR_results;

File fxdata;
CRGB leds[NUM_LEDS];


int maxFile = 0;
int dimmingValue = 0; //can be 0-9 (default '0' dim)
int speedValue = 50; //can be anything from 0-100 in 10ms increments
int file;
unsigned long sizeOfFile;

void setup()
{
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS); //se doc for different LED strips
  Serial.begin(115200); //For Debugging
  for (int y = 0 ; y < NUM_LEDS ; y++)
  {
    leds[y] = CRGB::Black; // set all leds to black during setup
  }
  FastLED.show();

  pinMode(SD_CS, OUTPUT); // CS/SS pin as output for SD library to work.
  digitalWrite(SD_CS, HIGH); // workaround for sdcard failed error...

  //pinMode(IR_recv, INPUT);

  if (!SD.begin(SD_CS))
  {
    Serial.println("sdcard initialization failed!");
    return;
  }
  Serial.println("sdcard initialization done.");

  // find maxFile.
  boolean morefiles = true;
  while (morefiles)
  {
    Serial.println("attempting to open file: " + String(maxFile + 1));
    fxdata = SD.open(String(maxFile + 1) + ".dat");
    if (fxdata)
    {
      maxFile = maxFile + 1;
      fxdata.close();
    }
    else if (maxFile == 0)
    {
      //No Files...
      Serial.println("No Files, halting program");
      while (1);
    }
    else
    {
      morefiles = false;
      Serial.println("Failed! No More files");
    }
  }
  Serial.println("Max files: " + String(maxFile));
  Serial.println("Enabling IR Remote");
  irrecv.enableIRIn();
  Serial.println("Enabled IRin");




}
void IR_implement()
{
  if (irrecv.decode(&IR_results))
  {
    Serial.println(IR_results.value);

    //Action result
    switch (IR_results.value)
    {
      case 551534655: //"incresedim":
        if (dimmingValue + 1 > 10)
        {
          dimmingValue = 10;
        }
        else
        {
          dimmingValue = dimmingValue + 1;
        }
        Serial.println("DimmingValue" + String(dimmingValue));
        break;
      case 551502015://"dim decrease":
        if (dimmingValue - 1 < 0)
        {
          dimmingValue = 0;
        }
        else
        {
          dimmingValue = dimmingValue - 1;
        }
        break;
      case 551485695://"speed up":
        if (speedValue - 10 < 0)
        {
          speedValue = 0;
        }
        else
        {
          speedValue = speedValue - 10;
        }
        Serial.println(speedValue);
        break;
      case 551518335://"speed down":
        if (speedValue + 10 > 100)
        {
          speedValue = 100;
        }
        else
        {
          speedValue = speedValue + 10;
          Serial.println(speedValue);
        }
        break;
      case 551510175://"next":
        fxdata.close();//Easy enough
        break;
      case 551542815://Previous
        fxdata.close();
        //Need to skip back two, as file will be incremented in for loop.
        if (file - 2 < 1)
        {
          if (file == 2)
          {
            file = maxFile;
          }
          else if (file == 1)
          {
            if (maxFile == 1)
            {
              file = maxFile; //We might only have 1 file.
            }
            else
            {
              file = maxFile - 1;
            }
          }
        }
        else
        {
          file = file - 2;
        }
        break;
      case 666://"pause":

        break;
    }
    irrecv.resume(); // Receive the next value
  }
}
void loop()
{
  //Variables
  char rubbishBYTES;
  // Decide FileNames etc
  //TryToRUN
  //String dir = sprintf(file,".dat");
  for (file = 1; file < maxFile + 1; file++)
  {
    fxdata = SD.open(String(file) + ".dat"); // read only
    if (fxdata)
    {
      sizeOfFile = fxdata.size();//Used for getting to end of file.
      Serial.println(file);
      Serial.println("File" + String(file) + "opened! Size of file: " + String(sizeOfFile) );
      //fxdata.readBytes((char*)rubbishBYTES,1);
      while (fxdata.available())
      {
        //Read IR Code
        IR_implement();
        fxdata.readBytes((char*)rubbishBYTES, 1); //Glediator stupid byte.
        fxdata.readBytes((char*)leds, NUM_LEDS * 3);
        for (int i = 0; i < NUM_LEDS + 1; i++)
        {

          int redValue = leds[i][1];
          int greenValue = leds[i][2];
          int blueValue = leds[i][3];
          redValue = map(redValue, 0, 255, 0, 250); //255 is hard to scale to reach 0
          greenValue = map(greenValue, 0, 255, 0, 250);
          blueValue = map(blueValue, 0, 255, 0, 250);
          if (redValue - (dimmingValue * 25) < 0)
          {
            redValue = 0;
          }
          else
          {
            redValue = redValue - (dimmingValue * 25);
          }
          if (greenValue - (dimmingValue * 25) < 0)
          {
            greenValue = 0;
          }
          else
          {
            greenValue = greenValue - (dimmingValue * 25);
          }
          if (blueValue - (dimmingValue * 25) < 0)
          {
            blueValue = 0;
          }
          else
          {
            blueValue = blueValue - (dimmingValue * 25);
          }
          leds[i][1] = redValue;
          leds[i][2] = greenValue;
          leds[i][3] = blueValue;
        }
        FastLED.show();
        delay(speedValue); // set the speed of the animation. 20 is appx ~ 500k bauds
      }

      // close the file in order to prevent hanging IO or similar throughout time
      fxdata.close();
    }
  }
}

Picture as promised:

I forgot to mention that an IR controller is used to skip through animations as well as adjust settings etc.

I hope you like, and I hope to see what people can think of for loading the files.

Thank you.

Check out the example on the SD openNextFile() page.

Do the same as in the example, walk through the directory where the files are stored. Then just take the name of each file and check if it has the desired ".dat" extension.

Cool display you've built there and the ping-pong balls are certainly a novelty; wouldn't like to have to clean them though. :wink:
If you happen to already have a online video of it in action, do feel free to post it...