Dikhan1's picture
Upload 24 files
96a5049 verified
raw
history blame
7.91 kB
#ifndef CLASSES_H
#define CLASSES_H
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include "structures.h"
// Класс для работы с SD картой
class SDCardManager {
public:
bool init() {
if (!SD.begin(SD_CS_PIN, SPI, SD_SPI_SPEED)) {
Serial.println("Ошибка инициализации SD карты");
return false;
}
return true;
}
bool saveData(const char* filename, const void* data, size_t size) {
File file = SD.open(filename, FILE_WRITE);
if (!file) {
Serial.println("Ошибка открытия файла для записи");
return false;
}
size_t written = file.write((const uint8_t*)data, size);
file.close();
return written == size;
}
bool loadData(const char* filename, void* data, size_t size) {
File file = SD.open(filename, FILE_READ);
if (!file) {
Serial.println("Ошибка открытия файла для чтения");
return false;
}
size_t read = file.read((uint8_t*)data, size);
file.close();
return read == size;
}
};
// Класс для работы с PSRAM
class PSRAMManager {
private:
void* psramData;
size_t dataSize;
bool initialized;
public:
PSRAMManager() : psramData(nullptr), dataSize(0), initialized(false) {}
bool init() {
if (!psramInit()) {
Serial.println("Ошибка инициализации PSRAM");
return false;
}
// Выделяем память для всех данных
dataSize = sizeof(ConfigData) + sizeof(LearningData) + sizeof(RXXLearningData);
psramData = ps_malloc(dataSize);
if (!psramData) {
Serial.println("Ошибка выделения памяти в PSRAM");
return false;
}
initialized = true;
Serial.println("PSRAM инициализирован");
return true;
}
bool saveData(const void* data, size_t size, size_t offset) {
if (!initialized) return false;
if (offset + size > dataSize) {
Serial.println("Ошибка: превышение размера PSRAM");
return false;
}
memcpy((uint8_t*)psramData + offset, data, size);
return true;
}
bool loadData(void* data, size_t size, size_t offset) {
if (!initialized) return false;
if (offset + size > dataSize) {
Serial.println("Ошибка: превышение размера PSRAM");
return false;
}
memcpy(data, (uint8_t*)psramData + offset, size);
return true;
}
size_t getFreeMemory() {
return ESP.getFreePsram();
}
size_t getTotalMemory() {
return ESP.getPsramSize();
}
};
// Класс для работы с веб-сервером
class WebServerManager {
private:
WebServer server;
PSRAMManager psramManager;
public:
void init() {
// Инициализация WiFi
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(WEB_SSID, WEB_PASSWORD);
// Настройка маршрутов
server.on("/", HTTP_GET, [this]() {
server.send(200, "text/html", htmlPage);
});
server.on("/config", HTTP_GET, [this]() {
StaticJsonDocument<1024> doc;
ConfigData config;
if (psramManager.loadData(&config, sizeof(ConfigData), 0)) {
doc["injectionTimeMin"] = config.injectionTimeMin;
doc["injectionTimeMax"] = config.injectionTimeMax;
// ... добавьте остальные поля конфигурации
}
String response;
serializeJson(doc, response);
server.send(200, "application/json", response);
});
server.on("/config", HTTP_POST, [this]() {
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, server.arg("plain"));
if (error) {
server.send(400, "text/plain", "Ошибка разбора JSON");
return;
}
ConfigData config;
// Обновление конфигурации
config.injectionTimeMin = doc["injectionTimeMin"];
config.injectionTimeMax = doc["injectionTimeMax"];
// ... обновите остальные поля конфигурации
if (psramManager.saveData(&config, sizeof(ConfigData), 0)) {
server.send(200, "text/plain", "Конфигурация сохранена");
} else {
server.send(500, "text/plain", "Ошибка сохранения конфигурации");
}
});
server.begin();
}
void handleClient() {
server.handleClient();
}
};
// Класс для управления двигателем
class EngineManager {
private:
float currentRPM;
float currentThrottle;
float currentTemp;
float currentLambda;
public:
void updateSensors(float rpm, float throttle, float temp, float lambda) {
currentRPM = rpm;
currentThrottle = throttle;
currentTemp = temp;
currentLambda = lambda;
}
float calculateInjectionTime() {
// Базовая логика расчета времени впрыска
float baseTime = map(currentRPM, 0, MAX_RPM,
configData.injectionTimeMin,
configData.injectionTimeMax);
// Коррекция по температуре
if (configData.tempCorrectionEnabled) {
baseTime *= getTempCorrection(currentTemp);
}
// Коррекция по лямбде
if (configData.lambdaCorrectionEnabled) {
baseTime *= getLambdaCorrection(currentLambda);
}
return baseTime;
}
float calculateAdvance() {
// Базовая логика расчета УОЗ
float baseAdvance = map(currentRPM, 0, MAX_RPM,
configData.minAdvance,
configData.maxAdvance);
// Коррекция для холостого хода
if (isIdle()) {
return getIdleAdvance();
}
return baseAdvance;
}
private:
bool isIdle() {
return currentRPM >= configData.idleRpmMin &&
currentRPM <= configData.idleRpmMax &&
currentThrottle < THROTTLE_IDLE_THRESHOLD;
}
float getTempCorrection(float temp) {
// Логика коррекции по температуре
return 1.0; // Заглушка
}
float getLambdaCorrection(float lambda) {
// Логика коррекции по лямбде
return 1.0; // Заглушка
}
float getIdleAdvance() {
// Логика расчета УОЗ на холостом ходу
return map(currentRPM, configData.idleRpmMin, configData.idleRpmMax,
configData.idleAdvanceMin, configData.idleAdvanceMax);
}
};
#endif // CLASSES_H