Эффективный способ сохранить данные акселерометра на 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 или могут быть другие способы быстрого сохранения данных?
@Kracozebr, 👍1
Обсуждение1 ответ
Я вижу, что безопасно каждый раз открывать/закрывать файл, особенно закрытие, так как если Arduino теряет питание, весь файл может быть поврежден.
Однако я могу найти несколько «решений»:
- Резервный аккумулятор
Откройте файл в setup()
и закройте файл только тогда, когда активируется резервная батарея (вместо закрытия файла после каждой записи). Однако для этого потребуется внешняя батарея и некоторая реализация, чтобы проверить, активна ли она. Кроме того, во время работы внешней батареи данные не должны записываться.
- Использование нескольких файлов
Более просто использовать несколько файлов и записывать каждый период времени (меньше размера файла, вызывающего проблемы) в отдельный файл. Вы можете либо закрыть файл после каждой записи, либо при запуске нового периода, то есть, когда Arduino теряет питание, вы теряете только последний период времени.
- Использование двоичного формата
Это можно использовать в сочетании с решением 1 и 2, и оно заключается в том, чтобы записывать файлы не в виде текстовых файлов, а в двоичном формате, что значительно уменьшает размер.
Спасибо за ответ. Что касается батареи, на данный момент я собираюсь использовать батарею crone в качестве основного источника питания для arduino, потому что она находится вдали от электричества. О втором вашем предложении я думал об этом, поэтому мне нужно измерить время цикла и время открытия файла с файлами разных размеров и найти максимальный размер, который он может открыть, чтобы не быть слишком медленным для получения данных от акселерометра. И ваше третье предложение здорово, я должен попробовать его!, @Kracozebr
Если ваш файл не должен быть удобочитаемым для человека, это самое простое решение. Я думаю, что это может сэкономить фактор 4, а может быть, и больше, если вы используете знаки препинания и пробелы., @Michel Keijzers
Спасибо, после этого я смогу расшифровать файл. У меня есть обновление, я измерил время операций открытия, записи и закрытия, и кажется, что это не лучший способ хранения логов на сд. Смотрите обновления, @Kracozebr
Используйте двоичный формат, что сократит время записи., @Michel Keijzers
- Как увеличить скорость записи на SD-карту в Ардуино
- SD-карта не инициализируется
- Что означают эти контакты? Куда мне их подключить?
- Режимы открытия файлов на SD-карте Arduino добавление/перезапись
- Какие контакты можно использовать для выбора микросхемы (CS, CC) на Arduino Nano Every?
- Понимание того, почему следует избегать «String» и альтернативных решений
- Сделать CS (chip select) для работаты в SPI (для и SD карты и OLED)
- Можно ли подключить экран SD-карты к плате Digispark ATtiny85?
Я думал о том, чтобы предложить это в качестве потенциального дубликата, но я не очень сильно к этому относился, и вы получили хороший совет (не упомянутый там ) ниже, что я собираюсь проголосовать. Тем не менее, вы можете найти это интересное чтение., @timemage
Спасибо за совет, буду читать, @Kracozebr
Вы отредактировали, включив строку: * «Может быть, есть способ ... серийный с Wi-Fi или Bluetooth или ... другие методы для быстрого хранения данных?» * Это правильный вопрос (или, по крайней мере, ядро) но это другой вопрос, который был втиснут туда. И это было сделано *после* того, как на первоначальный вопрос уже был дан вдумчивый ответ. ИМО, если вы хотите задать что-то подобное, удалите это из этого вопроса и начните новый. Вам нужно быть осторожным, чтобы вы спрашивали о том, на что можно дать фактический ответ, а не о чем-то, что является лишь вопросом мнения., @timemage