11 return "/calibration/custom.csv";
18 if (!LittleFS.begin(
true))
20 logError(
"LittleFS не инициализирован");
25 if (!LittleFS.exists(
"/calibration"))
27 LittleFS.mkdir(
"/calibration");
31 logSuccess(
"LittleFS инициализирован, доступен каталог /calibration");
37 if (!
init())
return false;
40 File f = LittleFS.open(path,
"w");
43 logError(
"Не удалось открыть файл %s для записи", path);
47 while (fileStream.available())
49 uint8_t b = fileStream.read();
54 logSuccess(
"Калибровочная таблица %s сохранена (%d байт)", path, f.size());
61 if (!
init())
return false;
63 File f = LittleFS.open(path,
"r");
66 logWarn(
"Нет калибровочной таблицы %s", path);
71 while (f.available() && outCount < maxEntries)
73 line = f.readStringUntil(
'\n');
75 if (line.length() == 0)
continue;
76 if (line[0] ==
'#')
continue;
79 if (!isDigit(line[0]) && line[0] !=
'-')
continue;
81 int comma = line.indexOf(
',');
82 if (comma < 0)
continue;
84 float raw = line.substring(0, comma).toFloat();
85 float corr = line.substring(comma + 1).toFloat();
86 outBuffer[outCount++] = {raw, corr};
90 logInfo(
"Загружено %d записей из %s", outCount, path);
96 if (!
init())
return false;
102 if (!
init())
return false;
104 if (LittleFS.exists(path))
106 return LittleFS.remove(path);
119 constexpr size_t MAX_ENTRIES = 100;
123 if (!
loadTable(profile, entries, MAX_ENTRIES, entryCount) || entryCount == 0) {
128 float lowerRaw = entries[0].
raw;
130 float upperRaw = entries[entryCount - 1].
raw;
131 float upperCorr = entries[entryCount - 1].
corrected;
134 for (
size_t i = 0; i < entryCount; i++) {
135 if (entries[i].raw == rawValue) {
140 if (entries[i].raw < rawValue) {
141 lowerRaw = entries[i].
raw;
143 }
else if (entries[i].raw > rawValue) {
144 upperRaw = entries[i].
raw;
151 if (upperRaw > lowerRaw) {
152 float ratio = (rawValue - lowerRaw) / (upperRaw - lowerRaw);
153 float interpolatedCoeff = lowerCorr + ratio * (upperCorr - lowerCorr);
154 return rawValue * interpolatedCoeff;
157 return rawValue * lowerCorr;
void logWarn(const char *format,...)
void logSuccess(const char *format,...)
void logError(const char *format,...)
void logInfo(const char *format,...)
Система логгирования с красивым форматированием
bool deleteTable(SoilProfile profile)
bool loadTable(SoilProfile profile, CalibrationEntry *outBuffer, size_t maxEntries, size_t &outCount)
bool hasTable(SoilProfile profile)
const char * profileToFilename(SoilProfile)
float applyCalibration(float rawValue, SoilProfile profile)
bool saveCsv(SoilProfile profile, Stream &fileStream)
Алгоритмы коррекции показаний датчиков