Arduino: как записать значение переменной в текстовый файл и изменить его на SD-карте?

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

//чтение кода

#include <SD.h>

int stepToLoad = 1;
int endOfLineNumber = 0;
int stepCount = 0;
int stringIndex = 0;
File configFile;
char inputString [1280];
char inputChar;

void setup() {
  stepToLoad = 13;
  if (!SD.begin(36)) {
    return;
  }

  if (SD.exists("config.txt")) {
    configFile = SD.open("config.txt");
    getStepCount();
    getStepData();
    configFile.close();
  }
}

void loop() {

}

void getStepData() {

  if (configFile) {
    while (configFile.available()) {
      inputChar = configFile.read(); // Получает один байт из последовательного буфера
      if (inputChar != '^') { // здесь определяем разделяющий символ

        inputString[stringIndex] = inputChar; // Сохраняем
        stringIndex++; // Увеличиваем, куда писать дальше

      } else {
        endOfLineNumber++;
        stringIndex++;
        if (endOfLineNumber == stepToLoad) { // это правильная строка для загрузки


          break; // выйти из цикла "пока"
        } else { // не та строка для загрузки, сброса и продолжения

          stringIndex = 0;
        }
      }

    }

  }
}

void getStepCount() {
  if (configFile) {
    while (configFile.available()) {
      inputChar = configFile.read(); // Получает один байт из последовательного буфера
      if (inputChar == '^') { // здесь определяем разделяющий символ
        stepCount++;
      }
    }
  }
}

, 👍-1


3 ответа


Лучший ответ:

1

Насколько я знаю, невозможно прочитать файл и при этом изменить значение.

Обычно делается следующее:

  • Читать файл
  • Сохранить в памяти
  • Изменить значение в памяти
  • Записать файл

Однако, поскольку память SRAM очень ограничена, лучше использовать следующий подход:

  • Для каждого буфера (512 байт):
    • Чтение буфера размером 512 байт
    • При необходимости измените значения в буфере
    • Записать 512 байт в другой файл
    • Пока не будет достигнут конец файла для чтения
  • Удалить исходный файл
  • Изменить имя нового файла на старое.
,

Вам не нужно заново копировать файл целиком, можно просто прочитать/изменить/записать отдельные блоки, содержащие изменяемые данные., @Chris Stratton

@ChrisStratton Верно, но, глядя на код из ОП, он также обрабатывает весь файл. Но, как вы упомянули, не обязательно читать его полностью или даже последовательно., @Michel Keijzers


1

Как записать значение переменной в текстовый файл и изменить его на SD-карте?

Эта проблема проектирования программного обеспечения во многом зависит от выбранного представления в файле. В принципе, есть два измерения дизайна. Первое представляет собой текстовое или бинарное представление. Второй — записи фиксированного или переменного размера.

При текстовом представлении (например, Serial.print) значения преобразуются в текст и сохраняются в файле. Размер записи (например, строки) зависит от количества символов, необходимых для значения. Новая строка часто используется в качестве разделителя записи. Чтобы найти конкретную запись, файл необходимо отсканировать. Невозможно вычислить позицию записи. При обратном считывании значения текстовое представление должно быть проанализировано, а внутреннее представление в памяти восстановлено.

При двоичном представлении (например, Serial.write) значения записываются непосредственно из памяти в файл. Размер записи фиксируется как размер структуры. Найти конкретную запись легко; индекс времени записи размер записи. Библиотека SD file.seek(position) идеально подходит для индексации записи. При чтении значения обратно в память нет необходимости в преобразовании, как в текстовом представлении.

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

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

Двоичный формат файла с фиксированными записями потребует инициализации.

Ура!

,

0

Сначала мне было очень сложно, но теперь я понимаю. Я загружу только код DS3231 с функциями SD-карты

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

DS3231 clock;
RTCDateTime dt;
File myFile;
String fileName = "000000.txt";

void setup()
{
  Serial.begin(9600);

  // Инициализировать DS3231
  Serial.println("Initialize DS3231");;
  clock.begin();

  // Установить время компиляции скетча
  clock.setDateTime(__DATE__, __TIME__);

  // Установить из временной метки UNIX
  // часы.setDateTime(1397408400);

  // Вручную (ГГГГ, ММ, ДД, ЧЧ, II, СС
  // clock.setDateTime(2016, 12, 9, 11, 46, 00);
}

void getName(){
  String date = clock.dateFormat("mdy", dt);
  fileName[0] = date[0];
  fileName[1] = date[1];
  fileName[2] = date[2];
  fileName[3] = date[3];
  fileName[4] = date[4];
  fileName[5] = date[5];
}

void sdCard() {
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }

  Serial.println("initialization done.");

  getName();

  myFile = SD.open(fileName, FILE_WRITE);

  if (myFile) {
    Serial.print("Writing to file...");
    myFile.println("testing 1, 2, 3.");
    Serial.println("done.");
  } 
  else {
    Serial.println("error opening file");
  }
}

void loop()
{
  dt = clock.getDateTime();


  Serial.print("Long number format:          ");
  Serial.println(clock.dateFormat("H:i:s", dt));

  sdCard();
  getName();

  myFile = SD.open(fileName, FILE_WRITE);
  myFile.println("Testing 1...2...3...")

}

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

,

Неясно, отвечает ли это на заданный вопрос, во многом потому, что вопрос совершенно неясен и его необходимо закрыть., @Chris Stratton