Непрерывная запись осциллограмм на SD карту

Andrik893

✩✩✩✩✩✩✩
10 Апр 2021
3
0
Здравствуйте. Стоит задача непрерывной записи аналоговых сигналов с 6 портов ардуино на sd карту, для изучения синусойды питающего напряжения частотой 50 Гц. Необходима максимальная скорость. Для увеличения скорости функции AnalogRead() было установлено ядро GyverCore, скорость измерения с 6 портов и записи на sd карту одного прохода около 1300мкс ( писалась строка "582348;63;60;60;62;63;67;" сначала текущие микросекунды потом 6 показаний с портов, разделитель ";" ), после записи каждых 18 - 19 строк происходит пауза около 7900мкс и через каждые 150 строк пауза около 37000 мкс. При переносе кода на STM32 BluePill увеличилась скорость записи строки до 370мкс, пауза 7800мкс стала через 12 строк (увеличилось количество символов строке "205372;1956;2165;2065;2015;2308;2141;") и пауза через каждые 100 строк около 36000 мкс.
C:
// Измерение скорости записи данных с аналоговы портов в течении 10 секунд
#include <SPI.h>
#include <SD.h>

File myFile;
unsigned long T;

const int analogInputPin0 = PA0;
const int analogInputPin1 = PA1;
const int analogInputPin2 = PA2;
const int analogInputPin3 = PA3;
const int analogInputPin4 = PB0;
const int analogInputPin5 = PB1;

void setup() {
  pinMode(PC13, OUTPUT); // пин светодиода для индикации завершения записи
  pinMode(analogInputPin0, INPUT_ANALOG);
  pinMode(analogInputPin1, INPUT_ANALOG);
  pinMode(analogInputPin2, INPUT_ANALOG);
  pinMode(analogInputPin3, INPUT_ANALOG);
  pinMode(analogInputPin4, INPUT_ANALOG);
  pinMode(analogInputPin5, INPUT_ANALOG);

  if (!SD.begin(4)) {
    while (1);
  }
  T = millis();
}
void loop() {
  digitalWrite(PC13, HIGH);  // Выключаем светодиод
  File dataFile = SD.open("test.txt", O_CREAT | O_WRITE); // FILE_WRITE не повлия ло на скорость записи

  if (dataFile) {
    while ((T + 10000) > millis()) {
      dataFile.print(String(micros()));
      dataFile.print(";");
      dataFile.print(analogRead(analogInputPin0));
      dataFile.print(";");
      dataFile.print(analogRead(analogInputPin1));
      dataFile.print(";");
      dataFile.print(analogRead(analogInputPin2));
      dataFile.print(";");
      dataFile.print(analogRead(analogInputPin3));
      dataFile.print(";");
      dataFile.print(analogRead(analogInputPin4));
      dataFile.print(";");
      dataFile.print(analogRead(analogInputPin5));
      dataFile.println(";");
    }
    dataFile.flush(); // сохранение данных из флеша на SD
    dataFile.close();
  }
  delay(1000);
  digitalWrite(PC13, LOW); // Включаем светодиод
  delay(1000);
}
Предполагаю что паузы возникают при переполнении буфера и записи блока 512кб на sd карту. Файл с данными прикрепил. Как сделать чтоб обойти паузы? И от чего возникают такие большие паузы в 37 мс? Увеличение скорости можно и добиться записью данных байтими а не символами (для отладки так удобнее, открыл посмотрел что записалось, без преобразований из байтов встроку)
 

Вложения

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
973
58
Марий-Эл
При переносе кода на STM32 BluePill увеличилась скорость записи строки
Чтобы получить что надо, нужно писать на HAL, а ещё лучше на CMSIS. Тогда таймингами и всем остальным можно рулить самому а не доверять всё это ядру, которое сжирает до 40% времени.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,262
1,300
Москва
Перенос кода на СТМ это просто заливка в СТМ через ардуино ИДЕ ? Из этого ничего хорошего не выйдет. Лучший вариант кмк может быть при использовании ESP и хранении данных в памяти с записью на карту уже после окончания измерений.
Буквально вчера баловался с чтением данных с аналогового порта, правда только с одноко и без гайвер коре. Использовал прерывание по окончанию измереня. Так вот при делители 32 (а это 4 раза ускоряет измерение ADC) я уже не успеваю в монитор порта что либо выводить, пока вывожу - пропускаю несколько измерений. Так что гайверкоре тут не нужно, все будет упираться в скорость записи на карту.

А если брать СТМ , то там есть возможность подключить много внешней памяти и писать прям в нее используюя DMA.

А точно ли надо писать столько всего с 6 портов с максимальной скоростью?
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Увеличение скорости можно и добиться записью данных байтими а не символами (для отладки так удобнее, открыл посмотрел что записалось, без преобразований из байтов встроку)
Вы определитесь - если это у вас "отладка" - тогда вам должно быть наплевать на задержки, которые эта отладка вносит. То что вы записываете данные на карту в текстовом виде - замедляет процесс почти на порядок.
Вы сначала теряете кучу времени на формирование строки, которая к тому же получается в 3-4 раза длинннее этих же данных в виде байт. А потом этот 3-4х кратный обьем пишете на карту.

Как верно выше отметили - Гайвер-коре тут не нужно вовсе, самая критичная операция - запись данных. Поэтому надо делать данные как можно компактнее, упаковывать в бинарном виде, никаких разделителей и знаков препинания.
 
Изменено:
  • Лойс +1
Реакции: Старик Похабыч

Andrik893

✩✩✩✩✩✩✩
10 Апр 2021
3
0
Избыточное цитирование
Чтобы получить что надо, нужно писать на HAL, а ещё лучше на CMSIS. Тогда таймингами и всем остальным можно рулить самому а не доверять всё это ядру, которое сжирает до 40% времени.
К сожалению, моего опыта программирования микроконтроллеров не хватит чтоб это реализовать

Вы определитесь - если это у вас "отладка" - тогда вам должно быть наплевать на задержки, которые эта отладка вносит. То что вы записываете данные на карту в текстовом виде - замедляет процесс почти на порядок.
Вы сначала теряете кучу времени на формирование строки, которая к тому же получается в 3-4 раза длинннее этих же данных в виде байт. А потом этот 3-4х кратный обьем пишете на карту.

Как верно выше отметили - Гайвер-коре тут не нужно вовсе, самая критичная операция - запись данных. Поэтому надо делать данные как можно компактнее, упаковывать в бинарном виде, никаких разделителей и знаков препинания.
Даже если в бинарном виде писать, возникают паузы при записи на sd карту, откуда они берутся?