使用arduino从SD卡存储文件的最后一个值
Storing the last value of a file from SD card using arduino
我正在做一个前后移动的设备,需要存储它的最后一个位置,以便在通电时,可以从 SD 卡上文件的最后一行中抓取最后存储的值,并且可以恢复运行。然后该文件将被销毁并重写。对于这个特定的应用程序,不能使用归位和其他方法,因为它必须从上次所在的位置开始。由于通过编码器进行位置跟踪,因此没有位置记忆 otherwise.The 文件设置为由逗号分隔的单个数据列。
目前,随着位置的变化,我正在成功地写入 SD 卡,并读取要在串行监视器上打印的整个文件。但是,我真的只需要最后一个值。文件的长度总是因系统操作而异。
我已经阅读了很多不同的解决方案,但其中 none 似乎适用于我的应用程序。
我可以使用以下方法读取整个文件:
void read_file() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
Serial.println("test8.txt:");
// read from the file until there's nothing else in it:
// read from the file until there's nothing else in it:
while (myFile.available()) {
String a = "";
for (int i = 0; i < 9; ++i)
{
int j;
char temp = myFile.read();
if (temp != ',' && temp != '\r')
{ //a=temp;
a += temp;
}
else if (temp == ',' || temp == '\r') {
j = a.toInt();
// Serial.println(a);
Serial.println(j);
break;
}
}
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test8.txt");
}
}
这给了我一个由 0 分隔的值流,如下所示:
20050
0
20071
0
20092
0
20113
0
20133
0
理想情况下,我只需要抓取 20133 并将其存储为一个整数。
我也试过:
void read_file_3() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
Serial.println("test8.txt:");
// read from the file until there's nothing else in it:
Serial.println(myFile.seek(myFile.size()));
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
这只是returns“1”,对我来说没有任何意义。
更新:
我找到了一个可以满足我要求的草图,但是由于使用了字符串 class,所以速度很慢。根据 post #6 这里:https://forum.arduino.cc/index.php?topic=379209.0
这确实会获取最后存储的值,但是随着文件变大需要相当长的时间,并且可能会耗尽内存。
没有字符串 class 怎么能做到这一点?
void read_file() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
while (myFile.available())
{
String line_str = myFile.readStringUntil(','); // string lavue reading from the stream - from , to , (coma to comma)
int line = line_str.toInt();
if (line != 0) // checking for the last NON-Zero value
{
line2 = line; // this really does the trick
}
// Serial.print(line2);
// delay(100);
}
Serial.print("Last line = ");
Serial.print(line2);
// close the file:
myFile.close();
// SD.remove("test3.txt");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
如有任何帮助,我们将不胜感激!
seek returns 如果它成功到达该位置则为真,如果在那里没有找到任何东西则为假,例如文件不是那么大。它不会给你那个位置的价值。这就是为什么你看到 1,seek 返回真,它能够到达位置 (myFile.size()),这就是你正在打印的内容。
除此之外,您不想转到文件末尾,那将在您的号码之后。如果您的号码是 5 位数字,您想转到文件末尾前 5 个字符的位置。
无论哪种方式,一旦您找到了那个位置,您仍然需要像在第一个代码中那样使用 read 来实际读取数字。 seek 不会这样做,它只会将您带到文件中的那个位置。
编辑:由于您编辑了 post,我将编辑答案以供参考。你在倒退。你第一次做对了。使用与开始时相同的读取方法,只需在开始读取之前查找文件末尾,这样就不必一直读取。你几乎拥有它。您第一次做错的唯一一件事是打印从查找中返回的内容,而不是查找正确的位置然后读取文件。
您使用字符串 class 查找的内容正在从您所在的位置倒退。忘记你曾经见过。它正在做你一开始就已经在做的同样的事情,只是它还在这个过程中浪费了大量的内存和代码space。
使用您的原始代码,只需添加一个跳转到文件末尾的搜索。
这假定它始终是一个 5 位数字。如果不是,那么您可能需要进行一些调整:
void read_file() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
Serial.println("test8.txt:");
/// ADDED THIS ONE LINE TO SKIP MOST OF THE FILE************
myFile.seek(myFile.size() - 5);
// read from the file until there's nothing else in it:
// read from the file until there's nothing else in it:
while (myFile.available()) {
String a = "";
for (int i = 0; i < 9; ++i)
{
int j;
char temp = myFile.read();
if (temp != ',' && temp != '\r')
{ //a=temp;
a += temp;
}
else if (temp == ',' || temp == '\r') {
j = a.toInt();
// Serial.println(a);
Serial.println(j);
break;
}
}
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test8.txt");
}
}
看,我所做的就是采用您的原始函数并添加一行以结束它。
我正在做一个前后移动的设备,需要存储它的最后一个位置,以便在通电时,可以从 SD 卡上文件的最后一行中抓取最后存储的值,并且可以恢复运行。然后该文件将被销毁并重写。对于这个特定的应用程序,不能使用归位和其他方法,因为它必须从上次所在的位置开始。由于通过编码器进行位置跟踪,因此没有位置记忆 otherwise.The 文件设置为由逗号分隔的单个数据列。
目前,随着位置的变化,我正在成功地写入 SD 卡,并读取要在串行监视器上打印的整个文件。但是,我真的只需要最后一个值。文件的长度总是因系统操作而异。
我已经阅读了很多不同的解决方案,但其中 none 似乎适用于我的应用程序。
我可以使用以下方法读取整个文件:
void read_file() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
Serial.println("test8.txt:");
// read from the file until there's nothing else in it:
// read from the file until there's nothing else in it:
while (myFile.available()) {
String a = "";
for (int i = 0; i < 9; ++i)
{
int j;
char temp = myFile.read();
if (temp != ',' && temp != '\r')
{ //a=temp;
a += temp;
}
else if (temp == ',' || temp == '\r') {
j = a.toInt();
// Serial.println(a);
Serial.println(j);
break;
}
}
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test8.txt");
}
}
这给了我一个由 0 分隔的值流,如下所示:
20050
0
20071
0
20092
0
20113
0
20133
0
理想情况下,我只需要抓取 20133 并将其存储为一个整数。
我也试过:
void read_file_3() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
Serial.println("test8.txt:");
// read from the file until there's nothing else in it:
Serial.println(myFile.seek(myFile.size()));
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
这只是returns“1”,对我来说没有任何意义。
更新: 我找到了一个可以满足我要求的草图,但是由于使用了字符串 class,所以速度很慢。根据 post #6 这里:https://forum.arduino.cc/index.php?topic=379209.0
这确实会获取最后存储的值,但是随着文件变大需要相当长的时间,并且可能会耗尽内存。
没有字符串 class 怎么能做到这一点?
void read_file() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
while (myFile.available())
{
String line_str = myFile.readStringUntil(','); // string lavue reading from the stream - from , to , (coma to comma)
int line = line_str.toInt();
if (line != 0) // checking for the last NON-Zero value
{
line2 = line; // this really does the trick
}
// Serial.print(line2);
// delay(100);
}
Serial.print("Last line = ");
Serial.print(line2);
// close the file:
myFile.close();
// SD.remove("test3.txt");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
如有任何帮助,我们将不胜感激!
seek returns 如果它成功到达该位置则为真,如果在那里没有找到任何东西则为假,例如文件不是那么大。它不会给你那个位置的价值。这就是为什么你看到 1,seek 返回真,它能够到达位置 (myFile.size()),这就是你正在打印的内容。
除此之外,您不想转到文件末尾,那将在您的号码之后。如果您的号码是 5 位数字,您想转到文件末尾前 5 个字符的位置。
无论哪种方式,一旦您找到了那个位置,您仍然需要像在第一个代码中那样使用 read 来实际读取数字。 seek 不会这样做,它只会将您带到文件中的那个位置。
编辑:由于您编辑了 post,我将编辑答案以供参考。你在倒退。你第一次做对了。使用与开始时相同的读取方法,只需在开始读取之前查找文件末尾,这样就不必一直读取。你几乎拥有它。您第一次做错的唯一一件事是打印从查找中返回的内容,而不是查找正确的位置然后读取文件。
您使用字符串 class 查找的内容正在从您所在的位置倒退。忘记你曾经见过。它正在做你一开始就已经在做的同样的事情,只是它还在这个过程中浪费了大量的内存和代码space。
使用您的原始代码,只需添加一个跳转到文件末尾的搜索。
这假定它始终是一个 5 位数字。如果不是,那么您可能需要进行一些调整:
void read_file() {
// open the file for reading:
myFile = SD.open("test8.txt");
if (myFile) {
Serial.println("test8.txt:");
/// ADDED THIS ONE LINE TO SKIP MOST OF THE FILE************
myFile.seek(myFile.size() - 5);
// read from the file until there's nothing else in it:
// read from the file until there's nothing else in it:
while (myFile.available()) {
String a = "";
for (int i = 0; i < 9; ++i)
{
int j;
char temp = myFile.read();
if (temp != ',' && temp != '\r')
{ //a=temp;
a += temp;
}
else if (temp == ',' || temp == '\r') {
j = a.toInt();
// Serial.println(a);
Serial.println(j);
break;
}
}
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test8.txt");
}
}
看,我所做的就是采用您的原始函数并添加一行以结束它。