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++;
}
}
}
}
@smc, 👍-1
3 ответа
Лучший ответ:
Насколько я знаю, невозможно прочитать файл и при этом изменить значение.
Обычно делается следующее:
- Читать файл
- Сохранить в памяти
- Изменить значение в памяти
- Записать файл
Однако, поскольку память SRAM очень ограничена, лучше использовать следующий подход:
- Для каждого буфера (512 байт):
- Чтение буфера размером 512 байт
- При необходимости измените значения в буфере
- Записать 512 байт в другой файл
- Пока не будет достигнут конец файла для чтения
- Удалить исходный файл
- Изменить имя нового файла на старое.
Как записать значение переменной в текстовый файл и изменить его на SD-карте?
Эта проблема проектирования программного обеспечения во многом зависит от выбранного представления в файле. В принципе, есть два измерения дизайна. Первое представляет собой текстовое или бинарное представление. Второй — записи фиксированного или переменного размера.
При текстовом представлении (например, Serial.print) значения преобразуются в текст и сохраняются в файле. Размер записи (например, строки) зависит от количества символов, необходимых для значения. Новая строка часто используется в качестве разделителя записи. Чтобы найти конкретную запись, файл необходимо отсканировать. Невозможно вычислить позицию записи. При обратном считывании значения текстовое представление должно быть проанализировано, а внутреннее представление в памяти восстановлено.
При двоичном представлении (например, Serial.write) значения записываются непосредственно из памяти в файл. Размер записи фиксируется как размер структуры. Найти конкретную запись легко; индекс времени записи размер записи. Библиотека SD file.seek(position) идеально подходит для индексации записи. При чтении значения обратно в память нет необходимости в преобразовании, как в текстовом представлении.
Следует добавить, что также возможно текстовое представление фиксированного размера , например, сделать каждую строку одинаковой длины, используя символ заполнения (пробел и т. д.).
Текстовый файл со значениями переменных более сложен, так как это и текстовое представление, и запись переменных. Он также является самым неэффективным, поскольку требует вычислительной мощности для преобразования представления значений. Основное преимущество заключается в том, что текстовый файл можно создать с помощью обычного текстового редактора. Никаких специальных инструментов или программ не требуется.
Двоичный формат файла с фиксированными записями потребует инициализации.
Ура!
Сначала мне было очень сложно, но теперь я понимаю. Я загружу только код 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
- Понимание того, почему следует избегать «String» и альтернативных решений
- Попытка прочитать случайную строку с SD-карты
- Очень простая операция Arduino Uno Serial.readString()
- Как преобразовать строку в массив байтов
- SD-карта не инициализируется
- Что означают эти контакты? Куда мне их подключить?
- Как отправить строку с подчиненного устройства Arduino с помощью SPI?
- Буфер char в String в Arduino UNO
Вам не нужно заново копировать файл целиком, можно просто прочитать/изменить/записать отдельные блоки, содержащие изменяемые данные., @Chris Stratton
@ChrisStratton Верно, но, глядя на код из ОП, он также обрабатывает весь файл. Но, как вы упомянули, не обязательно читать его полностью или даже последовательно., @Michel Keijzers