Проблема с повторным пересчетом количества строк. Библиотека SD

AlMaster
Offline
Зарегистрирован: 12.03.2014

Здравствуйте! Очень прошу о помощи, проблема с повторным запуском функции при работе с SD картой. Уже совсем замучался, а сроки диплома поджимают..

Имеется код:

#include <SPI.h
#include <SD.h>
String def_filename = "FILE"; //стандартное начало имени файла
String filename = "";
int slots_count = 20; //Количество файлов
int filesrows[20]; //массив со значениями количества строк в каждом файле
File workFile;

void setup() {
	if (!SD.begin(10)) {
		Serial.println("initialization failed!");
		return;
	}

upd_filesrows();
}

void upd_filesrows() {
	for(int i = 1 ; i <= slots_count; i +=1) { //проверяем все файлы (от 1 до 20)
		filename = def_filename + i; //составляем имя файла: FILE+i
		char temp[filename.length()+1];
		filename.toCharArray(temp, sizeof(temp)); //преобразуем в charArray
		if (!SD.exists(temp)) { //проверяем, если такого файла на карте нет,
			workFile = SD.open(temp, FILE_WRITE); //то создаем пустой файл
			workFile.close(); //закрываем файл
			filesrows[i-1] = 0; //записываем для него количество строк = 0
		} else {
			workFile = SD.open(temp); //если файл есть, то открываем
			counter = 0; //обнуляем счетчик
			while (workFile.available()) { //читаем все символы из файла до конца
				char sd_t = workFile.read();
				if (sd_t == '\n') counter++; //и увеличиваем счетчик, если символ - перенос строки
			}
			workFile.close(); //закрываем файл
			filesrows[i-1] = counter; //записываем в массив количество строк в файле
		}
		filename = "";
	}
}

И вроде как все работает, при инициализации недостающие файлы создаются, а у существующих пересчитываются строки и числа заносятся в массив. Проблема в том, что если в коде вызвать эту же функцию второй раз, все значения в массиве filesrows стабильно обнуляются. Причем не важно, что делали до этого. Можно просто вызвать функцию дважды и все элементы массива будут равны 0.

Почему это происходит и как это возможно исправить? Неужели проблема в библиотеке SD? До этого я столкнулся с проблемой чтения имен файлов, потому ввел фиксированные имена.

nick_shl
Offline
Зарегистрирован: 25.03.2014

Возможно траблы в указателе и пройдясь один раз по файлу он остается в конце. Попробуйте после открытия его перемещать вначало. Например сразу после "workFile = SD.open(temp); //если файл есть, то открываем" вызвать rewind();

gregoryl
Offline
Зарегистрирован: 09.09.2013

Хм... ошибок я не вижу, и вроде как должно все работать....

Поствте много разных  Serial.println и посмотрите в чем конкретно проблема, код вроде совсем не сложный

AlMaster
Offline
Зарегистрирован: 12.03.2014

Спасибо за ответы!

А что за функция такая rewind такая? В библиотеке SD её нет, да и не гуглиться. Есть rewindDirectory(), но это для папок.. 

Да, код максимально прост - должен работать и работает. Но только 1 раз. А в проекте я хочу после изменений в файле запустить эту функцию второй раз, чтобы она пересчитала все опять.

Пробовал уже ставить для диагностики вывод, так и не понял то ли он файлы не находит (но тогда он должен был их стирать при открытии?) или строк не находит..

nick_shl
Offline
Зарегистрирован: 25.03.2014

А, ну да... стандартная библиотека это враппер над библиотекой :)

rewind() есть у SdFile, но он приватный у File.

Впрочем это не важно. После "workFile = SD.open(temp); //если файл есть, то открываем" добавьте строчку "workFile.seek(0);" и посмотрите что будет.

AlMaster
Offline
Зарегистрирован: 12.03.2014

--УДАЛЕНО. Простите, писал с работы, а тут фаервол иногда дублирует запросы и сообщение дважды отправляется..

AlMaster
Offline
Зарегистрирован: 12.03.2014

Нет, workFile.seek(0) не помогла. Вызываю в setup() upd_filesrows(); два раза (на всякий случай через паузу). После первого в массиве есть значения (правильные количества строк), после второго уже только 0.

Может стринг какой то не обнуляется или еще чего не связанного с SD? Вообще по умолчанию файл открывается для чтения, а это подразумевает открытие файла с самого начала (запись с конца). По этому он после закрытия вроде как должен закрываться и все, в следующий раз с самого начала опять считать..

Кстати, вообще реально отказаться от стринга в моем случае? К примеру сделать имена файлов просто 1,2,3..20?

leshak
Offline
Зарегистрирован: 29.09.2011

>ообще реально отказаться от стринга в моем случае?

Смотря от какого. От String (объет) - возможно, а от string (массив чаров, сишная строка) - не выйдет.


char fileName[]="file**.txt";
//               0123456789    - позиции символов            

#define FIRST_DIGIT_POS 4 // позиция первой звездочки
#define SECOND_DIGIT_POS (FIRST_DIGIT_POS+1) // позиция второй звездочки

void setup(){
  Serial.begin(57600);
  
  for(byte i=0;i<20;i++){

    buildFileName(i+1); // формируем имя файла
    
    //выводим что получилось.
    Serial.println(fileName);
  }
}

// заменяет ** на fileNo в массиве fileName[]
void buildFileName(byte fileNo){
    // "разбиваем" число на первую и вторую цифры
    byte firstDigit=fileNo/10;
    byte secondDigit=fileNo %10;
    
    // заменяем звездочки
    fileName[FIRST_DIGIT_POS]=firstDigit+'0';// заменяем первую зведочку, и сразу переводим цифру в ее ASCII код
    fileName[SECOND_DIGIT_POS]=secondDigit+'0'; // то же самое для второй
    
}

void loop(){
}

Вывод:

file01.txt
file02.txt
file03.txt
file04.txt
file05.txt
file06.txt
file07.txt
file08.txt
file09.txt
file10.txt
file11.txt
file12.txt
file13.txt
file14.txt
file15.txt
file16.txt
file17.txt
file18.txt
file19.txt
file20.txt

 

mishgan
Offline
Зарегистрирован: 25.04.2014

Уменя тоже проблемма на подобии 

Есть функция которая сканирует флешку и пишет  в массив.

void scanSD() {
  kolfiles=0;
  memset(recfile, 0, sizeof(recfile));
  File dir=SD.open("/");
  while(true) {
     File entry =  dir.openNextFile();
     if (!entry) {break;}
     if (!entry.isDirectory() && entry.size()>15 && entry.size()<2600 && String(entry.name()).length()<=12) {

     strcpy(recfile[kolfiles], entry.name());
     kolfiles++;
     if (kolfiles>29) { entry.close();break;}
     } 
     entry.close();
   }
   dir.rewindDirectory();
 }

Я добавляю и удаляю файлы с флешки и после этого вызываю эту функцию. Но первый раз функция отрабатывает отлично, а в дальнейшем 1 файл кудато пропадает. Подскажите что я делаю не так.