#ifndef IGNITION_LEARNING_H #define IGNITION_LEARNING_H #include #include "config.h" // Размеры таблиц обучения #define LOAD_POINTS 16 // Точки по нагрузке #define RPM_POINTS 16 // Точки по оборотам class IgnitionLearningTable { private: float cells[LOAD_POINTS][RPM_POINTS]; // Таблица коррекции УОЗ float loadPoints[LOAD_POINTS]; // Точки по нагрузке (кПа) float rpmPoints[RPM_POINTS]; // Точки по оборотам float learningRate; // Скорость обучения float maxCorrection; // Максимальная коррекция float minCorrection; // Минимальная коррекция float knockThreshold; // Порог детонации float knockProtectionOffset; // Защитное смещение при детонации // История детонации для каждой ячейки uint8_t knockHistory[LOAD_POINTS][RPM_POINTS]; uint8_t knockHistorySize; // Вспомогательные методы int findNearestIndex(float value, const float* points, int size); float interpolate2D(float load, float rpm); void updateCell(int loadIdx, int rpmIdx, float correction); void updateKnockHistory(int loadIdx, int rpmIdx, bool knockDetected); public: IgnitionLearningTable(); // Основные методы void begin(); float getCorrection(float load, float rpm); void learn(float load, float rpm, float knockLevel); void reset(); // Методы сохранения/загрузки bool save(); bool load(); // Настройка параметров void setLearningRate(float rate); void setCorrectionLimits(float min, float max); void setKnockParameters(float threshold, float protection); // Доступ к данным для визуализации float getCellValue(int loadIdx, int rpmIdx); float getLoadPoint(int idx); float getRPMPoint(int idx); uint8_t getKnockCount(int loadIdx, int rpmIdx); }; #endif