Dear all,
I am trying to write an App that allows me to download data logged on an SD-card via the microcontroller, in my case, a Mega (selfmade clone with a FT321 for serial comm, passed all tests I made, propably works fine). Arduino IDE i 1.8.5, app will be a windows form in c#, written in Visual Studio 2013. Since I never progammed in c#, I just picked together what I needed on youtube and tutorials; still lots to be done.
In data transfer mode, the sketch uses first a file.openNext routine to count the files available, and then I want to use it again to go through the root directory file by file, first sending the filename to the host computer, then sending the content of the file with a modification of the getline example. Finally, I rename the file so that it ends up in an “old”-folder:
#include <BlockDriver.h>
#include <MinimumSerial.h>
#include <SdFat.h>
#include <SdFatConfig.h>
#include <SysCall.h>
// SD chip select pin
const uint8_t chipSelect = SS;
// file system object
SdFat sd;
SdFile file;
char Dateiname[13];
char NewFileName[17];
unsigned int nameLen;
// create a serial stream
ArduinoOutStream cout(Serial);
int cmd;
const int data_line_length = 256;
char data_line[data_line_length];
unsigned int file_count = 0;
//------------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
}
//------------------------------------------------------------------------------
void loop() {
while (!Serial.available()) {} // wait for Leonardo
cmd = Serial.read();
if (cmd == 99) //c for count
{
// open next file in root. The volume working directory, vwd, is root
while (file.openNext(sd.vwd(), O_READ))
{
if (file.isFile())
{
file_count++;
Serial.print("+");
}
file.close();
}
Serial.println(file_count);
file_count = 0;
sd.vwd()->rewind();
}
else if (cmd == 110) //n for name
{
Serial.println("n received");
do {
file.openNext(sd.vwd(), O_READ);
Serial.println("do loop");
} while (!file.isFile());
file.getName(Dateiname, &nameLen);
Serial.println(Dateiname);
}
else if (cmd == 115) //s for send
{
send_all_lines();
MakeNewFilename(NewFileName);
file.rename(sd.vwd(), NewFileName); //do the rename, or rather not
file.close();
}
}
void send_all_lines() {
const int data_line_length = 256;
char data_line[data_line_length];
ifstream sdin(Dateiname);
while (sdin.getline(data_line, data_line_length, '\n') || sdin.gcount()) {
int count = sdin.gcount();
if (sdin.fail()) {
cout << "Partial long line";
sdin.clear(sdin.rdstate() & ~ios_base::failbit);
} else if (sdin.eof()) {
cout << "Partial final line"; // sdin.fail() is false
} else {
count--; // Don’t include newline in count
}
//cout << " (" << count << " chars): " << data_line << endl;
cout << data_line << endl;
}
}
void MakeNewFilename(char *NewFileName)
{
NewFileName[0] = 'o';
NewFileName[1] = 'l';
NewFileName[2] = 'd';
NewFileName[3] = '/';
NewFileName[4] = Dateiname[0];
NewFileName[5] = Dateiname[1];
NewFileName[6] = Dateiname[2];
NewFileName[7] = Dateiname[3];
NewFileName[8] = Dateiname[4];
NewFileName[9] = Dateiname[5];
NewFileName[10] = Dateiname[6];
NewFileName[11] = Dateiname[7];
NewFileName[12] = Dateiname[8];
NewFileName[13] = Dateiname[9];
NewFileName[14] = Dateiname[10];
NewFileName[15] = Dateiname[11];
NewFileName[16] = Dateiname[12];
return;
}
But it doesn’t work. On a hunch, I took the original openNext example and modified it like this:
/*
Print size, modify date/time, and name for all files in root.
*/
#include <SdFat.h>
// SD chip select pin
const uint8_t chipSelect = SS;
// file system object
SdFat sd;
SdFile file;
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
while (!Serial) {} // wait for Leonardo
delay(1000);
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
// breadboards. use SPI_FULL_SPEED for better performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
// open next file in root. The volume working directory, vwd, is root
while (file.openNext(sd.vwd(), O_READ)) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printModifyDateTime(&Serial);
Serial.write(' ');
file.printName(&Serial);
if (file.isDir()) {
// Indicate a directory.
Serial.write('/');
}
Serial.println();
file.close();
}
Serial.println("Done!");
}
//------------------------------------------------------------------------------
void loop() {
// open next file in root. The volume working directory, vwd, is root
while (file.openNext(sd.vwd(), O_READ)) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printModifyDateTime(&Serial);
Serial.write(' ');
file.printName(&Serial);
if (file.isDir()) {
// Indicate a directory.
Serial.write('/');
}
Serial.println();
file.close();
}
Serial.println("Done!");
delay(5000);
}
That gives me one correct report of the contents of the SD-card, an immediate second “Done!”, and the another “Done!” every five seconds.
Is there a way to reset the openNext function? I want to count files first in order to make my app go through a loop the right amount of times, downloading one file at a time. But maybe that is not even the best way.
Thanks for any hints.
CHeers
Sebastian