Spaces:
Running
Running
IdleController::IdleController() : | |
targetRPM(800), | |
currentPosition(0), | |
lastUpdateTime(0), | |
isAirConditionerOn(false), | |
engineTemp(20.0), | |
engineControl(nullptr), | |
pid(0.1, 0.05, 0.02) // Начальные значения коэффициентов ПИД | |
{ | |
} | |
void IdleController::begin() { | |
// Настройка ШИМ каналов для РХХ | |
ledcSetup(0, IDLE_VALVE_PWM_FREQ, IDLE_VALVE_PWM_RES); // Канал 0 для пина A | |
ledcSetup(1, IDLE_VALVE_PWM_FREQ, IDLE_VALVE_PWM_RES); // Канал 1 для пина B | |
ledcAttachPin(IDLE_VALVE_PIN_A, 0); // Привязываем пин A к каналу 0 | |
ledcAttachPin(IDLE_VALVE_PIN_B, 1); // Привязываем пин B к каналу 1 | |
// Начальные значения ШИМ | |
ledcWrite(0, 0); | |
ledcWrite(1, 0); | |
// Инициализация ПИД-регулятора | |
pid.SetMode(true); // Включаем автоматический режим | |
pid.SetOutputLimits(0, 255); | |
pid.SetSampleTime(50); | |
lastUpdateTime = millis(); | |
// Установка начального положения | |
updateValvePosition(0); | |
} | |
void IdleController::updateValvePosition(float position) { | |
position = constrain(position, 0, 255); | |
currentPosition = position; | |
// Преобразование позиции в ШИМ | |
int pwmValue = mapf(position, 0, 255, 0, (1 << IDLE_VALVE_PWM_RES) - 1); | |
// Управление моторчиком РХХ | |
ledcWrite(0, pwmValue); | |
ledcWrite(1, 0); | |
} | |
void IdleController::update(float currentRPM) { | |
unsigned long currentTime = millis(); | |
float dt = (currentTime - lastUpdateTime) / 1000.0; | |
lastUpdateTime = currentTime; | |
// Проверяем наличие объекта управления двигателем | |
if (!engineControl) return; | |
// Получаем текущую температуру двигателя | |
float engineTemp = engineControl->getEngineTemp(); | |
// Корректируем целевые обороты в зависимости от температуры | |
float adjustedTargetRpm = targetRPM; | |
if (engineTemp < 60) { // Если двигатель холодный | |
adjustedTargetRpm += (60 - engineTemp) * 6.67f; // Увеличиваем на 400 RPM при 0°C, линейно уменьшая до 60°C | |
} | |
// Добавляем компенсацию для кондиционера | |
if (isAirConditionerOn) { | |
adjustedTargetRpm += 50; // Увеличиваем на 50 RPM при включенном кондиционере | |
} | |
// Обновляем ПИД | |
pid.SetSetpoint(adjustedTargetRpm); | |
pid.SetInput(currentRPM); | |
if (pid.Compute()) { | |
// Применяем выход ПИД к положению РХХ | |
setPosition(pid.GetOutput()); | |
} | |
} | |
void IdleController::setEngineTemperature(float temp) { | |
engineTemp = temp; | |
} | |
void IdleController::setAirConditioner(bool isOn) { | |
isAirConditionerOn = isOn; | |
} | |
void IdleController::loadSettings() { | |
// Здесь должна быть загрузка настроек из EEPROM или SD | |
// Пока используем значения по умолчанию | |
settings.targetRPM = 800; | |
settings.valveMinPosition = 0; | |
settings.valveMaxPosition = 255; | |
settings.rpmTolerance = 50; | |
} | |
void IdleController::saveSettings() { | |
// Здесь должно быть сохранение настроек в EEPROM или SD | |
} | |