Save and load text file onto/from SD card

It doesn’t work. At all. It just sits there and does nothing. I know it’s not my code to interpret the array because it works in RAM, and I know it’s not the saving because I put a test.txt file on there with just 1s so that way the robot would move forward with all its motors. It just doesn’t work. I don’t know how you have it working in your code because it quite literally does nothing in mine

So it seems like you have the issue narrowed down to loading the file. To start debugging, try just printing the values that it reads to the brain screen.

Ha that’s funny, because I can’t convert it into an integer. Which is what I thought the whole point of the code was, but whatever. It doesn’t come up with any errors in the editor, but when I build it it says that I can’t convert the string into an integer.

Why do you need it as an integer? Is that what the code that interprets your array requires?

I need it because I’m using integers to say what direction the motors should move. So yes I need them.

Adding onto the previous code, this is the simplest solution I can think of

#include "vex.h"
#include <fstream>

int main() {
  std::ifstream Auton("test.txt");

  std::string doot((std::istreambuf_iterator<char>(Auton)), std::istreambuf_iterator<char>());

  int size = doot.length() + 1;

  char shadow_auton[size];
  strcpy(shadow_auton, doot.c_str());

  int intArray[doot.length() + 1];

  for (int i=0; i < size; i++)
    intArray[i] = shadow_auton[i] - '0';
}
3 Likes

Assigning to char from incompatible type int*. Do you see the living hell I’ve been in since Thursday? :slight_smile:

Good grief, just send me the project.

10 Likes

this code has gotten to the point where i am unable to say i wrote a lot of it, though it crossed that line a while ago. definitely will not understate you and xTigr’s importance in this project (as your code did help me make the code that saved it to RAM, and xTigr’s just been trying his hardest here)

i hope you know im not just trying to offshore my work to you guys. i just genuinely have no idea how to do this, and all of the things on the internet about saving and loading files do it to the vex brains RAM. then savefile() and loadfile() just make the things saved unreadable, though i can maybe find a way around that if this method doesnt save to the SD card or just cant work (for whatever reason)

I believe you need to replace this line

shadow_autonLoaded[i] = shadow_auton[i] - '0';

with

shadow_autonSingleArray[i] = shadow_autonLoaded[i] - '0';

You were trying to load the int into a char instead of the other way around.

2 Likes

yes that makes it error free. ill get to writing a thing to change it from a single array to a 2d array, then test it out and tell you what happens. i hope to god it works.

doesnt work, but it could just be my array code. ill test something new.

edit: nope, this is the error in the terminal:

terminate called after throwing an instance of ‘std::bad_alloc’
what(): std::bad_alloc
terminate called after throwing an instance of ‘std::bad_alloc’
what(): std::bad_alloc

im gonna try out another debugging thing tho

edit again: yeah it isnt what i thought it was.

Hm, ok, sorry I asked that. There are way too many false starts in that code for me to get into it tonight, it’s hard to see what the latest is with 1500 lines of code, however, I think it’s worth your while to take a step back and try to understand what you code is actually trying to do.

It’s basic rerun code where you are recording the controller values (and perhaps some others). You record everything into a big array during driver, and then play back the contents of the array during autonomous, so far so good. The piece you are struggling with is saving/loading. You can go the C++ std::ostream way if you want, but it’s really overkill, all you need to do is have functionality that saves and loads that big RAM array to the SD card.

Have a look at this demo, see what I’m doing, it’s a very simple 4 motor rerun (no clever stuff here at all).

We record into an array (RAM) during driver, only 15 seconds of data is recorded. Then it saves to SD card. When auton triggers, the data is loaded from SD card and used as playback, essentially what you are trying to do.

code
/*----------------------------------------------------------------------------*/
/*                                                                            */
/*    Module:       main.cpp                                                  */
/*    Author:       james                                                     */
/*    Created:      Mon Feb 21 2022                                           */
/*    Description:  V5 project                                                */
/*                                                                            */
/*----------------------------------------------------------------------------*/
#include "vex.h"

using namespace vex;

// A global instance of vex::brain used for printing to the V5 brain screen
vex::brain       Brain;
// A global instance of vex::competition
vex::competition Competition;

vex::controller  Controller1;

vex::motor       m1(PORT1);
vex::motor       m2(PORT2);
vex::motor       m3(PORT3);
vex::motor       m4(PORT5);

#define         LOOP_DELAY    20          // 20mS delay in each rec/play loop
#define         MAX_SAMPLES  ((1000/LOOP_DELAY) * 15)

// storage for the rerun data
int8_t          auton_data[4][MAX_SAMPLES];  // 15 seconds at 50Hz, 4 axis

void autonomous( void ) {
    // Load from SD card
    int nRead = Brain.SDcard.loadfile( "auton.dat", (uint8_t *)auton_data, sizeof(auton_data));

    if( nRead == sizeof(auton_data) ) {
      // we are good

      for(int index =0;index<MAX_SAMPLES;index++ ){
        Brain.Screen.printAt(10, 60, "Play... %d", index );
    
        int8_t a1 = auton_data[0][index];
        int8_t a2 = auton_data[1][index];
        int8_t a3 = auton_data[2][index];
        int8_t a4 = auton_data[3][index];

        m1.spin(forward, a1, rpm );
        m2.spin(forward, a2, rpm );
        m3.spin(forward, a3, rpm );
        m4.spin(forward, a4, rpm );

        // same delay as before
        vex::task::sleep(LOOP_DELAY); 
      }
    }

    // we are finished
    m1.stop();
    m2.stop();
    m3.stop();
    m4.stop();
}

void usercontrol( void ) {
  int index = 0;

  // User control code here, inside the loop
  while (1) {
    Brain.Screen.printAt(10, 20, "Recording... %d", index );
    int8_t  a1 = Controller1.Axis1.value();
    int8_t  a2 = Controller1.Axis2.value();
    int8_t  a3 = Controller1.Axis3.value();
    int8_t  a4 = Controller1.Axis4.value();

    m1.spin(forward, a1, rpm );
    m2.spin(forward, a2, rpm );
    m3.spin(forward, a3, rpm );
    m4.spin(forward, a4, rpm );

    if( index < MAX_SAMPLES ) {
      auton_data[0][index] = a1;
      auton_data[1][index] = a2;
      auton_data[2][index] = a3;
      auton_data[3][index] = a4;
      index++;
    }
    else {
      // we are finished
      m1.stop();
      m2.stop();
      m3.stop();
      m4.stop();
      // save to SD card
      // this should probably be on a button
      Brain.SDcard.savefile( "auton.dat", (uint8_t *)auton_data, sizeof(auton_data));
      Brain.Screen.printAt(10, 40, "Done..." );
      return;
    }

    vex::task::sleep(LOOP_DELAY); 
  }
}

//
// Main will set up the competition functions and callbacks.
//
int main() {
    //Set up callbacks for autonomous and driver control periods.
    Competition.autonomous( autonomous );
    Competition.drivercontrol( usercontrol );
    
    //Prevent main from exiting with an infinite loop.                        
    while(1) {
      vex::task::sleep(100);//Sleep the task for a short amount of time to prevent wasted resources.
    }           
}

I’ll try and decipher your program tomorrow, too late today.

5 Likes

It seems to work. I’m going to do much more testing though, as I have said “it works” six times already lol. The problem was DEFINITELY the data type being int and not int8_t. Thank you for your aid, both of you. I’ll let you guys know if it actually works or it’s still broken

It saves and loads. I even fixed a bug with the drive train (im dumb so I did a static cast twice in the code making the drive train go less forward). Thank you for your help. With the loading of the SD card in hand, we may now be able to be #1 in my region, and (if the ranks don’t change and you can qualify off top 35 world skills still) automatically qualify for world.