Spaces:
Running
Running
| // Вспомогательные функции для преобразования значений | |
| 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(); | |
| } | |