SD - карта создает "лишний" файл?

Итак, возможно, я слишком устал, чтобы увидеть очевидную проблему здесь, но мой сценарий SD-карты вызывает создание "пустого" файла, а затем вторичного файла, который будет правильно создан.

Я пытаюсь хранить журналы данных, и я не хочу перезаписывать старые журналы, я просто хочу "переместить" их в конец очереди. Итак, я начинаю с шести файлов на SD-карте:

DATA.TXT
ДАННЫЕ~1.TXT
ДАННЫЕ~2.TXT
ДАННЫЕ~3.TXT
ДАННЫЕ~4.TXT
ДАННЫЕ~5.TXT

Все пишет в DATA.TXT, и ДАННЫЕ~1.TXT через ДАННЫЕ~5.TXT это "старые" журналы, от самых старых до самых новых. Это означает, что в следующий раз, когда я загружаю Arduino, мне нужно содержимое DATA.TXT для чтения в новый файл под названием DATA~6.TXT, Я хочу старый DATA.TXT для удаления, и я хочу новый DATA.TXT чтобы быть созданным для остальной части программы. Это должно выглядеть так:

DATA.TXT <=== Новый, пустой файл, загрунтованный для регистрации новых данных
ДАННЫЕ~1.TXT
ДАННЫЕ~2.TXT
ДАННЫЕ~3.TXT
ДАННЫЕ~4.TXT
ДАННЫЕ~5.TXT
ДАННЫЕ~6.TXT <=== "Старый" DATA.TXT

На самом деле он создает два файла: вместо ДАННЫХ~6.TXT удерживая содержимое, оно должно быть пустым-и файл называется DATA~7.TXT создается с содержанием "старого" DATA.TXT. После этого он пишет в "новую" DATA.TXT как и должно. Что-то теряется (или добавляется) при сдвиге данных, почему-то выглядит так:

DATA.TXT <=== Новый, пустой файл, загрунтованный для регистрации новых данных
ДАННЫЕ~1.TXT
ДАННЫЕ~2.TXT
ДАННЫЕ~3.TXT
ДАННЫЕ~4.TXT
ДАННЫЕ~5.TXT
ДАННЫЕ~6.TXT
ДАННЫЕ~7.TXT <=== "Старый" DATA.TXT

EDIT: Каждый файл содержит тестовые данные ( например, - file DATA~1.TXT содержит такую строку, как "ДАННЫЕ~1.TXT") Таким образом, я могу отслеживать, какие файлы "перемещаются" и куда они идут. Вот откуда я знаю, где "старый" DATA.TXT файл идет, и откуда я знаю ДАННЫЕ~6.TXT это "пусто." На самом деле это пустой файл, в котором нет данных.

ПРАВКА № 2: Как указано в комментариях ниже, Uno на самом деле не ждет последовательного соединения. Я только что проверил это, и это правда... как бы то ни было: я все еще получаю пустые ДАННЫЕ~6.TXT и DATA.TXT перемещается в ДАННЫЕ~7.TXT без причины.

Теперь, когда вы знаете цель и (вероятно) видите проблему, вот код:

/*
 * Проверяет слот для SD-карты, убеждаясь, что функциональный код не отсутствует.
 * для того, чтобы процесс BIB правильно регистрировал данные.
 *
 */

#include <SPI.h>
#include <SD.h>

String fileName = "DATA.TXT";                       // Объявите имя файла с соглашениями об именовании FAT 8.3
File dataLog;                                       // Хранить наш "открытый" файл в объекте

void setup(){
    Serial.begin( 115200 );
    while( !Serial ){                               // Дождитесь открытия последовательного порта, прежде чем что-либо делать
    }

    Serial.println( "\nInitializing SD card..." );  // Start SD card
    if( !SD.begin( 4 ) ){
        Serial.println( "Инициализация не удалась!" );
        while( 1 );
    }
    Serial.println( "Инициализация выполнена." );

    Serial.println( "\nChecking if we have a unique filename..." );
    if( SD.exists( fileName ) )                     // Дайте нашему журналу данных уникальное имя файла, если текущее имя файла уже существует
        moveFiles();

    dataLog = SD.open( fileName, FILE_WRITE );      // Откройте наш файл для редактирования, если он еще не существует
    Serial.println( "Created save file!" );

    // Write to file the first time
    if( dataLog ){
        Serial.println( "\nWriting int test to file..." );
        dataLog.println( "Testing Sequence1..." );
        dataLog.println( "\tSequence1 complete." );
        Serial.println( "\tFirst test written!" );
        dataLog.close();
        Serial.println( "\tData log closed." );
    }
    else
        Serial.println( "---Error opening data log file!---" );
}

void loop(){
}

// Перемещает последний `DATA.TXT` to `DATA~x.TXT-где " х` - самое большое целое.
// Это делает "самый высокий" пронумерованный файл последним журналом данных, и `DATA.TXT-текущий журнал данных.
// Следует SFN8.3 стандартам именования, с 8 символами для имени файла, 4 символами для расширения и предшествующими
// периоды преобразуются в символы`~`.
// Это оставляет нам только 999 возможных "резервных" журналов данных.
void moveFiles(){
    bool sdCardFull = false;                            // Keep track of if our SD card is "full" or not
    byte num = 1;
    File newFile;

    String existingFile = String( "DATA~" ) + String( num ) + String( ".TXT" );     // Creates a filename of `DATA~num.TXT` to test

    // Проверьте, существует ли это имя файла.  Повторите "num", чтобы избежать перезаписи существующих файлов
    while( SD.exists( existingFile ) ){
        if( num == 999 ){          // If the SD card is full
            sdCardFull = true;
            noMoreRoom( sdCardFull );
        }

        num++;
        existingFile = String( "DATA~" ) + String( num ) + String( ".TXT" );
    }

    dataLog = SD.open( fileName );
    // Создайте новый файл с новым именем
    newFile = SD.open( existingFile, FILE_WRITE );

    // Переместить старый журнал данных в новое имя файла
    while( dataLog.available() )
        newFile.write( dataLog.read() );

    // Close, remove, then re-open the data log
    newFile.close();
    dataLog.close();
    SD.remove( fileName );                          // Deletes the old data log
}

// Мы не можем найти хорошее имя файла для формата SFN8.3, так как все доступные имена файлов были
// израсходовано, поэтому мы остановим работу программы до тех пор, пока SD-карта не будет очищена, прежде чем мы "уничтожим"
// последний файл резервной копии.
void noMoreRoom( bool sdCardFull ){
    /*
    lcd.setCursor( 0, 0 );
    lcd.print( "   SD card is   " );
    lcd.setCursor( 0, 1 );
    lcd.print( "   too full!!   " );
    */

    Serial.println( "SD-карта заполнена, и мы не будем продолжать, пока она не будет очищена." );

    while( sdCardFull ){}       // Не делайте абсолютно ничего, пока SD-карта не будет "очищена"
}

, 👍1

Обсуждение

Дай угадаю... вы подключаете плату (или программируете плату), затем открываете последовательный терминал, и программа "начинает работать"...? А как насчет периода между подключением его (или программированием) и открытием последовательного терминала? Тогда он тоже работает, вы знаете... (предполагая Uno - но вы не указываете, какую плату используете...), @Majenko

Да, это Уно... и Нано... и Про-Мини. И скетч должен быть пойман в петлю "while( !Serial)" до тех пор, пока не будет подключен последовательный монитор, верно?, @stillborn86

Нет, эта линия предназначена только для родных USB-плат, насколько я помню. Он не будет ждать ничего на Uno или Nano, @chrisl

Возможно, вам следует сначала проверить, действительно ли файл содержит данные, прежде чем перемещать его., @chrisl

"while (!Serial)` работает только для MCU с родным USB (32u4, SAMD), а не для Uno, Nano, Mega, Mini. Uno & co. reset on new connection. они начинают работать, а затем сбрасываются при новом подключении, @Juraj

Все файлы содержат данные с соответствующими именами файлов ( например, - `File "DATA~1.TXT"'). Их правильно перемещают. Вот откуда я знаю, что " ДАННЫЕ~6.TXT-пусто., @stillborn86

Даже если MCU работает без задержки, DATA.TXT все еще должен идти к " ДАННЫМ~6.TXT, новый DATA.TXT должен быть создан с "тестовыми данными" в соответствии с кодом, затем последовательный монитор должен сбросить вещи, переместив файл "тестовые данные" в ДАННЫЕ~7.TXT-и дублировать "тестовые данные" на DATA.TXT` верно? Но этого не происходит... Я до сих пор не могу объяснить, что происходит., @stillborn86

Вы также видите это поведение с полной новой настройкой? (То есть все файлы удалены, позволяя коду начать с известной точки старта) Возможно, Arduino был однажды прерван сбросом, прежде чем он смог записать фактические данные в файл, @chrisl

На новой установке (отформатированная SD - карта без файлов на ней) я получаю два файла: DATA.TXT и ДАННЫЕ~1.TXT', с обоими записанными "данными тестовой последовательности". Кроме имени файла, они идентичны, согласно cmp и md5sum`. Я до сих пор не уверен на 100%, почему он создает два файла... обычно один из них пуст, но в данном случае они идентичны., @stillborn86

Вы можете выполнить несколько сбросов, нажав кнопку сброса или повторно открыв последовательный монитор, чтобы проверить, работает ли он при правильных обстоятельствах. Сброс во время записи на SD - карту может привести к повреждению данных. Возможно, целесообразно отключить сброс от последовательного, добавив конденсатор между сбросом и землей. Это предотвращает последовательный интерфейс для сброса микроконтроллера. Хотя это также предотвращает программирование, поэтому вам придется снова удалить конденсатор для программирования, @chrisl

попробуйте использовать - вместо ~, @Juraj

@Juraj Я следил за [SFN8.3](https://en.wikipedia.org/wiki/8.3_filename) формат, который рекомендуется [Arduino](https://www.arduino.cc/en/Reference/SDCardNotes). Он **должен** работать с"~", но он **должен** также работать с" -`. Пробуя и то, и другое, ни то, ни другое не приводит к желаемому результату., @stillborn86


1 ответ


0

Если в интегрированной среде разработки Arduino открыт последовательный монитор и вы выполняете загрузку, последовательный монитор отключается, чтобы освободить порт для avrdude. После завершения загрузки последовательный монитор снова подключается. При новом подключении Arduino сбрасывается.

Теперь, когда avrdude закончил загрузку, Arduino начинает работать и выполняет вашу функцию setup (). Он создает новый файл, и внезапно последовательный монитор снова подключается и сбрасывает Arduino. Программа установки() снова запускается и создает следующий файл.

Этого не произойдет, если последовательный монитор не открыт, но чтобы предотвратить это, вы можете поместить длительную задержку в начало настройки().

,

Если я загружу код, отформатирую SD-карту и подключу Arduino к коаксиальному разъему (без последовательного монитора), а затем подожду более минуты (пока Arduino выполнит любой необходимый код), проблема все еще существует. Так что я не на 100% убежден, что проблема здесь в последовательном мониторе. Вот почему я уверенно добавил в пост "ПРАВКА №2"., @stillborn86