Эффективный способ сохранить данные акселерометра на SD-карту

У меня есть аналоговый акселерометр, передающий ускорение по 3 осям с частотой 5 кГц. Я хочу сохранить эти данные на SD-карте в текстовом файле. Мой набросок следующий:

void loop()
{
  
  // Получить необработанные данные акселерометра для каждой оси
  int rawX = analogRead(A0);
  int rawY = analogRead(A1);
  int rawZ = analogRead(A2);

  
  // Масштабирование показаний АЦП акселерометра в общепринятые единицы
  // Масштаб карты зависит от того, используется ли микроконтроллер 5 В или 3,3 В
  float scaledX, scaledY, scaledZ; // Масштабированные значения для каждой оси
  if (micro_is_5V) // Микроконтроллер отключает 5В
  {

    scaledX = mapf(rawX, 0, 1023, -scale, scale); // 3,3/5 * 1023 =~ 675
    scaledY = mapf(rawY, 0, 1023, -scale, scale);
    scaledZ = mapf(rawZ, 0, 1023, -scale, scale);

  }
  else // Микроконтроллер теряет 3,3 В
  {
    scaledX = mapf(rawX, 0, 675, -scale, scale);
    scaledY = mapf(rawY, 0, 675, -scale, scale);
    scaledZ = mapf(rawZ, 0, 675, -scale, scale);
  }
 
   String dataString = "";
   // Объединить строку
   dataString += String(scaledX);
   dataString += "\t\t";
   dataString += String(scaledY);
   dataString += "\t\t";
   dataString += String(scaledZ);
   dataString += "\t\t";
   saveSD();  
}

// Та же функциональность, что и у стандартной функции карты Arduino, за исключением использования чисел с плавающей запятой
float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void saveSD()
{
  // создаем файл для записи
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // если файл доступен
  if (dataFile) {
    // сохранить данные
    dataFile.println(dataString);
    // закрыть файл
    dataFile.close();
  } else {
    // если файл недоступен
    Serial.println("Error opening datalog.txt");
  }
}

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

ОБНОВЛЕНИЕ: Я измерил время выполнения кода так:

 ...
start_open_t=micros(); // время в миллисекундах
Файл dataFile = SD.open("datalog.txt", FILE_WRITE);
delta_open_t=micros() - start_open_t ;
// если файл доступен для записи
если (файл данных) {
// сохранить данные
start_write_t=micros(); // время в миллисекундах
файл данных.println (строка данных);
delta_write_t=micros() - start_write_t ;
// закрыть файл
start_close_t=micros(); // время в миллисекундах
файл данных.close();
delta_close_t=micros() - start_close_t ;
...

И вот результат:

  ...
  start_open_t=micros(); // time in milli seconds
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  delta_open_t=micros() - start_open_t ;
  // if file is available for writing
  if (dataFile) {
    // save the data
    start_write_t=micros(); // time in milli seconds
    dataFile.println(dataString);
    delta_write_t=micros() - start_write_t ;
    // close the file
    start_close_t=micros(); // time in milli seconds
    dataFile.close();
    delta_close_t=micros() - start_close_t ;
    ...

Время открытия увеличивается, что неудивительно (с увеличением размера файла).
Запись в файл и время закрытия практически постоянно. Я думал открыть файл в setup() и инициализировать таймер. Записать в файл в цикле() и через некоторое время закрыть файл, после этого открыть новый файл и так далее. Но, как видно, операция печати dataFile.println(dataString); занимает примерно 2 мс, то есть 500 Гц, и это слишком медленно. Мне нужно зарегистрироваться с 5 кГц. Если я печатаю последовательно, данные печатаются намного быстрее, но я не могу подключиться к USB, потому что Arduino находится далеко (около 30 метров). Может быть, есть способ подключиться к последовательному порту через Wi-Fi или Bluetooth или могут быть другие способы быстрого сохранения данных?

, 👍1

Обсуждение

Я думал о том, чтобы предложить это в качестве потенциального дубликата, но я не очень сильно к этому относился, и вы получили хороший совет (не упомянутый там ) ниже, что я собираюсь проголосовать. Тем не менее, вы можете найти это интересное чтение., @timemage

Спасибо за совет, буду читать, @Kracozebr

Вы отредактировали, включив строку: * «Может быть, есть способ ... серийный с Wi-Fi или Bluetooth или ... другие методы для быстрого хранения данных?» * Это правильный вопрос (или, по крайней мере, ядро) но это другой вопрос, который был втиснут туда. И это было сделано *после* того, как на первоначальный вопрос уже был дан вдумчивый ответ. ИМО, если вы хотите задать что-то подобное, удалите это из этого вопроса и начните новый. Вам нужно быть осторожным, чтобы вы спрашивали о том, на что можно дать фактический ответ, а не о чем-то, что является лишь вопросом мнения., @timemage


1 ответ


1

Я вижу, что безопасно каждый раз открывать/закрывать файл, особенно закрытие, так как если Arduino теряет питание, весь файл может быть поврежден.

Однако я могу найти несколько «решений»:

  1. Резервный аккумулятор

Откройте файл в setup() и закройте файл только тогда, когда активируется резервная батарея (вместо закрытия файла после каждой записи). Однако для этого потребуется внешняя батарея и некоторая реализация, чтобы проверить, активна ли она. Кроме того, во время работы внешней батареи данные не должны записываться.

  1. Использование нескольких файлов

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

  1. Использование двоичного формата

Это можно использовать в сочетании с решением 1 и 2, и оно заключается в том, чтобы записывать файлы не в виде текстовых файлов, а в двоичном формате, что значительно уменьшает размер.

,

Спасибо за ответ. Что касается батареи, на данный момент я собираюсь использовать батарею crone в качестве основного источника питания для arduino, потому что она находится вдали от электричества. О втором вашем предложении я думал об этом, поэтому мне нужно измерить время цикла и время открытия файла с файлами разных размеров и найти максимальный размер, который он может открыть, чтобы не быть слишком медленным для получения данных от акселерометра. И ваше третье предложение здорово, я должен попробовать его!, @Kracozebr

Если ваш файл не должен быть удобочитаемым для человека, это самое простое решение. Я думаю, что это может сэкономить фактор 4, а может быть, и больше, если вы используете знаки препинания и пробелы., @Michel Keijzers

Спасибо, после этого я смогу расшифровать файл. У меня есть обновление, я измерил время операций открытия, записи и закрытия, и кажется, что это не лучший способ хранения логов на сд. Смотрите обновления, @Kracozebr

Используйте двоичный формат, что сократит время записи., @Michel Keijzers