File size: 3,683 Bytes
96a5049
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "idle_control.h"
#include "config.h"
#include <Arduino.h>
#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
}