#include "engine_control.h" #include "config.h" #include // Вспомогательные функции для преобразования значений float mapf(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } EngineControl::EngineControl() : rpm(0), map(0), tps(0), lambda(0), knockLevel(0), engineTemp(0), voltage(0), learningEnabled(false), knockEvents(0), currentFuelCorrection(1.0), currentIgnitionCorrection(0.0) { } void EngineControl::begin() { // Настройка пинов pinMode(HALL_SENSOR_PIN, INPUT); pinMode(MAP_SENSOR_PIN, INPUT); pinMode(TPS_PIN, INPUT); pinMode(LAMBDA_SENSOR_PIN, INPUT); pinMode(ENGINE_TEMP_SENSOR_PIN, INPUT); pinMode(BATTERY_VOLTAGE_PIN, INPUT); pinMode(KNOCK_SENSOR_1_3_PIN, INPUT); pinMode(KNOCK_SENSOR_4_5_PIN, INPUT); // Загрузка таблиц обучения fuelLearning.load(); ignitionLearning.load(); } void EngineControl::update() { // Чтение сенсоров rpm = analogRead(HALL_SENSOR_PIN); map = analogRead(MAP_SENSOR_PIN); tps = analogRead(TPS_PIN); lambda = analogRead(LAMBDA_SENSOR_PIN); engineTemp = analogRead(ENGINE_TEMP_SENSOR_PIN); voltage = analogRead(BATTERY_VOLTAGE_PIN); // Преобразование значений АЦП rpm = mapf(rpm, 0, 4095, 0, 7000); map = mapf(map, 0, 4095, 0, 100); tps = mapf(tps, 0, 4095, 0, 100); lambda = mapf(lambda, 0, 4095, 0.7, 1.3); engineTemp = mapf(engineTemp, 0, 4095, -40, 150); voltage = mapf(voltage, 0, 4095, 0, 15); if (learningEnabled && rpm > START_RPM_THRESHOLD) { float engineLoad = map; // В данном случае используем MAP как нагрузку // Обучение топливоподачи по лямбда-зонду if (lambda < 0.98) { fuelLearning.update(engineLoad, rpm, 0.98); } else if (lambda > 1.02) { fuelLearning.update(engineLoad, rpm, 1.02); } // Чтение датчиков детонации float knock1 = analogRead(KNOCK_SENSOR_1_3_PIN); float knock2 = analogRead(KNOCK_SENSOR_4_5_PIN); knockLevel = max(knock1, knock2); // Обучение УОЗ по детонации ignitionLearning.learn(engineLoad, rpm, knockLevel); // Если была детонация, увеличиваем счетчик if (knockLevel > DETONATION_THRESHOLD) { knockEvents++; } } // Получение текущих коррекций float engineLoad = map; currentFuelCorrection = fuelLearning.getCorrection(engineLoad, rpm); currentIgnitionCorrection = ignitionLearning.getCorrection(engineLoad, rpm); } float EngineControl::getLearningProgress() const { return (fuelLearning.getProgress() + ignitionLearning.getProgress()) / 2.0; } float EngineControl::getIgnitionAdvance() { float engineLoad = map; float baseAdvance = 10.0; // Базовый УОЗ // Добавляем коррекцию от обучения float ignitionCorr = ignitionLearning.getCorrection(engineLoad, rpm); return baseAdvance + ignitionCorr; } bool EngineControl::saveLearningTables() { return fuelLearning.save() && ignitionLearning.save(); } bool EngineControl::loadLearningTables() { return fuelLearning.load() && ignitionLearning.load(); }