Get steppers coordinates from sd card

Hello guys,
Let me explain what I want to do.
I have 5 steppers which are controlled with AccelStepper library.
Actually I have and multidimensional array which contains all the data that I need to operate the stepper.

long stepper0_data_[5][6]{
    {0, 3000, 200, 100, 1500, 2000}, //DELAY
    {600, 600, 700, 500, 600, 300}, //MAXSPEED
    {3000, 600, 3000, 600, 3000, 600}, //ACCELERATION
    {3000, 1500, 1900, 1000, 1500, 0}, //MOVE TO
    {false, true, true, true, true, true} //MOTION COMPLETED
  };

and my sketch to read this

#include "AccelStepper.h" 
#include <SPI.h> 
#include <MCP23S17.h>

MCP mcp(0, 49);

const int stepperAmount = 5;
AccelStepper stepper0(1, 31, 30);
AccelStepper stepper1(1, 29, 28);
AccelStepper stepper2(1, 27, 26);
AccelStepper stepper3(1, 25, 24);
AccelStepper stepper4(1, 23, 22);
AccelStepper* steppers[stepperAmount] ={&stepper0, &stepper1, &stepper2, &stepper3, &stepper4};

long enable_pin_[stepperAmount] = {1, 3, 5, 7, 9};

long stepper0_data_[5][6]{
    {0, 3000, 200, 100, 1500, 2000}, //DELAY
    {600, 600, 700, 500, 600, 300}, //MAXSPEED
    {3000, 600, 3000, 600, 3000, 600}, //ACCELERATION
    {3000, 1500, 1900, 1000, 1500, 0}, //MOVE TO
    {false, true, true, true, true, true} //MOTION COMPLETED
  };


unsigned long previousMillis=0;

void setup() {
   
 mcp.begin();
 mcp.pinMode(1, OUTPUT);  //FOR OTHER STEPPERS I WILL DO AFTER
 mcp.digitalWrite(1, HIGH); //FOR OTHER STEPPERS I WILL DO AFTER
 Serial.begin(9600);
 delay(3000);
}

void loop()
{
  stepper_move();
    stepper0.run(); 
    stepper1.run(); 
    stepper2.run(); 
    stepper3.run(); 
    stepper4.run(); 
}



void stepper_move()
{  
    unsigned long currentMillis = millis();
    
    if (stepper0.distanceToGo() == 0 ){ 
       mcp.digitalWrite(enable_pin_[0], HIGH);
    } else {
       mcp.digitalWrite(enable_pin_[0], LOW);
    }


   for (int coord_id=0; coord_id < 6; coord_id++){

     unsigned long next_coord_id = coord_id + 1;
     
     if ((unsigned long)(currentMillis - previousMillis) >= stepper0_data_[0][coord_id]) {
        if (!stepper0_data_[4][coord_id]){
          stepper0.setMaxSpeed(stepper0_data_[1][coord_id]);
          stepper0.setAcceleration(stepper0_data_[2][coord_id]);
          stepper0.moveTo(stepper0_data_[3][coord_id]);
          if (stepper0.distanceToGo() == 0 ){ 
             stepper0_data_[4][coord_id] = true;
             stepper0_data_[4][next_coord_id] = false;
             previousMillis = currentMillis;
             //Serial.println("Coord ID :");
             //Serial.println(stepper0_data_[3][coord_id]);
          }
        }
     }
   }

}

Also I have SD card module installed.

Now what I want to do is to have on SD card files containing different multidimensional arrays (with different rows and columns)

  • -01.TXT
  • -02.TXT
  • -99.TXT

and I want to have a SETTINGS.TXT which will contain the name of files to get coords ( for example if I want to move the stepper with this coords 01,02,05,08…) and after I have the possibility to activate or deactivate them.

What you can advise?
Is this a good approach?
Thank you!

If you have 5 steppers, one file for each stepper.
Each file has 5 rows with 6 elements separated by commas.

ieee488:
If you have 5 steppers, one file for each stepper.
Each file has 5 rows with 6 elements separated by commas.

5 rows with 6 elements is only an example. It will always be 5 rows but the elements could be different in different files.

berlogi:
Now what I want to do is to have on SD card files containing different multidimensional arrays (with different rows and columns)

Forget about the motors for a while and just write a short program to read the data from a file on the SD Card and use it to populate the array and then print the results on the Serial Monitor.

How do you propose to put the data onto the SD card in the first instance - perhaps with your PC?

...R

Robin2:
Forget about the motors for a while and just write a short program to read the data from a file on the SD Card and use it to populate the array and then print the results on the Serial Monitor.

How do you propose to put the data onto the SD card in the first instance - perhaps with your PC?

…R

Thank you for your answer.

That part is already done for one stepper

#include <SPI.h>
#include <SD.h>
#define CS_PIN 48

#define ROW_DIM 5
long COL_DIM;

File file;

size_t readField(File* file, char* str, size_t size, char* delim) {
  char ch;
  size_t n = 0;
  while ((n + 1) < size && file->read(&ch, 1) == 1) {
    // Delete CR.
    if (ch == '\r') {
      continue;
    }
    str[n++] = ch;
    if (strchr(delim, ch)) {
        break;
    }
  }
  str[n] = '\0';
  return n;
}
//------------------------------------------------------------------------------
#define errorHalt(msg) {Serial.println(F(msg)); while(1);}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Initialize the SD.
  if (!SD.begin(CS_PIN)) {
    errorHalt("begin failed");
  }
  // Create or open the file.
  file = SD.open("TEST.TXT", FILE_WRITE);
  if (!file) {
    errorHalt("open failed");
  }
  // Rewind file so test data is not appended.
  file.seek(0);

  /////////////////////////////////////////////////////////  
  
  File dataFile = SD.open("TEST.TXT");
  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      String stringOne = dataFile.readStringUntil('\n'); 
      //Serial.println(stringOne);
      int stringOneLenght = stringOne.length();
      //Serial.println(stringOneLenght);
      String stringTwo = stringOne;
      stringTwo.replace(",", "");
      //Serial.println(stringTwo);
      int stringTwoLenght = stringTwo.length();
      //Serial.println(stringTwoLenght);
      int COL_NUM = stringOneLenght - stringTwoLenght;
      //Serial.println(COL_NUM);
      COL_DIM = COL_NUM + 1;
      //Serial.println(COL_DIM);
      dataFile.close();
    }
  }
      
  ////////////////////////////////////////////////////////
  

  // Array for data.
  int array[ROW_DIM][COL_DIM];
  int i = 0;        // First array index.
  int j = 0;        // Second array index
  size_t n;         // Length of returned field with delimiter.
  char str[20];     // Must hold longest field with delimiter and zero byte.
  char *ptr;        // Test for valid field.
  char delim = 0;   // Delimiter from previous line. Start with no delimiter.

  // Read the file and store the data.
  while (true) {
    n = readField(&file, str, sizeof(str), ",\n");

    // Read error or at EOF.
    if (n == 0) {
      break;
    }
    // Advance indices based on previous delimiter.
    if (delim == '\n') {
      // previous delimiter was endl so start a new row.
      if (++i >= ROW_DIM) {
        errorHalt("too many lines");
      }
      if (j != (COL_DIM - 1)) {
        errorHalt("missing field");
      }
      j = 0;
    } else if (delim == ',') {
      // previous delimiter was comma so advance column.
      if (++j >= COL_DIM) {
        errorHalt("too many fields");
      }
    }
    array[i][j] = strtol(str, &ptr, 10);
    if (ptr == str) {
      errorHalt("bad number");
    }
    // Skip any blanks after number.
    while (*ptr == ' ') {
      ptr++;
    }
    // Save delimiter.
    delim = *ptr;

    if (delim != ',' && delim != '\n' && delim != 0) {
      errorHalt("extra data in field");
    }
    if (delim == 0 && file.available() != 0) {
      errorHalt("read error or long line");
    }
  }
  // Check that entire array was read.
  if (j != (COL_DIM - 1) || i != (ROW_DIM - 1)) {
    errorHalt("missing data");
  }
  // Print the array.
  for (i = 0; i < ROW_DIM; i++) {
    for (j = 0; j < COL_DIM; j++) {
      if (j) {
        Serial.print(' ');
      }
      Serial.print(array[i][j]);
    }
    Serial.println();
  }
  Serial.println("Done");
  file.close();
}

void loop() {
}

Now I need to multiply the content of my csv for all 5 steppers

That code is making my head spin. Those single-character variable names don't make sense without a lot of study - and I'm lazy.

I won't pretend to be an expert of using SD cards but I think I would read the data one line at a time and then the parse code in Serial Input Basics could decipher it.

I think it would be easiest if each line has all the data for one motor. Then if you have more or fewer motors yo just need to read a different number of lines.

...R