Fix UploadManager CSV bottleneck and measure() race condition

This commit is contained in:
2026-05-10 19:14:24 +02:00
parent 10d187eb37
commit 382433b91f
11 changed files with 58 additions and 242 deletions

View File

@@ -6,6 +6,8 @@
class ADXL345FastSPI { class ADXL345FastSPI {
public: public:
static constexpr uint8_t MAX_SENSORS = 4; // Maksymalna liczba ADXL345
enum Rate { RATE_100HZ, RATE_200HZ, RATE_400HZ, RATE_800HZ, RATE_1600HZ, RATE_3200HZ }; enum Rate { RATE_100HZ, RATE_200HZ, RATE_400HZ, RATE_800HZ, RATE_1600HZ, RATE_3200HZ };
enum Range { RANGE_2G, RANGE_4G, RANGE_8G, RANGE_16G }; enum Range { RANGE_2G, RANGE_4G, RANGE_8G, RANGE_16G };
@@ -56,7 +58,7 @@ public:
uint8_t refreshActiveMask(); uint8_t refreshActiveMask();
private: private:
static constexpr uint8_t MAX_NUM = 4; // MAX Ilość ADXL345 static constexpr uint8_t MAX_NUM = MAX_SENSORS;
SPIClass* spi_ = &SPI; SPIClass* spi_ = &SPI;
ADXL345FreshSPI dev_[MAX_NUM]; ADXL345FreshSPI dev_[MAX_NUM];

View File

@@ -39,7 +39,7 @@ struct Config {
char restUser[30]; // login RestAPI char restUser[30]; // login RestAPI
char restPass[50]; // hasło RestAPi char restPass[50]; // hasło RestAPi
uint8_t apiKey[32]; // Klucz API KEY uint8_t apiKey[32]; // Klucz API KEY
uint16_t pause; // Pomiar co sekund uint32_t pause; // Pomiar co milisekund (ms)
uint8_t duration; // Czas pomiaru w sekundach 1-25 uint8_t duration; // Czas pomiaru w sekundach 1-25
char S0[12]; // nazwy czujników 1-8 char S0[12]; // nazwy czujników 1-8
char S1[12]; char S1[12];
@@ -53,6 +53,7 @@ struct Config {
// Global config declaration // Global config declaration
extern Config config; extern Config config;
static_assert(sizeof(Config) + 1 <= EEPROM_SIZE, "Config struct exceeds EEPROM!");
class ConfigManager { class ConfigManager {
public: public:

View File

@@ -99,7 +99,7 @@ private:
bool ispress = (GPIO.in & (1UL << BTN_OK)) == 0; bool ispress = (GPIO.in & (1UL << BTN_OK)) == 0;
if(ispress) { if(ispress) {
isExit = true; isExit = true;
measurementActive_; measurementActive_ = false;
display_.textStatus("Cancelling. Wait!"); display_.textStatus("Cancelling. Wait!");
} }
return ispress; return ispress;

View File

@@ -1,7 +1,7 @@
#ifndef VERSION_H #ifndef VERSION_H
#define VERSION_H #define VERSION_H
#define VERSION "1.3.4.1" #define VERSION "1.3.4.2"
// 1: graphical 128x64, 2: LCD I2C Text 4x20 // 1: graphical 128x64, 2: LCD I2C Text 4x20
#define LCD_TYPE 2 #define LCD_TYPE 2

View File

@@ -16,59 +16,34 @@ String UploadManager::getCurrentTimestamp() {
} }
void UploadManager::appendLog(const String& filePath, const String& status) { void UploadManager::appendLog(const String& filePath, const String& status) {
File f = SD.open(LOG_FILE, FILE_APPEND); // Legacy CSV log removed to fix O(N^2) SD card bottleneck
if (f) {
f.printf("%s,%s,%s\n", getCurrentTimestamp().c_str(), filePath.c_str(), status.c_str());
f.close();
}
} }
bool UploadManager::isAlreadyUploaded(const String& filePath) { bool UploadManager::isAlreadyUploaded(const String& filePath) {
File f = SD.open(LOG_FILE, FILE_READ); // We now rely on file extensions (.wmt = pending, .upl = uploaded)
if (!f) return false; return false;
bool found = false;
while (f.available()) {
String line = f.readStringUntil('\n');
line.trim();
if (line.length() == 0) continue;
int firstComma = line.indexOf(',');
if (firstComma < 0) continue;
int secondComma = line.indexOf(',', firstComma + 1);
if (secondComma < 0) continue;
String logPath = line.substring(firstComma + 1, secondComma);
String logStatus = line.substring(secondComma + 1);
if (logPath == filePath) {
if (logStatus == "OK") found = true;
else found = false; // A retry might be needed if last status wasn't OK
}
Watchdog::feed();
}
f.close();
return found;
} }
void UploadManager::uploadFile(const String& filePath) { void UploadManager::uploadFile(const String& filePath) {
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
ESP_LOGE(TAG_UPLOAD, "No WiFi. Cannot upload %s", filePath.c_str()); ESP_LOGE(TAG_UPLOAD, "No WiFi. Cannot upload %s", filePath.c_str());
appendLog(filePath, "ERROR: No WiFi");
return; return;
} }
bool success = apiClient.uploadMeasurement(filePath); bool success = apiClient.uploadMeasurement(filePath);
if (success) { if (success) {
appendLog(filePath, "OK");
String newPath = filePath; String newPath = filePath;
newPath.replace(".wmt", ".upl"); newPath.replace(".wmt", ".upl");
SD.rename(filePath, newPath); if (SD.rename(filePath, newPath)) {
ESP_LOGI(TAG_UPLOAD, "Renamed %s to .upl", filePath.c_str());
} else {
ESP_LOGE(TAG_UPLOAD, "Rename to .upl failed for %s", filePath.c_str());
}
} else { } else {
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
appendLog(filePath, "ERROR: WiFi lost during upload"); ESP_LOGE(TAG_UPLOAD, "WiFi lost during upload");
} else { } else {
appendLog(filePath, "ERROR: Upload Failed"); ESP_LOGE(TAG_UPLOAD, "Upload Failed");
} }
} }
} }

View File

@@ -369,7 +369,7 @@ void measure(){
ESP_LOGI(TAG_MAIN, "MEASURE RUNNING"); ESP_LOGI(TAG_MAIN, "MEASURE RUNNING");
xSemaphoreTake(sdMutex, portMAX_DELAY); xSemaphoreTake(sdMutex, portMAX_DELAY);
capture.captureAuto(config.duration, "/"); capture.captureAuto(config.duration, "/");
xSemaphoreGive(sdMutex);
testingNow = false; testingNow = false;
Watchdog::feed(); Watchdog::feed();
if(!capture.isExit){ if(!capture.isExit){
@@ -379,6 +379,7 @@ void measure(){
} else { } else {
ESP_LOGI(TAG_MAIN, "MEASURE INTERRUPT"); ESP_LOGI(TAG_MAIN, "MEASURE INTERRUPT");
} }
xSemaphoreGive(sdMutex);
runMeasure = false; runMeasure = false;
ESP_LOGI(TAG_MAIN, "DISPLAY Offline"); ESP_LOGI(TAG_MAIN, "DISPLAY Offline");

View File

@@ -39,6 +39,7 @@ void ConfigManager::readConfig() {
// Save config to EEPROM // Save config to EEPROM
void ConfigManager::saveConfig() { void ConfigManager::saveConfig() {
ESP_LOGI(TAG_CONF, "SAVE CONFIG"); ESP_LOGI(TAG_CONF, "SAVE CONFIG");
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(1, config); EEPROM.put(1, config);
EEPROM.write(0, 253); EEPROM.write(0, 253);
if (EEPROM.commit()) { if (EEPROM.commit()) {
@@ -46,7 +47,6 @@ void ConfigManager::saveConfig() {
} else { } else {
ESP_LOGE(TAG_CONF, "Error save config"); ESP_LOGE(TAG_CONF, "Error save config");
} }
EEPROM.end();
} }
void ConfigManager::generateApiKey(uint8_t *buf, size_t len) { void ConfigManager::generateApiKey(uint8_t *buf, size_t len) {

View File

@@ -158,7 +158,9 @@ void Display::showAccel(float a, float b, float c) {
void Display::displayOffline(bool measure, uint8_t count, float freeSpace, long licznik, bool refresh){ void Display::displayOffline(bool measure, uint8_t count, float freeSpace, long licznik, bool refresh){
if(refresh){ if(refresh){
oyear, omonth, oday, ohour, omin, osec, ospace, oadxlcnt = 100; oyear = 0; omonth = 0; oday = 0;
ohour = 0; omin = 0; osec = 0;
ospace = 0; oadxlcnt = 100;
_lcd->clear(); _lcd->clear();
_lcd->setCursor(0, 0); _lcd->setCursor(0, 0);
} }

View File

@@ -78,152 +78,6 @@ bool DataCapture::captureAuto(uint32_t captureSeconds, const char * /*baseDirect
} }
// --- main measure function --- // --- main measure function ---
// bool DataCapture::capture(uint32_t captureSeconds, const char *filename) {
// Watchdog::feed();
// if (!buffer_) {
// ESP_LOGE(TAG_CAPTURE, "No buffer - cancel.");
// display_.textStatus("Buffer error");
// return false;
// }
// ESP_LOGI(TAG_CAPTURE, "Capture %u sec. -> %s", (unsigned)captureSeconds, filename);
// File dataFile = _fs.open(filename, FILE_WRITE);
// if (!dataFile) {
// ESP_LOGE(TAG_CAPTURE, "Can't open file: %s", filename);
// char buf[100];
// snprintf(buf, sizeof(buf), "Can't open: %s", filename);
// display_.textStatus(buf);
// //s2etTestingIndicator_(false, _baseDir, filename);
// return false;
// }
// // Bufory RAMKI (po 1 próbce z każdego sensora)
// static const uint8_t MAXN = 7; // zgodnie z projektem
// int16_t X[MAXN]{}, Y[MAXN]{}, Z[MAXN]{};
// uint32_t TS[MAXN]{};
// Watchdog::feed();
// const uint32_t tStart_us = micros();
// const uint32_t captureDuration_us = captureSeconds * 1000000UL;
// // Czas startu (UTC) — tylko w nagłówku!
// const DateTime now = rtc_.now();
// const int32_t unix_start = now.unixtime();
// // Nagłówek
// FileHeader hdr;
// memcpy(hdr.magic, "WMT", 3);
// hdr.version = 1;
// hdr.headerSize = sizeof(FileHeader);
// hdr.sampleSize = sizeof(Sample);
// hdr.timestamp = unix_start;
// hdr.reccount = 0;
// if (dataFile.write(reinterpret_cast<const uint8_t*>(&hdr), sizeof(hdr)) != sizeof(hdr)) {
// ESP_LOGE(TAG_CAPTURE, "Header write failed");
// display_.textStatus("Header SD failed");
// dataFile.close();
// return false;
// }
// measurementActive_ = true;
// bufferIndex_ = 0;
// setTestingIndicator_(true, _baseDir, filename);
// uint32_t frames = 0; // liczba zebranych „ramek”
// const uint8_t presentCnt = adxl_.size(); // wykryte sensory (wg begin)
// // --- Pętla akwizycji wyrównanych ramek ---
// while (measurementActive_) {
// if(isEscape()) break; // wyjście z pętli gdy OK przerwie
// uint32_t now_us = micros();
// if ((now_us - tStart_us) >= captureDuration_us) break;
// // 1) Czekamy aż KAŻDY obecny sensor ma >= 1 próbkę w FIFO (DATA_READY)
// while (!adxl_.availableAll()) {
// if(isEscape()) break; //????? sprawdź kHz pomiaru!
// // krótki spin; unikamy delay(1), aby nie zrywać 3.2 kHz
// // (opcjonalnie yield(); jeśli system wymaga)
// }
// // 2) Zdejmij po 1 NAJSTARSZEJ próbce z każdego sensora (STREAM FIFO)
// const uint8_t got = adxl_.readAlignedOnce(X, Y, Z, TS);
// if (got != presentCnt) {
// // rzadki przypadek niepełna ramka; pomiń
// continue;
// }
// // 3) Wspólny timestamp ramki: minimalny z TS[i]
// uint32_t tmin = UINT32_MAX;
// for (uint8_t i = 0; i < MAXN; ++i) {
// if (!adxl_.isPresent(i)) continue;
// if (TS[i] < tmin) tmin = TS[i];
// }
// const uint32_t frame_offset_us = tmin - tStart_us;
// // 4) Zapis 7 rekordów Sample do bufora
// for (uint8_t i = 0; i < MAXN; ++i) {
// if (!adxl_.isPresent(i)) continue;
// // Konstruuj rekord bezpośrednio w buforze (bez memcpy)
// if (bufferIndex_ + sizeof(Sample) > bufferSize_) {
// if (!flushToFile(dataFile)) { measurementActive_ = false; break; }
// }
// Sample *dst = reinterpret_cast<Sample*>(buffer_ + bufferIndex_);
// dst->offset = frame_offset_us;
// dst->sensor_id = i;
// dst->x = X[i]; dst->y = Y[i]; dst->z = Z[i];
// dst->ready = true;
// bufferIndex_ += sizeof(Sample);
// }
// if (!measurementActive_) break;
// frames++;
// // Watchdog rzadziej, żeby nie zwiększać jittera
// if ((frames & 0xFF) == 0) Watchdog::feed();
// } // while
// // Statystyki
// ESP_LOGI(TAG_CAPTURE, "Frames: %u, sensors: %u", (unsigned)frames, (unsigned)presentCnt);
// printSamplingRate(frames, captureSeconds); // liczymy ramki/sek.
// // Domknij bufor
// if (bufferIndex_ > 0) {
// if (!flushToFile(dataFile)) {
// Watchdog::feed();
// ESP_LOGE(TAG_CAPTURE, "Finish save error.");
// display_.textStatus("Save SD error");
// delay(1000);
// }
// }
// ESP_LOGI(TAG_CAPTURE, "Saved to SD successful");
// display_.textStatus("Saved SD OK");
// delay(700);
// // Uzupełnij nagłówek o liczbę rekordów (Sample)
// hdr.reccount = frames * presentCnt;
// dataFile.seek(0);
// dataFile.write(reinterpret_cast<const uint8_t*>(&hdr), sizeof(hdr));
// dataFile.flush();
// dataFile.close();
// //setTestingIndicator_(false, _baseDir, filename);
// bool ok = measurementActive_;
// measurementActive_ = false;
// if (ok) {
// ESP_LOGI(TAG_CAPTURE, "Successful");
// display_.textStatus("Successfull");
// Watchdog::feed();
// return true;
// } else {
// ESP_LOGE(TAG_CAPTURE, "Measurement aborted");
// display_.textStatus("Aborted");
// Watchdog::feed();
// return false;f
// }
// }
// --- main measure function --- V2
bool DataCapture::capture(uint32_t captureSeconds, const char *filename) { bool DataCapture::capture(uint32_t captureSeconds, const char *filename) {
Watchdog::feed(); Watchdog::feed();
if (!buffer_) { if (!buffer_) {
@@ -241,7 +95,7 @@ bool DataCapture::capture(uint32_t captureSeconds, const char *filename) {
ESP_LOGI(TAG_CAPTURE, "Start RAM capture: %u sec.", (unsigned)captureSeconds); ESP_LOGI(TAG_CAPTURE, "Start RAM capture: %u sec.", (unsigned)captureSeconds);
display_.textStatus("Sampling..."); display_.textStatus("Sampling...");
static const uint8_t MAXN = 7; static constexpr uint8_t MAXN = ADXL345FastSPI::MAX_SENSORS;
int16_t X[MAXN]{}, Y[MAXN]{}, Z[MAXN]{}; int16_t X[MAXN]{}, Y[MAXN]{}, Z[MAXN]{};
uint32_t TS[MAXN]{}; uint32_t TS[MAXN]{};
@@ -327,16 +181,21 @@ bool DataCapture::capture(uint32_t captureSeconds, const char *filename) {
hdr.reccount = frames * presentCnt; hdr.reccount = frames * presentCnt;
// Zapis nagłówka // Zapis nagłówka
dataFile.write(reinterpret_cast<const uint8_t*>(&hdr), sizeof(hdr)); size_t hdrWritten = dataFile.write(reinterpret_cast<const uint8_t*>(&hdr), sizeof(hdr));
if (hdrWritten != sizeof(hdr)) {
ESP_LOGE(TAG_CAPTURE, "Header write failed!");
dataFile.close();
return false;
}
// Zapis całego bufora PSRAM jednym ciągiem // Zapis całego bufora PSRAM jednym ciągiem
size_t written = dataFile.write(buffer_, bufferIndex_); size_t written = dataFile.write(buffer_, bufferIndex_);
if (written == bufferIndex_) { if (written == bufferIndex_) {
ESP_LOGI(TAG_CAPTURE, "SD Save Successful: %u bytes", (unsigned)written); ESP_LOGI(TAG_CAPTURE, "SD Save Successful: %u bytes", (unsigned)written);
//display_.textStatus("Save OK"); dataFile.flush(); // Power-loss resilience: wymuszenie zapisu na kartę
display_.textStatus(basenameFromPath(filename)); display_.textStatus(basenameFromPath(filename));
delay(2000); // Tutaj zrob to inaczej delay(500);
} else { } else {
ESP_LOGE(TAG_CAPTURE, "SD Write Error!"); ESP_LOGE(TAG_CAPTURE, "SD Write Error!");
display_.textStatus("SD Write Err"); display_.textStatus("SD Write Err");
@@ -390,7 +249,7 @@ void DataCapture::printSamplingRate(uint32_t reccount, uint32_t captureSeconds,
ESP_LOGI(TAG_CAPTURE,"Rate: %.3f kHz (frames)", fs_kHz); ESP_LOGI(TAG_CAPTURE,"Rate: %.3f kHz (frames)", fs_kHz);
display_.displaySampleRateSummary(reccount, captureSeconds, fs_kHz, filename); display_.displaySampleRateSummary(reccount, captureSeconds, fs_kHz, filename);
display_.textStatus("Summary"); display_.textStatus("Summary");
delay(2000); delay(500);
} }
// --- Zarządzanie katalogami/plikiem --- // --- Zarządzanie katalogami/plikiem ---
@@ -594,15 +453,8 @@ void DataCapture::printLastFileInfoSerial() {
snprintf(buf, sizeof(buf), "Size:%.2f KB", kb); snprintf(buf, sizeof(buf), "Size:%.2f KB", kb);
display_.textStatus(buf); display_.textStatus(buf);
#else #else
// Wariant zachowawczy dla platform bez %llu; pokazujemy rozmiar w MB/KB. ESP_LOGI(TAG_CAPTURE, "Last file: %s", info.path.c_str());
ESP_LOGI(TAG_CAPTURE, "Last file info: ")); ESP_LOGI(TAG_CAPTURE, "Size: %.2f MB", mb);
ESP_LOGI(TAG_CAPTURE, info.path);
ESP_LOGI(TAG_CAPTURE, "Size: "));
ESP_LOGI(TAG_CAPTURE, mb);
//ESP_LOGI(TAG_CAPTURE, " MB"));
//Serial.print(F(" ("));
//Serial.print(kb, 2);
//Serial.println(F(" KB)"));
#endif #endif
} }

View File

@@ -16,59 +16,34 @@ String UploadManager::getCurrentTimestamp() {
} }
void UploadManager::appendLog(const String& filePath, const String& status) { void UploadManager::appendLog(const String& filePath, const String& status) {
File f = SD.open(LOG_FILE, FILE_APPEND); // Legacy CSV log removed to fix O(N^2) SD card bottleneck
if (f) {
f.printf("%s,%s,%s\n", getCurrentTimestamp().c_str(), filePath.c_str(), status.c_str());
f.close();
}
} }
bool UploadManager::isAlreadyUploaded(const String& filePath) { bool UploadManager::isAlreadyUploaded(const String& filePath) {
File f = SD.open(LOG_FILE, FILE_READ); // We now rely on file extensions (.wmt = pending, .upl = uploaded)
if (!f) return false; return false;
bool found = false;
while (f.available()) {
String line = f.readStringUntil('\n');
line.trim();
if (line.length() == 0) continue;
int firstComma = line.indexOf(',');
if (firstComma < 0) continue;
int secondComma = line.indexOf(',', firstComma + 1);
if (secondComma < 0) continue;
String logPath = line.substring(firstComma + 1, secondComma);
String logStatus = line.substring(secondComma + 1);
if (logPath == filePath) {
if (logStatus == "OK") found = true;
else found = false; // A retry might be needed if last status wasn't OK
}
Watchdog::feed();
}
f.close();
return found;
} }
void UploadManager::uploadFile(const String& filePath) { void UploadManager::uploadFile(const String& filePath) {
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
ESP_LOGE(TAG_UPLOAD, "No WiFi. Cannot upload %s", filePath.c_str()); ESP_LOGE(TAG_UPLOAD, "No WiFi. Cannot upload %s", filePath.c_str());
appendLog(filePath, "ERROR: No WiFi");
return; return;
} }
bool success = apiClient.uploadMeasurement(filePath); bool success = apiClient.uploadMeasurement(filePath);
if (success) { if (success) {
appendLog(filePath, "OK");
String newPath = filePath; String newPath = filePath;
newPath.replace(".wmt", ".upl"); newPath.replace(".wmt", ".upl");
SD.rename(filePath, newPath); if (SD.rename(filePath, newPath)) {
ESP_LOGI(TAG_UPLOAD, "Renamed %s to .upl", filePath.c_str());
} else {
ESP_LOGE(TAG_UPLOAD, "Rename to .upl failed for %s", filePath.c_str());
}
} else { } else {
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
appendLog(filePath, "ERROR: WiFi lost during upload"); ESP_LOGE(TAG_UPLOAD, "WiFi lost during upload");
} else { } else {
appendLog(filePath, "ERROR: Upload Failed"); ESP_LOGE(TAG_UPLOAD, "Upload Failed");
} }
} }
} }

View File

@@ -24,8 +24,7 @@
SPIClass SPI_ADXL(FSPI); // SPI2 (VSPI) SPIClass SPI_ADXL(FSPI); // SPI2 (VSPI)
SPIClass SPI_SD(HSPI); // SPI3 (HSPI) SPIClass SPI_SD(HSPI); // SPI3 (HSPI)
float x, y, z = 0; // Dane odczytane z akcelerometru
String name;
bool isRebootRequired = false; bool isRebootRequired = false;
bool isAccelExists = false; // Czy istnieje jakiś podłączony do SPI czujnik bool isAccelExists = false; // Czy istnieje jakiś podłączony do SPI czujnik
@@ -55,15 +54,19 @@ Thread offlineThread = Thread(); // Jeśli offline
Thread measureThread = Thread(); // Pomiar i zapis na SD Thread measureThread = Thread(); // Pomiar i zapis na SD
TaskHandle_t uploadTaskHandle = NULL; TaskHandle_t uploadTaskHandle = NULL;
SemaphoreHandle_t sdMutex = NULL; // Mutex chroniący dostęp do karty SD
void uploadTaskCode(void *parameter) { void uploadTaskCode(void *parameter) {
Watchdog::addThisTask(); Watchdog::addThisTask();
while(true) { while(true) {
if (config.connect && WiFi.status() == WL_CONNECTED && !testingNow) { if (config.connect && WiFi.status() == WL_CONNECTED && !testingNow) {
uploadManager.processPendingUploads(); if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(1000)) == pdTRUE) {
uploadManager.processPendingUploads();
xSemaphoreGive(sdMutex);
}
} }
Watchdog::feed(); Watchdog::feed();
vTaskDelay(pdMS_TO_TICKS(5000)); // wait 5 seconds before checking again vTaskDelay(pdMS_TO_TICKS(5000));
} }
} }
@@ -190,6 +193,9 @@ void setup() {
ESP_LOGI(TAG_MAIN, "SD Card OK"); ESP_LOGI(TAG_MAIN, "SD Card OK");
display.print("OK"); display.print("OK");
// Inicjalizacja mutex SD (po SD.begin)
sdMutex = xSemaphoreCreateMutex();
ESP_LOGI(TAG_MAIN, "ADXL345 SPI3 SCK: %d, MISO: %d, MOSI: %d", CLK_ADSX, MISO_ADSX, MOSI_ADSX); ESP_LOGI(TAG_MAIN, "ADXL345 SPI3 SCK: %d, MISO: %d, MOSI: %d", CLK_ADSX, MISO_ADSX, MOSI_ADSX);
SPI_ADXL.begin(CLK_ADSX, MISO_ADSX, MOSI_ADSX); SPI_ADXL.begin(CLK_ADSX, MISO_ADSX, MOSI_ADSX);
@@ -361,8 +367,9 @@ void measure(){
snprintf(btime, sizeof(btime), "%02d:%02d:%02d", now.hour(), now.minute(), now.second()); snprintf(btime, sizeof(btime), "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
display.initMeasure(config.measure, testingNow, runMeasure, config.pause, config.duration, config.connect, licznik, bdate, btime); display.initMeasure(config.measure, testingNow, runMeasure, config.pause, config.duration, config.connect, licznik, bdate, btime);
ESP_LOGI(TAG_MAIN, "MEASURE RUNNING"); ESP_LOGI(TAG_MAIN, "MEASURE RUNNING");
//delay(1000); xSemaphoreTake(sdMutex, portMAX_DELAY);
capture.captureAuto(config.duration, "/"); capture.captureAuto(config.duration, "/");
testingNow = false; testingNow = false;
Watchdog::feed(); Watchdog::feed();
if(!capture.isExit){ if(!capture.isExit){
@@ -372,6 +379,7 @@ void measure(){
} else { } else {
ESP_LOGI(TAG_MAIN, "MEASURE INTERRUPT"); ESP_LOGI(TAG_MAIN, "MEASURE INTERRUPT");
} }
xSemaphoreGive(sdMutex);
runMeasure = false; runMeasure = false;
ESP_LOGI(TAG_MAIN, "DISPLAY Offline"); ESP_LOGI(TAG_MAIN, "DISPLAY Offline");