File size: 3,638 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
104
105
106
107
108
109
#include "engine_control.h"
#include "config.h"
#include <Arduino.h>

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