Запись данных в файл с акселерометра на ESP32+ADXL103

Привет! Я не студент. В свободное время занимаюсь исследованиями вибрации в живых организмах. Если кому-то будет интересно, могу рассказать подробнее. Для этого мне требуется именно беспроводной датчик. Я остановился на ESP32 и аналоговом акселерометре ADXL103. Данные передаются по bluetooth. Данных много и для анализа важна частота (хотелось хотя бы 5КГц). Поэтому сначала сохраняю в файл, потом передаю. Когда воздействие на датчик небольшое данные приходят нормально. Как только начинаю колебать более интенсивно, часть данных теряется. Пробовал передавать и через COM-порт по проводу, тоже самое. Пожалуйста, помогите разобраться.

#include "BluetoothSerial.h"
#include "FS.h"
#include "SPIFFS.h"

BluetoothSerial ACC_BT;
File myFile;

void setup(){
  Serial.begin(9600); 
  SPIFFS.begin();
  ACC_BT.begin("Accelerometer");
  SPIFFS.format(); 
}

void loop(){
  if (ACC_BT.available()){
    if (ACC_BT.read() == 49){
      myFile = SPIFFS.open("/file.txt", FILE_WRITE);
      for (int i = 0; i < 1024; i++){
        myFile.print (analogRead(27), DEC);
        delayMicroseconds(200);      
      }
      myFile.close();
      myFile = SPIFFS.open("/file.txt", FILE_READ);
      while(myFile.available()){
        for (int i = 0; i < 4; i++){
          ACC_BT.write(myFile.read());
        }
        ACC_BT.println();
      }
      myFile.close();
      SPIFFS.remove("/file.txt");
      ACC_BT.println("END");
    }
  }
}

Пишете в файл числа без пробелов?

что там внутри получится? - 023456765438888764543345567654343 ? - как вы потом в этом разбираетесь?

Что касается того, почему теряются данные - вы же попеременно то снимаете данные то отсылаете их, пока отсылаете - новые данные с датчика теряются…

Может скорость порта повысить?

это не решит проблему, а лишь чуть скрасит ее

ESP32 двухядерная, разнести по ним считывание и отправку

Давайте прикинем.

1048576 bytes written in 45808 ms

Т.е. 1 миллион байт записывается за ~45,8 сек. Значит за 1мс возможно записать ~22,9 байта. Вы пишете 5 раз в миллисекунду по ~4 байта. Т.е. ~20 байт в 1 мс.
Еще там, может, накладные расходы какие-то… Вобщем, на пределе, но, теоретически, тащить будет.

А теперь вопрос - что такое “теряется часть данных”. Ткните пальцем в то, место дампа, которое исчезает? Оно в начале, в конце, середине?

PS. Я догадываюсь… Сначала пишете, потом читаете и в БТ кидаете и в этот период времени данные не пишутся и “пропадают”?

Да. Но запсываю в порт по 4 знака и перенос.

for (int i = 0; i < 4; i++){
      ACC_BT.write(myFile.read());
   }
ACC_BT.println();

Поэтому на ПК получаю:
1297
1191
1424

Сначала работал на скорости 115200. Думал, что в этом причина. Стал проверять на 9600. Ничего не изменялось. Все равно теряю данные когда есть колебания.

Конечно в этом ракурсе кажется правильным разделить потоки записи и чтения. Но, если вспомнить, что микросхемка одна и пока её читают, записывать нет возможности, а работаете вы на пределе скорости SPIFFS, то выхода в данном случае не наблюдается.

Как вариант - писать весь срез данных, а потом его пересылать. Но такое вот “кусочничество” обречено на провал.

Писать нужно во что-то на порядок более быстрое. Я бы предложил прямо через UDP на комп. шарашить, но не представляю, как вы эти данные будете на той стороне забирать.

значит писать надо в более быстрое что-то…циклический буфер в ОЗУ?

Я пробовал записывать даже в бинарном виде, чтобы экономить место и время (по 12 бит каждое значение, если я правильно понимаю) Но на суть тоже не повлияло. Когда датчик в покое получаю 1024 значения, когда колеблется ~80%. А моем случае пропуск одного знака, превращает данные в бессмысленный набор символов. Может добавить разделитель? На самом деле мне нужно гораздо больше, чем 1024 отсчета (хотя бы в 100 раз).

B707 прав, в общем-то, пишите в файл сразу с разделителями

for (int i = 0; i < 1024; i++){
        myFile.println(analogRead(27), DEC); // << println() instead print()
        delayMicroseconds(200);      
      }
...
   while(myFile.available()) {
        ACC_BT.write(myFile.read()); 
      }

Спасибо. Понял.

В циклический наврядли.

Если через трубу А втекает быстрее, чем из трубы Б вытекает, то кранты бассейну.
А если труба Б шире трубы А, то зачем нужен бассейн?

Тут вопрос больше в том - успевают ли через БТ данные проскакивать. Теоретически там до 1900Kbps (по инфе от Expressiff). И в связи с этим я не понимаю, отчего сразу в BT не совать результат analogRead(). Затык на приёмной стороне?

Сначала я питался сразу отправлять данные в порт. Но при передаче большого объема, буфер порта заполнялся, и начинались задержки, а мне нужно чтобы отсчеты были записаны с одинаковым интервалом (например, 200 мкс), чтобы получить 5 КГц.

The output of the ADXL103/ADXL203 has a typical bandwidth
of 2.5 kHz.

Вот и нужно понять, почему он заполнялся. Проблема в шумной радиосреде, которая БТ давит, в приёмной части? Что с другой стороны БТ стоит - компутер с экселем?

Знаю это диапазон частот, до которых датчик нормально работает. Для того чтобы записать такой сигнал нужно минимум 2,5*2=5 КГц (по теореме Котельникова).

Да. Матлаб, Эксель и т.п. Я пробовал через кабель, результат тот же. Проблема точно в BT.

у вас даже без пропуска знака может бессмыслица получится.
Вы учитываете, что analogRead() вполне может выдать число менее 1000 - например 999 ? - и все, вся цепочка сбилась