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(); | |
} | |