#include "idle_control.h" #include "config.h" #include #include "maps.h" 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 }