Arduino SD Bash Terminal!

For one of my current projects, I'm doing datalogging on an SD card, but because of how everything is mounted, I don't have physical access to the card. This means I can't just pop it into my PC when I have to access the data, delete files, etc.

To get around this problem, I've developed a terminal style interface that allows you to execute certain file management functions on your SD card through a serial interface (such as the Serial Montior or Putty).

The interface is a library can can be found here. It will soon be listed in the Arduino IDE's Libraries Manager under "SdTerminal.h".

Here are the supported functions:

  • ">" - Create file if it doesn't already exist.
  • ap - Append a line to an existing file.
  • cd - Change present working directory.
  • cp - Copy a file to another location.
  • echo - Turn on or off echoing user commands.
  • help - Provide info on commands. Can specify a specific command for help.
  • ls - List the contents of the card. Can specify a specific dir for listing.
  • mkdir - Make a new directory at a specific location.
  • mv - Move or rename a file.
  • print - Print the contents of the given file.
  • pwd - Print the present working directory.
  • rm - Remove a file or dir.

As of release 0.2.1, all of the commands work except for "cp", which will do deep copies for directories. That I will tackle soon... [Edit: Fixed as of release 1.0.0]

I'm not very experienced with interfacing with SD cards so if anyone notices any bugs or notices a better way to implement one of the lib's features, please let me know! Also, if there is a feature you would like to see, please post those requests either here in this thread, or as an issue in the repo.

1 Like

Here is an example Serial Monitor printout while using the lib:

help

For more information on a specific command, type help command-name

  • Create file if it doesn't already exist.
    ap - Append a line to an existing file.
    cd - Change present working directory.
    cp - Copy a file to another location.
    echo - Turn on or off echoing user commands.
    help - Provide info on commands. Can specify a specific command for help.
    ls - List the contents of the card. Can specify a specific dir for listing.
    mkdir - Make a new directory at a specific location.
    mv - Move or rename a file.
    print - Print the contents of the given file.
    pwd - Print the present working directory.
    rm - Remove a file or dir

help mv

mv src dest - Move file src to location dest.

echo off

Echo turned off


mv src dest - Move file src to location dest.


Echo turned on

ls

85759 flight_1.txt
107223 flight_2.txt

mkdir mp3/stuff

mp3/stuff
created

ls

85759 flight_1.txt
144200 flight_2.txt
0 mp3/
0 stuff/

mv flight_1.txt mp3/flight_1.txt

flight_1.txt moved to mp3/flight_1.txt

ls

215575 flight_2.txt
0 mp3/
0 stuff/
85759 flight_1.txt

rm mp3

Deleted: mp3/flight_1.txt
Deleted: mp3

ls

268419 flight_2.txt

print flight_2.txt

flight_2.txt found:
epoch_ms,alt_cm,roll_deg,pitch_deg,velocity_m/s,lat_dd,lon_dd,year,month,day,hour,min,sec,sog,cog,throttle_command,pitch_command,yaw_command,roll_command
37946,7.00,0.075818,-4.043278,13444.000000,0,0,2020,5,1,3,53,12.80,0.03,270.29,50,1493,1500,1508
37995,7.00,0.075818,-4.043278,11652.000000,0,0,2020,5,1,3,53,12.90,0.02,270.29,50,1493,1500,1508
38046,7.00,0.075818,-4.043278,12741.000000,0,0,2020,5,1,3,53,12.90,0.02,270.29,50,1493,1500,1508
38095,7.00,0.075818,-4.043278,9926.000000,0,0,2020,5,1,3,53,13.00,0.05,270.29,50,1493,1500,1508
38145,7.00,0.075818,-4.043278,12465.000000,0,0,2020,5,1,3,53,13.00,0.05,270.29,50,1493,1500,1508
38196,7.00,0.075818,-4.043278,5792.000000,0,0,2020,5,1,3,53,13.10,0.05,270.29,50,1493,1500,1508
38245,7.00,0.075818,-4.043278,12068.000000,0,0,2020,5,1,3,53,13.10,0.05,270.29,50,1493,1500,1508
38296,7.00,0.075818,-4.043278,12655.000000,0,0,2020,5,1,3,53,13.20,0.01,270.29,50,1493,1500,1508
38345,7.00,0.075818,-4.043278,11014.000000,0,0,2020,5,1,3,53,13.20,0.01,270.29,50,1493,1500,1508

And here is the source code used:

#include "SdTerminal.h"


Terminal myTerminal;


void setup()
{
  Serial.begin(115200);
  while (!myTerminal.begin());
}


void loop()
{
  myTerminal.handleCmds();
}

You know, we should colaborate..

My last handheld screen. Called sTerm..

And how do you move or rename a file? When I tried awhile ago it wasn't supported.

-jim lee

@jimLee

Is that the contents of a file on the device's SD card? Either way, it looks super cool!

jimLee:
And how do you move or rename a file? When I tried awhile ago it wasn't supported.

Moving and renaming files are actually pretty simple. The "File" class has a built-in member "rename()" that can be used for (deep) moving and renaming.

More specifically, here is the function I have for moving/renaming:

void Terminal::handle_MV(char input[])
{
	char* arg1 = findSubStr(input, 1);
	char* arg2 = findSubStr(input, 2);

	if (sd.exists(arg1) && !sd.exists(arg2))
	{
		File file = sd.open(arg1);

		file.rename(arg2);

		if (sd.exists(arg2))
		{
			_serial->print(arg1);
			_serial->print(F(" moved to "));
			_serial->println(arg2);
		}
		else
		{
			_serial->print(F("Failed to move "));
			_serial->print(arg1);
			_serial->print(F(" to "));
			_serial->println(arg2);
		}
	}
	else
	{
		if (!sd.exists(arg1))
		{
			_serial->print(arg2);
			_serial->println(F(" does not exists"));
		}
		
		if (sd.exists(arg2))
		{
			_serial->print(arg2);
			_serial->println(F(" already exists"));
		}
	}

	// garbage collection
	free(arg1);
	free(arg2);
}

Copying/deep copying, on the other hand was a real pain in the... :slight_smile:

Its not the SD drive, but a parameter list from one of my plant watering devices. The window you see is basically a serial text terminal. The plant watering gizmo has a command processor that I can talk to. It also has an SD drive and I can grab a listing from that. And transfer files from there to the SD card in my handheld, but the file transfer is bloody slow.

I just figured if you needed something to use as a handheld for your project, you could use this.

-jim lee

As of release 1.1.0, you can now traverse the folders of the SD card by changing/printing the present working directory using the commands "cd" and "pwd" (respectively).

Also, the use of "cd .." is supported.

So, Ive been looking at your terminal code. Could I suggest separating the mechanics of connecting to the SD drive out of it? For example most of the projects I work on has a bunch of stuff on SPI or I2C busses and all that is taken care of elsewhere. Displays, mp3 players, grabbing icon image files, messing about with database files. Having yours want to get its fingers into the innards makes it extremely tough to incorporate.

Just a thought.

-jim lee

I might be able to have the lib accept the "sd" class (although there are multiple possible class types) in either the constructor or begin() method. That's honestly a really good idea.

I'll poke around and see what I can do.

And that's why you have rename for files and my stuff never has. You use SDFat and I've just been using plain vanilla SD.

Would you like a general purpose parser class to simplify your command line?

-jim lee

jimLee:
And that's why you have rename for files and my stuff never has. You use SDFat and I've just been using plain vanilla SD.

Ah, interesting. Why don't you use SDFat?

jimLee:
Would you like a general purpose parser class to simplify your command line?

Yeah, that would be cool to take a look at.

As of release 1.2.0, you must pass a reference to an SD file class in “.begin()” instance as requested by JimLee.

Ok, If you'd like to try the parser, I set up a test/demo program you can play with. Its in with the parser code.

You will need to grab two folders from my library files..

Github library

LC_baseTools - Stuff everything I write needs to work.

LC_Parser. - The parser library.

Enjoy, Let me know if you try it out and what you think.

-jim lee

SdTerminal.h is now compatible with SdFat.h v2 as of release 2.0.0