From f3d64e938d36a80e4f2077d3d683a0c8a91af948 Mon Sep 17 00:00:00 2001 From: Lubos Petrovic Date: Mon, 30 Nov 2020 23:27:42 +0100 Subject: [PATCH] Refactoring --- BoardInterface.cpp | 0 BoardInterface.h | 0 BoardM5stackCore.cpp | 0 BoardM5stackCore.h | 33 ++ BoardTtgoT4v13.cpp | 0 BoardTtgoT4v13.h | 32 ++ CarHyundaiIoniq.cpp | 381 ++++++++++++++++++ CarHyundaiIoniq.h | 16 + CarInterface.cpp | 23 ++ CarInterface.h | 17 + CarKiaDebugObd2.cpp | 520 +++++++++++++++++++++++++ CarKiaDebugObd2.h | 16 + CarKiaEniro.cpp | 436 +++++++++++++++++++++ CarKiaEniro.h | 16 + INSTALLATION.md | 34 ++ LiveData.cpp | 37 ++ struct.h => LiveData.h | 88 ++--- README.md | 112 +----- RELEASENOTES.md | 81 ++++ car_debug_obd2_kia.h | 518 ------------------------- car_hyundai_ioniq.h | 376 ------------------ car_kia_eniro.h | 430 --------------------- car_renault_zoe.h | 66 ---- config.h | 108 +----- enirodashboard.ino | 859 ++++++++++++++++++++--------------------- menu.h | 11 +- 26 files changed, 2137 insertions(+), 2073 deletions(-) create mode 100644 BoardInterface.cpp create mode 100644 BoardInterface.h create mode 100644 BoardM5stackCore.cpp create mode 100644 BoardM5stackCore.h create mode 100644 BoardTtgoT4v13.cpp create mode 100644 BoardTtgoT4v13.h create mode 100644 CarHyundaiIoniq.cpp create mode 100644 CarHyundaiIoniq.h create mode 100644 CarInterface.cpp create mode 100644 CarInterface.h create mode 100644 CarKiaDebugObd2.cpp create mode 100644 CarKiaDebugObd2.h create mode 100644 CarKiaEniro.cpp create mode 100644 CarKiaEniro.h create mode 100644 INSTALLATION.md create mode 100644 LiveData.cpp rename struct.h => LiveData.h (69%) create mode 100644 RELEASENOTES.md delete mode 100644 car_debug_obd2_kia.h delete mode 100644 car_hyundai_ioniq.h delete mode 100644 car_kia_eniro.h delete mode 100644 car_renault_zoe.h diff --git a/BoardInterface.cpp b/BoardInterface.cpp new file mode 100644 index 0000000..e69de29 diff --git a/BoardInterface.h b/BoardInterface.h new file mode 100644 index 0000000..e69de29 diff --git a/BoardM5stackCore.cpp b/BoardM5stackCore.cpp new file mode 100644 index 0000000..e69de29 diff --git a/BoardM5stackCore.h b/BoardM5stackCore.h new file mode 100644 index 0000000..c289d05 --- /dev/null +++ b/BoardM5stackCore.h @@ -0,0 +1,33 @@ + +// Setup for m5stack core +#define USER_SETUP_LOADED 1 +#define SPI_FREQUENCY 27000000 +#define SPI_TOUCH_FREQUENCY 2500000 + +#ifdef BOARD_M5STACK_CORE + +#define USER_SETUP_LOADED 1 +#define ILI9341_DRIVER +#define M5STACK +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 14 // Chip select control pin +#define TFT_DC 27 // Data Command control pin +#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +#define TFT_BL 32 // LED back-light +#define SPI_FREQUENCY 27000000 +#define SPI_READ_FREQUENCY 5000000 +#define SPEAKER_PIN 25 +#define INVERT_DISPLAY + +#define BUTTON_LEFT 37 +#define BUTTON_MIDDLE 38 +#define BUTTON_RIGHT 39 + +#define SD_CS 4 +#define SD_MOSI 23 +#define SD_MISO 19 +#define SD_SCLK 18 + +#endif // BOARD_M5STACK_CORE diff --git a/BoardTtgoT4v13.cpp b/BoardTtgoT4v13.cpp new file mode 100644 index 0000000..e69de29 diff --git a/BoardTtgoT4v13.h b/BoardTtgoT4v13.h new file mode 100644 index 0000000..ed9d1a4 --- /dev/null +++ b/BoardTtgoT4v13.h @@ -0,0 +1,32 @@ + +// Setup for TTGO T4 v13 +#define USER_SETUP_LOADED 1 +#define SPI_FREQUENCY 27000000 +#define SPI_TOUCH_FREQUENCY 2500000 + +#ifdef BOARD_TTGO_T4 + +#define ILI9341_DRIVER +#define TFT_MISO 12 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 27 +#define TFT_DC 32 +#define TFT_RST 5 +//#define TFT_BACKLIGHT_ON HIGH +#define TFT_BL 4 + +#define USE_HSPI_PORT +//#define SPI_FREQUENCY 40000000 // Maximum for ILI9341 +#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V + +#define SD_CS 13 +#define SD_MOSI 15 +#define SD_MISO 2 +#define SD_SCLK 14 + +#define BUTTON_LEFT 38 +#define BUTTON_MIDDLE 37 +#define BUTTON_RIGHT 39 + +#endif // BOARD_TTGO_T4 diff --git a/CarHyundaiIoniq.cpp b/CarHyundaiIoniq.cpp new file mode 100644 index 0000000..7ae1991 --- /dev/null +++ b/CarHyundaiIoniq.cpp @@ -0,0 +1,381 @@ +#ifndef CARHYUNDAIIONIQ_CPP +#define CARHYUNDAIIONIQ_CPP + +#include "CarHyundaiIoniq.h" + +#define commandQueueCountHyundaiIoniq 25 +#define commandQueueLoopFromHyundaiIoniq 8 + +/** + activatethis->liveData->commandQueue +*/ +void CarHyundaiIoniq::activateCommandQueue() { + + String commandQueueHyundaiIoniq[commandQueueCountHyundaiIoniq] = { + "AT Z", // Reset all + "AT I", // Print the version ID + "AT E0", // Echo off + "AT L0", // Linefeeds off + "AT S0", // Printing of spaces on + "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) + //"AT AL", // Allow Long (>7 byte) messages + //"AT AR", // Automatically receive + //"AT H1", // Headers on (debug only) + //"AT D1", // Display of the DLC on + //"AT CAF0", // Automatic formatting off + "AT DP", + "AT ST16", + + // Loop from (HYUNDAI IONIQ) + // BMS + "ATSH7E4", + "2101", // power kw, ... + "2102", // cell voltages, screen 3 only + "2103", // cell voltages, screen 3 only + "2104", // cell voltages, screen 3 only + "2105", // soh, soc, .. + "2106", // cooling water temp + + // VMCU + "ATSH7E2", + "2101", // speed, ... + "2102", // aux, ... + + //"ATSH7Df", + //"2106", + //"220106", + + // Aircondition + // IONIQ OK + "ATSH7B3", + "220100", // in/out temp + "220102", // coolant temp1, 2 + + // BCM / TPMS + // IONIQ OK + "ATSH7A0", + "22c00b", // tire pressure/temp + + // CLUSTER MODULE + // IONIQ OK + "ATSH7C6", + "22B002", // odo + }; + + // 28kWh version + this->liveData->params.batteryTotalAvailableKWh = 28; + this->liveData->params.batModuleTempCount = 12; + + // Empty and fill command queue + for (int i = 0; i < 300; i++) { + this->liveData->commandQueue[i] = ""; + } + for (int i = 0; i < commandQueueCountHyundaiIoniq; i++) { + this->liveData->commandQueue[i] = commandQueueHyundaiIoniq[i]; + } + + this->liveData->commandQueueLoopFrom = commandQueueLoopFromHyundaiIoniq; + this->liveData->commandQueueCount = commandQueueCountHyundaiIoniq; +} + +/** + parseRowMerged +*/ +void CarHyundaiIoniq::parseRowMerged() { + + // VMCU 7E2 + if (this->liveData->currentAtshRequest.equals("ATSH7E2")) { + if (this->liveData->commandRequest.equals("2101")) { + this->liveData->params.speedKmh = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 36).c_str(), 2, false) * 0.0155; // / 100.0 *1.609 = real to gps is 1.750 + if (this->liveData->params.speedKmh < -99 || this->liveData->params.speedKmh > 200) + this->liveData->params.speedKmh = 0; + } + if (this->liveData->commandRequest.equals("2102")) { + this->liveData->params.auxPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, false); + this->liveData->params.auxCurrentAmp = - this->liveData->hexToDec(this->liveData->responseRowMerged.substring(46, 50).c_str(), 2, true) / 1000.0; + } + } + + // Cluster module 7c6 + if (this->liveData->currentAtshRequest.equals("ATSH7C6")) { + if (this->liveData->commandRequest.equals("22B002")) { + this->liveData->params.odoKm = float(strtol(this->liveData->responseRowMerged.substring(18, 24).c_str(), 0, 16)); + } + } + + // Aircon 7b3 + if (this->liveData->currentAtshRequest.equals("ATSH7B3")) { + if (this->liveData->commandRequest.equals("220100")) { + this->liveData->params.indoorTemperature = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; + this->liveData->params.outdoorTemperature = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(18, 20).c_str(), 1, false) / 2) - 40; + } + if (this->liveData->commandRequest.equals("220102") && this->liveData->responseRowMerged.substring(12, 14) == "00") { + this->liveData->params.coolantTemp1C = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false) / 2) - 40; + this->liveData->params.coolantTemp2C = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; + } + } + + // BMS 7e4 + if (this->liveData->currentAtshRequest.equals("ATSH7E4")) { + if (this->liveData->commandRequest.equals("2101")) { + this->liveData->params.cumulativeEnergyChargedKWh = float(strtol(this->liveData->responseRowMerged.substring(80, 88).c_str(), 0, 16)) / 10.0; + if (this->liveData->params.cumulativeEnergyChargedKWhStart == -1) + this->liveData->params.cumulativeEnergyChargedKWhStart = this->liveData->params.cumulativeEnergyChargedKWh; + this->liveData->params.cumulativeEnergyDischargedKWh = float(strtol(this->liveData->responseRowMerged.substring(88, 96).c_str(), 0, 16)) / 10.0; + if (this->liveData->params.cumulativeEnergyDischargedKWhStart == -1) + this->liveData->params.cumulativeEnergyDischargedKWhStart = this->liveData->params.cumulativeEnergyDischargedKWh; + this->liveData->params.availableChargePower = float(strtol(this->liveData->responseRowMerged.substring(16, 20).c_str(), 0, 16)) / 100.0; + this->liveData->params.availableDischargePower = float(strtol(this->liveData->responseRowMerged.substring(20, 24).c_str(), 0, 16)) / 100.0; + this->liveData->params.isolationResistanceKOhm = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(118, 122).c_str(), 2, true); + this->liveData->params.batFanStatus = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(58, 60).c_str(), 2, true); + this->liveData->params.batFanFeedbackHz = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(60, 62).c_str(), 2, true); + this->liveData->params.auxVoltage = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(62, 64).c_str(), 2, true) / 10.0; + this->liveData->params.batPowerAmp = - this->liveData->hexToDec(this->liveData->responseRowMerged.substring(24, 28).c_str(), 2, true) / 10.0; + this->liveData->params.batVoltage = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(28, 32).c_str(), 2, false) / 10.0; + this->liveData->params.batPowerKw = (this->liveData->params.batPowerAmp * this->liveData->params.batVoltage) / 1000.0; + if (this->liveData->params.batPowerKw < 1) // Reset charging start time + this->liveData->params.chargingStartTime = this->liveData->params.currentTime; + this->liveData->params.batPowerKwh100 = this->liveData->params.batPowerKw / this->liveData->params.speedKmh * 100; + this->liveData->params.batCellMaxV = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, false) / 50.0; + this->liveData->params.batCellMinV = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(54, 56).c_str(), 1, false) / 50.0; + this->liveData->params.batModuleTempC[0] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + this->liveData->params.batModuleTempC[1] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(38, 40).c_str(), 1, true); + this->liveData->params.batModuleTempC[2] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(40, 42).c_str(), 1, true); + this->liveData->params.batModuleTempC[3] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(42, 44).c_str(), 1, true); + this->liveData->params.batModuleTempC[4] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(44, 46).c_str(), 1, true); + //this->liveData->params.batTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(34, 36).c_str(), 1, true); + //this->liveData->params.batMaxC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 34).c_str(), 1, true); + //this->liveData->params.batMinC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(34, 36).c_str(), 1, true); + + // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) + this->liveData->params.batInletC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(48, 50).c_str(), 1, true); + if (this->liveData->params.speedKmh < 10 && this->liveData->params.batPowerKw >= 1 && this->liveData->params.socPerc > 0 && this->liveData->params.socPerc <= 100) { + if ( this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)] == -100 || this->liveData->params.batPowerKw < this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)]) + this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)] = this->liveData->params.batPowerKw; + if ( this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)] == -100 || this->liveData->params.batPowerKw > this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)]) + this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)] = this->liveData->params.batPowerKw; + this->liveData->params.chargingGraphBatMinTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batMinC; + this->liveData->params.chargingGraphBatMaxTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batMaxC; + this->liveData->params.chargingGraphHeaterTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batHeaterC; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("2102") && this->liveData->responseRowMerged.substring(10, 12) == "FF") { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(12 + (i * 2), 12 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("2103")) { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[32 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(12 + (i * 2), 12 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("2104")) { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[64 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(12 + (i * 2), 12 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("2105")) { + this->liveData->params.socPercPrevious = this->liveData->params.socPerc; + this->liveData->params.sohPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(54, 58).c_str(), 2, false) / 10.0; + this->liveData->params.socPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(66, 68).c_str(), 1, false) / 2.0; + + // Remaining battery modules (tempC) + this->liveData->params.batModuleTempC[5] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(22, 24).c_str(), 1, true); + this->liveData->params.batModuleTempC[6] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(24, 26).c_str(), 1, true); + this->liveData->params.batModuleTempC[7] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(26, 28).c_str(), 1, true); + this->liveData->params.batModuleTempC[8] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(28, 30).c_str(), 1, true); + this->liveData->params.batModuleTempC[9] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 32).c_str(), 1, true); + this->liveData->params.batModuleTempC[10] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 34).c_str(), 1, true); + this->liveData->params.batModuleTempC[11] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(34, 36).c_str(), 1, true); + + this->liveData->params.batMinC = this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[0]; + for (uint16_t i = 1; i < this->liveData->params.batModuleTempCount; i++) { + if (this->liveData->params.batModuleTempC[i] < this->liveData->params.batMinC) + this->liveData->params.batMinC = this->liveData->params.batModuleTempC[i]; + if (this->liveData->params.batModuleTempC[i] > this->liveData->params.batMaxC) + this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[i]; + } + this->liveData->params.batTempC = this->liveData->params.batMinC; + + // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) + if (this->liveData->params.socPercPrevious - this->liveData->params.socPerc > 0) { + byte index = (int(this->liveData->params.socPerc) == 4) ? 0 : (int)(this->liveData->params.socPerc / 10) + 1; + if ((int(this->liveData->params.socPerc) % 10 == 9 || int(this->liveData->params.socPerc) == 4) && this->liveData->params.soc10ced[index] == -1) { + this->liveData->params.soc10ced[index] = this->liveData->params.cumulativeEnergyDischargedKWh; + this->liveData->params.soc10cec[index] = this->liveData->params.cumulativeEnergyChargedKWh; + this->liveData->params.soc10odo[index] = this->liveData->params.odoKm; + this->liveData->params.soc10time[index] = this->liveData->params.currentTime; + } + } + this->liveData->params.batHeaterC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, true); + // + for (int i = 30; i < 32; i++) { // ai/aj position + this->liveData->params.cellVoltage[96 - 30 + i] = -1; + } + } + // BMS 7e4 + // IONIQ FAILED + if (this->liveData->commandRequest.equals("2106")) { + this->liveData->params.coolingWaterTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false); + } + } + + // TPMS 7a0 + if (this->liveData->currentAtshRequest.equals("ATSH7A0")) { + if (this->liveData->commandRequest.equals("22c00b")) { + this->liveData->params.tireFrontLeftPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireFrontRightPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(22, 24).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireRearRightPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 32).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireRearLeftPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(38, 40).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireFrontLeftTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireFrontRightTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(24, 26).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireRearRightTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 34).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireRearLeftTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(40, 42).c_str(), 2, false) - 50; // === OK Valid + } + } + +} + +/** + loadTestData +*/ +void CarHyundaiIoniq::loadTestData() { + + // VMCU ATSH7E2 + this->liveData->currentAtshRequest = "ATSH7E2"; + // 2101 + this->liveData->commandRequest = "2101"; + this->liveData->responseRowMerged = "6101FFE0000009211222062F03000000001D7734"; + this->parseRowMerged(); + // 2102 + this->liveData->commandRequest = "2102"; + this->liveData->responseRowMerged = "6102FF80000001010000009315B2888D390B08618B683900000000"; + this->parseRowMerged(); + + // "ATSH7DF", + this->liveData->currentAtshRequest = "ATSH7DF"; + + // AIRCON / ACU ATSH7B3 + this->liveData->currentAtshRequest = "ATSH7B3"; + // 220100 + this->liveData->commandRequest = "220100"; + this->liveData->responseRowMerged = "6201007E5007C8FF8A876A011010FFFF10FF10FFFFFFFFFFFFFFFFFF2EEF767D00FFFF00FFFF000000"; + this->parseRowMerged(); + // 220102 + this->liveData->commandRequest = "220102"; + this->liveData->responseRowMerged = "620102FF800000A3950000000000002600000000"; + this->parseRowMerged(); + + // BMS ATSH7E4 + this->liveData->currentAtshRequest = "ATSH7E4"; + // 220101 + this->liveData->commandRequest = "2101"; + this->liveData->responseRowMerged = "6101FFFFFFFF5026482648A3FFC30D9E181717171718170019B50FB501000090000142230001425F0000771B00007486007815D809015C0000000003E800"; + this->parseRowMerged(); + // 220102 + this->liveData->commandRequest = "2102"; + this->liveData->responseRowMerged = "6102FFFFFFFFB5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5000000"; + this->parseRowMerged(); + // 220103 + this->liveData->commandRequest = "2103"; + this->liveData->responseRowMerged = "6103FFFFFFFFB5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5000000"; + this->parseRowMerged(); + // 220104 + this->liveData->commandRequest = "2104"; + this->liveData->responseRowMerged = "6104FFFFFFFFB5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5000000"; + this->parseRowMerged(); + // 220105 + this->liveData->commandRequest = "2105"; + this->liveData->responseRowMerged = "6105FFFFFFFF00000000001717171817171726482648000150181703E81A03E801520029000000000000000000000000"; + this->parseRowMerged(); + // 220106 + this->liveData->commandRequest = "2106"; + this->liveData->responseRowMerged = "7F2112"; // n/a on ioniq + this->parseRowMerged(); + + // BCM / TPMS ATSH7A0 + this->liveData->currentAtshRequest = "ATSH7A0"; + // 22c00b + this->liveData->commandRequest = "22c00b"; + this->liveData->responseRowMerged = "62C00BFFFF0000B9510100B9510100B84F0100B54F0100AAAAAAAA"; + this->parseRowMerged(); + + // ATSH7C6 + this->liveData->currentAtshRequest = "ATSH7C6"; + // 22b002 + this->liveData->commandRequest = "22b002"; + this->liveData->responseRowMerged = "62B002E000000000AD003D2D0000000000000000"; + this->parseRowMerged(); + + /* this->liveData->params.batModule01TempC = 28; + this->liveData->params.batModule02TempC = 29; + this->liveData->params.batModule03TempC = 28; + this->liveData->params.batModule04TempC = 30; + //this->liveData->params.batTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + //this->liveData->params.batMaxC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(34, 36).c_str(), 1, true); + //this->liveData->params.batMinC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + + // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) + this->liveData->params.batMinC = this->liveData->params.batMaxC = this->liveData->params.batModule01TempC; + this->liveData->params.batMinC = (this->liveData->params.batModule02TempC < this->liveData->params.batMinC) ? this->liveData->params.batModule02TempC : this->liveData->params.batMinC ; + this->liveData->params.batMinC = (this->liveData->params.batModule03TempC < this->liveData->params.batMinC) ? this->liveData->params.batModule03TempC : this->liveData->params.batMinC ; + this->liveData->params.batMinC = (this->liveData->params.batModule04TempC < this->liveData->params.batMinC) ? this->liveData->params.batModule04TempC : this->liveData->params.batMinC ; + this->liveData->params.batMaxC = (this->liveData->params.batModule02TempC > this->liveData->params.batMaxC) ? this->liveData->params.batModule02TempC : this->liveData->params.batMaxC ; + this->liveData->params.batMaxC = (this->liveData->params.batModule03TempC > this->liveData->params.batMaxC) ? this->liveData->params.batModule03TempC : this->liveData->params.batMaxC ; + this->liveData->params.batMaxC = (this->liveData->params.batModule04TempC > this->liveData->params.batMaxC) ? this->liveData->params.batModule04TempC : this->liveData->params.batMaxC ; + this->liveData->params.batTempC = this->liveData->params.batMinC; + + // + this->liveData->params.soc10ced[10] = 2200; + this->liveData->params.soc10cec[10] = 2500; + this->liveData->params.soc10odo[10] = 13000; + this->liveData->params.soc10time[10] = 13000; + this->liveData->params.soc10ced[9] = this->liveData->params.soc10ced[10] + 6.4; + this->liveData->params.soc10cec[9] = this->liveData->params.soc10cec[10] + 0; + this->liveData->params.soc10odo[9] = this->liveData->params.soc10odo[10] + 30; + this->liveData->params.soc10time[9] = this->liveData->params.soc10time[10] + 900; + this->liveData->params.soc10ced[8] = this->liveData->params.soc10ced[9] + 6.8; + this->liveData->params.soc10cec[8] = this->liveData->params.soc10cec[9] + 0; + this->liveData->params.soc10odo[8] = this->liveData->params.soc10odo[9] + 30; + this->liveData->params.soc10time[8] = this->liveData->params.soc10time[9] + 900; + this->liveData->params.soc10ced[7] = this->liveData->params.soc10ced[8] + 7.2; + this->liveData->params.soc10cec[7] = this->liveData->params.soc10cec[8] + 0.6; + this->liveData->params.soc10odo[7] = this->liveData->params.soc10odo[8] + 30; + this->liveData->params.soc10time[7] = this->liveData->params.soc10time[8] + 900; + this->liveData->params.soc10ced[6] = this->liveData->params.soc10ced[7] + 6.7; + this->liveData->params.soc10cec[6] = this->liveData->params.soc10cec[7] + 0; + this->liveData->params.soc10odo[6] = this->liveData->params.soc10odo[7] + 30; + this->liveData->params.soc10time[6] = this->liveData->params.soc10time[7] + 900; + this->liveData->params.soc10ced[5] = this->liveData->params.soc10ced[6] + 6.7; + this->liveData->params.soc10cec[5] = this->liveData->params.soc10cec[6] + 0; + this->liveData->params.soc10odo[5] = this->liveData->params.soc10odo[6] + 30; + this->liveData->params.soc10time[5] = this->liveData->params.soc10time[6] + 900; + this->liveData->params.soc10ced[4] = this->liveData->params.soc10ced[5] + 6.4; + this->liveData->params.soc10cec[4] = this->liveData->params.soc10cec[5] + 0.3; + this->liveData->params.soc10odo[4] = this->liveData->params.soc10odo[5] + 30; + this->liveData->params.soc10time[4] = this->liveData->params.soc10time[5] + 900; + this->liveData->params.soc10ced[3] = this->liveData->params.soc10ced[4] + 6.4; + this->liveData->params.soc10cec[3] = this->liveData->params.soc10cec[4] + 0; + this->liveData->params.soc10odo[3] = this->liveData->params.soc10odo[4] + 30; + this->liveData->params.soc10time[3] = this->liveData->params.soc10time[4] + 900; + this->liveData->params.soc10ced[2] = this->liveData->params.soc10ced[3] + 5.4; + this->liveData->params.soc10cec[2] = this->liveData->params.soc10cec[3] + 0.1; + this->liveData->params.soc10odo[2] = this->liveData->params.soc10odo[3] + 30; + this->liveData->params.soc10time[2] = this->liveData->params.soc10time[3] + 900; + this->liveData->params.soc10ced[1] = this->liveData->params.soc10ced[2] + 6.2; + this->liveData->params.soc10cec[1] = this->liveData->params.soc10cec[2] + 0.1; + this->liveData->params.soc10odo[1] = this->liveData->params.soc10odo[2] + 30; + this->liveData->params.soc10time[1] = this->liveData->params.soc10time[2] + 900; + this->liveData->params.soc10ced[0] = this->liveData->params.soc10ced[1] + 2.9; + this->liveData->params.soc10cec[0] = this->liveData->params.soc10cec[1] + 0.5; + this->liveData->params.soc10odo[0] = this->liveData->params.soc10odo[1] + 15; + this->liveData->params.soc10time[0] = this->liveData->params.soc10time[1] + 900; + */ + +} + +#endif //CARHYUNDAIIONIQ_CPP diff --git a/CarHyundaiIoniq.h b/CarHyundaiIoniq.h new file mode 100644 index 0000000..32a5802 --- /dev/null +++ b/CarHyundaiIoniq.h @@ -0,0 +1,16 @@ +#ifndef CARHYUNDAIIONIQ_H +#define CARHYUNDAIIONIQ_H + +#include "CarInterface.h" + +class CarHyundaiIoniq : public CarInterface { + + private: + + public: + void activateCommandQueue() override; + void parseRowMerged() override; + void loadTestData() override; +}; + +#endif diff --git a/CarInterface.cpp b/CarInterface.cpp new file mode 100644 index 0000000..0dc7540 --- /dev/null +++ b/CarInterface.cpp @@ -0,0 +1,23 @@ +#ifndef CARINTERFACE_CPP +#define CARINTERFACE_CPP + +#include "CarInterface.h" +#include "LiveData.h" + +void CarInterface::setLiveData(LiveData* pLiveData) { + this->liveData = pLiveData; +} + +void CarInterface::activateCommandQueue() { + +} + +void CarInterface::parseRowMerged() { + +} + +void CarInterface::loadTestData() { + +} + +#endif // CARINTERFACE_CPP diff --git a/CarInterface.h b/CarInterface.h new file mode 100644 index 0000000..46966a9 --- /dev/null +++ b/CarInterface.h @@ -0,0 +1,17 @@ +#ifndef CARINTERFACE_H +#define CARINTERFACE_H + +#include "LiveData.h" + +class CarInterface { + + private: + public: + LiveData* liveData; + void setLiveData(LiveData* pLiveData); + virtual void activateCommandQueue(); + virtual void parseRowMerged(); + virtual void loadTestData(); +}; + +#endif // CARINTERFACE_H diff --git a/CarKiaDebugObd2.cpp b/CarKiaDebugObd2.cpp new file mode 100644 index 0000000..e2a3f43 --- /dev/null +++ b/CarKiaDebugObd2.cpp @@ -0,0 +1,520 @@ +#ifndef CARKIADEBUGOBD2_CPP +#define CARKIADEBUGOBD2_CPP + +#include "CarKiaDebugObd2.h" + +#define commandQueueCountDebugObd2Kia 256 +#define commandQueueLoopFromDebugObd2Kia 8 + +/** + activateCommandQueue +*/ +void CarKiaDebugObd2::activateCommandQueue() { + + String commandQueueDebugObd2Kia[commandQueueCountDebugObd2Kia] = { + "AT Z", // Reset all + "AT I", // Print the version ID + "AT E0", // Echo off + "AT L0", // Linefeeds off + "AT S0", // Printing of spaces on + "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) + "AT DP", + "AT ST16", + + // Loop from here + + // Request ID Response ID ECU name Can bus Protocol Description + // 725 72D WPS B Wireless phone charger + //"ATSH725", + //"2201", // All with negative resp. "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 736 73E VESS P Virtual Engine Sound system + //"ATSH736", + //"2201", // All with negative resp. "2202", "2203", "2101", "2102", + //"220101", // All with 62 response "220102", "22B001", "22C001", "22C101", + + // 755 75D BSD Right Blind spot detection Right + // "ATSH755", + // "2201", // ALL with negative 7F2213, etc "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 770 778 IGPM All UDS Integrated Gateway and power control module + "ATSH770", + "22BC01", // 009 62BC01400000000001AAAAAAAA + "22BC02", // 62BC0200000000 + "22BC03", // 00B 62BC03FDEE7C730A600000AAAA + "22BC04", // 00B 62BC04B33F74EA0D002042AAAA + "22BC05", // 00B 62BC05BF13200001000000AAAA + "22BC06", // 00B 62BC06B48000002C000000AAAA + "22BC07", // 00B 62BC070849DBC000101900AAAA + //"22BC08", // ALL with NEGATIVE RESPONSE "22BC09", "22BC0A", "22BC0B", "22BC0C", "22BC0D", "22BC0E", "22BC0F", + + // 783 78B AMP M Amplifier + //"ATSH783", + // "2201",// ALL with NEGATIVE RESPONSE "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 796 79E PGS C Parking Guide System + //"ATSH796", + //"2201", // ALL with NEGATIVE RESPONSE "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 7A0 7A8 BCM / TPMS B UDS Body control module 22 B0 01 to 22 B0 0E + // C Tire Pressure Monitoring "At least 22 C0 01 to 22 C0 02 & 22 C0 0B to 22 C0 0F" + "ATSH7A0", + "22B001", // 016 62B00140C20000000000000000000001010000000001AAAAAAAAAA + "22B002", // 009 62B002C00000000300AAAAAAAA + "22B003", // 018 62B003BFCB8000A23D63B164F8F7F73DF80000A400A4A4A4AAAAAA + "22B004", // 00B 62B0047402994E0E008800AAAA + "22B005", // 00B 62B0052000100000000800AAAA + "22B006", // 00B 62B0062000000000000000AAAA + "22B007", // 00B 62B007002001E000040000AAAA + "22B008", // 00B 62B00800510C2000880004AAAA + "22B009", // 00B 62B009FEEEFEEE08000800AAAA + "22B00A", // 00B 62B00AE3FEE3000040C500AAAA + //"22B00B", // 7F2231 + "22B00C", // 00B 62B00C3F00000000000000AAAA + "22B00D", // 00B 62B00DFCFCFC0000000000AAAA + "22B00E", // 00B 62B00E0800000000000000AAAA + //"22B00F", // 7F2231 + "22C001", // 01D 62C001000000002E2E02500706B5B50A098C3C0000000001FF01000101AAAAAAAAAA + "22C002", // 017 62C002FFFF0000D2E149F3D2DBDACBD2E84EBBD2E84E93AAAAAAAA + "22C003", // 021 62C00300000000444F303101002E2E02500706B5B50A098C3C0000000001FF0100AA + "22C004", // 021 62C004000000004E41303101002E2E024B0005B5B508088C3C0100000001FF0100AA + "22C005", // 021 62C005000000004E54504D0100302F02500000ABAB00008C3C0000030001FF0000AA + "22C006", // 021 62C00600000000444F303201002E2E02500706B5AB0A098C3C0000000001010100AA + "22C007", // 021 62C007000000004E41303201002E2E024B0005B5AB08088C3C0100000001010100AA + "22C008", // 021 62C00800000000434E303101002E2E02500706B5B50A098C3C0000020001FF0100AA + "22C009", // 021 62C00900000000303030360000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA + "22C00A", // 021 62C00A00000000303030370000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA + "22C00B", // 017 62C00BFFFF0000AF470100B4480100B5460100B3460100AAAAAAAA + "22C00C", // 025 62C00CFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA + "22C00D", // 025 62C00DFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA + "22C00E", // 025 62C00EFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA + "22C00F", // 025 62C00FFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA + + // 7A1 7A9 DDM B Driver door module + // "ATSH7A1", + // "2201", // All with NO DATA "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 7A2 7AA ADM B Assist door module + //"ATSH7A2", + // "2201", // ALL with NO DATA "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 7A3 7AB PSM B UDS Power Seat Module + // "ATSH7A3", + // "22B401", // All with NO DATA "22B402", "22B403", "22B404", "22B405", "22B406", "22B407", "22B408", "22B409", "22B40A", + + // 7A5 7AD SMK B UDS Smart Key + "ATSH7A5", + "22B001", // 7F2278 7F2231 + "22B002", // positive + "22B003", // positive + "22B004", // 7F2278 7F2231 + "22B005", // positive + "22B006", // positive + "22B007", // positive + "22B008", // positive + "22B009", // positive + "22B00A", // positive + + // 7B3 7BB AIRCON / ACU UDS Aircondition + "ATSH7B3", + "220100", // 026 6201007E5027C8FF7C6D6B05EFBCFFFFEFFF10FFFFFFFFFFFFBFFFFF52B3919900FFFF01FFFF000000 in/out temp + // "220101", // 7F2231 + "220102", // 014 620102FFF80000B36B0101000101003C00016E12 coolant temp1, 2 + // "220103", // 7F2231 + + // 7B7 7BF BSD Left Blind spot detection Left + "ATSH7B7", + // "2201", // ALL NEGATIVE RESP "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", + + // 7C4 7CC MFC Multi Function Camera + "ATSH7C4", + "220101", // 6201010E + "220102", // 62010200000000 + + // 7C6 7CE CM C & M UDS Cluster Module + "ATSH7C6", + "22B001", // 008 62B00100000000000000000000 + "22B002", // 00F 62B002E0000000FFA200AD8F0000000000000000 odo + "22B003", // 008 62B00398000000010000000000 + //"22B004", // NO DATA + + // 7D0 7D8 AEB UDS? Autonomous Emergency Breaking + // "ATSH7D0", + // "2201", // ALL CODES WITH NEGATIVE RESPONSE + // "2202", // "2203", // "2101", // "2102", // "220101", // "220102", // "22B001", // "22C001", // "22C101", + + // 7D1 7D9 ABS / ESP + AHB UDS + "ATSH7D1", + "22C101", // 02A 62C1015FD7E7D0FFFF00FF04D0D400000000FF7EFF0030F5010000FFFF7F6307F207FE05FF00FF3FFFFFAAAAAAAAAAAA + "22C102", // 01A 62C10237000000FFFFFFFFFFFF00FF05FFFFFF00FF5501FFFFFFAA + "22C103", // 01A 62C103BE3000000DFFF0FCFE7FFF7FFFFFFFFFFF000005B50000AA + + // 7D2 7DA AIRBAG SRS Sytem + // "ATSH7D2", + // "2101", // 7F2211 + // "2102", // 7F2211 + // "220101", // 7F2211 + // "220102", // 7F2211 + // "22B001", // 7F2211 + // "22C001", // 7F2211 + // "22C101", // 7F2211 + + // 7D4 7DC EPS Electric power steering + "ATSH7D4", + //"2101", // 7F2121 + //"2102", // 7F2121 + "220101", // 012 6201018387FD009DFFF90100000010101921AAAA + "220102", // 008 6201020000000500AAAAAAAAAA + // "22B001", // 7F2231 + // "22C001", // 7F2231 + // "22C101", // 7F2231 + + // 7DF UNKNOWN + //"ATSH7DF", + //"2106", // 013 7F2112 028 6106FFFF800000000000000300001C001C001C000600060006000F000000010000000000000000015801580158015700 + //"220106", // 01B 620106FFFFFFFF12001200307C7C00317C830000B4B3000A28EA00 + + // 7E2 7EA VMCU H & P KWP2000 Vehicle Motor Control Unit 21 01 to 21 02 & 1A 80++ + "ATSH7E2", + "2101", // 018 6101FFF8000009285A3806480300000000C4693404080805000000 speed, .. + "2102", // 027 6102F8FFFC000101000000851BB5780234FA0BAB8D1933E07F5B211C74000001010100000007000000 aux, .. + //"2103", // 7F2112 + //"1A80", // Working VIN 1A 8A 8C 8D .. + + // 7E3 7EB MCU H & P KWP2000 Motor Control Unit 21 01 to 21 06 + "ATSH7E3", + "2101", // 01E 610100007FFF0C3C00BD8D0A3300B00900002D0252025033D500C3FF68FF00000000 + "2102", // 03A 610207FFFFFF00000D000D00260008080909000001004614CDABC2CD3F005581720085CAF5265D0DC1CD0000EC3400000000000000000000FF0000000000 + "2103", // 06E 610300007FFF0000000000000000000000000000000000005C010E02FDFD040400000000000000000000000048058D0C0200160000000000AA3F000005000000AE0102000000000000000000000000000000000000000000BB0B00000000000000000000680000000000E803000000 + "2104", // 060 6104000001FF000000000000D7425D03000000000000050000007A2B00000000000000003200000000000000000000000000000000000000000000000000000000000000010000000100010001000000030000000000000000006D0000008E1B00 + "2105", // 067 6105000001FF630200010000005900000C00630200010000000100000C006B0200020000003300250D0136010096BA03000100000C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + "2106", // 013 6106000000030000000000000000000000000300 + //"2107", // 7F2112 + + // 7E4 7EC BMS P UDS Battery Management System 22 01 01 to 22 01 06 + "ATSH7E4", + "220101", // 03E 620101FFF7E7FF6B0000000003001C0E2F161414141513000012B930B9380000830003E1E30003C95B0001722C00015B5B0040D1660D016B0000000003E8 power kw, .. + "220102", // 027 620102FFFFFFFFB9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9AAAA cell voltages, screen 3 only + "220103", // 027 620103FFFFFFFFB9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9AAAA cell voltages, screen 3 only + "220104", // 027 620104FFFFFFFFB9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9AAAA + "220105", // 02E 620105003FFF90000000000000000012836A0142684268000150126E03E8000000006E0000B9B900000F00000000AAAA soh, soc, . + "220106", // 01B 620106FFFFFFFF12001200307C7C00007C030000B4B3000A28EA00 cooling water temp + // "220107", // 7F2231 + + // 7E5 7ED OBC KWP2000 OnBoard Charger 21 01 to 21 03 + "ATSH7E5", + "2101", // 01A 6101DFE0000001010001000000000E2F0533051D0078000000C800 + "2102", // 011 6102FE000000000403E8000001BF000028000000 + "2103", // 039 6103FFFFFDF80000000000000000000000000000000000000000000000000000000000000000007576767600000000000000000004000400030000000000 + "2104", // 022 6104FFF000000A280A280A280000E324006900000003000000000000000000000000 + "2105", // 046 61050000000081AA791E8013791E779C791E8BD37907874A79108D67791473777915727E7914753179156FAE7917768F79147650792876257930757E7914759379167545791D000000000000 + "2106", // 028 6106FFFF8000001C001C001C000600060006000E000000010000000000000000015801580158015800 + //"2107", // ret 7F2112 + + // 7E6 7EE ?? ?? 21 08 05 to 21 08 0F -> All negative response + //"ATSH7E6", + //"210805", // ret 7F2112 + //"210806", // ret 7F2112 + //"210807", // ret 7F2112 + }; + + // 39 or 64 kWh model? + this->liveData->params.batteryTotalAvailableKWh = 64; + + // Empty and fill command queue + for (uint16_t i = 0; i < 300; i++) { + this->liveData->commandQueue[i] = ""; + } + for (uint16_t i = 0; i < commandQueueCountDebugObd2Kia; i++) { + this->liveData->commandQueue[i] = commandQueueDebugObd2Kia[i]; + } + + this->liveData->commandQueueLoopFrom = commandQueueLoopFromDebugObd2Kia; + this->liveData->commandQueueCount = commandQueueCountDebugObd2Kia; +} + +/** + parseRowMerged +*/ +void CarKiaDebugObd2::parseRowMerged() { + + // VMCU 7E2 + if (this->liveData->currentAtshRequest.equals("ATSH7E2")) { + if (this->liveData->commandRequest.equals("2101")) { + this->liveData->params.speedKmh = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 36).c_str(), 2, false) * 0.0155; // / 100.0 *1.609 = real to gps is 1.750 + if (this->liveData->params.speedKmh < -99 || this->liveData->params.speedKmh > 200) + this->liveData->params.speedKmh = 0; + } + if (this->liveData->commandRequest.equals("2102")) { + this->liveData->params.auxPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, false); + this->liveData->params.auxCurrentAmp = - this->liveData->hexToDec(this->liveData->responseRowMerged.substring(46, 50).c_str(), 2, true) / 1000.0; + } + } + + // Cluster module 7c6 + if (this->liveData->currentAtshRequest.equals("ATSH7C6")) { + if (this->liveData->commandRequest.equals("22B002")) { + this->liveData->params.odoKm = float(strtol(this->liveData->responseRowMerged.substring(18, 24).c_str(), 0, 16)); + } + } + + // Aircon 7b3 + if (this->liveData->currentAtshRequest.equals("ATSH7B3")) { + if (this->liveData->commandRequest.equals("220100")) { + this->liveData->params.indoorTemperature = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; + this->liveData->params.outdoorTemperature = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(18, 20).c_str(), 1, false) / 2) - 40; + } + if (this->liveData->commandRequest.equals("220102") && this->liveData->responseRowMerged.substring(12, 14) == "00") { + this->liveData->params.coolantTemp1C = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false) / 2) - 40; + this->liveData->params.coolantTemp2C = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; + } + } + + // BMS 7e4 + if (this->liveData->currentAtshRequest.equals("ATSH7E4")) { + if (this->liveData->commandRequest.equals("220101")) { + this->liveData->params.cumulativeEnergyChargedKWh = float(strtol(this->liveData->responseRowMerged.substring(82, 90).c_str(), 0, 16)) / 10.0; + if (this->liveData->params.cumulativeEnergyChargedKWhStart == -1) + this->liveData->params.cumulativeEnergyChargedKWhStart = this->liveData->params.cumulativeEnergyChargedKWh; + this->liveData->params.cumulativeEnergyDischargedKWh = float(strtol(this->liveData->responseRowMerged.substring(90, 98).c_str(), 0, 16)) / 10.0; + if (this->liveData->params.cumulativeEnergyDischargedKWhStart == -1) + this->liveData->params.cumulativeEnergyDischargedKWhStart = this->liveData->params.cumulativeEnergyDischargedKWh; + this->liveData->params.auxVoltage = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(64, 66).c_str(), 2, true) / 10.0; + this->liveData->params.batPowerAmp = - this->liveData->hexToDec(this->liveData->responseRowMerged.substring(26, 30).c_str(), 2, true) / 10.0; + this->liveData->params.batVoltage = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 34).c_str(), 2, false) / 10.0; + this->liveData->params.batPowerKw = (this->liveData->params.batPowerAmp * this->liveData->params.batVoltage) / 1000.0; + this->liveData->params.batPowerKwh100 = this->liveData->params.batPowerKw / this->liveData->params.speedKmh * 100; + this->liveData->params.batCellMaxV = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(52, 54).c_str(), 1, false) / 50.0; + this->liveData->params.batCellMinV = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(56, 58).c_str(), 1, false) / 50.0; + this->liveData->params.batModuleTempC[0] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(38, 40).c_str(), 1, true); + this->liveData->params.batModuleTempC[1] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(40, 42).c_str(), 1, true); + this->liveData->params.batModuleTempC[2] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(42, 44).c_str(), 1, true); + this->liveData->params.batModuleTempC[3] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(44, 46).c_str(), 1, true); + //this->liveData->params.batTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + //this->liveData->params.batMaxC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(34, 36).c_str(), 1, true); + //this->liveData->params.batMinC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + + // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) + this->liveData->params.batMinC = this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[0]; + this->liveData->params.batMinC = (this->liveData->params.batModuleTempC[1] < this->liveData->params.batMinC) ? this->liveData->params.batModuleTempC[1] : this->liveData->params.batMinC; + this->liveData->params.batMinC = (this->liveData->params.batModuleTempC[2] < this->liveData->params.batMinC) ? this->liveData->params.batModuleTempC[2] : this->liveData->params.batMinC; + this->liveData->params.batMinC = (this->liveData->params.batModuleTempC[3] < this->liveData->params.batMinC) ? this->liveData->params.batModuleTempC[3] : this->liveData->params.batMinC; + this->liveData->params.batMaxC = (this->liveData->params.batModuleTempC[1] > this->liveData->params.batMaxC) ? this->liveData->params.batModuleTempC[1] : this->liveData->params.batMaxC; + this->liveData->params.batMaxC = (this->liveData->params.batModuleTempC[2] > this->liveData->params.batMaxC) ? this->liveData->params.batModuleTempC[2] : this->liveData->params.batMaxC; + this->liveData->params.batMaxC = (this->liveData->params.batModuleTempC[3] > this->liveData->params.batMaxC) ? this->liveData->params.batModuleTempC[3] : this->liveData->params.batMaxC; + this->liveData->params.batTempC = this->liveData->params.batMinC; + + this->liveData->params.batInletC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, true); + if (this->liveData->params.speedKmh < 10 && this->liveData->params.batPowerKw >= 1 && this->liveData->params.socPerc > 0 && this->liveData->params.socPerc <= 100) { + if ( this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)] == -100 || this->liveData->params.batPowerKw < this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)]) + this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)] = this->liveData->params.batPowerKw; + if ( this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)] == -100 || this->liveData->params.batPowerKw > this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)]) + this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)] = this->liveData->params.batPowerKw; + this->liveData->params.chargingGraphBatMinTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batMinC; + this->liveData->params.chargingGraphBatMaxTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batMaxC; + this->liveData->params.chargingGraphHeaterTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batHeaterC; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220102") && this->liveData->responseRowMerged.substring(12, 14) == "FF") { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220103")) { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[32 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220104")) { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[64 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220105")) { + this->liveData->params.socPercPrevious = this->liveData->params.socPerc; + this->liveData->params.sohPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(56, 60).c_str(), 2, false) / 10.0; + this->liveData->params.socPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(68, 70).c_str(), 1, false) / 2.0; + + // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) + if (this->liveData->params.socPercPrevious - this->liveData->params.socPerc > 0) { + byte index = (int(this->liveData->params.socPerc) == 4) ? 0 : (int)(this->liveData->params.socPerc / 10) + 1; + if ((int(this->liveData->params.socPerc) % 10 == 9 || int(this->liveData->params.socPerc) == 4) && this->liveData->params.soc10ced[index] == -1) { + struct tm now; + getLocalTime(&now, 0); + time_t time_now_epoch = mktime(&now); + this->liveData->params.soc10ced[index] = this->liveData->params.cumulativeEnergyDischargedKWh; + this->liveData->params.soc10cec[index] = this->liveData->params.cumulativeEnergyChargedKWh; + this->liveData->params.soc10odo[index] = this->liveData->params.odoKm; + this->liveData->params.soc10time[index] = time_now_epoch; + } + } + this->liveData->params.batHeaterC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(52, 54).c_str(), 1, true); + // + for (int i = 30; i < 32; i++) { // ai/aj position + this->liveData->params.cellVoltage[96 - 30 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220106")) { + this->liveData->params.coolingWaterTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false); + } + } + + // TPMS 7a0 + if (this->liveData->currentAtshRequest.equals("ATSH7A0")) { + if (this->liveData->commandRequest.equals("22c00b")) { + this->liveData->params.tireFrontLeftPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireFrontRightPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(22, 24).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireRearRightPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 32).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireRearLeftPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(38, 40).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireFrontLeftTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireFrontRightTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(24, 26).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireRearRightTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 34).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireRearLeftTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(40, 42).c_str(), 2, false) - 50; // === OK Valid + } + } + +} + +/** + loadTestData +*/ +void CarKiaDebugObd2::loadTestData() { + + // VMCU ATSH7E2 + this->liveData->currentAtshRequest = "ATSH7E2"; + // 2101 + this->liveData->commandRequest = "2101"; + this->liveData->responseRowMerged = "6101FFF8000009285A3B0648030000B4179D763404080805000000"; + this->parseRowMerged(); + // 2102 + this->liveData->commandRequest = "2102"; + this->liveData->responseRowMerged = "6102F8FFFC000101000000840FBF83BD33270680953033757F59291C76000001010100000007000000"; + this->liveData->responseRowMerged = "6102F8FFFC000101000000931CC77F4C39040BE09BA7385D8158832175000001010100000007000000"; + this->parseRowMerged(); + + // "ATSH7DF", + this->liveData->currentAtshRequest = "ATSH7DF"; + // 2106 + this->liveData->commandRequest = "2106"; + this->liveData->responseRowMerged = "6106FFFF800000000000000200001B001C001C000600060006000E000000010000000000000000013D013D013E013E00"; + this->parseRowMerged(); + + // AIRCON / ACU ATSH7B3 + this->liveData->currentAtshRequest = "ATSH7B3"; + // 220100 + this->liveData->commandRequest = "220100"; + this->liveData->responseRowMerged = "6201007E5027C8FF7F765D05B95AFFFF5AFF11FFFFFFFFFFFF6AFFFF2DF0757630FFFF00FFFF000000"; + this->liveData->responseRowMerged = "6201007E5027C8FF867C58121010FFFF10FF8EFFFFFFFFFFFF10FFFF0DF0617900FFFF01FFFF000000"; + this->parseRowMerged(); + + // BMS ATSH7E4 + this->liveData->currentAtshRequest = "ATSH7E4"; + // 220101 + this->liveData->commandRequest = "220101"; + this->liveData->responseRowMerged = "620101FFF7E7FF99000000000300B10EFE120F11100F12000018C438C30B00008400003864000035850000153A00001374000647010D017F0BDA0BDA03E8"; + this->liveData->responseRowMerged = "620101FFF7E7FFB3000000000300120F9B111011101011000014CC38CB3B00009100003A510000367C000015FB000013D3000690250D018E0000000003E8"; + this->parseRowMerged(); + // 220102 + this->liveData->commandRequest = "220102"; + this->liveData->responseRowMerged = "620102FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; + this->parseRowMerged(); + // 220103 + this->liveData->commandRequest = "220103"; + this->liveData->responseRowMerged = "620103FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCACBCACACFCCCBCBCBCBCBCBCBCBAAAA"; + this->parseRowMerged(); + // 220104 + this->liveData->commandRequest = "220104"; + this->liveData->responseRowMerged = "620104FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; + this->parseRowMerged(); + // 220105 + this->liveData->commandRequest = "220105"; + this->liveData->responseRowMerged = "620105003fff9000000000000000000F8A86012B4946500101500DAC03E800000000AC0000C7C701000F00000000AAAA"; + this->liveData->responseRowMerged = "620105003FFF90000000000000000014918E012927465000015013BB03E800000000BB0000CBCB01001300000000AAAA"; + this->parseRowMerged(); + // 220106 + this->liveData->commandRequest = "220106"; + this->liveData->responseRowMerged = "620106FFFFFFFF14001A00240000003A7C86B4B30000000928EA00"; + this->parseRowMerged(); + + // BCM / TPMS ATSH7A0 + this->liveData->currentAtshRequest = "ATSH7A0"; + // 22c00b + this->liveData->commandRequest = "22c00b"; + this->liveData->responseRowMerged = "62C00BFFFF0000B93D0100B43E0100B43D0100BB3C0100AAAAAAAA"; + this->parseRowMerged(); + + // ATSH7C6 + this->liveData->currentAtshRequest = "ATSH7C6"; + // 22b002 + this->liveData->commandRequest = "22b002"; + this->liveData->responseRowMerged = "62B002E0000000FFB400330B0000000000000000"; + this->parseRowMerged(); + + this->liveData->params.batModuleTempC[0] = 28; + this->liveData->params.batModuleTempC[1] = 29; + this->liveData->params.batModuleTempC[2] = 28; + this->liveData->params.batModuleTempC[3] = 30; + // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) + this->liveData->params.batMinC = this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[0]; + for (uint16_t i = 1; i < this->liveData->params.batModuleTempCount; i++) { + if (this->liveData->params.batModuleTempC[i] < this->liveData->params.batMinC) + this->liveData->params.batMinC = this->liveData->params.batModuleTempC[i]; + if (this->liveData->params.batModuleTempC[i] > this->liveData->params.batMaxC) + this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[i]; + } + this->liveData->params.batTempC = this->liveData->params.batMinC; + + // + this->liveData->params.soc10ced[10] = 2200; + this->liveData->params.soc10cec[10] = 2500; + this->liveData->params.soc10odo[10] = 13000; + this->liveData->params.soc10time[10] = 13000; + this->liveData->params.soc10ced[9] = this->liveData->params.soc10ced[10] + 6.4; + this->liveData->params.soc10cec[9] = this->liveData->params.soc10cec[10] + 0; + this->liveData->params.soc10odo[9] = this->liveData->params.soc10odo[10] + 30; + this->liveData->params.soc10time[9] = this->liveData->params.soc10time[10] + 900; + this->liveData->params.soc10ced[8] = this->liveData->params.soc10ced[9] + 6.8; + this->liveData->params.soc10cec[8] = this->liveData->params.soc10cec[9] + 0; + this->liveData->params.soc10odo[8] = this->liveData->params.soc10odo[9] + 30; + this->liveData->params.soc10time[8] = this->liveData->params.soc10time[9] + 900; + this->liveData->params.soc10ced[7] = this->liveData->params.soc10ced[8] + 7.2; + this->liveData->params.soc10cec[7] = this->liveData->params.soc10cec[8] + 0.6; + this->liveData->params.soc10odo[7] = this->liveData->params.soc10odo[8] + 30; + this->liveData->params.soc10time[7] = this->liveData->params.soc10time[8] + 900; + this->liveData->params.soc10ced[6] = this->liveData->params.soc10ced[7] + 6.7; + this->liveData->params.soc10cec[6] = this->liveData->params.soc10cec[7] + 0; + this->liveData->params.soc10odo[6] = this->liveData->params.soc10odo[7] + 30; + this->liveData->params.soc10time[6] = this->liveData->params.soc10time[7] + 900; + this->liveData->params.soc10ced[5] = this->liveData->params.soc10ced[6] + 6.7; + this->liveData->params.soc10cec[5] = this->liveData->params.soc10cec[6] + 0; + this->liveData->params.soc10odo[5] = this->liveData->params.soc10odo[6] + 30; + this->liveData->params.soc10time[5] = this->liveData->params.soc10time[6] + 900; + this->liveData->params.soc10ced[4] = this->liveData->params.soc10ced[5] + 6.4; + this->liveData->params.soc10cec[4] = this->liveData->params.soc10cec[5] + 0.3; + this->liveData->params.soc10odo[4] = this->liveData->params.soc10odo[5] + 30; + this->liveData->params.soc10time[4] = this->liveData->params.soc10time[5] + 900; + this->liveData->params.soc10ced[3] = this->liveData->params.soc10ced[4] + 6.4; + this->liveData->params.soc10cec[3] = this->liveData->params.soc10cec[4] + 0; + this->liveData->params.soc10odo[3] = this->liveData->params.soc10odo[4] + 30; + this->liveData->params.soc10time[3] = this->liveData->params.soc10time[4] + 900; + this->liveData->params.soc10ced[2] = this->liveData->params.soc10ced[3] + 5.4; + this->liveData->params.soc10cec[2] = this->liveData->params.soc10cec[3] + 0.1; + this->liveData->params.soc10odo[2] = this->liveData->params.soc10odo[3] + 30; + this->liveData->params.soc10time[2] = this->liveData->params.soc10time[3] + 900; + this->liveData->params.soc10ced[1] = this->liveData->params.soc10ced[2] + 6.2; + this->liveData->params.soc10cec[1] = this->liveData->params.soc10cec[2] + 0.1; + this->liveData->params.soc10odo[1] = this->liveData->params.soc10odo[2] + 30; + this->liveData->params.soc10time[1] = this->liveData->params.soc10time[2] + 900; + this->liveData->params.soc10ced[0] = this->liveData->params.soc10ced[1] + 2.9; + this->liveData->params.soc10cec[0] = this->liveData->params.soc10cec[1] + 0.5; + this->liveData->params.soc10odo[0] = this->liveData->params.soc10odo[1] + 15; + this->liveData->params.soc10time[0] = this->liveData->params.soc10time[1] + 900; + +} + +#endif // CARKIADEBUGOBD2_CPP diff --git a/CarKiaDebugObd2.h b/CarKiaDebugObd2.h new file mode 100644 index 0000000..35d7c64 --- /dev/null +++ b/CarKiaDebugObd2.h @@ -0,0 +1,16 @@ +#ifndef CARKIADEBUGOBD2_H +#define CARKIADEBUGOBD2_H + +#include "CarInterface.h" + +class CarKiaDebugObd2 : public CarInterface { + + private: + + public: + void activateCommandQueue() override; + void parseRowMerged() override; + void loadTestData() override; +}; + +#endif // CARKIADEBUGOBD2_H diff --git a/CarKiaEniro.cpp b/CarKiaEniro.cpp new file mode 100644 index 0000000..4987deb --- /dev/null +++ b/CarKiaEniro.cpp @@ -0,0 +1,436 @@ +#ifndef CARKIAENIRO_CPP +#define CARKIAENIRO_CPP + +#include +#include +#include +#include +#include +#include "LiveData.h" +#include "CarKiaEniro.h" + +#define commandQueueCountKiaENiro 30 +#define commandQueueLoopFromKiaENiro 10 + +/** + * activateCommandQueue + */ +void CarKiaEniro::activateCommandQueue() { + + String commandQueueKiaENiro[commandQueueCountKiaENiro] = { + "AT Z", // Reset all + "AT I", // Print the version ID + "AT S0", // Printing of spaces on + "AT E0", // Echo off + "AT L0", // Linefeeds off + "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) + //"AT AL", // Allow Long (>7 byte) messages + //"AT AR", // Automatically receive + //"AT H1", // Headers on (debug only) + //"AT D1", // Display of the DLC on + //"AT CAF0", // Automatic formatting off + ////"AT AT0", // disabled adaptive timing + "AT DP", + "AT ST16", // reduced timeout to 1, orig.16 + + // Loop from (KIA ENIRO) + + // ABS / ESP + AHB + "ATSH7D1", + "22C101", // brake, park/drive mode + + // IGPM + "ATSH770", + "22BC03", // low beam + "22BC06", // brake light + + // VMCU + "ATSH7E2", + "2101", // speed, ... + "2102", // aux, ... + + // BMS + "ATSH7E4", + "220101", // power kw, ... + "220102", // cell voltages + "220103", // cell voltages + "220104", // cell voltages + "220105", // soh, soc, .. + "220106", // cooling water temp + + // Aircondition + "ATSH7B3", + "220100", // in/out temp + "220102", // coolant temp1, 2 + + // BCM / TPMS + "ATSH7A0", + "22c00b", // tire pressure/temp + + // CLUSTER MODULE + "ATSH7C6", + "22B002", // odo + + }; + + // 39 or 64 kWh model? + this->liveData->params.batModuleTempCount = 4; + this->liveData->params.batteryTotalAvailableKWh = 64; + // =(I18*0,615)*(1+(I18*0,0008)) soc to kwh niro ev 2020 + if (this->liveData->settings.carType == CAR_KIA_ENIRO_2020_39 || this->liveData->settings.carType == CAR_HYUNDAI_KONA_2020_39) { + this->liveData->params.batteryTotalAvailableKWh = 39.2; + } + + // Empty and fill command queue + for (int i = 0; i < 300; i++) { + this->liveData->commandQueue[i] = ""; + } + for (int i = 0; i < commandQueueCountKiaENiro; i++) { + this->liveData->commandQueue[i] = commandQueueKiaENiro[i]; + } + + this->liveData->commandQueueLoopFrom = commandQueueLoopFromKiaENiro; + this->liveData->commandQueueCount = commandQueueCountKiaENiro; +} + +/** + * parseRowMerged + */ +void CarKiaEniro::parseRowMerged() { + + bool tempByte; + + // ABS / ESP + AHB 7D1 + if (this->liveData->currentAtshRequest.equals("ATSH7D1")) { + if (this->liveData->commandRequest.equals("22C101")) { + uint8_t driveMode = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(22, 24).c_str(), 1, false); + this->liveData->params.forwardDriveMode = (driveMode == 4); + this->liveData->params.reverseDriveMode = (driveMode == 2); + this->liveData->params.parkModeOrNeutral = (driveMode == 1); + } + } + + // IGPM + if (this->liveData->currentAtshRequest.equals("ATSH770")) { + if (this->liveData->commandRequest.equals("22BC03")) { + tempByte = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false); + this->liveData->params.ignitionOnPrevious = this->liveData->params.ignitionOn; + this->liveData->params.ignitionOn = (bitRead(tempByte, 5) == 1); + if (this->liveData->params.ignitionOnPrevious && !this->liveData->params.ignitionOn) + this->liveData->params.automatickShutdownTimer = this->liveData->params.currentTime; + + this->liveData->params.lightInfo = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(18, 20).c_str(), 1, false); + this->liveData->params.headLights = (bitRead(this->liveData->params.lightInfo, 5) == 1); + this->liveData->params.dayLights = (bitRead(this->liveData->params.lightInfo, 3) == 1); + } + if (this->liveData->commandRequest.equals("22BC06")) { + this->liveData->params.brakeLightInfo = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false); + this->liveData->params.brakeLights = (bitRead(this->liveData->params.brakeLightInfo, 5) == 1); + } + } + + // VMCU 7E2 + if (this->liveData->currentAtshRequest.equals("ATSH7E2")) { + if (this->liveData->commandRequest.equals("2101")) { + this->liveData->params.speedKmh = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 36).c_str(), 2, false) * 0.0155; // / 100.0 *1.609 = real to gps is 1.750 + if (this->liveData->params.speedKmh < -99 || this->liveData->params.speedKmh > 200) + this->liveData->params.speedKmh = 0; + } + if (this->liveData->commandRequest.equals("2102")) { + this->liveData->params.auxPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, false); + this->liveData->params.auxCurrentAmp = - this->liveData->hexToDec(this->liveData->responseRowMerged.substring(46, 50).c_str(), 2, true) / 1000.0; + } + } + + // Cluster module 7c6 + if (this->liveData->currentAtshRequest.equals("ATSH7C6")) { + if (this->liveData->commandRequest.equals("22B002")) { + this->liveData->params.odoKm = float(strtol(this->liveData->responseRowMerged.substring(18, 24).c_str(), 0, 16)); + } + } + + // Aircon 7b3 + if (this->liveData->currentAtshRequest.equals("ATSH7B3")) { + if (this->liveData->commandRequest.equals("220100")) { + this->liveData->params.indoorTemperature = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; + this->liveData->params.outdoorTemperature = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(18, 20).c_str(), 1, false) / 2) - 40; + } + if (this->liveData->commandRequest.equals("220102") && this->liveData->responseRowMerged.substring(12, 14) == "00") { + this->liveData->params.coolantTemp1C = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false) / 2) - 40; + this->liveData->params.coolantTemp2C = (this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; + } + } + + // BMS 7e4 + if (this->liveData->currentAtshRequest.equals("ATSH7E4")) { + if (this->liveData->commandRequest.equals("220101")) { + this->liveData->params.cumulativeEnergyChargedKWh = float(strtol(this->liveData->responseRowMerged.substring(82, 90).c_str(), 0, 16)) / 10.0; + if (this->liveData->params.cumulativeEnergyChargedKWhStart == -1) + this->liveData->params.cumulativeEnergyChargedKWhStart = this->liveData->params.cumulativeEnergyChargedKWh; + this->liveData->params.cumulativeEnergyDischargedKWh = float(strtol(this->liveData->responseRowMerged.substring(90, 98).c_str(), 0, 16)) / 10.0; + if (this->liveData->params.cumulativeEnergyDischargedKWhStart == -1) + this->liveData->params.cumulativeEnergyDischargedKWhStart = this->liveData->params.cumulativeEnergyDischargedKWh; + this->liveData->params.availableChargePower = float(strtol(this->liveData->responseRowMerged.substring(16, 20).c_str(), 0, 16)) / 100.0; + this->liveData->params.availableDischargePower = float(strtol(this->liveData->responseRowMerged.substring(20, 24).c_str(), 0, 16)) / 100.0; + //this->liveData->params.isolationResistanceKOhm = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(118, 122).c_str(), 2, true); + this->liveData->params.batFanStatus = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(60, 62).c_str(), 2, true); + this->liveData->params.batFanFeedbackHz = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(62, 64).c_str(), 2, true); + this->liveData->params.auxVoltage = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(64, 66).c_str(), 2, true) / 10.0; + this->liveData->params.batPowerAmp = - this->liveData->hexToDec(this->liveData->responseRowMerged.substring(26, 30).c_str(), 2, true) / 10.0; + this->liveData->params.batVoltage = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 34).c_str(), 2, false) / 10.0; + this->liveData->params.batPowerKw = (this->liveData->params.batPowerAmp * this->liveData->params.batVoltage) / 1000.0; + if (this->liveData->params.batPowerKw < 0) // Reset charging start time + this->liveData->params.chargingStartTime = this->liveData->params.currentTime; + this->liveData->params.batPowerKwh100 = this->liveData->params.batPowerKw / this->liveData->params.speedKmh * 100; + this->liveData->params.batCellMaxV = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(52, 54).c_str(), 1, false) / 50.0; + this->liveData->params.batCellMinV = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(56, 58).c_str(), 1, false) / 50.0; + this->liveData->params.batModuleTempC[0] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(38, 40).c_str(), 1, true); + this->liveData->params.batModuleTempC[1] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(40, 42).c_str(), 1, true); + this->liveData->params.batModuleTempC[2] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(42, 44).c_str(), 1, true); + this->liveData->params.batModuleTempC[3] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(44, 46).c_str(), 1, true); + this->liveData->params.motorRpm = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(112, 116).c_str(), 2, false); + //this->liveData->params.batTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + //this->liveData->params.batMaxC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(34, 36).c_str(), 1, true); + //this->liveData->params.batMinC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(36, 38).c_str(), 1, true); + + // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) + this->liveData->params.batMinC = this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[0]; + for (uint16_t i = 1; i < this->liveData->params.batModuleTempCount; i++) { + if (this->liveData->params.batModuleTempC[i] < this->liveData->params.batMinC) + this->liveData->params.batMinC = this->liveData->params.batModuleTempC[i]; + if (this->liveData->params.batModuleTempC[i] > this->liveData->params.batMaxC) + this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[i]; + } + this->liveData->params.batTempC = this->liveData->params.batMinC; + + this->liveData->params.batInletC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(50, 52).c_str(), 1, true); + if (this->liveData->params.speedKmh < 10 && this->liveData->params.batPowerKw >= 1 && this->liveData->params.socPerc > 0 && this->liveData->params.socPerc <= 100) { + if ( this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)] < 0 || this->liveData->params.batPowerKw < this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)]) + this->liveData->params.chargingGraphMinKw[int(this->liveData->params.socPerc)] = this->liveData->params.batPowerKw; + if ( this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)] < 0 || this->liveData->params.batPowerKw > this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)]) + this->liveData->params.chargingGraphMaxKw[int(this->liveData->params.socPerc)] = this->liveData->params.batPowerKw; + this->liveData->params.chargingGraphBatMinTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batMinC; + this->liveData->params.chargingGraphBatMaxTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batMaxC; + this->liveData->params.chargingGraphHeaterTempC[int(this->liveData->params.socPerc)] = this->liveData->params.batHeaterC; + this->liveData->params.chargingGraphWaterCoolantTempC[int(this->liveData->params.socPerc)] = this->liveData->params.coolingWaterTempC; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220102") && this->liveData->responseRowMerged.substring(12, 14) == "FF") { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220103")) { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[32 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220104")) { + for (int i = 0; i < 32; i++) { + this->liveData->params.cellVoltage[64 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220105")) { + this->liveData->params.socPercPrevious = this->liveData->params.socPerc; + this->liveData->params.sohPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(56, 60).c_str(), 2, false) / 10.0; + this->liveData->params.socPerc = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(68, 70).c_str(), 1, false) / 2.0; + + // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) + if (this->liveData->params.socPercPrevious - this->liveData->params.socPerc > 0) { + byte index = (int(this->liveData->params.socPerc) == 4) ? 0 : (int)(this->liveData->params.socPerc / 10) + 1; + if ((int(this->liveData->params.socPerc) % 10 == 9 || int(this->liveData->params.socPerc) == 4) && this->liveData->params.soc10ced[index] == -1) { + this->liveData->params.soc10ced[index] = this->liveData->params.cumulativeEnergyDischargedKWh; + this->liveData->params.soc10cec[index] = this->liveData->params.cumulativeEnergyChargedKWh; + this->liveData->params.soc10odo[index] = this->liveData->params.odoKm; + this->liveData->params.soc10time[index] = this->liveData->params.currentTime; + } + } + this->liveData->params.bmsUnknownTempA = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 32).c_str(), 1, true); + this->liveData->params.batHeaterC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(52, 54).c_str(), 1, true); + this->liveData->params.bmsUnknownTempB = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(82, 84).c_str(), 1, true); + // + for (int i = 30; i < 32; i++) { // ai/aj position + this->liveData->params.cellVoltage[96 - 30 + i] = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; + } + } + // BMS 7e4 + if (this->liveData->commandRequest.equals("220106")) { + this->liveData->params.coolingWaterTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 1, false); + this->liveData->params.bmsUnknownTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(18, 20).c_str(), 1, true); + this->liveData->params.bmsUnknownTempD = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(46, 48).c_str(), 1, true); + } + } + + // TPMS 7a0 + if (this->liveData->currentAtshRequest.equals("ATSH7A0")) { + if (this->liveData->commandRequest.equals("22c00b")) { + this->liveData->params.tireFrontLeftPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(14, 16).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireFrontRightPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(22, 24).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireRearRightPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(30, 32).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireRearLeftPressureBar = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(38, 40).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 + this->liveData->params.tireFrontLeftTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(16, 18).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireFrontRightTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(24, 26).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireRearRightTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(32, 34).c_str(), 2, false) - 50; // === OK Valid + this->liveData->params.tireRearLeftTempC = this->liveData->hexToDec(this->liveData->responseRowMerged.substring(40, 42).c_str(), 2, false) - 50; // === OK Valid + } + } +} + +/** + * loadTestData + */ +void CarKiaEniro::loadTestData() { + + // IGPM + this->liveData->currentAtshRequest = "ATSH770"; + // 22BC03 + this->liveData->commandRequest = "22BC03"; + this->liveData->responseRowMerged = "62BC03FDEE7C730A600000AAAA"; + this->parseRowMerged(); + + // ABS / ESP + AHB ATSH7D1 + this->liveData->currentAtshRequest = "ATSH7D1"; + // 2101 + this->liveData->commandRequest = "22C101"; + this->liveData->responseRowMerged = "62C1015FD7E7D0FFFF00FF04D0D400000000FF7EFF0030F5010000FFFF7F6307F207FE05FF00FF3FFFFFAAAAAAAAAAAA"; + this->parseRowMerged(); + + // VMCU ATSH7E2 + this->liveData->currentAtshRequest = "ATSH7E2"; + // 2101 + this->liveData->commandRequest = "2101"; + this->liveData->responseRowMerged = "6101FFF8000009285A3B0648030000B4179D763404080805000000"; + this->parseRowMerged(); + // 2102 + this->liveData->commandRequest = "2102"; + this->liveData->responseRowMerged = "6102F8FFFC000101000000840FBF83BD33270680953033757F59291C76000001010100000007000000"; + this->liveData->responseRowMerged = "6102F8FFFC000101000000931CC77F4C39040BE09BA7385D8158832175000001010100000007000000"; + this->parseRowMerged(); + + // "ATSH7DF", + this->liveData->currentAtshRequest = "ATSH7DF"; + // 2106 + this->liveData->commandRequest = "2106"; + this->liveData->responseRowMerged = "6106FFFF800000000000000200001B001C001C000600060006000E000000010000000000000000013D013D013E013E00"; + this->parseRowMerged(); + + // AIRCON / ACU ATSH7B3 + this->liveData->currentAtshRequest = "ATSH7B3"; + // 220100 + this->liveData->commandRequest = "220100"; + this->liveData->responseRowMerged = "6201007E5027C8FF7F765D05B95AFFFF5AFF11FFFFFFFFFFFF6AFFFF2DF0757630FFFF00FFFF000000"; + this->liveData->responseRowMerged = "6201007E5027C8FF867C58121010FFFF10FF8EFFFFFFFFFFFF10FFFF0DF0617900FFFF01FFFF000000"; + this->parseRowMerged(); + + // BMS ATSH7E4 + this->liveData->currentAtshRequest = "ATSH7E4"; + // 220101 + this->liveData->commandRequest = "220101"; + this->liveData->responseRowMerged = "620101FFF7E7FF99000000000300B10EFE120F11100F12000018C438C30B00008400003864000035850000153A00001374000647010D017F0BDA0BDA03E8"; + this->liveData->responseRowMerged = "620101FFF7E7FFB3000000000300120F9B111011101011000014CC38CB3B00009100003A510000367C000015FB000013D3000690250D018E0000000003E8"; + this->parseRowMerged(); + // 220102 + this->liveData->commandRequest = "220102"; + this->liveData->responseRowMerged = "620102FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; + this->parseRowMerged(); + // 220103 + this->liveData->commandRequest = "220103"; + this->liveData->responseRowMerged = "620103FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCACBCACACFCCCBCBCBCBCBCBCBCBAAAA"; + this->parseRowMerged(); + // 220104 + this->liveData->commandRequest = "220104"; + this->liveData->responseRowMerged = "620104FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; + this->parseRowMerged(); + // 220105 + this->liveData->commandRequest = "220105"; + this->liveData->responseRowMerged = "620105003fff9000000000000000000F8A86012B4946500101500DAC03E800000000AC0000C7C701000F00000000AAAA"; + this->liveData->responseRowMerged = "620105003FFF90000000000000000014918E012927465000015013BB03E800000000BB0000CBCB01001300000000AAAA"; + this->parseRowMerged(); + // 220106 + this->liveData->commandRequest = "220106"; + this->liveData->responseRowMerged = "620106FFFFFFFF14001A00240000003A7C86B4B30000000928EA00"; + this->parseRowMerged(); + + // BCM / TPMS ATSH7A0 + this->liveData->currentAtshRequest = "ATSH7A0"; + // 22c00b + this->liveData->commandRequest = "22c00b"; + this->liveData->responseRowMerged = "62C00BFFFF0000B93D0100B43E0100B43D0100BB3C0100AAAAAAAA"; + this->parseRowMerged(); + + // ATSH7C6 + this->liveData->currentAtshRequest = "ATSH7C6"; + // 22b002 + this->liveData->commandRequest = "22b002"; + this->liveData->responseRowMerged = "62B002E0000000FFB400330B0000000000000000"; + this->parseRowMerged(); + + this->liveData->params.batModuleTempC[0] = 28; + this->liveData->params.batModuleTempC[1] = 29; + this->liveData->params.batModuleTempC[2] = 28; + this->liveData->params.batModuleTempC[3] = 30; + + // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) + this->liveData->params.batMinC = this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[0]; + for (uint16_t i = 1; i < this->liveData->params.batModuleTempCount; i++) { + if (this->liveData->params.batModuleTempC[i] < this->liveData->params.batMinC) + this->liveData->params.batMinC = this->liveData->params.batModuleTempC[i]; + if (this->liveData->params.batModuleTempC[i] > this->liveData->params.batMaxC) + this->liveData->params.batMaxC = this->liveData->params.batModuleTempC[i]; + } + this->liveData->params.batTempC = this->liveData->params.batMinC; + + + // + this->liveData->params.soc10ced[10] = 2200; + this->liveData->params.soc10cec[10] = 2500; + this->liveData->params.soc10odo[10] = 13000; + this->liveData->params.soc10time[10] = 13000; + this->liveData->params.soc10ced[9] = this->liveData->params.soc10ced[10] + 6.4; + this->liveData->params.soc10cec[9] = this->liveData->params.soc10cec[10] + 0; + this->liveData->params.soc10odo[9] = this->liveData->params.soc10odo[10] + 30; + this->liveData->params.soc10time[9] = this->liveData->params.soc10time[10] + 900; + this->liveData->params.soc10ced[8] = this->liveData->params.soc10ced[9] + 6.8; + this->liveData->params.soc10cec[8] = this->liveData->params.soc10cec[9] + 0; + this->liveData->params.soc10odo[8] = this->liveData->params.soc10odo[9] + 30; + this->liveData->params.soc10time[8] = this->liveData->params.soc10time[9] + 900; + this->liveData->params.soc10ced[7] = this->liveData->params.soc10ced[8] + 7.2; + this->liveData->params.soc10cec[7] = this->liveData->params.soc10cec[8] + 0.6; + this->liveData->params.soc10odo[7] = this->liveData->params.soc10odo[8] + 30; + this->liveData->params.soc10time[7] = this->liveData->params.soc10time[8] + 900; + this->liveData->params.soc10ced[6] = this->liveData->params.soc10ced[7] + 6.7; + this->liveData->params.soc10cec[6] = this->liveData->params.soc10cec[7] + 0; + this->liveData->params.soc10odo[6] = this->liveData->params.soc10odo[7] + 30; + this->liveData->params.soc10time[6] = this->liveData->params.soc10time[7] + 900; + this->liveData->params.soc10ced[5] = this->liveData->params.soc10ced[6] + 6.7; + this->liveData->params.soc10cec[5] = this->liveData->params.soc10cec[6] + 0; + this->liveData->params.soc10odo[5] = this->liveData->params.soc10odo[6] + 30; + this->liveData->params.soc10time[5] = this->liveData->params.soc10time[6] + 900; + this->liveData->params.soc10ced[4] = this->liveData->params.soc10ced[5] + 6.4; + this->liveData->params.soc10cec[4] = this->liveData->params.soc10cec[5] + 0.3; + this->liveData->params.soc10odo[4] = this->liveData->params.soc10odo[5] + 30; + this->liveData->params.soc10time[4] = this->liveData->params.soc10time[5] + 900; + this->liveData->params.soc10ced[3] = this->liveData->params.soc10ced[4] + 6.4; + this->liveData->params.soc10cec[3] = this->liveData->params.soc10cec[4] + 0; + this->liveData->params.soc10odo[3] = this->liveData->params.soc10odo[4] + 30; + this->liveData->params.soc10time[3] = this->liveData->params.soc10time[4] + 900; + this->liveData->params.soc10ced[2] = this->liveData->params.soc10ced[3] + 5.4; + this->liveData->params.soc10cec[2] = this->liveData->params.soc10cec[3] + 0.1; + this->liveData->params.soc10odo[2] = this->liveData->params.soc10odo[3] + 30; + this->liveData->params.soc10time[2] = this->liveData->params.soc10time[3] + 900; + this->liveData->params.soc10ced[1] = this->liveData->params.soc10ced[2] + 6.2; + this->liveData->params.soc10cec[1] = this->liveData->params.soc10cec[2] + 0.1; + this->liveData->params.soc10odo[1] = this->liveData->params.soc10odo[2] + 30; + this->liveData->params.soc10time[1] = this->liveData->params.soc10time[2] + 900; + this->liveData->params.soc10ced[0] = this->liveData->params.soc10ced[1] + 2.9; + this->liveData->params.soc10cec[0] = this->liveData->params.soc10cec[1] + 0.5; + this->liveData->params.soc10odo[0] = this->liveData->params.soc10odo[1] + 15; + this->liveData->params.soc10time[0] = this->liveData->params.soc10time[1] + 900; + +} + +#endif // CARKIAENIRO_CPP diff --git a/CarKiaEniro.h b/CarKiaEniro.h new file mode 100644 index 0000000..a3f282a --- /dev/null +++ b/CarKiaEniro.h @@ -0,0 +1,16 @@ +#ifndef CARKIAENIRO_H +#define CARKIAENIRO_H + +#include "CarInterface.h" + +class CarKiaEniro : public CarInterface { + + private: + + public: + void activateCommandQueue() override; + void parseRowMerged() override; + void loadTestData() override; +}; + +#endif // CARKIAENIRO_H diff --git a/INSTALLATION.md b/INSTALLATION.md new file mode 100644 index 0000000..c58a6ee --- /dev/null +++ b/INSTALLATION.md @@ -0,0 +1,34 @@ +# INSTALLATION + +## Quick installation from binary files with ESP32 flash tool + +M5STACK (Many thanks to DimZen) + +https://docs.google.com/document/d/17vJmeveNfN0exQy9wKC-5igU8zzNjsuOn1DPuPV_yJA/edit?usp=sharing + +TTGO-T4 (older) + +https://docs.google.com/document/d/1nEezrtXY-8X6mQ1hiZVWDjBVse1sXQg1SlnizaRmJwU/edit?usp=sharing + +## Installation from sources +- install arduino IDE + ESP32 support +- https://github.com/Bodmer/TFT_eSPI - display library +- Configure TFT eSPI + W:\Documents\Arduino\libraries\TFT_eSP\User_Setup_Select.h +``` +// Comment +//#include // Default setup is root library folder +// And uncomment +#include // Setup file for ESP32 and TTGO T4 version 1.3 +``` + +My configuration +- Board ESP32 Dev module +- Upload speed 921600 +- CPU freq: 240MHz (Wifi/BT) +- Flash freq: 80MHz +- Flash mode: QIO +- Flash size 4MB (32mb) +- Partion scheme: default 4MB with spiffs +- Core debug level: none +- PSRAM: disable diff --git a/LiveData.cpp b/LiveData.cpp new file mode 100644 index 0000000..ad4ccbe --- /dev/null +++ b/LiveData.cpp @@ -0,0 +1,37 @@ + +#ifndef LIVEDATA_CPP +#define LIVEDATA_CPP + +#include "LiveData.h" + +/** + Hex to dec (1-2 byte values, signed/unsigned) + For 4 byte change int to long and add part for signed numbers +*/ +float LiveData::hexToDec(String hexString, byte bytes, bool signedNum) { + + unsigned int decValue = 0; + unsigned int nextInt; + + for (int i = 0; i < hexString.length(); i++) { + nextInt = int(hexString.charAt(i)); + if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9); + if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15); + if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15); + nextInt = constrain(nextInt, 0, 15); + decValue = (decValue * 16) + nextInt; + } + + // Unsigned - do nothing + if (!signedNum) { + return decValue; + } + // Signed for 1, 2 bytes + if (bytes == 1) { + return (decValue > 127 ? (float)decValue - 256.0 : decValue); + } + return (decValue > 32767 ? (float)decValue - 65536.0 : decValue); +} + +// +#endif // LIVEDATA_CPP diff --git a/struct.h b/LiveData.h similarity index 69% rename from struct.h rename to LiveData.h index 0bf51d9..c549dda 100644 --- a/struct.h +++ b/LiveData.h @@ -1,4 +1,13 @@ +#ifndef LIVEDATA_H +#define LIVEDATA_H + +#include +#include +#include +#include +#include + // SUPPORTED CARS #define CAR_KIA_ENIRO_2020_64 0 #define CAR_HYUNDAI_KONA_2020_64 1 @@ -18,21 +27,10 @@ #define SCREEN_SOC10 6 #define SCREEN_DEBUG 7 -// Commands loop -uint16_t commandQueueCount; -uint16_t commandQueueLoopFrom; -String commandQueue[300]; -String responseRow; -String responseRowMerged; -uint16_t commandQueueIndex; -bool canSendNextAtCommand = false; -String commandRequest = ""; -String currentAtshRequest = ""; - // Structure with realtime values typedef struct { - time_t currentTime; - time_t chargingStartTime; + time_t currentTime; + time_t chargingStartTime; time_t automatickShutdownTimer; #ifdef SIM800L_ENABLED time_t lastDataSent; @@ -49,7 +47,7 @@ typedef struct { uint8_t lightInfo; uint8_t brakeLightInfo; uint8_t espState; - float batteryTotalAvailableKWh; + float batteryTotalAvailableKWh; float speedKmh; float motorRpm; float odoKm; @@ -114,13 +112,13 @@ typedef struct { time_t soc10time[11]; // time for avg speed // additional /* - uint8_t bmsIgnition; - uint8_t bmsMainRelay; - uint8_t highVoltageCharging; - float inverterCapacitorVoltage; - float normalChargePort; - float rapidChargePort; - float operationTimeHours;*/ + uint8_t bmsIgnition; + uint8_t bmsMainRelay; + uint8_t highVoltageCharging; + float inverterCapacitorVoltage; + float normalChargePort; + float rapidChargePort; + float operationTimeHours;*/ } PARAMS_STRUC; // Setting stored to flash @@ -143,34 +141,26 @@ typedef struct { byte predrawnChargingGraphs; // 0 - off, 1 - on } SETTINGS_STRUC; -PARAMS_STRUC params; // Realtime sensor values -SETTINGS_STRUC settings, tmpSettings; // Settings stored into flash -/** - Hex to dec (1-2 byte values, signed/unsigned) - For 4 byte change int to long and add part for signed numbers -*/ -float hexToDec(String hexString, byte bytes = 2, bool signedNum = true) { +class LiveData { + private: + public: + // Command loop + uint16_t commandQueueCount; + uint16_t commandQueueLoopFrom; + String commandQueue[300]; + String responseRow; + String responseRowMerged; + uint16_t commandQueueIndex; + bool canSendNextAtCommand = false; + String commandRequest = ""; + String currentAtshRequest = ""; + // + PARAMS_STRUC params; // Realtime sensor values + SETTINGS_STRUC settings, tmpSettings; // Settings stored into flash + float hexToDec(String hexString, byte bytes = 2, bool signedNum = true); +}; - unsigned int decValue = 0; - unsigned int nextInt; - for (int i = 0; i < hexString.length(); i++) { - nextInt = int(hexString.charAt(i)); - if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9); - if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15); - if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15); - nextInt = constrain(nextInt, 0, 15); - decValue = (decValue * 16) + nextInt; - } - - // Unsigned - do nothing - if (!signedNum) { - return decValue; - } - // Signed for 1, 2 bytes - if (bytes == 1) { - return (decValue > 127 ? (float)decValue - 256.0 : decValue); - } - return (decValue > 32767 ? (float)decValue - 65536.0 : decValue); -} +// +#endif // LIVEDATA_H diff --git a/README.md b/README.md index 0dd09b4..f7bfad7 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,14 @@ Others ## Quick installation with ESP32 flash tool -M5STACK (Many thanks to DimZen) +See INSTALLATION.md -https://docs.google.com/document/d/17vJmeveNfN0exQy9wKC-5igU8zzNjsuOn1DPuPV_yJA/edit?usp=sharing +## RELEASE NOTES +see. RELEASENOTES.md file -TTGO-T4 (older) +## Installation from sources -https://docs.google.com/document/d/1nEezrtXY-8X6mQ1hiZVWDjBVse1sXQg1SlnizaRmJwU/edit?usp=sharing +See INSTALLATION.md ## Screens and shortcuts - Middle button - menu @@ -56,110 +57,7 @@ Screen list - no6. consumption table. Can be used to measure available battery capacity! - no7. debug screen (default off in the menu) - ![image](https://github.com/nickn17/enirodashboard/blob/master/screenshots/v1.jpg) [![Watch the video](https://github.com/nickn17/enirodashboard/blob/master/screenshots/v0.9.jpg)](https://www.youtube.com/watch?v=Jg5VP2P58Yg&) -### v1.8.3 2020-11-28 -- Automatic shutdown when car goes off -- Fixed M5stack speaker noise -- Fixed menu, added scroll support - -### v1.8.2 2020-11-25 -- Removed screen flickering. (via Sprites, esp32 with SRAM is now required!) -- Code cleaning. Removed force no/yes redraw mode. Not required with sprites -- Arrow for current (based on bat.temperature) pre-drawn charging graph - -### v1.8.1 2020-11-23 -- Pre-drawn charging graphs (based on coldgates) -- Show version in menu - -### v1.8.0 2020-11-20 -- Support for new device m5stack core1 iot development kit -- TTGO T4 is still supported device! - -### v1.7.5 2020-11-17 -- Settings: Debug screen off/on -- Settings: LCD brightness (auto, 20, 50, 100%) -- Speed screen: added motor rpm, brake lights indicator -- Soc% to kWh is now calibrated for NiroEV/KonaEV 2020 -- eNiroDashboard speed improvements - -### v1.7.4 2020-11-12 -- Added default screen option to settings -- Initial config for Renault ZOE 22kWh -- ODB response analyzer. Please help community to decode unknown values like BMS valves, heater ON switch,... - https://docs.google.com/spreadsheets/d/1eT2R8hmsD1hC__9LtnkZ3eDjLcdib9JR-3Myc97jy8M/edit?usp=sharing - -### v1.7.3 2020-11-11 -- Headlights reminder (if drive mode & headlights are off) - -### v1.7.2 2020-11-10 -- improved charging graph - -### v1.7.1 2020-10-20 -- added new screen 1 - auto mode - - automatically shows screen 3 - speed when speed is >5kph - - screen 5 chargin graph when power kw > 1kW -- added bat.fan status and fan feedback in Hz for Ioniq - -### v1.7 2020-09-16 -- added support for 39.2kWh Hyundai Kona and Kia e-Niro -- added initial support for Hyundai Ioniq 28kWh (not working yet) - -### v1.6 2020-06-30 -- fixed ble device pairing -- added command to set protocol ISO 15765-4 CAN (11 bit ID, 500 kbit/s) - some vgate adapters freezes during "init at command" phase - -### v1.5 2020-06-03 -- added support for different units (miles, fahrenheits, psi) - -### v1.4 2020-05-29 -- added menu -- Pairing with VGATE iCar Pro BLE4 adapter via menu! -- Installation with flash tool. You don't have to install Arduino and compile sources :) -- New screen 5. Conpumption... Can be used to measure available battery capacity! -- Load/Save settings -- Flip screen vertical option -- Several different improvements - -### v1.1 2020-04-12 -- added new screens (switch via left button) -- screen 0. (blank screen, lcd off) -- screen 1. (default) summary info -- screen 2. speed kmh + kwh/100km (or kw for discharge) -- screen 3. battery cells + battery module temperatures -- screen 4. charging graph -- added low batery temperature detection for slow charging on 50kW DC (15°C) and UFC >70kW (25°C). - -### v1.0 2020-03-23 -- first release -- basic dashboard - -## About T4 -ESP32-TTGO-T4 -https://github.com/fdufnews/ESP32-TTGO-T4 - -## Installation from sources -- install arduino IDE + ESP32 support -- https://github.com/Bodmer/TFT_eSPI - display library -- Configure TFT eSPI - W:\Documents\Arduino\libraries\TFT_eSP\User_Setup_Select.h -``` -// Comment -//#include // Default setup is root library folder -// And uncomment -#include // Setup file for ESP32 and TTGO T4 version 1.3 -``` - -My configuration -- Board ESP32 Dev module -- Upload speed 921600 -- CPU freq: 240MHz (Wifi/BT) -- Flash freq: 80MHz -- Flash mode: QIO -- Flash size 4MB (32mb) -- Partion scheme: default 4MB with spiffs -- Core debug level: none -- PSRAM: disable diff --git a/RELEASENOTES.md b/RELEASENOTES.md new file mode 100644 index 0000000..805031a --- /dev/null +++ b/RELEASENOTES.md @@ -0,0 +1,81 @@ +# RELEASE NOTES + +### v1.9.0 2020-11-30 +- Refactoring (classes) + +### v1.8.3 2020-11-28 +- Automatic shutdown when car goes off +- Fixed M5stack speaker noise +- Fixed menu, added scroll support + +### v1.8.2 2020-11-25 +- Removed screen flickering. (via Sprites, esp32 with SRAM is now required!) +- Code cleaning. Removed force no/yes redraw mode. Not required with sprites +- Arrow for current (based on bat.temperature) pre-drawn charging graph + +### v1.8.1 2020-11-23 +- Pre-drawn charging graphs (based on coldgates) +- Show version in menu + +### v1.8.0 2020-11-20 +- Support for new device m5stack core1 iot development kit +- TTGO T4 is still supported device! + +### v1.7.5 2020-11-17 +- Settings: Debug screen off/on +- Settings: LCD brightness (auto, 20, 50, 100%) +- Speed screen: added motor rpm, brake lights indicator +- Soc% to kWh is now calibrated for NiroEV/KonaEV 2020 +- eNiroDashboard speed improvements + +### v1.7.4 2020-11-12 +- Added default screen option to settings +- Initial config for Renault ZOE 22kWh +- ODB response analyzer. Please help community to decode unknown values like BMS valves, heater ON switch,... + https://docs.google.com/spreadsheets/d/1eT2R8hmsD1hC__9LtnkZ3eDjLcdib9JR-3Myc97jy8M/edit?usp=sharing + +### v1.7.3 2020-11-11 +- Headlights reminder (if drive mode & headlights are off) + +### v1.7.2 2020-11-10 +- improved charging graph + +### v1.7.1 2020-10-20 +- added new screen 1 - auto mode + - automatically shows screen 3 - speed when speed is >5kph + - screen 5 chargin graph when power kw > 1kW +- added bat.fan status and fan feedback in Hz for Ioniq + +### v1.7 2020-09-16 +- added support for 39.2kWh Hyundai Kona and Kia e-Niro +- added initial support for Hyundai Ioniq 28kWh (not working yet) + +### v1.6 2020-06-30 +- fixed ble device pairing +- added command to set protocol ISO 15765-4 CAN (11 bit ID, 500 kbit/s) - some vgate adapters freezes during "init at command" phase + +### v1.5 2020-06-03 +- added support for different units (miles, fahrenheits, psi) + +### v1.4 2020-05-29 +- added menu +- Pairing with VGATE iCar Pro BLE4 adapter via menu! +- Installation with flash tool. You don't have to install Arduino and compile sources :) +- New screen 5. Conpumption... Can be used to measure available battery capacity! +- Load/Save settings +- Flip screen vertical option +- Several different improvements + +### v1.1 2020-04-12 +- added new screens (switch via left button) +- screen 0. (blank screen, lcd off) +- screen 1. (default) summary info +- screen 2. speed kmh + kwh/100km (or kw for discharge) +- screen 3. battery cells + battery module temperatures +- screen 4. charging graph +- added low batery temperature detection for slow charging on 50kW DC (15°C) and UFC >70kW (25°C). + +### v1.0 2020-03-23 +- first release +- basic dashboard + diff --git a/car_debug_obd2_kia.h b/car_debug_obd2_kia.h deleted file mode 100644 index 1888dd5..0000000 --- a/car_debug_obd2_kia.h +++ /dev/null @@ -1,518 +0,0 @@ - -#define commandQueueCountDebugObd2Kia 256 -#define commandQueueLoopFromDebugObd2Kia 8 - -String commandQueueDebugObd2Kia[commandQueueCountDebugObd2Kia] = { - "AT Z", // Reset all - "AT I", // Print the version ID - "AT E0", // Echo off - "AT L0", // Linefeeds off - "AT S0", // Printing of spaces on - "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) - "AT DP", - "AT ST16", - - // Loop from here - - // Request ID Response ID ECU name Can bus Protocol Description - // 725 72D WPS B Wireless phone charger - //"ATSH725", - //"2201", // All with negative resp. "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 736 73E VESS P Virtual Engine Sound system - //"ATSH736", - //"2201", // All with negative resp. "2202", "2203", "2101", "2102", - //"220101", // All with 62 response "220102", "22B001", "22C001", "22C101", - - // 755 75D BSD Right Blind spot detection Right - // "ATSH755", - // "2201", // ALL with negative 7F2213, etc "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 770 778 IGPM All UDS Integrated Gateway and power control module - "ATSH770", - "22BC01", // 009 62BC01400000000001AAAAAAAA - "22BC02", // 62BC0200000000 - "22BC03", // 00B 62BC03FDEE7C730A600000AAAA - "22BC04", // 00B 62BC04B33F74EA0D002042AAAA - "22BC05", // 00B 62BC05BF13200001000000AAAA - "22BC06", // 00B 62BC06B48000002C000000AAAA - "22BC07", // 00B 62BC070849DBC000101900AAAA - //"22BC08", // ALL with NEGATIVE RESPONSE "22BC09", "22BC0A", "22BC0B", "22BC0C", "22BC0D", "22BC0E", "22BC0F", - - // 783 78B AMP M Amplifier - //"ATSH783", - // "2201",// ALL with NEGATIVE RESPONSE "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 796 79E PGS C Parking Guide System - //"ATSH796", - //"2201", // ALL with NEGATIVE RESPONSE "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 7A0 7A8 BCM / TPMS B UDS Body control module 22 B0 01 to 22 B0 0E - // C Tire Pressure Monitoring "At least 22 C0 01 to 22 C0 02 & 22 C0 0B to 22 C0 0F" - "ATSH7A0", - "22B001", // 016 62B00140C20000000000000000000001010000000001AAAAAAAAAA - "22B002", // 009 62B002C00000000300AAAAAAAA - "22B003", // 018 62B003BFCB8000A23D63B164F8F7F73DF80000A400A4A4A4AAAAAA - "22B004", // 00B 62B0047402994E0E008800AAAA - "22B005", // 00B 62B0052000100000000800AAAA - "22B006", // 00B 62B0062000000000000000AAAA - "22B007", // 00B 62B007002001E000040000AAAA - "22B008", // 00B 62B00800510C2000880004AAAA - "22B009", // 00B 62B009FEEEFEEE08000800AAAA - "22B00A", // 00B 62B00AE3FEE3000040C500AAAA - //"22B00B", // 7F2231 - "22B00C", // 00B 62B00C3F00000000000000AAAA - "22B00D", // 00B 62B00DFCFCFC0000000000AAAA - "22B00E", // 00B 62B00E0800000000000000AAAA - //"22B00F", // 7F2231 - "22C001", // 01D 62C001000000002E2E02500706B5B50A098C3C0000000001FF01000101AAAAAAAAAA - "22C002", // 017 62C002FFFF0000D2E149F3D2DBDACBD2E84EBBD2E84E93AAAAAAAA - "22C003", // 021 62C00300000000444F303101002E2E02500706B5B50A098C3C0000000001FF0100AA - "22C004", // 021 62C004000000004E41303101002E2E024B0005B5B508088C3C0100000001FF0100AA - "22C005", // 021 62C005000000004E54504D0100302F02500000ABAB00008C3C0000030001FF0000AA - "22C006", // 021 62C00600000000444F303201002E2E02500706B5AB0A098C3C0000000001010100AA - "22C007", // 021 62C007000000004E41303201002E2E024B0005B5AB08088C3C0100000001010100AA - "22C008", // 021 62C00800000000434E303101002E2E02500706B5B50A098C3C0000020001FF0100AA - "22C009", // 021 62C00900000000303030360000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA - "22C00A", // 021 62C00A00000000303030370000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA - "22C00B", // 017 62C00BFFFF0000AF470100B4480100B5460100B3460100AAAAAAAA - "22C00C", // 025 62C00CFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA - "22C00D", // 025 62C00DFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA - "22C00E", // 025 62C00EFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA - "22C00F", // 025 62C00FFFFF03000000000000FFFF0000000000000000FFFF0000000000000000FFFF000000AAAAAAAA - - // 7A1 7A9 DDM B Driver door module - // "ATSH7A1", - // "2201", // All with NO DATA "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 7A2 7AA ADM B Assist door module - //"ATSH7A2", - // "2201", // ALL with NO DATA "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 7A3 7AB PSM B UDS Power Seat Module - // "ATSH7A3", - // "22B401", // All with NO DATA "22B402", "22B403", "22B404", "22B405", "22B406", "22B407", "22B408", "22B409", "22B40A", - - // 7A5 7AD SMK B UDS Smart Key - "ATSH7A5", - "22B001", // 7F2278 7F2231 - "22B002", // positive - "22B003", // positive - "22B004", // 7F2278 7F2231 - "22B005", // positive - "22B006", // positive - "22B007", // positive - "22B008", // positive - "22B009", // positive - "22B00A", // positive - - // 7B3 7BB AIRCON / ACU UDS Aircondition - "ATSH7B3", - "220100", // 026 6201007E5027C8FF7C6D6B05EFBCFFFFEFFF10FFFFFFFFFFFFBFFFFF52B3919900FFFF01FFFF000000 in/out temp - // "220101", // 7F2231 - "220102", // 014 620102FFF80000B36B0101000101003C00016E12 coolant temp1, 2 - // "220103", // 7F2231 - - // 7B7 7BF BSD Left Blind spot detection Left - "ATSH7B7", - // "2201", // ALL NEGATIVE RESP "2202", "2203", "2101", "2102", "220101", "220102", "22B001", "22C001", "22C101", - - // 7C4 7CC MFC Multi Function Camera - "ATSH7C4", - "220101", // 6201010E - "220102", // 62010200000000 - - // 7C6 7CE CM C & M UDS Cluster Module - "ATSH7C6", - "22B001", // 008 62B00100000000000000000000 - "22B002", // 00F 62B002E0000000FFA200AD8F0000000000000000 odo - "22B003", // 008 62B00398000000010000000000 - //"22B004", // NO DATA - - // 7D0 7D8 AEB UDS? Autonomous Emergency Breaking - // "ATSH7D0", - // "2201", // ALL CODES WITH NEGATIVE RESPONSE - // "2202", // "2203", // "2101", // "2102", // "220101", // "220102", // "22B001", // "22C001", // "22C101", - - // 7D1 7D9 ABS / ESP + AHB UDS - "ATSH7D1", - "22C101", // 02A 62C1015FD7E7D0FFFF00FF04D0D400000000FF7EFF0030F5010000FFFF7F6307F207FE05FF00FF3FFFFFAAAAAAAAAAAA - "22C102", // 01A 62C10237000000FFFFFFFFFFFF00FF05FFFFFF00FF5501FFFFFFAA - "22C103", // 01A 62C103BE3000000DFFF0FCFE7FFF7FFFFFFFFFFF000005B50000AA - - // 7D2 7DA AIRBAG SRS Sytem - // "ATSH7D2", - // "2101", // 7F2211 - // "2102", // 7F2211 - // "220101", // 7F2211 - // "220102", // 7F2211 - // "22B001", // 7F2211 - // "22C001", // 7F2211 - // "22C101", // 7F2211 - - // 7D4 7DC EPS Electric power steering - "ATSH7D4", - //"2101", // 7F2121 - //"2102", // 7F2121 - "220101", // 012 6201018387FD009DFFF90100000010101921AAAA - "220102", // 008 6201020000000500AAAAAAAAAA - // "22B001", // 7F2231 - // "22C001", // 7F2231 - // "22C101", // 7F2231 - - // 7DF UNKNOWN - //"ATSH7DF", - //"2106", // 013 7F2112 028 6106FFFF800000000000000300001C001C001C000600060006000F000000010000000000000000015801580158015700 - //"220106", // 01B 620106FFFFFFFF12001200307C7C00317C830000B4B3000A28EA00 - - // 7E2 7EA VMCU H & P KWP2000 Vehicle Motor Control Unit 21 01 to 21 02 & 1A 80++ - "ATSH7E2", - "2101", // 018 6101FFF8000009285A3806480300000000C4693404080805000000 speed, ... - "2102", // 027 6102F8FFFC000101000000851BB5780234FA0BAB8D1933E07F5B211C74000001010100000007000000 aux, ... - //"2103", // 7F2112 - //"1A80", // Working VIN 1A 8A 8C 8D ... - - // 7E3 7EB MCU H & P KWP2000 Motor Control Unit 21 01 to 21 06 - "ATSH7E3", - "2101", // 01E 610100007FFF0C3C00BD8D0A3300B00900002D0252025033D500C3FF68FF00000000 - "2102", // 03A 610207FFFFFF00000D000D00260008080909000001004614CDABC2CD3F005581720085CAF5265D0DC1CD0000EC3400000000000000000000FF0000000000 - "2103", // 06E 610300007FFF0000000000000000000000000000000000005C010E02FDFD040400000000000000000000000048058D0C0200160000000000AA3F000005000000AE0102000000000000000000000000000000000000000000BB0B00000000000000000000680000000000E803000000 - "2104", // 060 6104000001FF000000000000D7425D03000000000000050000007A2B00000000000000003200000000000000000000000000000000000000000000000000000000000000010000000100010001000000030000000000000000006D0000008E1B00 - "2105", // 067 6105000001FF630200010000005900000C00630200010000000100000C006B0200020000003300250D0136010096BA03000100000C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - "2106", // 013 6106000000030000000000000000000000000300 - //"2107", // 7F2112 - - // 7E4 7EC BMS P UDS Battery Management System 22 01 01 to 22 01 06 - "ATSH7E4", - "220101", // 03E 620101FFF7E7FF6B0000000003001C0E2F161414141513000012B930B9380000830003E1E30003C95B0001722C00015B5B0040D1660D016B0000000003E8 power kw, ... - "220102", // 027 620102FFFFFFFFB9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9AAAA cell voltages, screen 3 only - "220103", // 027 620103FFFFFFFFB9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9AAAA cell voltages, screen 3 only - "220104", // 027 620104FFFFFFFFB9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9AAAA - "220105", // 02E 620105003FFF90000000000000000012836A0142684268000150126E03E8000000006E0000B9B900000F00000000AAAA soh, soc, .. - "220106", // 01B 620106FFFFFFFF12001200307C7C00007C030000B4B3000A28EA00 cooling water temp - // "220107", // 7F2231 - - // 7E5 7ED OBC KWP2000 OnBoard Charger 21 01 to 21 03 - "ATSH7E5", - "2101", // 01A 6101DFE0000001010001000000000E2F0533051D0078000000C800 - "2102", // 011 6102FE000000000403E8000001BF000028000000 - "2103", // 039 6103FFFFFDF80000000000000000000000000000000000000000000000000000000000000000007576767600000000000000000004000400030000000000 - "2104", // 022 6104FFF000000A280A280A280000E324006900000003000000000000000000000000 - "2105", // 046 61050000000081AA791E8013791E779C791E8BD37907874A79108D67791473777915727E7914753179156FAE7917768F79147650792876257930757E7914759379167545791D000000000000 - "2106", // 028 6106FFFF8000001C001C001C000600060006000E000000010000000000000000015801580158015800 - //"2107", // ret 7F2112 - - // 7E6 7EE ?? ?? 21 08 05 to 21 08 0F -> All negative response - //"ATSH7E6", - //"210805", // ret 7F2112 - //"210806", // ret 7F2112 - //"210807", // ret 7F2112 -}; - -/** - Init command queue -*/ -bool activateCommandQueueForDebugObd2Kia() { - - // 39 or 64 kWh model? - params.batteryTotalAvailableKWh = 64; - - // Empty and fill command queue - for (uint16_t i = 0; i < 300; i++) { - commandQueue[i] = ""; - } - for (uint16_t i = 0; i < commandQueueCountDebugObd2Kia; i++) { - commandQueue[i] = commandQueueDebugObd2Kia[i]; - } - - commandQueueLoopFrom = commandQueueLoopFromDebugObd2Kia; - commandQueueCount = commandQueueCountDebugObd2Kia; - - return true; -} - -/** - Parse merged row -*/ -bool parseRowMergedDebugObd2Kia() { - - // VMCU 7E2 - if (currentAtshRequest.equals("ATSH7E2")) { - if (commandRequest.equals("2101")) { - params.speedKmh = hexToDec(responseRowMerged.substring(32, 36).c_str(), 2, false) * 0.0155; // / 100.0 *1.609 = real to gps is 1.750 - if (params.speedKmh < -99 || params.speedKmh > 200) - params.speedKmh = 0; - } - if (commandRequest.equals("2102")) { - params.auxPerc = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, false); - params.auxCurrentAmp = - hexToDec(responseRowMerged.substring(46, 50).c_str(), 2, true) / 1000.0; - } - } - - // Cluster module 7c6 - if (currentAtshRequest.equals("ATSH7C6")) { - if (commandRequest.equals("22B002")) { - params.odoKm = float(strtol(responseRowMerged.substring(18, 24).c_str(), 0, 16)); - } - } - - // Aircon 7b3 - if (currentAtshRequest.equals("ATSH7B3")) { - if (commandRequest.equals("220100")) { - params.indoorTemperature = (hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; - params.outdoorTemperature = (hexToDec(responseRowMerged.substring(18, 20).c_str(), 1, false) / 2) - 40; - } - if (commandRequest.equals("220102") && responseRowMerged.substring(12, 14) == "00") { - params.coolantTemp1C = (hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false) / 2) - 40; - params.coolantTemp2C = (hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; - } - } - - // BMS 7e4 - if (currentAtshRequest.equals("ATSH7E4")) { - if (commandRequest.equals("220101")) { - params.cumulativeEnergyChargedKWh = float(strtol(responseRowMerged.substring(82, 90).c_str(), 0, 16)) / 10.0; - if (params.cumulativeEnergyChargedKWhStart == -1) - params.cumulativeEnergyChargedKWhStart = params.cumulativeEnergyChargedKWh; - params.cumulativeEnergyDischargedKWh = float(strtol(responseRowMerged.substring(90, 98).c_str(), 0, 16)) / 10.0; - if (params.cumulativeEnergyDischargedKWhStart == -1) - params.cumulativeEnergyDischargedKWhStart = params.cumulativeEnergyDischargedKWh; - params.auxVoltage = hexToDec(responseRowMerged.substring(64, 66).c_str(), 2, true) / 10.0; - params.batPowerAmp = - hexToDec(responseRowMerged.substring(26, 30).c_str(), 2, true) / 10.0; - params.batVoltage = hexToDec(responseRowMerged.substring(30, 34).c_str(), 2, false) / 10.0; - params.batPowerKw = (params.batPowerAmp * params.batVoltage) / 1000.0; - params.batPowerKwh100 = params.batPowerKw / params.speedKmh * 100; - params.batCellMaxV = hexToDec(responseRowMerged.substring(52, 54).c_str(), 1, false) / 50.0; - params.batCellMinV = hexToDec(responseRowMerged.substring(56, 58).c_str(), 1, false) / 50.0; - params.batModuleTempC[0] = hexToDec(responseRowMerged.substring(38, 40).c_str(), 1, true); - params.batModuleTempC[1] = hexToDec(responseRowMerged.substring(40, 42).c_str(), 1, true); - params.batModuleTempC[2] = hexToDec(responseRowMerged.substring(42, 44).c_str(), 1, true); - params.batModuleTempC[3] = hexToDec(responseRowMerged.substring(44, 46).c_str(), 1, true); - //params.batTempC = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - //params.batMaxC = hexToDec(responseRowMerged.substring(34, 36).c_str(), 1, true); - //params.batMinC = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - - // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) - params.batMinC = params.batMaxC = params.batModuleTempC[0]; - params.batMinC = (params.batModuleTempC[1] < params.batMinC) ? params.batModuleTempC[1] : params.batMinC; - params.batMinC = (params.batModuleTempC[2] < params.batMinC) ? params.batModuleTempC[2] : params.batMinC; - params.batMinC = (params.batModuleTempC[3] < params.batMinC) ? params.batModuleTempC[3] : params.batMinC; - params.batMaxC = (params.batModuleTempC[1] > params.batMaxC) ? params.batModuleTempC[1] : params.batMaxC; - params.batMaxC = (params.batModuleTempC[2] > params.batMaxC) ? params.batModuleTempC[2] : params.batMaxC; - params.batMaxC = (params.batModuleTempC[3] > params.batMaxC) ? params.batModuleTempC[3] : params.batMaxC; - params.batTempC = params.batMinC; - - params.batInletC = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, true); - if (params.speedKmh < 10 && params.batPowerKw >= 1 && params.socPerc > 0 && params.socPerc <= 100) { - if ( params.chargingGraphMinKw[int(params.socPerc)] == -100 || params.batPowerKw < params.chargingGraphMinKw[int(params.socPerc)]) - params.chargingGraphMinKw[int(params.socPerc)] = params.batPowerKw; - if ( params.chargingGraphMaxKw[int(params.socPerc)] == -100 || params.batPowerKw > params.chargingGraphMaxKw[int(params.socPerc)]) - params.chargingGraphMaxKw[int(params.socPerc)] = params.batPowerKw; - params.chargingGraphBatMinTempC[int(params.socPerc)] = params.batMinC; - params.chargingGraphBatMaxTempC[int(params.socPerc)] = params.batMaxC; - params.chargingGraphHeaterTempC[int(params.socPerc)] = params.batHeaterC; - } - } - // BMS 7e4 - if (commandRequest.equals("220102") && responseRowMerged.substring(12, 14) == "FF") { - for (int i = 0; i < 32; i++) { - params.cellVoltage[i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220103")) { - for (int i = 0; i < 32; i++) { - params.cellVoltage[32 + i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220104")) { - for (int i = 0; i < 32; i++) { - params.cellVoltage[64 + i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220105")) { - params.socPercPrevious = params.socPerc; - params.sohPerc = hexToDec(responseRowMerged.substring(56, 60).c_str(), 2, false) / 10.0; - params.socPerc = hexToDec(responseRowMerged.substring(68, 70).c_str(), 1, false) / 2.0; - - // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) - if (params.socPercPrevious - params.socPerc > 0) { - byte index = (int(params.socPerc) == 4) ? 0 : (int)(params.socPerc / 10) + 1; - if ((int(params.socPerc) % 10 == 9 || int(params.socPerc) == 4) && params.soc10ced[index] == -1) { - struct tm now; - getLocalTime(&now, 0); - time_t time_now_epoch = mktime(&now); - params.soc10ced[index] = params.cumulativeEnergyDischargedKWh; - params.soc10cec[index] = params.cumulativeEnergyChargedKWh; - params.soc10odo[index] = params.odoKm; - params.soc10time[index] = time_now_epoch; - } - } - params.batHeaterC = hexToDec(responseRowMerged.substring(52, 54).c_str(), 1, true); - // - for (int i = 30; i < 32; i++) { // ai/aj position - params.cellVoltage[96 - 30 + i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220106")) { - params.coolingWaterTempC = hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false); - } - } - - // TPMS 7a0 - if (currentAtshRequest.equals("ATSH7A0")) { - if (commandRequest.equals("22c00b")) { - params.tireFrontLeftPressureBar = hexToDec(responseRowMerged.substring(14, 16).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireFrontRightPressureBar = hexToDec(responseRowMerged.substring(22, 24).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireRearRightPressureBar = hexToDec(responseRowMerged.substring(30, 32).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireRearLeftPressureBar = hexToDec(responseRowMerged.substring(38, 40).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireFrontLeftTempC = hexToDec(responseRowMerged.substring(16, 18).c_str(), 2, false) - 50; // === OK Valid - params.tireFrontRightTempC = hexToDec(responseRowMerged.substring(24, 26).c_str(), 2, false) - 50; // === OK Valid - params.tireRearRightTempC = hexToDec(responseRowMerged.substring(32, 34).c_str(), 2, false) - 50; // === OK Valid - params.tireRearLeftTempC = hexToDec(responseRowMerged.substring(40, 42).c_str(), 2, false) - 50; // === OK Valid - } - } - - return true; -} - -/** - Test data -*/ -bool testDataDebugObd2Kia() { - - // VMCU ATSH7E2 - currentAtshRequest = "ATSH7E2"; - // 2101 - commandRequest = "2101"; - responseRowMerged = "6101FFF8000009285A3B0648030000B4179D763404080805000000"; - parseRowMergedDebugObd2Kia(); - // 2102 - commandRequest = "2102"; - responseRowMerged = "6102F8FFFC000101000000840FBF83BD33270680953033757F59291C76000001010100000007000000"; - responseRowMerged = "6102F8FFFC000101000000931CC77F4C39040BE09BA7385D8158832175000001010100000007000000"; - parseRowMergedDebugObd2Kia(); - - // "ATSH7DF", - currentAtshRequest = "ATSH7DF"; - // 2106 - commandRequest = "2106"; - responseRowMerged = "6106FFFF800000000000000200001B001C001C000600060006000E000000010000000000000000013D013D013E013E00"; - parseRowMergedDebugObd2Kia(); - - // AIRCON / ACU ATSH7B3 - currentAtshRequest = "ATSH7B3"; - // 220100 - commandRequest = "220100"; - responseRowMerged = "6201007E5027C8FF7F765D05B95AFFFF5AFF11FFFFFFFFFFFF6AFFFF2DF0757630FFFF00FFFF000000"; - responseRowMerged = "6201007E5027C8FF867C58121010FFFF10FF8EFFFFFFFFFFFF10FFFF0DF0617900FFFF01FFFF000000"; - parseRowMergedDebugObd2Kia(); - - // BMS ATSH7E4 - currentAtshRequest = "ATSH7E4"; - // 220101 - commandRequest = "220101"; - responseRowMerged = "620101FFF7E7FF99000000000300B10EFE120F11100F12000018C438C30B00008400003864000035850000153A00001374000647010D017F0BDA0BDA03E8"; - responseRowMerged = "620101FFF7E7FFB3000000000300120F9B111011101011000014CC38CB3B00009100003A510000367C000015FB000013D3000690250D018E0000000003E8"; - parseRowMergedDebugObd2Kia(); - // 220102 - commandRequest = "220102"; - responseRowMerged = "620102FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; - parseRowMergedDebugObd2Kia(); - // 220103 - commandRequest = "220103"; - responseRowMerged = "620103FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCACBCACACFCCCBCBCBCBCBCBCBCBAAAA"; - parseRowMergedDebugObd2Kia(); - // 220104 - commandRequest = "220104"; - responseRowMerged = "620104FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; - parseRowMergedDebugObd2Kia(); - // 220105 - commandRequest = "220105"; - responseRowMerged = "620105003fff9000000000000000000F8A86012B4946500101500DAC03E800000000AC0000C7C701000F00000000AAAA"; - responseRowMerged = "620105003FFF90000000000000000014918E012927465000015013BB03E800000000BB0000CBCB01001300000000AAAA"; - parseRowMergedDebugObd2Kia(); - // 220106 - commandRequest = "220106"; - responseRowMerged = "620106FFFFFFFF14001A00240000003A7C86B4B30000000928EA00"; - parseRowMergedDebugObd2Kia(); - - // BCM / TPMS ATSH7A0 - currentAtshRequest = "ATSH7A0"; - // 22c00b - commandRequest = "22c00b"; - responseRowMerged = "62C00BFFFF0000B93D0100B43E0100B43D0100BB3C0100AAAAAAAA"; - parseRowMergedDebugObd2Kia(); - - // ATSH7C6 - currentAtshRequest = "ATSH7C6"; - // 22b002 - commandRequest = "22b002"; - responseRowMerged = "62B002E0000000FFB400330B0000000000000000"; - parseRowMergedDebugObd2Kia(); - - params.batModuleTempC[0] = 28; - params.batModuleTempC[1] = 29; - params.batModuleTempC[2] = 28; - params.batModuleTempC[3] = 30; - // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) - params.batMinC = params.batMaxC = params.batModuleTempC[0]; - for (uint16_t i = 1; i < params.batModuleTempCount; i++) { - if (params.batModuleTempC[i] < params.batMinC) - params.batMinC = params.batModuleTempC[i]; - if (params.batModuleTempC[i] > params.batMaxC) - params.batMaxC = params.batModuleTempC[i]; - } - params.batTempC = params.batMinC; - - // - params.soc10ced[10] = 2200; - params.soc10cec[10] = 2500; - params.soc10odo[10] = 13000; - params.soc10time[10] = 13000; - params.soc10ced[9] = params.soc10ced[10] + 6.4; - params.soc10cec[9] = params.soc10cec[10] + 0; - params.soc10odo[9] = params.soc10odo[10] + 30; - params.soc10time[9] = params.soc10time[10] + 900; - params.soc10ced[8] = params.soc10ced[9] + 6.8; - params.soc10cec[8] = params.soc10cec[9] + 0; - params.soc10odo[8] = params.soc10odo[9] + 30; - params.soc10time[8] = params.soc10time[9] + 900; - params.soc10ced[7] = params.soc10ced[8] + 7.2; - params.soc10cec[7] = params.soc10cec[8] + 0.6; - params.soc10odo[7] = params.soc10odo[8] + 30; - params.soc10time[7] = params.soc10time[8] + 900; - params.soc10ced[6] = params.soc10ced[7] + 6.7; - params.soc10cec[6] = params.soc10cec[7] + 0; - params.soc10odo[6] = params.soc10odo[7] + 30; - params.soc10time[6] = params.soc10time[7] + 900; - params.soc10ced[5] = params.soc10ced[6] + 6.7; - params.soc10cec[5] = params.soc10cec[6] + 0; - params.soc10odo[5] = params.soc10odo[6] + 30; - params.soc10time[5] = params.soc10time[6] + 900; - params.soc10ced[4] = params.soc10ced[5] + 6.4; - params.soc10cec[4] = params.soc10cec[5] + 0.3; - params.soc10odo[4] = params.soc10odo[5] + 30; - params.soc10time[4] = params.soc10time[5] + 900; - params.soc10ced[3] = params.soc10ced[4] + 6.4; - params.soc10cec[3] = params.soc10cec[4] + 0; - params.soc10odo[3] = params.soc10odo[4] + 30; - params.soc10time[3] = params.soc10time[4] + 900; - params.soc10ced[2] = params.soc10ced[3] + 5.4; - params.soc10cec[2] = params.soc10cec[3] + 0.1; - params.soc10odo[2] = params.soc10odo[3] + 30; - params.soc10time[2] = params.soc10time[3] + 900; - params.soc10ced[1] = params.soc10ced[2] + 6.2; - params.soc10cec[1] = params.soc10cec[2] + 0.1; - params.soc10odo[1] = params.soc10odo[2] + 30; - params.soc10time[1] = params.soc10time[2] + 900; - params.soc10ced[0] = params.soc10ced[1] + 2.9; - params.soc10cec[0] = params.soc10cec[1] + 0.5; - params.soc10odo[0] = params.soc10odo[1] + 15; - params.soc10time[0] = params.soc10time[1] + 900; - - return true; -} diff --git a/car_hyundai_ioniq.h b/car_hyundai_ioniq.h deleted file mode 100644 index 5462528..0000000 --- a/car_hyundai_ioniq.h +++ /dev/null @@ -1,376 +0,0 @@ -#define commandQueueCountHyundaiIoniq 25 -#define commandQueueLoopFromHyundaiIoniq 8 -String commandQueueHyundaiIoniq[commandQueueCountHyundaiIoniq] = { - "AT Z", // Reset all - "AT I", // Print the version ID - "AT E0", // Echo off - "AT L0", // Linefeeds off - "AT S0", // Printing of spaces on - "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) - //"AT AL", // Allow Long (>7 byte) messages - //"AT AR", // Automatically receive - //"AT H1", // Headers on (debug only) - //"AT D1", // Display of the DLC on - //"AT CAF0", // Automatic formatting off - "AT DP", - "AT ST16", - - // Loop from (HYUNDAI IONIQ) - // BMS - "ATSH7E4", - "2101", // power kw, ... - "2102", // cell voltages, screen 3 only - "2103", // cell voltages, screen 3 only - "2104", // cell voltages, screen 3 only - "2105", // soh, soc, .. - "2106", // cooling water temp - - // VMCU - "ATSH7E2", - "2101", // speed, ... - "2102", // aux, ... - - //"ATSH7Df", - //"2106", - //"220106", - - // Aircondition - // IONIQ OK - "ATSH7B3", - "220100", // in/out temp - "220102", // coolant temp1, 2 - - // BCM / TPMS - // IONIQ OK - "ATSH7A0", - "22c00b", // tire pressure/temp - - // CLUSTER MODULE - // IONIQ OK - "ATSH7C6", - "22B002", // odo -}; - -/** - Init command queue -*/ -bool activateCommandQueueForHyundaiIoniq() { - - // 28kWh version - params.batteryTotalAvailableKWh = 28; - params.batModuleTempCount = 12; - - // Empty and fill command queue - for (int i = 0; i < 300; i++) { - commandQueue[i] = ""; - } - for (int i = 0; i < commandQueueCountHyundaiIoniq; i++) { - commandQueue[i] = commandQueueHyundaiIoniq[i]; - } - - commandQueueLoopFrom = commandQueueLoopFromHyundaiIoniq; - commandQueueCount = commandQueueCountHyundaiIoniq; - - return true; -} - -/** - Parse merged row -*/ -bool parseRowMergedHyundaiIoniq() { - - // VMCU 7E2 - if (currentAtshRequest.equals("ATSH7E2")) { - if (commandRequest.equals("2101")) { - params.speedKmh = hexToDec(responseRowMerged.substring(32, 36).c_str(), 2, false) * 0.0155; // / 100.0 *1.609 = real to gps is 1.750 - if (params.speedKmh < -99 || params.speedKmh > 200) - params.speedKmh = 0; - } - if (commandRequest.equals("2102")) { - params.auxPerc = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, false); - params.auxCurrentAmp = - hexToDec(responseRowMerged.substring(46, 50).c_str(), 2, true) / 1000.0; - } - } - - // Cluster module 7c6 - if (currentAtshRequest.equals("ATSH7C6")) { - if (commandRequest.equals("22B002")) { - params.odoKm = float(strtol(responseRowMerged.substring(18, 24).c_str(), 0, 16)); - } - } - - // Aircon 7b3 - if (currentAtshRequest.equals("ATSH7B3")) { - if (commandRequest.equals("220100")) { - params.indoorTemperature = (hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; - params.outdoorTemperature = (hexToDec(responseRowMerged.substring(18, 20).c_str(), 1, false) / 2) - 40; - } - if (commandRequest.equals("220102") && responseRowMerged.substring(12, 14) == "00") { - params.coolantTemp1C = (hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false) / 2) - 40; - params.coolantTemp2C = (hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; - } - } - - // BMS 7e4 - if (currentAtshRequest.equals("ATSH7E4")) { - if (commandRequest.equals("2101")) { - params.cumulativeEnergyChargedKWh = float(strtol(responseRowMerged.substring(80, 88).c_str(), 0, 16)) / 10.0; - if (params.cumulativeEnergyChargedKWhStart == -1) - params.cumulativeEnergyChargedKWhStart = params.cumulativeEnergyChargedKWh; - params.cumulativeEnergyDischargedKWh = float(strtol(responseRowMerged.substring(88, 96).c_str(), 0, 16)) / 10.0; - if (params.cumulativeEnergyDischargedKWhStart == -1) - params.cumulativeEnergyDischargedKWhStart = params.cumulativeEnergyDischargedKWh; - params.availableChargePower = float(strtol(responseRowMerged.substring(16, 20).c_str(), 0, 16)) / 100.0; - params.availableDischargePower = float(strtol(responseRowMerged.substring(20, 24).c_str(), 0, 16)) / 100.0; - params.isolationResistanceKOhm = hexToDec(responseRowMerged.substring(118, 122).c_str(), 2, true); - params.batFanStatus = hexToDec(responseRowMerged.substring(58, 60).c_str(), 2, true); - params.batFanFeedbackHz = hexToDec(responseRowMerged.substring(60, 62).c_str(), 2, true); - params.auxVoltage = hexToDec(responseRowMerged.substring(62, 64).c_str(), 2, true) / 10.0; - params.batPowerAmp = - hexToDec(responseRowMerged.substring(24, 28).c_str(), 2, true) / 10.0; - params.batVoltage = hexToDec(responseRowMerged.substring(28, 32).c_str(), 2, false) / 10.0; - params.batPowerKw = (params.batPowerAmp * params.batVoltage) / 1000.0; - if (params.batPowerKw < 1) // Reset charging start time - params.chargingStartTime = params.currentTime; - params.batPowerKwh100 = params.batPowerKw / params.speedKmh * 100; - params.batCellMaxV = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, false) / 50.0; - params.batCellMinV = hexToDec(responseRowMerged.substring(54, 56).c_str(), 1, false) / 50.0; - params.batModuleTempC[0] = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - params.batModuleTempC[1] = hexToDec(responseRowMerged.substring(38, 40).c_str(), 1, true); - params.batModuleTempC[2] = hexToDec(responseRowMerged.substring(40, 42).c_str(), 1, true); - params.batModuleTempC[3] = hexToDec(responseRowMerged.substring(42, 44).c_str(), 1, true); - params.batModuleTempC[4] = hexToDec(responseRowMerged.substring(44, 46).c_str(), 1, true); - //params.batTempC = hexToDec(responseRowMerged.substring(34, 36).c_str(), 1, true); - //params.batMaxC = hexToDec(responseRowMerged.substring(32, 34).c_str(), 1, true); - //params.batMinC = hexToDec(responseRowMerged.substring(34, 36).c_str(), 1, true); - - // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) - params.batInletC = hexToDec(responseRowMerged.substring(48, 50).c_str(), 1, true); - if (params.speedKmh < 10 && params.batPowerKw >= 1 && params.socPerc > 0 && params.socPerc <= 100) { - if ( params.chargingGraphMinKw[int(params.socPerc)] == -100 || params.batPowerKw < params.chargingGraphMinKw[int(params.socPerc)]) - params.chargingGraphMinKw[int(params.socPerc)] = params.batPowerKw; - if ( params.chargingGraphMaxKw[int(params.socPerc)] == -100 || params.batPowerKw > params.chargingGraphMaxKw[int(params.socPerc)]) - params.chargingGraphMaxKw[int(params.socPerc)] = params.batPowerKw; - params.chargingGraphBatMinTempC[int(params.socPerc)] = params.batMinC; - params.chargingGraphBatMaxTempC[int(params.socPerc)] = params.batMaxC; - params.chargingGraphHeaterTempC[int(params.socPerc)] = params.batHeaterC; - } - } - // BMS 7e4 - if (commandRequest.equals("2102") && responseRowMerged.substring(10, 12) == "FF") { - for (int i = 0; i < 32; i++) { - params.cellVoltage[i] = hexToDec(responseRowMerged.substring(12 + (i * 2), 12 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("2103")) { - for (int i = 0; i < 32; i++) { - params.cellVoltage[32 + i] = hexToDec(responseRowMerged.substring(12 + (i * 2), 12 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("2104")) { - for (int i = 0; i < 32; i++) { - params.cellVoltage[64 + i] = hexToDec(responseRowMerged.substring(12 + (i * 2), 12 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("2105")) { - params.socPercPrevious = params.socPerc; - params.sohPerc = hexToDec(responseRowMerged.substring(54, 58).c_str(), 2, false) / 10.0; - params.socPerc = hexToDec(responseRowMerged.substring(66, 68).c_str(), 1, false) / 2.0; - - // Remaining battery modules (tempC) - params.batModuleTempC[5] = hexToDec(responseRowMerged.substring(22, 24).c_str(), 1, true); - params.batModuleTempC[6] = hexToDec(responseRowMerged.substring(24, 26).c_str(), 1, true); - params.batModuleTempC[7] = hexToDec(responseRowMerged.substring(26, 28).c_str(), 1, true); - params.batModuleTempC[8] = hexToDec(responseRowMerged.substring(28, 30).c_str(), 1, true); - params.batModuleTempC[9] = hexToDec(responseRowMerged.substring(30, 32).c_str(), 1, true); - params.batModuleTempC[10] = hexToDec(responseRowMerged.substring(32, 34).c_str(), 1, true); - params.batModuleTempC[11] = hexToDec(responseRowMerged.substring(34, 36).c_str(), 1, true); - - params.batMinC = params.batMaxC = params.batModuleTempC[0]; - for (uint16_t i = 1; i < params.batModuleTempCount; i++) { - if (params.batModuleTempC[i] < params.batMinC) - params.batMinC = params.batModuleTempC[i]; - if (params.batModuleTempC[i] > params.batMaxC) - params.batMaxC = params.batModuleTempC[i]; - } - params.batTempC = params.batMinC; - - // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) - if (params.socPercPrevious - params.socPerc > 0) { - byte index = (int(params.socPerc) == 4) ? 0 : (int)(params.socPerc / 10) + 1; - if ((int(params.socPerc) % 10 == 9 || int(params.socPerc) == 4) && params.soc10ced[index] == -1) { - params.soc10ced[index] = params.cumulativeEnergyDischargedKWh; - params.soc10cec[index] = params.cumulativeEnergyChargedKWh; - params.soc10odo[index] = params.odoKm; - params.soc10time[index] = params.currentTime; - } - } - params.batHeaterC = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, true); - // - for (int i = 30; i < 32; i++) { // ai/aj position - params.cellVoltage[96 - 30 + i] = -1; - } - } - // BMS 7e4 - // IONIQ FAILED - if (commandRequest.equals("2106")) { - params.coolingWaterTempC = hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false); - } - } - - // TPMS 7a0 - if (currentAtshRequest.equals("ATSH7A0")) { - if (commandRequest.equals("22c00b")) { - params.tireFrontLeftPressureBar = hexToDec(responseRowMerged.substring(14, 16).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireFrontRightPressureBar = hexToDec(responseRowMerged.substring(22, 24).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireRearRightPressureBar = hexToDec(responseRowMerged.substring(30, 32).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireRearLeftPressureBar = hexToDec(responseRowMerged.substring(38, 40).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireFrontLeftTempC = hexToDec(responseRowMerged.substring(16, 18).c_str(), 2, false) - 50; // === OK Valid - params.tireFrontRightTempC = hexToDec(responseRowMerged.substring(24, 26).c_str(), 2, false) - 50; // === OK Valid - params.tireRearRightTempC = hexToDec(responseRowMerged.substring(32, 34).c_str(), 2, false) - 50; // === OK Valid - params.tireRearLeftTempC = hexToDec(responseRowMerged.substring(40, 42).c_str(), 2, false) - 50; // === OK Valid - } - } - - return true; -} - -/** - Test data -*/ -bool testDataHyundaiIoniq() { - - // VMCU ATSH7E2 - currentAtshRequest = "ATSH7E2"; - // 2101 - commandRequest = "2101"; - responseRowMerged = "6101FFE0000009211222062F03000000001D7734"; - parseRowMergedHyundaiIoniq(); - // 2102 - commandRequest = "2102"; - responseRowMerged = "6102FF80000001010000009315B2888D390B08618B683900000000"; - parseRowMergedHyundaiIoniq(); - - // "ATSH7DF", - currentAtshRequest = "ATSH7DF"; - - // AIRCON / ACU ATSH7B3 - currentAtshRequest = "ATSH7B3"; - // 220100 - commandRequest = "220100"; - responseRowMerged = "6201007E5007C8FF8A876A011010FFFF10FF10FFFFFFFFFFFFFFFFFF2EEF767D00FFFF00FFFF000000"; - parseRowMergedHyundaiIoniq(); - // 220102 - commandRequest = "220102"; - responseRowMerged = "620102FF800000A3950000000000002600000000"; - parseRowMergedHyundaiIoniq(); - - // BMS ATSH7E4 - currentAtshRequest = "ATSH7E4"; - // 220101 - commandRequest = "2101"; - responseRowMerged = "6101FFFFFFFF5026482648A3FFC30D9E181717171718170019B50FB501000090000142230001425F0000771B00007486007815D809015C0000000003E800"; - parseRowMergedHyundaiIoniq(); - // 220102 - commandRequest = "2102"; - responseRowMerged = "6102FFFFFFFFB5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5000000"; - parseRowMergedHyundaiIoniq(); - // 220103 - commandRequest = "2103"; - responseRowMerged = "6103FFFFFFFFB5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5000000"; - parseRowMergedHyundaiIoniq(); - // 220104 - commandRequest = "2104"; - responseRowMerged = "6104FFFFFFFFB5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5000000"; - parseRowMergedHyundaiIoniq(); - // 220105 - commandRequest = "2105"; - responseRowMerged = "6105FFFFFFFF00000000001717171817171726482648000150181703E81A03E801520029000000000000000000000000"; - parseRowMergedHyundaiIoniq(); - // 220106 - commandRequest = "2106"; - responseRowMerged = "7F2112"; // n/a on ioniq - parseRowMergedHyundaiIoniq(); - - // BCM / TPMS ATSH7A0 - currentAtshRequest = "ATSH7A0"; - // 22c00b - commandRequest = "22c00b"; - responseRowMerged = "62C00BFFFF0000B9510100B9510100B84F0100B54F0100AAAAAAAA"; - parseRowMergedHyundaiIoniq(); - - // ATSH7C6 - currentAtshRequest = "ATSH7C6"; - // 22b002 - commandRequest = "22b002"; - responseRowMerged = "62B002E000000000AD003D2D0000000000000000"; - parseRowMergedHyundaiIoniq(); - - /* params.batModule01TempC = 28; - params.batModule02TempC = 29; - params.batModule03TempC = 28; - params.batModule04TempC = 30; - //params.batTempC = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - //params.batMaxC = hexToDec(responseRowMerged.substring(34, 36).c_str(), 1, true); - //params.batMinC = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - - // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) - params.batMinC = params.batMaxC = params.batModule01TempC; - params.batMinC = (params.batModule02TempC < params.batMinC) ? params.batModule02TempC : params.batMinC ; - params.batMinC = (params.batModule03TempC < params.batMinC) ? params.batModule03TempC : params.batMinC ; - params.batMinC = (params.batModule04TempC < params.batMinC) ? params.batModule04TempC : params.batMinC ; - params.batMaxC = (params.batModule02TempC > params.batMaxC) ? params.batModule02TempC : params.batMaxC ; - params.batMaxC = (params.batModule03TempC > params.batMaxC) ? params.batModule03TempC : params.batMaxC ; - params.batMaxC = (params.batModule04TempC > params.batMaxC) ? params.batModule04TempC : params.batMaxC ; - params.batTempC = params.batMinC; - - // - params.soc10ced[10] = 2200; - params.soc10cec[10] = 2500; - params.soc10odo[10] = 13000; - params.soc10time[10] = 13000; - params.soc10ced[9] = params.soc10ced[10] + 6.4; - params.soc10cec[9] = params.soc10cec[10] + 0; - params.soc10odo[9] = params.soc10odo[10] + 30; - params.soc10time[9] = params.soc10time[10] + 900; - params.soc10ced[8] = params.soc10ced[9] + 6.8; - params.soc10cec[8] = params.soc10cec[9] + 0; - params.soc10odo[8] = params.soc10odo[9] + 30; - params.soc10time[8] = params.soc10time[9] + 900; - params.soc10ced[7] = params.soc10ced[8] + 7.2; - params.soc10cec[7] = params.soc10cec[8] + 0.6; - params.soc10odo[7] = params.soc10odo[8] + 30; - params.soc10time[7] = params.soc10time[8] + 900; - params.soc10ced[6] = params.soc10ced[7] + 6.7; - params.soc10cec[6] = params.soc10cec[7] + 0; - params.soc10odo[6] = params.soc10odo[7] + 30; - params.soc10time[6] = params.soc10time[7] + 900; - params.soc10ced[5] = params.soc10ced[6] + 6.7; - params.soc10cec[5] = params.soc10cec[6] + 0; - params.soc10odo[5] = params.soc10odo[6] + 30; - params.soc10time[5] = params.soc10time[6] + 900; - params.soc10ced[4] = params.soc10ced[5] + 6.4; - params.soc10cec[4] = params.soc10cec[5] + 0.3; - params.soc10odo[4] = params.soc10odo[5] + 30; - params.soc10time[4] = params.soc10time[5] + 900; - params.soc10ced[3] = params.soc10ced[4] + 6.4; - params.soc10cec[3] = params.soc10cec[4] + 0; - params.soc10odo[3] = params.soc10odo[4] + 30; - params.soc10time[3] = params.soc10time[4] + 900; - params.soc10ced[2] = params.soc10ced[3] + 5.4; - params.soc10cec[2] = params.soc10cec[3] + 0.1; - params.soc10odo[2] = params.soc10odo[3] + 30; - params.soc10time[2] = params.soc10time[3] + 900; - params.soc10ced[1] = params.soc10ced[2] + 6.2; - params.soc10cec[1] = params.soc10cec[2] + 0.1; - params.soc10odo[1] = params.soc10odo[2] + 30; - params.soc10time[1] = params.soc10time[2] + 900; - params.soc10ced[0] = params.soc10ced[1] + 2.9; - params.soc10cec[0] = params.soc10cec[1] + 0.5; - params.soc10odo[0] = params.soc10odo[1] + 15; - params.soc10time[0] = params.soc10time[1] + 900; - */ - return true; -} diff --git a/car_kia_eniro.h b/car_kia_eniro.h deleted file mode 100644 index 8d56d3d..0000000 --- a/car_kia_eniro.h +++ /dev/null @@ -1,430 +0,0 @@ - -#define commandQueueCountKiaENiro 30 -#define commandQueueLoopFromKiaENiro 10 - -String commandQueueKiaENiro[commandQueueCountKiaENiro] = { - "AT Z", // Reset all - "AT I", // Print the version ID - "AT S0", // Printing of spaces on - "AT E0", // Echo off - "AT L0", // Linefeeds off - "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) - //"AT AL", // Allow Long (>7 byte) messages - //"AT AR", // Automatically receive - //"AT H1", // Headers on (debug only) - //"AT D1", // Display of the DLC on - //"AT CAF0", // Automatic formatting off - ////"AT AT0", // disabled adaptive timing - "AT DP", - "AT ST16", // reduced timeout to 1, orig.16 - - // Loop from (KIA ENIRO) - - // ABS / ESP + AHB - "ATSH7D1", - "22C101", // brake, park/drive mode - - // IGPM - "ATSH770", - "22BC03", // low beam - "22BC06", // brake light - - // VMCU - "ATSH7E2", - "2101", // speed, ... - "2102", // aux, ... - - // BMS - "ATSH7E4", - "220101", // power kw, ... - "220102", // cell voltages - "220103", // cell voltages - "220104", // cell voltages - "220105", // soh, soc, .. - "220106", // cooling water temp - - // Aircondition - "ATSH7B3", - "220100", // in/out temp - "220102", // coolant temp1, 2 - - // BCM / TPMS - "ATSH7A0", - "22c00b", // tire pressure/temp - - // CLUSTER MODULE - "ATSH7C6", - "22B002", // odo - -}; - -/** - Init command queue -*/ -bool activateCommandQueueForKiaENiro() { - - // 39 or 64 kWh model? - params.batModuleTempCount = 4; - params.batteryTotalAvailableKWh = 64; - // =(I18*0,615)*(1+(I18*0,0008)) soc to kwh niro ev 2020 - if (settings.carType == CAR_KIA_ENIRO_2020_39 || settings.carType == CAR_HYUNDAI_KONA_2020_39) { - params.batteryTotalAvailableKWh = 39.2; - } - - // Empty and fill command queue - for (int i = 0; i < 300; i++) { - commandQueue[i] = ""; - } - for (int i = 0; i < commandQueueCountKiaENiro; i++) { - commandQueue[i] = commandQueueKiaENiro[i]; - } - - commandQueueLoopFrom = commandQueueLoopFromKiaENiro; - commandQueueCount = commandQueueCountKiaENiro; - - return true; -} - -/** - Parse merged row -*/ -bool parseRowMergedKiaENiro() { - - bool tempByte; - - // ABS / ESP + AHB 7D1 - if (currentAtshRequest.equals("ATSH7D1")) { - if (commandRequest.equals("22C101")) { - uint8_t driveMode = hexToDec(responseRowMerged.substring(22, 24).c_str(), 1, false); - params.forwardDriveMode = (driveMode == 4); - params.reverseDriveMode = (driveMode == 2); - params.parkModeOrNeutral = (driveMode == 1); - } - } - - // IGPM - if (currentAtshRequest.equals("ATSH770")) { - if (commandRequest.equals("22BC03")) { - tempByte = hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false); - params.ignitionOnPrevious = params.ignitionOn; - params.ignitionOn = (bitRead(tempByte, 5) == 1); - if (params.ignitionOnPrevious && !params.ignitionOn) - params.automatickShutdownTimer = params.currentTime; - - params.lightInfo = hexToDec(responseRowMerged.substring(18, 20).c_str(), 1, false); - params.headLights = (bitRead(params.lightInfo, 5) == 1); - params.dayLights = (bitRead(params.lightInfo, 3) == 1); - } - if (commandRequest.equals("22BC06")) { - params.brakeLightInfo = hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false); - params.brakeLights = (bitRead(params.brakeLightInfo, 5) == 1); - } - } - - // VMCU 7E2 - if (currentAtshRequest.equals("ATSH7E2")) { - if (commandRequest.equals("2101")) { - params.speedKmh = hexToDec(responseRowMerged.substring(32, 36).c_str(), 2, false) * 0.0155; // / 100.0 *1.609 = real to gps is 1.750 - if (params.speedKmh < -99 || params.speedKmh > 200) - params.speedKmh = 0; - } - if (commandRequest.equals("2102")) { - params.auxPerc = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, false); - params.auxCurrentAmp = - hexToDec(responseRowMerged.substring(46, 50).c_str(), 2, true) / 1000.0; - } - } - - // Cluster module 7c6 - if (currentAtshRequest.equals("ATSH7C6")) { - if (commandRequest.equals("22B002")) { - params.odoKm = float(strtol(responseRowMerged.substring(18, 24).c_str(), 0, 16)); - } - } - - // Aircon 7b3 - if (currentAtshRequest.equals("ATSH7B3")) { - if (commandRequest.equals("220100")) { - params.indoorTemperature = (hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; - params.outdoorTemperature = (hexToDec(responseRowMerged.substring(18, 20).c_str(), 1, false) / 2) - 40; - } - if (commandRequest.equals("220102") && responseRowMerged.substring(12, 14) == "00") { - params.coolantTemp1C = (hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false) / 2) - 40; - params.coolantTemp2C = (hexToDec(responseRowMerged.substring(16, 18).c_str(), 1, false) / 2) - 40; - } - } - - // BMS 7e4 - if (currentAtshRequest.equals("ATSH7E4")) { - if (commandRequest.equals("220101")) { - params.cumulativeEnergyChargedKWh = float(strtol(responseRowMerged.substring(82, 90).c_str(), 0, 16)) / 10.0; - if (params.cumulativeEnergyChargedKWhStart == -1) - params.cumulativeEnergyChargedKWhStart = params.cumulativeEnergyChargedKWh; - params.cumulativeEnergyDischargedKWh = float(strtol(responseRowMerged.substring(90, 98).c_str(), 0, 16)) / 10.0; - if (params.cumulativeEnergyDischargedKWhStart == -1) - params.cumulativeEnergyDischargedKWhStart = params.cumulativeEnergyDischargedKWh; - params.availableChargePower = float(strtol(responseRowMerged.substring(16, 20).c_str(), 0, 16)) / 100.0; - params.availableDischargePower = float(strtol(responseRowMerged.substring(20, 24).c_str(), 0, 16)) / 100.0; - //params.isolationResistanceKOhm = hexToDec(responseRowMerged.substring(118, 122).c_str(), 2, true); - params.batFanStatus = hexToDec(responseRowMerged.substring(60, 62).c_str(), 2, true); - params.batFanFeedbackHz = hexToDec(responseRowMerged.substring(62, 64).c_str(), 2, true); - params.auxVoltage = hexToDec(responseRowMerged.substring(64, 66).c_str(), 2, true) / 10.0; - params.batPowerAmp = - hexToDec(responseRowMerged.substring(26, 30).c_str(), 2, true) / 10.0; - params.batVoltage = hexToDec(responseRowMerged.substring(30, 34).c_str(), 2, false) / 10.0; - params.batPowerKw = (params.batPowerAmp * params.batVoltage) / 1000.0; - if (params.batPowerKw < 0) // Reset charging start time - params.chargingStartTime = params.currentTime; - params.batPowerKwh100 = params.batPowerKw / params.speedKmh * 100; - params.batCellMaxV = hexToDec(responseRowMerged.substring(52, 54).c_str(), 1, false) / 50.0; - params.batCellMinV = hexToDec(responseRowMerged.substring(56, 58).c_str(), 1, false) / 50.0; - params.batModuleTempC[0] = hexToDec(responseRowMerged.substring(38, 40).c_str(), 1, true); - params.batModuleTempC[1] = hexToDec(responseRowMerged.substring(40, 42).c_str(), 1, true); - params.batModuleTempC[2] = hexToDec(responseRowMerged.substring(42, 44).c_str(), 1, true); - params.batModuleTempC[3] = hexToDec(responseRowMerged.substring(44, 46).c_str(), 1, true); - params.motorRpm = hexToDec(responseRowMerged.substring(112, 116).c_str(), 2, false); - //params.batTempC = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - //params.batMaxC = hexToDec(responseRowMerged.substring(34, 36).c_str(), 1, true); - //params.batMinC = hexToDec(responseRowMerged.substring(36, 38).c_str(), 1, true); - - // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) - params.batMinC = params.batMaxC = params.batModuleTempC[0]; - for (uint16_t i = 1; i < params.batModuleTempCount; i++) { - if (params.batModuleTempC[i] < params.batMinC) - params.batMinC = params.batModuleTempC[i]; - if (params.batModuleTempC[i] > params.batMaxC) - params.batMaxC = params.batModuleTempC[i]; - } - params.batTempC = params.batMinC; - - params.batInletC = hexToDec(responseRowMerged.substring(50, 52).c_str(), 1, true); - if (params.speedKmh < 10 && params.batPowerKw >= 1 && params.socPerc > 0 && params.socPerc <= 100) { - if ( params.chargingGraphMinKw[int(params.socPerc)] < 0 || params.batPowerKw < params.chargingGraphMinKw[int(params.socPerc)]) - params.chargingGraphMinKw[int(params.socPerc)] = params.batPowerKw; - if ( params.chargingGraphMaxKw[int(params.socPerc)] < 0 || params.batPowerKw > params.chargingGraphMaxKw[int(params.socPerc)]) - params.chargingGraphMaxKw[int(params.socPerc)] = params.batPowerKw; - params.chargingGraphBatMinTempC[int(params.socPerc)] = params.batMinC; - params.chargingGraphBatMaxTempC[int(params.socPerc)] = params.batMaxC; - params.chargingGraphHeaterTempC[int(params.socPerc)] = params.batHeaterC; - params.chargingGraphWaterCoolantTempC[int(params.socPerc)] = params.coolingWaterTempC; - } - } - // BMS 7e4 - if (commandRequest.equals("220102") && responseRowMerged.substring(12, 14) == "FF") { - for (int i = 0; i < 32; i++) { - params.cellVoltage[i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220103")) { - for (int i = 0; i < 32; i++) { - params.cellVoltage[32 + i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220104")) { - for (int i = 0; i < 32; i++) { - params.cellVoltage[64 + i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220105")) { - params.socPercPrevious = params.socPerc; - params.sohPerc = hexToDec(responseRowMerged.substring(56, 60).c_str(), 2, false) / 10.0; - params.socPerc = hexToDec(responseRowMerged.substring(68, 70).c_str(), 1, false) / 2.0; - - // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) - if (params.socPercPrevious - params.socPerc > 0) { - byte index = (int(params.socPerc) == 4) ? 0 : (int)(params.socPerc / 10) + 1; - if ((int(params.socPerc) % 10 == 9 || int(params.socPerc) == 4) && params.soc10ced[index] == -1) { - params.soc10ced[index] = params.cumulativeEnergyDischargedKWh; - params.soc10cec[index] = params.cumulativeEnergyChargedKWh; - params.soc10odo[index] = params.odoKm; - params.soc10time[index] = params.currentTime; - } - } - params.bmsUnknownTempA = hexToDec(responseRowMerged.substring(30, 32).c_str(), 1, true); - params.batHeaterC = hexToDec(responseRowMerged.substring(52, 54).c_str(), 1, true); - params.bmsUnknownTempB = hexToDec(responseRowMerged.substring(82, 84).c_str(), 1, true); - // - for (int i = 30; i < 32; i++) { // ai/aj position - params.cellVoltage[96 - 30 + i] = hexToDec(responseRowMerged.substring(14 + (i * 2), 14 + (i * 2) + 2).c_str(), 1, false) / 50; - } - } - // BMS 7e4 - if (commandRequest.equals("220106")) { - params.coolingWaterTempC = hexToDec(responseRowMerged.substring(14, 16).c_str(), 1, false); - params.bmsUnknownTempC = hexToDec(responseRowMerged.substring(18, 20).c_str(), 1, true); - params.bmsUnknownTempD = hexToDec(responseRowMerged.substring(46, 48).c_str(), 1, true); - } - } - - // TPMS 7a0 - if (currentAtshRequest.equals("ATSH7A0")) { - if (commandRequest.equals("22c00b")) { - params.tireFrontLeftPressureBar = hexToDec(responseRowMerged.substring(14, 16).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireFrontRightPressureBar = hexToDec(responseRowMerged.substring(22, 24).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireRearRightPressureBar = hexToDec(responseRowMerged.substring(30, 32).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireRearLeftPressureBar = hexToDec(responseRowMerged.substring(38, 40).c_str(), 2, false) / 72.51886900361; // === OK Valid *0.2 / 14.503773800722 - params.tireFrontLeftTempC = hexToDec(responseRowMerged.substring(16, 18).c_str(), 2, false) - 50; // === OK Valid - params.tireFrontRightTempC = hexToDec(responseRowMerged.substring(24, 26).c_str(), 2, false) - 50; // === OK Valid - params.tireRearRightTempC = hexToDec(responseRowMerged.substring(32, 34).c_str(), 2, false) - 50; // === OK Valid - params.tireRearLeftTempC = hexToDec(responseRowMerged.substring(40, 42).c_str(), 2, false) - 50; // === OK Valid - } - } - - return true; -} - -/** - Test data -*/ -bool testDataKiaENiro() { - - - // IGPM - currentAtshRequest = "ATSH770"; - // 22BC03 - commandRequest = "22BC03"; - responseRowMerged = "62BC03FDEE7C730A600000AAAA"; - parseRowMergedKiaENiro(); - - // ABS / ESP + AHB ATSH7D1 - currentAtshRequest = "ATSH7D1"; - // 2101 - commandRequest = "22C101"; - responseRowMerged = "62C1015FD7E7D0FFFF00FF04D0D400000000FF7EFF0030F5010000FFFF7F6307F207FE05FF00FF3FFFFFAAAAAAAAAAAA"; - parseRowMergedKiaENiro(); - - // VMCU ATSH7E2 - currentAtshRequest = "ATSH7E2"; - // 2101 - commandRequest = "2101"; - responseRowMerged = "6101FFF8000009285A3B0648030000B4179D763404080805000000"; - parseRowMergedKiaENiro(); - // 2102 - commandRequest = "2102"; - responseRowMerged = "6102F8FFFC000101000000840FBF83BD33270680953033757F59291C76000001010100000007000000"; - responseRowMerged = "6102F8FFFC000101000000931CC77F4C39040BE09BA7385D8158832175000001010100000007000000"; - parseRowMergedKiaENiro(); - - // "ATSH7DF", - currentAtshRequest = "ATSH7DF"; - // 2106 - commandRequest = "2106"; - responseRowMerged = "6106FFFF800000000000000200001B001C001C000600060006000E000000010000000000000000013D013D013E013E00"; - parseRowMergedKiaENiro(); - - // AIRCON / ACU ATSH7B3 - currentAtshRequest = "ATSH7B3"; - // 220100 - commandRequest = "220100"; - responseRowMerged = "6201007E5027C8FF7F765D05B95AFFFF5AFF11FFFFFFFFFFFF6AFFFF2DF0757630FFFF00FFFF000000"; - responseRowMerged = "6201007E5027C8FF867C58121010FFFF10FF8EFFFFFFFFFFFF10FFFF0DF0617900FFFF01FFFF000000"; - parseRowMergedKiaENiro(); - - // BMS ATSH7E4 - currentAtshRequest = "ATSH7E4"; - // 220101 - commandRequest = "220101"; - responseRowMerged = "620101FFF7E7FF99000000000300B10EFE120F11100F12000018C438C30B00008400003864000035850000153A00001374000647010D017F0BDA0BDA03E8"; - responseRowMerged = "620101FFF7E7FFB3000000000300120F9B111011101011000014CC38CB3B00009100003A510000367C000015FB000013D3000690250D018E0000000003E8"; - parseRowMergedKiaENiro(); - // 220102 - commandRequest = "220102"; - responseRowMerged = "620102FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; - parseRowMergedKiaENiro(); - // 220103 - commandRequest = "220103"; - responseRowMerged = "620103FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCACBCACACFCCCBCBCBCBCBCBCBCBAAAA"; - parseRowMergedKiaENiro(); - // 220104 - commandRequest = "220104"; - responseRowMerged = "620104FFFFFFFFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAAAA"; - parseRowMergedKiaENiro(); - // 220105 - commandRequest = "220105"; - responseRowMerged = "620105003fff9000000000000000000F8A86012B4946500101500DAC03E800000000AC0000C7C701000F00000000AAAA"; - responseRowMerged = "620105003FFF90000000000000000014918E012927465000015013BB03E800000000BB0000CBCB01001300000000AAAA"; - parseRowMergedKiaENiro(); - // 220106 - commandRequest = "220106"; - responseRowMerged = "620106FFFFFFFF14001A00240000003A7C86B4B30000000928EA00"; - parseRowMergedKiaENiro(); - - // BCM / TPMS ATSH7A0 - currentAtshRequest = "ATSH7A0"; - // 22c00b - commandRequest = "22c00b"; - responseRowMerged = "62C00BFFFF0000B93D0100B43E0100B43D0100BB3C0100AAAAAAAA"; - parseRowMergedKiaENiro(); - - // ATSH7C6 - currentAtshRequest = "ATSH7C6"; - // 22b002 - commandRequest = "22b002"; - responseRowMerged = "62B002E0000000FFB400330B0000000000000000"; - parseRowMergedKiaENiro(); - - params.batModuleTempC[0] = 28; - params.batModuleTempC[1] = 29; - params.batModuleTempC[2] = 28; - params.batModuleTempC[3] = 30; - - // This is more accurate than min/max from BMS. It's required to detect kona/eniro cold gates (min 15C is needed > 43kW charging, min 25C is needed > 58kW charging) - params.batMinC = params.batMaxC = params.batModuleTempC[0]; - for (uint16_t i = 1; i < params.batModuleTempCount; i++) { - if (params.batModuleTempC[i] < params.batMinC) - params.batMinC = params.batModuleTempC[i]; - if (params.batModuleTempC[i] > params.batMaxC) - params.batMaxC = params.batModuleTempC[i]; - } - params.batTempC = params.batMinC; - - - // - params.soc10ced[10] = 2200; - params.soc10cec[10] = 2500; - params.soc10odo[10] = 13000; - params.soc10time[10] = 13000; - params.soc10ced[9] = params.soc10ced[10] + 6.4; - params.soc10cec[9] = params.soc10cec[10] + 0; - params.soc10odo[9] = params.soc10odo[10] + 30; - params.soc10time[9] = params.soc10time[10] + 900; - params.soc10ced[8] = params.soc10ced[9] + 6.8; - params.soc10cec[8] = params.soc10cec[9] + 0; - params.soc10odo[8] = params.soc10odo[9] + 30; - params.soc10time[8] = params.soc10time[9] + 900; - params.soc10ced[7] = params.soc10ced[8] + 7.2; - params.soc10cec[7] = params.soc10cec[8] + 0.6; - params.soc10odo[7] = params.soc10odo[8] + 30; - params.soc10time[7] = params.soc10time[8] + 900; - params.soc10ced[6] = params.soc10ced[7] + 6.7; - params.soc10cec[6] = params.soc10cec[7] + 0; - params.soc10odo[6] = params.soc10odo[7] + 30; - params.soc10time[6] = params.soc10time[7] + 900; - params.soc10ced[5] = params.soc10ced[6] + 6.7; - params.soc10cec[5] = params.soc10cec[6] + 0; - params.soc10odo[5] = params.soc10odo[6] + 30; - params.soc10time[5] = params.soc10time[6] + 900; - params.soc10ced[4] = params.soc10ced[5] + 6.4; - params.soc10cec[4] = params.soc10cec[5] + 0.3; - params.soc10odo[4] = params.soc10odo[5] + 30; - params.soc10time[4] = params.soc10time[5] + 900; - params.soc10ced[3] = params.soc10ced[4] + 6.4; - params.soc10cec[3] = params.soc10cec[4] + 0; - params.soc10odo[3] = params.soc10odo[4] + 30; - params.soc10time[3] = params.soc10time[4] + 900; - params.soc10ced[2] = params.soc10ced[3] + 5.4; - params.soc10cec[2] = params.soc10cec[3] + 0.1; - params.soc10odo[2] = params.soc10odo[3] + 30; - params.soc10time[2] = params.soc10time[3] + 900; - params.soc10ced[1] = params.soc10ced[2] + 6.2; - params.soc10cec[1] = params.soc10cec[2] + 0.1; - params.soc10odo[1] = params.soc10odo[2] + 30; - params.soc10time[1] = params.soc10time[2] + 900; - params.soc10ced[0] = params.soc10ced[1] + 2.9; - params.soc10cec[0] = params.soc10cec[1] + 0.5; - params.soc10odo[0] = params.soc10odo[1] + 15; - params.soc10time[0] = params.soc10time[1] + 900; - - return true; -} diff --git a/car_renault_zoe.h b/car_renault_zoe.h deleted file mode 100644 index 11fd32c..0000000 --- a/car_renault_zoe.h +++ /dev/null @@ -1,66 +0,0 @@ - -#define commandQueueCountRenaultZoe 10 -#define commandQueueLoopFromRenaultZoe 8 - -String commandQueueRenaultZoe[commandQueueCountRenaultZoe] = { - "AT Z", // Reset all - "AT I", // Print the version ID - "AT E0", // Echo off - "AT L0", // Linefeeds off - "AT S0", // Printing of spaces on - "AT SP 6", // Select protocol to ISO 15765-4 CAN (11 bit ID, 500 kbit/s) - //"AT AL", // Allow Long (>7 byte) messages - //"AT AR", // Automatically receive - //"AT H1", // Headers on (debug only) - //"AT D1", // Display of the DLC on - //"AT CAF0", // Automatic formatting off - "AT DP", - "AT ST16", - - // Loop from (KIA ENIRO) // TODO - // BMS - "ATSH7E4", - "220101", // power kw, ... -}; - -/** - Init command queue -*/ -bool activateCommandQueueForRenaultZoe() { - - params.batModuleTempCount = 4; - params.batteryTotalAvailableKWh = 22; - - // Empty and fill command queue - for (int i = 0; i < 300; i++) { - commandQueue[i] = ""; - } - for (int i = 0; i < commandQueueCountRenaultZoe; i++) { - commandQueue[i] = commandQueueRenaultZoe[i]; - } - - commandQueueLoopFrom = commandQueueLoopFromRenaultZoe; - commandQueueCount = commandQueueCountRenaultZoe; - - return true; -} - -/** - Parse merged row -*/ -bool parseRowMergedRenaultZoe() { - - // TODO - - return true; -} - -/** - Test data -*/ -bool testDataRenaultZoe() { - - // TODO - - return true; -} diff --git a/config.h b/config.h index eb28d35..0442df7 100644 --- a/config.h +++ b/config.h @@ -1,94 +1,5 @@ -//////////////////////////////////////////////////////////// -// SELECT HARDWARE !!!! -//////////////////////////////////////////////////////////// - -#define BOARD_TTGO_T4 -//#define BOARD_M5STACK_CORE - -//#define SIM800L_ENABLED - -//////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////// - -#define USER_SETUP_LOADED 1 -#define SPI_FREQUENCY 27000000 -//#define SPI_READ_FREQUENCY 20000000 -#define SPI_TOUCH_FREQUENCY 2500000 - -//////////////////////////////////////////////////////////// -// BOARD LILYGO TTGO T4 v1.3 -///////////////////////////////////////////////////////////// -#ifdef BOARD_TTGO_T4 - -#define ILI9341_DRIVER -#define TFT_MISO 12 -#define TFT_MOSI 23 -#define TFT_SCLK 18 -#define TFT_CS 27 -#define TFT_DC 32 -#define TFT_RST 5 -//#define TFT_BACKLIGHT_ON HIGH -#define TFT_BL 4 - -#define USE_HSPI_PORT -//#define SPI_FREQUENCY 40000000 // Maximum for ILI9341 -#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V - -#define SD_CS 13 -#define SD_MOSI 15 -#define SD_MISO 2 -#define SD_SCLK 14 - -#define BUTTON_LEFT 38 -#define BUTTON_MIDDLE 37 -#define BUTTON_RIGHT 39 - -#endif // BOARD_TTGO_T4 - -///////////////////////////////////////////////////////////// -// BOARD M5STACK CORE IOT (M5-K001) -///////////////////////////////////////////////////////////// -#ifdef BOARD_M5STACK_CORE - -#define USER_SETUP_LOADED 1 -#define ILI9341_DRIVER -#define M5STACK -#define TFT_MISO 19 -#define TFT_MOSI 23 -#define TFT_SCLK 18 -#define TFT_CS 14 // Chip select control pin -#define TFT_DC 27 // Data Command control pin -#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -#define TFT_BL 32 // LED back-light -#define SPI_FREQUENCY 27000000 -#define SPI_READ_FREQUENCY 5000000 -#define SPEAKER_PIN 25 -#define INVERT_DISPLAY - -#define BUTTON_LEFT 37 -#define BUTTON_MIDDLE 38 -#define BUTTON_RIGHT 39 - -#define SD_CS 4 -#define SD_MOSI 23 -#define SD_MISO 19 -#define SD_SCLK 18 - -#endif // BOARD_M5STACK_CORE - -//////////////////////////////////////////////////////////// -// SIM800L -///////////////////////////////////////////////////////////// - -#ifdef SIM800L_ENABLED -#define SIM800L_RX 16 -#define SIM800L_TX 17 -#define SIM800L_RST 5 -#define SIM800L_TIMER 120 -#endif //SIM800L_ENABLED - -///////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////// +#ifndef CONFIG_H +#define CONFIG_H // TFT COMMON #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH @@ -139,3 +50,18 @@ #define TFT_GRAPH_COLDGATE15_24 0x0008 #define TFT_GRAPH_OPTIMAL25 0x0200 #define TFT_GRAPH_RAPIDGATE35 0x8300 + +//////////////////////////////////////////////////////////// +// SIM800L +///////////////////////////////////////////////////////////// + +#ifdef SIM800L_ENABLED +#define SIM800L_RX 16 +#define SIM800L_TX 17 +#define SIM800L_RST 5 +#define SIM800L_TIMER 120 +#endif //SIM800L_ENABLED + +///////////////////////////////////////////////////////////// +// +#endif // CONFIG_H diff --git a/enirodashboard.ino b/enirodashboard.ino index 15abdc8..7fe249e 100644 --- a/enirodashboard.ino +++ b/enirodashboard.ino @@ -1,22 +1,9 @@ /* - KIA eNiro Dashboard 1.8.2, 2020-11-25 !! working only with OBD BLE 4.0 adapters !! Supported adapter is Vgate ICar Pro (must be BLE4.0 version) !! Not working with standard BLUETOOTH 3 adapters - IMPORTANT Replace HM_MAC, serviceUUID, charTxUUID, charRxUUID as described below - - !! How to obtain MAC + 3x UUID? You don't need it for Vgate iCar Pro BLE 4.0 adapter - - Run Android BLE scanner - - choose IOS-VLINK device - - get mac address a replace HM_MAC constant, then open CUSTOM service (first of 2) - - there is serviceUUID (replace bellow in code) - - open it.. there are 2x custom characteristics (first is for NOTIFY (read), and second for WRITE,WRITE_REQUEST). - set charTxUUID with UUID from NOTIFY section - set charRxUUID with UUID from WRITE section - --- eNiro/Kona chargins limits depending on battery temperature (min.value of 01-04 battery module) >= 35°C BMS allows max 180A @@ -27,23 +14,44 @@ <= 0°C BMS allows max 40A */ -#define APP_VERSION "v1.8.3b" +//////////////////////////////////////////////////////////// +// SELECT HARDWARE +//////////////////////////////////////////////////////////// + +#define BOARD_TTGO_T4 +//#define BOARD_M5STACK_CORE + +//#define SIM800L_ENABLED + +//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// + +#define APP_VERSION "v1.9.0" +#define APP_RELEASE_DATE "2020-11-29" #include #include + #include -#include "./config.h" +#ifdef BOARD_TTGO_T4 +#include "BoardTtgoT4v13.h" +#endif // BOARD_TTGO_T4 +#ifdef BOARD_M5STACK_CORE +#include "BoardM5stackCore.h" +#endif // BOARD_M5STACK_CORE +#include "config.h" + #include //#include #include #include #include -#include "./struct.h" -#include "./menu.h" -#include "./car_kia_eniro.h" -#include "./car_hyundai_ioniq.h" -#include "./car_renault_zoe.h" -#include "./car_debug_obd2_kia.h" +#include "LiveData.h" +#include "menu.h" +#include "CarInterface.h" +#include "CarKiaEniro.h" +#include "CarHyundaiIoniq.h" +#include "CarKiaDebugObd2.h" #ifdef SIM800L_ENABLED #include @@ -103,6 +111,10 @@ String debugTmpChargingLast06 = ""; String debugTmpChargingPrevious06 = ""; String debugTmpChargingRef06 = "620106FFFFFFFF--00--########################00--28EA00"; +// Car +CarInterface* carInterface; +LiveData* liveData; + /** Clear screen a display two lines message */ @@ -153,7 +165,7 @@ bool saveSettings() { // Flash to memory Serial.println("Settings saved to eeprom."); - EEPROM.put(0, settings); + EEPROM.put(0, liveData->settings); EEPROM.commit(); return true; @@ -166,8 +178,8 @@ bool resetSettings() { // Flash to memory Serial.println("Factory reset."); - settings.initFlag = 1; - EEPROM.put(0, settings); + liveData->settings.initFlag = 1; + EEPROM.put(0, liveData->settings); EEPROM.commit(); displayMessage("Settings erased", "Restarting in 5 seconds"); @@ -186,78 +198,80 @@ bool loadSettings() { String tmpStr; // Init - settings.initFlag = 183; - settings.settingsVersion = 3; - settings.carType = CAR_KIA_ENIRO_2020_64; + liveData->settings.initFlag = 183; + liveData->settings.settingsVersion = 3; + liveData->settings.carType = CAR_KIA_ENIRO_2020_64; // Default OBD adapter MAC and UUID's tmpStr = "00:00:00:00:00:00"; // Pair via menu (middle button) - tmpStr.toCharArray(settings.obdMacAddress, 18); + tmpStr.toCharArray(liveData->settings.obdMacAddress, 18); tmpStr = "000018f0-0000-1000-8000-00805f9b34fb"; // Default UUID's for VGate iCar Pro BLE4 adapter - tmpStr.toCharArray(settings.serviceUUID, 37); + tmpStr.toCharArray(liveData->settings.serviceUUID, 37); tmpStr = "00002af0-0000-1000-8000-00805f9b34fb"; - tmpStr.toCharArray(settings.charTxUUID, 37); + tmpStr.toCharArray(liveData->settings.charTxUUID, 37); tmpStr = "00002af1-0000-1000-8000-00805f9b34fb"; - tmpStr.toCharArray(settings.charRxUUID, 37); + tmpStr.toCharArray(liveData->settings.charRxUUID, 37); - settings.displayRotation = 1; // 1,3 - settings.distanceUnit = 'k'; - settings.temperatureUnit = 'c'; - settings.pressureUnit = 'b'; - settings.defaultScreen = 1; - settings.lcdBrightness = 0; - settings.debugScreen = 0; - settings.predrawnChargingGraphs = 1; + liveData->settings.displayRotation = 1; // 1,3 + liveData->settings.distanceUnit = 'k'; + liveData->settings.temperatureUnit = 'c'; + liveData->settings.pressureUnit = 'b'; + liveData->settings.defaultScreen = 1; + liveData->settings.lcdBrightness = 0; + liveData->settings.debugScreen = 0; + liveData->settings.predrawnChargingGraphs = 1; // Load settings and replace default values Serial.println("Reading settings from eeprom."); EEPROM.begin(sizeof(SETTINGS_STRUC)); - EEPROM.get(0, tmpSettings); + EEPROM.get(0, liveData->tmpSettings); // Init flash with default settings - if (tmpSettings.initFlag != 183) { + if (liveData->tmpSettings.initFlag != 183) { Serial.println("Settings not found. Initialization."); saveSettings(); } else { Serial.print("Loaded settings ver.: "); - Serial.println(settings.settingsVersion); + Serial.println(liveData->settings.settingsVersion); // Upgrade structure - if (settings.settingsVersion != tmpSettings.settingsVersion) { - if (tmpSettings.settingsVersion == 1) { - tmpSettings.settingsVersion = 2; - tmpSettings.defaultScreen = settings.defaultScreen; - tmpSettings.lcdBrightness = settings.lcdBrightness; - tmpSettings.debugScreen = settings.debugScreen; + if (liveData->settings.settingsVersion != liveData->tmpSettings.settingsVersion) { + if (liveData->tmpSettings.settingsVersion == 1) { + liveData->tmpSettings.settingsVersion = 2; + liveData->tmpSettings.defaultScreen = liveData->settings.defaultScreen; + liveData->tmpSettings.lcdBrightness = liveData->settings.lcdBrightness; + liveData->tmpSettings.debugScreen = liveData->settings.debugScreen; } - if (tmpSettings.settingsVersion == 2) { - tmpSettings.settingsVersion = 3; - tmpSettings.predrawnChargingGraphs = settings.predrawnChargingGraphs; + if (liveData->tmpSettings.settingsVersion == 2) { + liveData->tmpSettings.settingsVersion = 3; + liveData->tmpSettings.predrawnChargingGraphs = liveData->settings.predrawnChargingGraphs; } saveSettings(); } // Save version? No need to upgrade structure - if (settings.settingsVersion == tmpSettings.settingsVersion) { - settings = tmpSettings; + if (liveData->settings.settingsVersion == liveData->tmpSettings.settingsVersion) { + liveData->settings = liveData->tmpSettings; } } // Load command queue - if (settings.carType == CAR_KIA_ENIRO_2020_64 || settings.carType == CAR_HYUNDAI_KONA_2020_64 || - settings.carType == CAR_KIA_ENIRO_2020_39 || settings.carType == CAR_HYUNDAI_KONA_2020_39) { - activateCommandQueueForKiaENiro(); + if (liveData->settings.carType == CAR_KIA_ENIRO_2020_64 || liveData->settings.carType == CAR_HYUNDAI_KONA_2020_64 || + liveData->settings.carType == CAR_KIA_ENIRO_2020_39 || liveData->settings.carType == CAR_HYUNDAI_KONA_2020_39) { + CarKiaEniro* tmpCar = new CarKiaEniro(); + carInterface = tmpCar; + } else + if (liveData->settings.carType == CAR_HYUNDAI_IONIQ_2018) { + CarHyundaiIoniq* tmpCar = new CarHyundaiIoniq(); + carInterface = tmpCar; + } else { + // if (liveData->settings.carType == CAR_DEBUG_OBD2_KIA) + CarKiaDebugObd2* tmpCar = new CarKiaDebugObd2(); + carInterface = tmpCar; } - if (settings.carType == CAR_HYUNDAI_IONIQ_2018) { - activateCommandQueueForHyundaiIoniq(); - } - if (settings.carType == CAR_RENAULT_ZOE) { - activateCommandQueueForRenaultZoe(); - } - if (settings.carType == CAR_DEBUG_OBD2_KIA) { - activateCommandQueueForDebugObd2Kia(); - } - debugCommandIndex = commandQueueLoopFrom; + carInterface->setLiveData(liveData); + carInterface->activateCommandQueue(); + debugCommandIndex = liveData->commandQueueLoopFrom; return true; } @@ -267,91 +281,91 @@ bool loadSettings() { */ bool initStructure() { - params.automatickShutdownTimer = 0; + liveData->params.automatickShutdownTimer = 0; #ifdef SIM800L_ENABLED - params.lastDataSent = 0; - params.sim800l_enabled = true; + liveData->params.lastDataSent = 0; + liveData->params.sim800l_enabled = true; #endif //SIM800L_ENABLED - params.ignitionOn = false; - params.ignitionOnPrevious = false; - params.chargingStartTime = params.currentTime = 0; - params.lightInfo = 0; - params.headLights = false; - params.dayLights = false; - params.brakeLights = false; - params.brakeLightInfo = 0; - params.forwardDriveMode = false; - params.reverseDriveMode = false; - params.parkModeOrNeutral = false; - params.espState = 0; - params.speedKmh = -1; - params.motorRpm = -1; - params.odoKm = -1; - params.socPerc = -1; - params.socPercPrevious = -1; - params.sohPerc = -1; - params.cumulativeEnergyChargedKWh = -1; - params.cumulativeEnergyChargedKWhStart = -1; - params.cumulativeEnergyDischargedKWh = -1; - params.cumulativeEnergyDischargedKWhStart = -1; - params.availableChargePower = -1; - params.availableDischargePower = -1; - params.isolationResistanceKOhm = -1; - params.batPowerAmp = -1; - params.batPowerKw = -1; - params.batPowerKwh100 = -1; - params.batVoltage = -1; - params.batCellMinV = -1; - params.batCellMaxV = -1; - params.batTempC = -1; - params.batHeaterC = -1; - params.batInletC = -1; - params.batFanStatus = -1; - params.batFanFeedbackHz = -1; - params.batMinC = -1; - params.batMaxC = -1; + liveData->params.ignitionOn = false; + liveData->params.ignitionOnPrevious = false; + liveData->params.chargingStartTime = liveData->params.currentTime = 0; + liveData->params.lightInfo = 0; + liveData->params.headLights = false; + liveData->params.dayLights = false; + liveData->params.brakeLights = false; + liveData->params.brakeLightInfo = 0; + liveData->params.forwardDriveMode = false; + liveData->params.reverseDriveMode = false; + liveData->params.parkModeOrNeutral = false; + liveData->params.espState = 0; + liveData->params.speedKmh = -1; + liveData->params.motorRpm = -1; + liveData->params.odoKm = -1; + liveData->params.socPerc = -1; + liveData->params.socPercPrevious = -1; + liveData->params.sohPerc = -1; + liveData->params.cumulativeEnergyChargedKWh = -1; + liveData->params.cumulativeEnergyChargedKWhStart = -1; + liveData->params.cumulativeEnergyDischargedKWh = -1; + liveData->params.cumulativeEnergyDischargedKWhStart = -1; + liveData->params.availableChargePower = -1; + liveData->params.availableDischargePower = -1; + liveData->params.isolationResistanceKOhm = -1; + liveData->params.batPowerAmp = -1; + liveData->params.batPowerKw = -1; + liveData->params.batPowerKwh100 = -1; + liveData->params.batVoltage = -1; + liveData->params.batCellMinV = -1; + liveData->params.batCellMaxV = -1; + liveData->params.batTempC = -1; + liveData->params.batHeaterC = -1; + liveData->params.batInletC = -1; + liveData->params.batFanStatus = -1; + liveData->params.batFanFeedbackHz = -1; + liveData->params.batMinC = -1; + liveData->params.batMaxC = -1; for (int i = 0; i < 12; i++) { - params.batModuleTempC[i] = 0; + liveData->params.batModuleTempC[i] = 0; } - params.batModuleTempC[0] = -1; - params.batModuleTempC[1] = -1; - params.batModuleTempC[2] = -1; - params.batModuleTempC[3] = -1; - params.coolingWaterTempC = -1; - params.coolantTemp1C = -1; - params.coolantTemp2C = -1; - params.bmsUnknownTempA = -1; - params.bmsUnknownTempB = -1; - params.bmsUnknownTempC = -1; - params.bmsUnknownTempD = -1; - params.auxPerc = -1; - params.auxCurrentAmp = -1; - params.auxVoltage = -1; - params.indoorTemperature = -1; - params.outdoorTemperature = -1; - params.tireFrontLeftTempC = -1; - params.tireFrontLeftPressureBar = -1; - params.tireFrontRightTempC = -1; - params.tireFrontRightPressureBar = -1; - params.tireRearLeftTempC = -1; - params.tireRearLeftPressureBar = -1; - params.tireRearRightTempC = -1; - params.tireRearRightPressureBar = -1; + liveData->params.batModuleTempC[0] = -1; + liveData->params.batModuleTempC[1] = -1; + liveData->params.batModuleTempC[2] = -1; + liveData->params.batModuleTempC[3] = -1; + liveData->params.coolingWaterTempC = -1; + liveData->params.coolantTemp1C = -1; + liveData->params.coolantTemp2C = -1; + liveData->params.bmsUnknownTempA = -1; + liveData->params.bmsUnknownTempB = -1; + liveData->params.bmsUnknownTempC = -1; + liveData->params.bmsUnknownTempD = -1; + liveData->params.auxPerc = -1; + liveData->params.auxCurrentAmp = -1; + liveData->params.auxVoltage = -1; + liveData->params.indoorTemperature = -1; + liveData->params.outdoorTemperature = -1; + liveData->params.tireFrontLeftTempC = -1; + liveData->params.tireFrontLeftPressureBar = -1; + liveData->params.tireFrontRightTempC = -1; + liveData->params.tireFrontRightPressureBar = -1; + liveData->params.tireRearLeftTempC = -1; + liveData->params.tireRearLeftPressureBar = -1; + liveData->params.tireRearRightTempC = -1; + liveData->params.tireRearRightPressureBar = -1; for (int i = 0; i <= 10; i++) { - params.soc10ced[i] = params.soc10cec[i] = params.soc10odo[i] = -1; - params.soc10time[i] = 0; + liveData->params.soc10ced[i] = liveData->params.soc10cec[i] = liveData->params.soc10odo[i] = -1; + liveData->params.soc10time[i] = 0; } for (int i = 0; i < 98; i++) { - params.cellVoltage[i] = 0; + liveData->params.cellVoltage[i] = 0; } - params.cellCount = 0; + liveData->params.cellCount = 0; for (int i = 0; i <= 100; i++) { - params.chargingGraphMinKw[i] = -1; - params.chargingGraphMaxKw[i] = -1; - params.chargingGraphBatMinTempC[i] = -100; - params.chargingGraphBatMaxTempC[i] = -100; - params.chargingGraphHeaterTempC[i] = -100; - params.chargingGraphWaterCoolantTempC[i] = -100; + liveData->params.chargingGraphMinKw[i] = -1; + liveData->params.chargingGraphMaxKw[i] = -1; + liveData->params.chargingGraphBatMinTempC[i] = -100; + liveData->params.chargingGraphBatMaxTempC[i] = -100; + liveData->params.chargingGraphHeaterTempC[i] = -100; + liveData->params.chargingGraphWaterCoolantTempC[i] = -100; } return true; @@ -361,21 +375,21 @@ bool initStructure() { Convert km to km or miles */ float km2distance(float inKm) { - return (settings.distanceUnit == 'k') ? inKm : inKm / 1.609344; + return (liveData->settings.distanceUnit == 'k') ? inKm : inKm / 1.609344; } /** Convert celsius to celsius or farenheit */ float celsius2temperature(float inCelsius) { - return (settings.temperatureUnit == 'c') ? inCelsius : (inCelsius * 1.8) + 32; + return (liveData->settings.temperatureUnit == 'c') ? inCelsius : (inCelsius * 1.8) + 32; } /** Convert bar to bar or psi */ float bar2pressure(float inBar) { - return (settings.pressureUnit == 'b') ? inBar : inBar * 14.503773800722; + return (liveData->settings.pressureUnit == 'b') ? inBar : inBar * 14.503773800722; } /** @@ -402,13 +416,13 @@ bool monitoringRect(int32_t x, int32_t y, int32_t w, int32_t h, const char* text // Bottom 2 numbers with charged/discharged kWh from start posx = (x * 80) + 5; posy = ((y + h) * 60) - 32; - sprintf(tmpStr3, "-%01.01f", params.cumulativeEnergyDischargedKWh - params.cumulativeEnergyDischargedKWhStart); + sprintf(tmpStr3, "-%01.01f", liveData->params.cumulativeEnergyDischargedKWh - liveData->params.cumulativeEnergyDischargedKWhStart); spr.setFreeFont(&Roboto_Thin_24); spr.setTextDatum(TL_DATUM); spr.drawString(tmpStr3, posx, posy, GFXFF); posx = ((x + w) * 80) - 8; - sprintf(tmpStr3, "+%01.01f", params.cumulativeEnergyChargedKWh - params.cumulativeEnergyChargedKWhStart); + sprintf(tmpStr3, "+%01.01f", liveData->params.cumulativeEnergyChargedKWh - liveData->params.cumulativeEnergyChargedKWhStart); spr.setTextDatum(TR_DATUM); spr.drawString(tmpStr3, posx, posy, GFXFF); @@ -497,78 +511,78 @@ bool drawSceneMain() { // Tire pressure char pressureStr[4] = "bar"; char temperatureStr[2] = "C"; - if (settings.pressureUnit != 'b') + if (liveData->settings.pressureUnit != 'b') strcpy(pressureStr, "psi"); - if (settings.temperatureUnit != 'c') + if (liveData->settings.temperatureUnit != 'c') strcpy(temperatureStr, "F"); - sprintf(tmpStr1, "%01.01f%s %02.00f%s", bar2pressure(params.tireFrontLeftPressureBar), pressureStr, celsius2temperature(params.tireFrontLeftTempC), temperatureStr); - sprintf(tmpStr2, "%02.00f%s %01.01f%s", celsius2temperature(params.tireFrontRightTempC), temperatureStr, bar2pressure(params.tireFrontRightPressureBar), pressureStr); - sprintf(tmpStr3, "%01.01f%s %02.00f%s", bar2pressure(params.tireRearLeftPressureBar), pressureStr, celsius2temperature(params.tireRearLeftTempC), temperatureStr); - sprintf(tmpStr4, "%02.00f%s %01.01f%s", celsius2temperature(params.tireRearRightTempC), temperatureStr, bar2pressure(params.tireRearRightPressureBar), pressureStr); + sprintf(tmpStr1, "%01.01f%s %02.00f%s", bar2pressure(liveData->params.tireFrontLeftPressureBar), pressureStr, celsius2temperature(liveData->params.tireFrontLeftTempC), temperatureStr); + sprintf(tmpStr2, "%02.00f%s %01.01f%s", celsius2temperature(liveData->params.tireFrontRightTempC), temperatureStr, bar2pressure(liveData->params.tireFrontRightPressureBar), pressureStr); + sprintf(tmpStr3, "%01.01f%s %02.00f%s", bar2pressure(liveData->params.tireRearLeftPressureBar), pressureStr, celsius2temperature(liveData->params.tireRearLeftTempC), temperatureStr); + sprintf(tmpStr4, "%02.00f%s %01.01f%s", celsius2temperature(liveData->params.tireRearRightTempC), temperatureStr, bar2pressure(liveData->params.tireRearRightPressureBar), pressureStr); showTires(1, 0, 2, 1, tmpStr1, tmpStr2, tmpStr3, tmpStr4, TFT_BLACK); // Added later - kwh total in tires box // TODO: refactoring spr.setTextDatum(TL_DATUM); spr.setTextColor(TFT_GREEN, TFT_BLACK); - sprintf(tmpStr1, "C: %01.01f +%01.01fkWh", params.cumulativeEnergyChargedKWh, params.cumulativeEnergyChargedKWh - params.cumulativeEnergyChargedKWhStart); + sprintf(tmpStr1, "C: %01.01f +%01.01fkWh", liveData->params.cumulativeEnergyChargedKWh, liveData->params.cumulativeEnergyChargedKWh - liveData->params.cumulativeEnergyChargedKWhStart); spr.drawString(tmpStr1, (1 * 80) + 4, (0 * 60) + 30, 2); spr.setTextColor(TFT_YELLOW, TFT_BLACK); - sprintf(tmpStr1, "D: %01.01f -%01.01fkWh", params.cumulativeEnergyDischargedKWh, params.cumulativeEnergyDischargedKWh - params.cumulativeEnergyDischargedKWhStart); + sprintf(tmpStr1, "D: %01.01f -%01.01fkWh", liveData->params.cumulativeEnergyDischargedKWh, liveData->params.cumulativeEnergyDischargedKWh - liveData->params.cumulativeEnergyDischargedKWhStart); spr.drawString(tmpStr1, (1 * 80) + 4, (0 * 60) + 44, 2); // batPowerKwh100 on roads, else batPowerAmp - if (params.speedKmh > 20) { - sprintf(tmpStr1, "%01.01f", km2distance(params.batPowerKwh100)); - monitoringRect(1, 1, 2, 2, tmpStr1, ((settings.distanceUnit == 'k') ? "POWER KWH/100KM" : "POWER KWH/100MI"), (params.batPowerKwh100 >= 0 ? TFT_DARKGREEN2 : (params.batPowerKwh100 < -30.0 ? TFT_RED : TFT_DARKRED)), TFT_WHITE); + if (liveData->params.speedKmh > 20) { + sprintf(tmpStr1, "%01.01f", km2distance(liveData->params.batPowerKwh100)); + monitoringRect(1, 1, 2, 2, tmpStr1, ((liveData->settings.distanceUnit == 'k') ? "POWER KWH/100KM" : "POWER KWH/100MI"), (liveData->params.batPowerKwh100 >= 0 ? TFT_DARKGREEN2 : (liveData->params.batPowerKwh100 < -30.0 ? TFT_RED : TFT_DARKRED)), TFT_WHITE); } else { // batPowerAmp on chargers (under 10kmh) - sprintf(tmpStr1, "%01.01f", params.batPowerKw); - monitoringRect(1, 1, 2, 2, tmpStr1, "POWER KW", (params.batPowerKw >= 0 ? TFT_DARKGREEN2 : (params.batPowerKw <= -30 ? TFT_RED : TFT_DARKRED)), TFT_WHITE); + sprintf(tmpStr1, "%01.01f", liveData->params.batPowerKw); + monitoringRect(1, 1, 2, 2, tmpStr1, "POWER KW", (liveData->params.batPowerKw >= 0 ? TFT_DARKGREEN2 : (liveData->params.batPowerKw <= -30 ? TFT_RED : TFT_DARKRED)), TFT_WHITE); } // socPerc - sprintf(tmpStr1, "%01.00f%%", params.socPerc); - sprintf(tmpStr2, (params.sohPerc == 100.0 ? "SOC/H%01.00f%%" : "SOC/H%01.01f%%"), params.sohPerc); - monitoringRect(0, 0, 1, 1, tmpStr1, tmpStr2, (params.socPerc < 10 || params.sohPerc < 100 ? TFT_RED : (params.socPerc > 80 ? TFT_DARKGREEN2 : TFT_DEFAULT_BK)), TFT_WHITE); + sprintf(tmpStr1, "%01.00f%%", liveData->params.socPerc); + sprintf(tmpStr2, (liveData->params.sohPerc == 100.0 ? "SOC/H%01.00f%%" : "SOC/H%01.01f%%"), liveData->params.sohPerc); + monitoringRect(0, 0, 1, 1, tmpStr1, tmpStr2, (liveData->params.socPerc < 10 || liveData->params.sohPerc < 100 ? TFT_RED : (liveData->params.socPerc > 80 ? TFT_DARKGREEN2 : TFT_DEFAULT_BK)), TFT_WHITE); // batPowerAmp - sprintf(tmpStr1, (abs(params.batPowerAmp) > 9.9 ? "%01.00f" : "%01.01f"), params.batPowerAmp); - monitoringRect(0, 1, 1, 1, tmpStr1, "CURRENT A", (params.batPowerAmp >= 0 ? TFT_DARKGREEN2 : TFT_DARKRED), TFT_WHITE); + sprintf(tmpStr1, (abs(liveData->params.batPowerAmp) > 9.9 ? "%01.00f" : "%01.01f"), liveData->params.batPowerAmp); + monitoringRect(0, 1, 1, 1, tmpStr1, "CURRENT A", (liveData->params.batPowerAmp >= 0 ? TFT_DARKGREEN2 : TFT_DARKRED), TFT_WHITE); // batVoltage - sprintf(tmpStr1, "%03.00f", params.batVoltage); + sprintf(tmpStr1, "%03.00f", liveData->params.batVoltage); monitoringRect(0, 2, 1, 1, tmpStr1, "VOLTAGE", TFT_DEFAULT_BK, TFT_WHITE); // batCellMinV - sprintf(tmpStr1, "%01.02f", params.batCellMaxV - params.batCellMinV); - sprintf(tmpStr2, "CELLS %01.02f", params.batCellMinV); - monitoringRect(0, 3, 1, 1, ( params.batCellMaxV - params.batCellMinV == 0.00 ? "OK" : tmpStr1), tmpStr2, TFT_DEFAULT_BK, TFT_WHITE); + sprintf(tmpStr1, "%01.02f", liveData->params.batCellMaxV - liveData->params.batCellMinV); + sprintf(tmpStr2, "CELLS %01.02f", liveData->params.batCellMinV); + monitoringRect(0, 3, 1, 1, ( liveData->params.batCellMaxV - liveData->params.batCellMinV == 0.00 ? "OK" : tmpStr1), tmpStr2, TFT_DEFAULT_BK, TFT_WHITE); // batTempC - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f" : "%01.01f"), celsius2temperature(params.batMinC)); - sprintf(tmpStr2, ((settings.temperatureUnit == 'c') ? "BATT. %01.00fC" : "BATT. %01.01fF"), celsius2temperature(params.batMaxC)); - monitoringRect(1, 3, 1, 1, tmpStr1, tmpStr2, TFT_TEMP, (params.batTempC >= 15) ? ((params.batTempC >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f" : "%01.01f"), celsius2temperature(liveData->params.batMinC)); + sprintf(tmpStr2, ((liveData->settings.temperatureUnit == 'c') ? "BATT. %01.00fC" : "BATT. %01.01fF"), celsius2temperature(liveData->params.batMaxC)); + monitoringRect(1, 3, 1, 1, tmpStr1, tmpStr2, TFT_TEMP, (liveData->params.batTempC >= 15) ? ((liveData->params.batTempC >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); // batHeaterC - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f" : "%01.01f"), celsius2temperature(params.batHeaterC)); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f" : "%01.01f"), celsius2temperature(liveData->params.batHeaterC)); monitoringRect(2, 3, 1, 1, tmpStr1, "BAT.HEAT", TFT_TEMP, TFT_WHITE); // Aux perc - sprintf(tmpStr1, "%01.00f%%", params.auxPerc); - monitoringRect(3, 0, 1, 1, tmpStr1, "AUX BAT.", (params.auxPerc < 60 ? TFT_RED : TFT_DEFAULT_BK), TFT_WHITE); + sprintf(tmpStr1, "%01.00f%%", liveData->params.auxPerc); + monitoringRect(3, 0, 1, 1, tmpStr1, "AUX BAT.", (liveData->params.auxPerc < 60 ? TFT_RED : TFT_DEFAULT_BK), TFT_WHITE); // Aux amp - sprintf(tmpStr1, (abs(params.auxCurrentAmp) > 9.9 ? "%01.00f" : "%01.01f"), params.auxCurrentAmp); - monitoringRect(3, 1, 1, 1, tmpStr1, "AUX AMPS", (params.auxCurrentAmp >= 0 ? TFT_DARKGREEN2 : TFT_DARKRED), TFT_WHITE); + sprintf(tmpStr1, (abs(liveData->params.auxCurrentAmp) > 9.9 ? "%01.00f" : "%01.01f"), liveData->params.auxCurrentAmp); + monitoringRect(3, 1, 1, 1, tmpStr1, "AUX AMPS", (liveData->params.auxCurrentAmp >= 0 ? TFT_DARKGREEN2 : TFT_DARKRED), TFT_WHITE); // auxVoltage - sprintf(tmpStr1, "%01.01f", params.auxVoltage); - monitoringRect(3, 2, 1, 1, tmpStr1, "AUX VOLTS", (params.auxVoltage < 12.1 ? TFT_RED : (params.auxVoltage < 12.6 ? TFT_ORANGE : TFT_DEFAULT_BK)), TFT_WHITE); + sprintf(tmpStr1, "%01.01f", liveData->params.auxVoltage); + monitoringRect(3, 2, 1, 1, tmpStr1, "AUX VOLTS", (liveData->params.auxVoltage < 12.1 ? TFT_RED : (liveData->params.auxVoltage < 12.6 ? TFT_ORANGE : TFT_DEFAULT_BK)), TFT_WHITE); // indoorTemperature - sprintf(tmpStr1, "%01.01f", celsius2temperature(params.indoorTemperature)); - sprintf(tmpStr2, "IN/OUT%01.01f", celsius2temperature(params.outdoorTemperature)); + sprintf(tmpStr1, "%01.01f", celsius2temperature(liveData->params.indoorTemperature)); + sprintf(tmpStr2, "IN/OUT%01.01f", celsius2temperature(liveData->params.outdoorTemperature)); monitoringRect(3, 3, 1, 1, tmpStr1, tmpStr2, TFT_TEMP, TFT_WHITE); return true; @@ -594,29 +608,29 @@ bool drawSceneSpeed() { tft.setTextColor(TFT_WHITE, TFT_BLACK); // foreground, background text color // Draw speed - tft.setTextSize((params.speedKmh > 99) ? 1 : 2); + tft.setTextSize((liveData->params.speedKmh > 99) ? 1 : 2); sprintf(tmpStr3, "0"); - if (params.speedKmh > 10) - sprintf(tmpStr3, "%01.00f", km2distance(params.speedKmh)); + if (liveData->params.speedKmh > 10) + sprintf(tmpStr3, "%01.00f", km2distance(liveData->params.speedKmh)); tft.drawString(tmpStr3, 240, 0, 8); // Draw power kWh/100km (>25kmh) else kW tft.setTextSize(1); - if (params.speedKmh > 25 && params.batPowerKw < 0) - sprintf(tmpStr3, "%01.01f", km2distance(params.batPowerKwh100)); + if (liveData->params.speedKmh > 25 && liveData->params.batPowerKw < 0) + sprintf(tmpStr3, "%01.01f", km2distance(liveData->params.batPowerKwh100)); else - sprintf(tmpStr3, "%01.01f", params.batPowerKw); + sprintf(tmpStr3, "%01.01f", liveData->params.batPowerKw); tft.drawString(tmpStr3, 240, 150, 8); // Draw soc% - sprintf(tmpStr3, "%01.00f", params.socPerc); + sprintf(tmpStr3, "%01.00f", liveData->params.socPerc); tft.drawString(tmpStr3, 240 , 230, 8); // Cold gate cirlce - tft.fillCircle(30, 280, 25, (params.batTempC >= 15) ? ((params.batTempC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED); + tft.fillCircle(30, 280, 25, (liveData->params.batTempC >= 15) ? ((liveData->params.batTempC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED); // Brake lights - tft.fillRect(0, 310, 240, 10, (params.brakeLights) ? TFT_RED : TFT_BLACK); + tft.fillRect(0, 310, 240, 10, (liveData->params.brakeLights) ? TFT_RED : TFT_BLACK); return true; } @@ -630,17 +644,17 @@ bool drawSceneSpeed() { spr.setTextColor(TFT_WHITE, TFT_DARKRED); spr.setTextSize(2); // Size for small 5cix7 font sprintf(tmpStr3, "0"); - if (params.speedKmh > 10) - sprintf(tmpStr3, "%01.00f", km2distance(params.speedKmh)); + if (liveData->params.speedKmh > 10) + sprintf(tmpStr3, "%01.00f", km2distance(liveData->params.speedKmh)); spr.drawString(tmpStr3, 200, posy, 7); posy = 145; spr.setTextDatum(TR_DATUM); // Top center spr.setTextSize(1); - if (params.speedKmh > 25 && params.batPowerKw < 0) { - sprintf(tmpStr3, "%01.01f", km2distance(params.batPowerKwh100)); + if (liveData->params.speedKmh > 25 && liveData->params.batPowerKw < 0) { + sprintf(tmpStr3, "%01.01f", km2distance(liveData->params.batPowerKwh100)); } else { - sprintf(tmpStr3, "%01.01f", params.batPowerKw); + sprintf(tmpStr3, "%01.01f", liveData->params.batPowerKw); } spr.drawString(tmpStr3, 200, posy, 7); @@ -650,52 +664,52 @@ bool drawSceneSpeed() { posx = 5; posy = 5; spr.setTextDatum(TL_DATUM); - sprintf(tmpStr3, ((settings.distanceUnit == 'k') ? "%01.00fkm " : "%01.00fmi "), km2distance(params.odoKm)); + sprintf(tmpStr3, ((liveData->settings.distanceUnit == 'k') ? "%01.00fkm " : "%01.00fmi "), km2distance(liveData->params.odoKm)); spr.drawString(tmpStr3, posx, posy, GFXFF); - if (params.motorRpm > -1) { + if (liveData->params.motorRpm > -1) { spr.setTextDatum(TR_DATUM); - sprintf(tmpStr3, " %01.00frpm" , params.motorRpm); + sprintf(tmpStr3, " %01.00frpm" , liveData->params.motorRpm); spr.drawString(tmpStr3, 320 - posx, posy, GFXFF); } // Bottom info // Cummulative regen/power posy = 240 - 5; - sprintf(tmpStr3, "-%01.01f ", params.cumulativeEnergyDischargedKWh - params.cumulativeEnergyDischargedKWhStart); + sprintf(tmpStr3, "-%01.01f ", liveData->params.cumulativeEnergyDischargedKWh - liveData->params.cumulativeEnergyDischargedKWhStart); spr.setTextDatum(BL_DATUM); spr.drawString(tmpStr3, posx, posy, GFXFF); posx = 320 - 5; - sprintf(tmpStr3, " +%01.01f", params.cumulativeEnergyChargedKWh - params.cumulativeEnergyChargedKWhStart); + sprintf(tmpStr3, " +%01.01f", liveData->params.cumulativeEnergyChargedKWh - liveData->params.cumulativeEnergyChargedKWhStart); spr.setTextDatum(BR_DATUM); spr.drawString(tmpStr3, posx, posy, GFXFF); // Bat.power posx = 320 / 2; - sprintf(tmpStr3, " %01.01fkw ", params.batPowerKw); + sprintf(tmpStr3, " %01.01fkw ", liveData->params.batPowerKw); spr.setTextDatum(BC_DATUM); spr.drawString(tmpStr3, posx, posy, GFXFF); // RIGHT INFO // Battery "cold gate" detection - red < 15C (43KW limit), <25 (blue - 55kW limit), green all ok - spr.fillCircle(290, 60, 25, (params.batTempC >= 15) ? ((params.batTempC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED); - spr.setTextColor(TFT_WHITE, (params.batTempC >= 15) ? ((params.batTempC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED); + spr.fillCircle(290, 60, 25, (liveData->params.batTempC >= 15) ? ((liveData->params.batTempC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED); + spr.setTextColor(TFT_WHITE, (liveData->params.batTempC >= 15) ? ((liveData->params.batTempC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED); spr.setFreeFont(&Roboto_Thin_24); spr.setTextDatum(MC_DATUM); - sprintf(tmpStr3, "%01.00f", celsius2temperature(params.batTempC)); + sprintf(tmpStr3, "%01.00f", celsius2temperature(liveData->params.batTempC)); spr.drawString(tmpStr3, 290, 60, GFXFF); // Brake lights - spr.fillRect(210, 40, 40, 40, (params.brakeLights) ? TFT_RED : TFT_BLACK); + spr.fillRect(210, 40, 40, 40, (liveData->params.brakeLights) ? TFT_RED : TFT_BLACK); // Soc%, bat.kWh spr.setFreeFont(&Orbitron_Light_32); spr.setTextColor(TFT_WHITE, TFT_BLACK); spr.setTextDatum(TR_DATUM); - sprintf(tmpStr3, " %01.00f%%", params.socPerc); + sprintf(tmpStr3, " %01.00f%%", liveData->params.socPerc); spr.drawString(tmpStr3, 320, 94, GFXFF); - if (params.socPerc > 0) { - float capacity = params.batteryTotalAvailableKWh * (params.socPerc / 100); + if (liveData->params.socPerc > 0) { + float capacity = liveData->params.batteryTotalAvailableKWh * (liveData->params.socPerc / 100); // calibration for Niro/Kona, real available capacity is ~66.5kWh, 0-10% ~6.2kWh, 90-100% ~7.2kWh - if (settings.carType == CAR_KIA_ENIRO_2020_64 || settings.carType == CAR_HYUNDAI_KONA_2020_64) { - capacity = (params.socPerc * 0.615) * (1 + (params.socPerc * 0.0008)); + if (liveData->settings.carType == CAR_KIA_ENIRO_2020_64 || liveData->settings.carType == CAR_HYUNDAI_KONA_2020_64) { + capacity = (liveData->params.socPerc * 0.615) * (1 + (liveData->params.socPerc * 0.0008)); } sprintf(tmpStr3, " %01.01f", capacity); spr.drawString(tmpStr3, 320, 129, GFXFF); @@ -712,29 +726,29 @@ bool drawSceneBatteryCells() { int32_t posx, posy; - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batHeaterC)); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batHeaterC)); drawSmallRect(0, 0, 1, 1, tmpStr1, "HEATER", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batInletC)); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batInletC)); drawSmallRect(1, 0, 1, 1, tmpStr1, "BAT.INLET", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batModuleTempC[0])); - drawSmallRect(0, 1, 1, 1, tmpStr1, "MO1", TFT_TEMP, (params.batModuleTempC[0] >= 15) ? ((params.batModuleTempC[0] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batModuleTempC[1])); - drawSmallRect(1, 1, 1, 1, tmpStr1, "MO2", TFT_TEMP, (params.batModuleTempC[1] >= 15) ? ((params.batModuleTempC[1] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batModuleTempC[2])); - drawSmallRect(2, 1, 1, 1, tmpStr1, "MO3", TFT_TEMP, (params.batModuleTempC[2] >= 15) ? ((params.batModuleTempC[2] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batModuleTempC[3])); - drawSmallRect(3, 1, 1, 1, tmpStr1, "MO4", TFT_TEMP, (params.batModuleTempC[3] >= 15) ? ((params.batModuleTempC[3] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batModuleTempC[0])); + drawSmallRect(0, 1, 1, 1, tmpStr1, "MO1", TFT_TEMP, (liveData->params.batModuleTempC[0] >= 15) ? ((liveData->params.batModuleTempC[0] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batModuleTempC[1])); + drawSmallRect(1, 1, 1, 1, tmpStr1, "MO2", TFT_TEMP, (liveData->params.batModuleTempC[1] >= 15) ? ((liveData->params.batModuleTempC[1] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batModuleTempC[2])); + drawSmallRect(2, 1, 1, 1, tmpStr1, "MO3", TFT_TEMP, (liveData->params.batModuleTempC[2] >= 15) ? ((liveData->params.batModuleTempC[2] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batModuleTempC[3])); + drawSmallRect(3, 1, 1, 1, tmpStr1, "MO4", TFT_TEMP, (liveData->params.batModuleTempC[3] >= 15) ? ((liveData->params.batModuleTempC[3] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED); // Ioniq (up to 12 cells) - for (uint16_t i = 4; i < params.batModuleTempCount; i++) { - if (params.batModuleTempC[i] == 0) + for (uint16_t i = 4; i < liveData->params.batModuleTempCount; i++) { + if (liveData->params.batModuleTempC[i] == 0) continue; posx = (((i - 4) % 8) * 40); posy = ((floor((i - 4) / 8)) * 13) + 64; //spr.fillRect(x * 80, y * 32, ((w) * 80), ((h) * 32), bgColor); spr.setTextSize(1); // Size for small 5x7 font spr.setTextDatum(TL_DATUM); - spr.setTextColor(((params.batModuleTempC[i] >= 15) ? ((params.batModuleTempC[i] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED), TFT_BLACK); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00fC" : "%01.01fF"), celsius2temperature(params.batModuleTempC[i])); + spr.setTextColor(((liveData->params.batModuleTempC[i] >= 15) ? ((liveData->params.batModuleTempC[i] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED), TFT_BLACK); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00fC" : "%01.01fF"), celsius2temperature(liveData->params.batModuleTempC[i])); spr.drawString(tmpStr1, posx + 4, posy, 2); } @@ -744,25 +758,25 @@ bool drawSceneBatteryCells() { // Find min and max val float minVal = -1, maxVal = -1; for (int i = 0; i < 98; i++) { - if ((params.cellVoltage[i] < minVal || minVal == -1) && params.cellVoltage[i] != -1) - minVal = params.cellVoltage[i]; - if ((params.cellVoltage[i] > maxVal || maxVal == -1) && params.cellVoltage[i] != -1) - maxVal = params.cellVoltage[i]; - if (params.cellVoltage[i] > 0 && i > params.cellCount + 1) - params.cellCount = i + 1; + if ((liveData->params.cellVoltage[i] < minVal || minVal == -1) && liveData->params.cellVoltage[i] != -1) + minVal = liveData->params.cellVoltage[i]; + if ((liveData->params.cellVoltage[i] > maxVal || maxVal == -1) && liveData->params.cellVoltage[i] != -1) + maxVal = liveData->params.cellVoltage[i]; + if (liveData->params.cellVoltage[i] > 0 && i > liveData->params.cellCount + 1) + liveData->params.cellCount = i + 1; } // Draw cell matrix for (int i = 0; i < 98; i++) { - if (params.cellVoltage[i] == -1) + if (liveData->params.cellVoltage[i] == -1) continue; posx = ((i % 8) * 40) + 4; - posy = ((floor(i / 8) + (params.cellCount > 96 ? 0 : 1)) * 13) + 68; - sprintf(tmpStr3, "%01.02f", params.cellVoltage[i]); + posy = ((floor(i / 8) + (liveData->params.cellCount > 96 ? 0 : 1)) * 13) + 68; + sprintf(tmpStr3, "%01.02f", liveData->params.cellVoltage[i]); spr.setTextColor(TFT_NAVY, TFT_BLACK); - if (params.cellVoltage[i] == minVal && minVal != maxVal) + if (liveData->params.cellVoltage[i] == minVal && minVal != maxVal) spr.setTextColor(TFT_RED, TFT_BLACK); - if (params.cellVoltage[i] == maxVal && minVal != maxVal) + if (liveData->params.cellVoltage[i] == maxVal && minVal != maxVal) spr.setTextColor(TFT_GREEN, TFT_BLACK); spr.drawString(tmpStr3, posx, posy, 2); } @@ -838,13 +852,13 @@ bool drawPreDrawnChargingGraphs(int zeroX, int zeroY, int mulX, int mulY) { // Triangles int x = zeroX; int y; - if (params.batMaxC >= 35) { + if (liveData->params.batMaxC >= 35) { y = zeroY - (/*I*/ 180 * /*U SOC*/ (1 * 55 / 100 + 352) /**/ / 1000 * mulY); - } else if (params.batMinC >= 25) { + } else if (liveData->params.batMinC >= 25) { y = zeroY - (/*I*/ 200 * /*U SOC*/ (1 * 55 / 100 + 352) /**/ / 1000 * mulY); - } else if (params.batMinC >= 15) { + } else if (liveData->params.batMinC >= 15) { y = zeroY - (/*I*/ 150 * /*U SOC*/ (1 * 55 / 100 + 352) /**/ / 1000 * mulY); - } else if (params.batMinC >= 5) { + } else if (liveData->params.batMinC >= 5) { y = zeroY - (/*I*/ 110 * /*U SOC*/ (1 * 55 / 100 + 352) /**/ / 1000 * mulY); } else { y = zeroY - (/*I*/ 60 * /*U SOC*/ (1 * 55 / 100 + 352) /**/ / 1000 * mulY); @@ -867,22 +881,22 @@ bool drawSceneChargingGraph() { spr.fillSprite(TFT_BLACK); - sprintf(tmpStr1, "%01.00f", params.socPerc); + sprintf(tmpStr1, "%01.00f", liveData->params.socPerc); drawSmallRect(0, 0, 1, 1, tmpStr1, "SOC", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, "%01.01f", params.batPowerKw); + sprintf(tmpStr1, "%01.01f", liveData->params.batPowerKw); drawSmallRect(1, 0, 1, 1, tmpStr1, "POWER kW", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, "%01.01f", params.batPowerAmp); + sprintf(tmpStr1, "%01.01f", liveData->params.batPowerAmp); drawSmallRect(2, 0, 1, 1, tmpStr1, "CURRENT A", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, "%03.00f", params.batVoltage); + sprintf(tmpStr1, "%03.00f", liveData->params.batVoltage); drawSmallRect(3, 0, 1, 1, tmpStr1, "VOLTAGE", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batHeaterC)); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batHeaterC)); drawSmallRect(0, 1, 1, 1, tmpStr1, "HEATER", TFT_TEMP, TFT_RED); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batInletC)); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batInletC)); drawSmallRect(1, 1, 1, 1, tmpStr1, "BAT.INLET", TFT_TEMP, TFT_CYAN); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.batMinC)); - drawSmallRect(2, 1, 1, 1, tmpStr1, "BAT.MIN", (params.batMinC >= 15) ? ((params.batMinC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED, TFT_CYAN); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(params.outdoorTemperature)); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.batMinC)); + drawSmallRect(2, 1, 1, 1, tmpStr1, "BAT.MIN", (liveData->params.batMinC >= 15) ? ((liveData->params.batMinC >= 25) ? TFT_DARKGREEN2 : TFT_BLUE) : TFT_RED, TFT_CYAN); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "%01.00f C" : "%01.01f F"), celsius2temperature(liveData->params.outdoorTemperature)); drawSmallRect(3, 1, 1, 1, tmpStr1, "OUT.TEMP.", TFT_TEMP, TFT_CYAN); spr.setTextColor(TFT_SILVER, TFT_TEMP); @@ -908,102 +922,102 @@ bool drawSceneChargingGraph() { } // Draw suggested curves - if (settings.predrawnChargingGraphs == 1) { + if (liveData->settings.predrawnChargingGraphs == 1) { drawPreDrawnChargingGraphs(zeroX, zeroY, mulX, mulY); } // Draw realtime values for (int i = 0; i <= 100; i++) { - if (params.chargingGraphBatMinTempC[i] > -10) - spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (params.chargingGraphBatMinTempC[i]*mulY), mulX, TFT_BLUE); - if (params.chargingGraphBatMaxTempC[i] > -10) - spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (params.chargingGraphBatMaxTempC[i]*mulY), mulX, TFT_BLUE); - if (params.chargingGraphWaterCoolantTempC[i] > -10) - spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (params.chargingGraphWaterCoolantTempC[i]*mulY), mulX, TFT_PURPLE); - if (params.chargingGraphHeaterTempC[i] > -10) - spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (params.chargingGraphHeaterTempC[i]*mulY), mulX, TFT_RED); + if (liveData->params.chargingGraphBatMinTempC[i] > -10) + spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (liveData->params.chargingGraphBatMinTempC[i]*mulY), mulX, TFT_BLUE); + if (liveData->params.chargingGraphBatMaxTempC[i] > -10) + spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (liveData->params.chargingGraphBatMaxTempC[i]*mulY), mulX, TFT_BLUE); + if (liveData->params.chargingGraphWaterCoolantTempC[i] > -10) + spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (liveData->params.chargingGraphWaterCoolantTempC[i]*mulY), mulX, TFT_PURPLE); + if (liveData->params.chargingGraphHeaterTempC[i] > -10) + spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (liveData->params.chargingGraphHeaterTempC[i]*mulY), mulX, TFT_RED); - if (params.chargingGraphMinKw[i] > 0) - spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (params.chargingGraphMinKw[i]*mulY), mulX, TFT_GREENYELLOW); - if (params.chargingGraphMaxKw[i] > 0) - spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (params.chargingGraphMaxKw[i]*mulY), mulX, TFT_YELLOW); + if (liveData->params.chargingGraphMinKw[i] > 0) + spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (liveData->params.chargingGraphMinKw[i]*mulY), mulX, TFT_GREENYELLOW); + if (liveData->params.chargingGraphMaxKw[i] > 0) + spr.drawFastHLine(zeroX + (i * mulX) - (mulX / 2), zeroY - (liveData->params.chargingGraphMaxKw[i]*mulY), mulX, TFT_YELLOW); } // Bat.module temperatures spr.setTextSize(1); // Size for small 5x7 font spr.setTextDatum(BL_DATUM); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "1=%01.00fC " : "1=%01.00fF "), celsius2temperature(params.batModuleTempC[0])); - spr.setTextColor((params.batModuleTempC[0] >= 15) ? ((params.batModuleTempC[0] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "1=%01.00fC " : "1=%01.00fF "), celsius2temperature(liveData->params.batModuleTempC[0])); + spr.setTextColor((liveData->params.batModuleTempC[0] >= 15) ? ((liveData->params.batModuleTempC[0] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); spr.drawString(tmpStr1, 0, zeroY - (maxKw * mulY), 2); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "2=%01.00fC " : "2=%01.00fF "), celsius2temperature(params.batModuleTempC[1])); - spr.setTextColor((params.batModuleTempC[1] >= 15) ? ((params.batModuleTempC[1] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "2=%01.00fC " : "2=%01.00fF "), celsius2temperature(liveData->params.batModuleTempC[1])); + spr.setTextColor((liveData->params.batModuleTempC[1] >= 15) ? ((liveData->params.batModuleTempC[1] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); spr.drawString(tmpStr1, 48, zeroY - (maxKw * mulY), 2); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "3=%01.00fC " : "3=%01.00fF "), celsius2temperature(params.batModuleTempC[2])); - spr.setTextColor((params.batModuleTempC[2] >= 15) ? ((params.batModuleTempC[2] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "3=%01.00fC " : "3=%01.00fF "), celsius2temperature(liveData->params.batModuleTempC[2])); + spr.setTextColor((liveData->params.batModuleTempC[2] >= 15) ? ((liveData->params.batModuleTempC[2] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); spr.drawString(tmpStr1, 96, zeroY - (maxKw * mulY), 2); - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "4=%01.00fC " : "4=%01.00fF "), celsius2temperature(params.batModuleTempC[3])); - spr.setTextColor((params.batModuleTempC[3] >= 15) ? ((params.batModuleTempC[3] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "4=%01.00fC " : "4=%01.00fF "), celsius2temperature(liveData->params.batModuleTempC[3])); + spr.setTextColor((liveData->params.batModuleTempC[3] >= 15) ? ((liveData->params.batModuleTempC[3] >= 25) ? TFT_GREEN : TFT_BLUE) : TFT_RED, TFT_TEMP); spr.drawString(tmpStr1, 144, zeroY - (maxKw * mulY), 2); - sprintf(tmpStr1, "ir %01.00fkOhm", params.isolationResistanceKOhm ); + sprintf(tmpStr1, "ir %01.00fkOhm", liveData->params.isolationResistanceKOhm ); // Bms max.regen/power available spr.setTextColor(TFT_WHITE, TFT_BLACK); - sprintf(tmpStr1, "xC=%01.00fkW ", params.availableChargePower); + sprintf(tmpStr1, "xC=%01.00fkW ", liveData->params.availableChargePower); spr.drawString(tmpStr1, 192, zeroY - (maxKw * mulY), 2); spr.setTextColor(TFT_WHITE, TFT_BLACK); - sprintf(tmpStr1, "xD=%01.00fkW", params.availableDischargePower); + sprintf(tmpStr1, "xD=%01.00fkW", liveData->params.availableDischargePower); spr.drawString(tmpStr1, 256, zeroY - (maxKw * mulY), 2); // spr.setTextDatum(TR_DATUM); - if (params.coolingWaterTempC != -1) { - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "W=%01.00fC" : "W=%01.00fF"), celsius2temperature(params.coolingWaterTempC)); + if (liveData->params.coolingWaterTempC != -1) { + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "W=%01.00fC" : "W=%01.00fF"), celsius2temperature(liveData->params.coolingWaterTempC)); spr.setTextColor(TFT_PURPLE, TFT_TEMP); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } spr.setTextColor(TFT_WHITE, TFT_TEMP); - if (params.batFanFeedbackHz > 0) { - sprintf(tmpStr1, "FF=%03.00fHz", params.batFanFeedbackHz); + if (liveData->params.batFanFeedbackHz > 0) { + sprintf(tmpStr1, "FF=%03.00fHz", liveData->params.batFanFeedbackHz); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } - if (params.batFanStatus > 0) { - sprintf(tmpStr1, "FS=%03.00f", params.batFanStatus); + if (liveData->params.batFanStatus > 0) { + sprintf(tmpStr1, "FS=%03.00f", liveData->params.batFanStatus); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } - if (params.coolantTemp1C != -1 && params.coolantTemp2C != -1) { - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "C1/2:%01.00f/%01.00fC" : "C1/2:%01.00f/%01.00fF"), celsius2temperature(params.coolantTemp1C), celsius2temperature(params.coolantTemp2C)); + if (liveData->params.coolantTemp1C != -1 && liveData->params.coolantTemp2C != -1) { + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "C1/2:%01.00f/%01.00fC" : "C1/2:%01.00f/%01.00fF"), celsius2temperature(liveData->params.coolantTemp1C), celsius2temperature(liveData->params.coolantTemp2C)); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } - if (params.bmsUnknownTempA != -1) { - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "A=%01.00fC" : "W=%01.00fF"), celsius2temperature(params.bmsUnknownTempA)); + if (liveData->params.bmsUnknownTempA != -1) { + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "A=%01.00fC" : "W=%01.00fF"), celsius2temperature(liveData->params.bmsUnknownTempA)); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } - if (params.bmsUnknownTempB != -1) { - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "B=%01.00fC" : "W=%01.00fF"), celsius2temperature(params.bmsUnknownTempB)); + if (liveData->params.bmsUnknownTempB != -1) { + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "B=%01.00fC" : "W=%01.00fF"), celsius2temperature(liveData->params.bmsUnknownTempB)); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } - if (params.bmsUnknownTempC != -1) { - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "C=%01.00fC" : "W=%01.00fF"), celsius2temperature(params.bmsUnknownTempC)); + if (liveData->params.bmsUnknownTempC != -1) { + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "C=%01.00fC" : "W=%01.00fF"), celsius2temperature(liveData->params.bmsUnknownTempC)); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } - if (params.bmsUnknownTempD != -1) { - sprintf(tmpStr1, ((settings.temperatureUnit == 'c') ? "D=%01.00fC" : "W=%01.00fF"), celsius2temperature(params.bmsUnknownTempD)); + if (liveData->params.bmsUnknownTempD != -1) { + sprintf(tmpStr1, ((liveData->settings.temperatureUnit == 'c') ? "D=%01.00fC" : "W=%01.00fF"), celsius2temperature(liveData->params.bmsUnknownTempD)); spr.drawString(tmpStr1, zeroX + (10 * 10 * mulX), zeroY - (maxKw * mulY) + (posy * 15), 2); posy++; } // Print charging time - time_t diffTime = params.currentTime - params.chargingStartTime; + time_t diffTime = liveData->params.currentTime - liveData->params.chargingStartTime; if ((diffTime / 60) > 99) sprintf(tmpStr1, "%02d:%02d:%02d", (diffTime / 3600) % 24, (diffTime / 60) % 60, diffTime % 60); else @@ -1014,7 +1028,7 @@ bool drawSceneChargingGraph() { // Debug info if (debugTmpCharging) { - if (params.currentTime % 10 > 5) { + if (liveData->params.currentTime % 10 > 5) { int32_t posx, posy; String chHex, chHex2, chRef; uint8_t chByte; @@ -1031,7 +1045,7 @@ bool drawSceneChargingGraph() { if (chRef.equals("--") || chRef.equals(chHex)) continue; spr.setTextColor(((chHex.equals(chHex2)) ? TFT_SILVER : TFT_GREEN), TFT_TEMP); - chByte = hexToDec(chHex.c_str(), 1, false); + chByte = liveData->hexToDec(chHex.c_str(), 1, false); posx = (((i) % 10) * 32) + 24; posy = ((floor((i) / 10)) * 13) + 240 - 104; sprintf(tmpStr1, "%03d", chByte); @@ -1044,7 +1058,7 @@ bool drawSceneChargingGraph() { if (chRef.equals("--") || chRef.equals(chHex)) continue; spr.setTextColor(((chHex.equals(chHex2)) ? TFT_SILVER : TFT_GREEN), TFT_TEMP); - chByte = hexToDec(chHex.c_str(), 1, false); + chByte = liveData->hexToDec(chHex.c_str(), 1, false); posx = (((i) % 10) * 32) + 24; posy = ((floor((i) / 10)) * 13) + 65 + 240 - 104; sprintf(tmpStr1, "%03d", chByte); @@ -1078,7 +1092,7 @@ bool drawSceneSoc10Table() { spr.setTextDatum(TR_DATUM); spr.drawString("dis./char.kWh", 128, zeroY + (1 * 15), 2); - spr.drawString(((settings.distanceUnit == 'k') ? "km" : "mi"), 160, zeroY + (1 * 15), 2); + spr.drawString(((liveData->settings.distanceUnit == 'k') ? "km" : "mi"), 160, zeroY + (1 * 15), 2); spr.drawString("kWh100", 224, zeroY + (1 * 15), 2); spr.drawString("avg.speed", 310, zeroY + (1 * 15), 2); @@ -1086,18 +1100,18 @@ bool drawSceneSoc10Table() { sprintf(tmpStr1, "%d%%", (i == 0) ? 5 : i * 10); spr.drawString(tmpStr1, 32, zeroY + ((12 - i) * 15), 2); - firstCed = (params.soc10ced[i] != -1) ? params.soc10ced[i] : firstCed; - lastCed = (lastCed == -1 && params.soc10ced[i] != -1) ? params.soc10ced[i] : lastCed; - firstCec = (params.soc10cec[i] != -1) ? params.soc10cec[i] : firstCec; - lastCec = (lastCec == -1 && params.soc10cec[i] != -1) ? params.soc10cec[i] : lastCec; - firstOdo = (params.soc10odo[i] != -1) ? params.soc10odo[i] : firstOdo; - lastOdo = (lastOdo == -1 && params.soc10odo[i] != -1) ? params.soc10odo[i] : lastOdo; + firstCed = (liveData->params.soc10ced[i] != -1) ? liveData->params.soc10ced[i] : firstCed; + lastCed = (lastCed == -1 && liveData->params.soc10ced[i] != -1) ? liveData->params.soc10ced[i] : lastCed; + firstCec = (liveData->params.soc10cec[i] != -1) ? liveData->params.soc10cec[i] : firstCec; + lastCec = (lastCec == -1 && liveData->params.soc10cec[i] != -1) ? liveData->params.soc10cec[i] : lastCec; + firstOdo = (liveData->params.soc10odo[i] != -1) ? liveData->params.soc10odo[i] : firstOdo; + lastOdo = (lastOdo == -1 && liveData->params.soc10odo[i] != -1) ? liveData->params.soc10odo[i] : lastOdo; if (i != 10) { - diffCec = (params.soc10cec[i + 1] != -1 && params.soc10cec[i] != -1) ? (params.soc10cec[i] - params.soc10cec[i + 1]) : 0; - diffCed = (params.soc10ced[i + 1] != -1 && params.soc10ced[i] != -1) ? (params.soc10ced[i + 1] - params.soc10ced[i]) : 0; - diffOdo = (params.soc10odo[i + 1] != -1 && params.soc10odo[i] != -1) ? (params.soc10odo[i] - params.soc10odo[i + 1]) : -1; - diffTime = (params.soc10time[i + 1] != -1 && params.soc10time[i] != -1) ? (params.soc10time[i] - params.soc10time[i + 1]) : -1; + diffCec = (liveData->params.soc10cec[i + 1] != -1 && liveData->params.soc10cec[i] != -1) ? (liveData->params.soc10cec[i] - liveData->params.soc10cec[i + 1]) : 0; + diffCed = (liveData->params.soc10ced[i + 1] != -1 && liveData->params.soc10ced[i] != -1) ? (liveData->params.soc10ced[i + 1] - liveData->params.soc10ced[i]) : 0; + diffOdo = (liveData->params.soc10odo[i + 1] != -1 && liveData->params.soc10odo[i] != -1) ? (liveData->params.soc10odo[i] - liveData->params.soc10odo[i + 1]) : -1; + diffTime = (liveData->params.soc10time[i + 1] != -1 && liveData->params.soc10time[i] != -1) ? (liveData->params.soc10time[i] - liveData->params.soc10time[i + 1]) : -1; if (diffCec != 0) { sprintf(tmpStr1, "+%01.01f", diffCec); spr.drawString(tmpStr1, 128, zeroY + ((12 - i) * 15), 2); @@ -1123,8 +1137,8 @@ bool drawSceneSoc10Table() { } } - if (diffOdo == -1 && params.soc10odo[i] != -1) { - sprintf(tmpStr1, "%01.00f", km2distance(params.soc10odo[i])); + if (diffOdo == -1 && liveData->params.soc10odo[i] != -1) { + sprintf(tmpStr1, "%01.00f", km2distance(liveData->params.soc10odo[i])); spr.drawString(tmpStr1, 160, zeroY + ((12 - i) * 15), 2); } } @@ -1162,14 +1176,14 @@ bool drawSceneDebug() { spr.setTextDatum(TL_DATUM); spr.drawString(debugAtshRequest, 0, 0, 2); spr.drawString(debugCommandRequest, 128, 0, 2); - spr.drawString(commandRequest, 256, 0, 2); + spr.drawString(liveData->commandRequest, 256, 0, 2); spr.setTextDatum(TR_DATUM); for (int i = 0; i < debugLastString.length() / 2; i++) { chHex = debugLastString.substring(i * 2, (i * 2) + 2); chHex2 = debugPreviousString.substring(i * 2, (i * 2) + 2); spr.setTextColor(((chHex.equals(chHex2)) ? TFT_SILVER : TFT_GREEN), TFT_TEMP); - chByte = hexToDec(chHex.c_str(), 1, false); + chByte = liveData->hexToDec(chHex.c_str(), 1, false); posx = (((i) % 10) * 32) + 24; posy = ((floor((i) / 10)) * 32) + 24; sprintf(tmpStr1, "%03d", chByte); @@ -1196,11 +1210,11 @@ String menuItemCaption(int16_t menuItemId, String title) { suffix = APP_VERSION; if (menuItemId == 401) // distance - suffix = (settings.distanceUnit == 'k') ? "[km]" : "[mi]"; + suffix = (liveData->settings.distanceUnit == 'k') ? "[km]" : "[mi]"; if (menuItemId == 402) // temperature - suffix = (settings.temperatureUnit == 'c') ? "[C]" : "[F]"; + suffix = (liveData->settings.temperatureUnit == 'c') ? "[C]" : "[F]"; if (menuItemId == 403) // pressure - suffix = (settings.pressureUnit == 'b') ? "[bar]" : "[psi]"; + suffix = (liveData->settings.pressureUnit == 'b') ? "[bar]" : "[psi]"; title = ((prefix == "") ? "" : prefix + " ") + title + ((suffix == "") ? "" : " " + suffix); return title; @@ -1312,51 +1326,50 @@ bool menuItemClick() { Serial.println(tmpMenuItem.id); // Device list if (tmpMenuItem.id > 10000 && tmpMenuItem.id < 10100) { - strlcpy((char*)settings.obdMacAddress, (char*)tmpMenuItem.obdMacAddress, 20); + strlcpy((char*)liveData->settings.obdMacAddress, (char*)tmpMenuItem.obdMacAddress, 20); Serial.print("Selected adapter MAC address "); - Serial.println(settings.obdMacAddress); + Serial.println(liveData->settings.obdMacAddress); saveSettings(); ESP.restart(); } // Other menus switch (tmpMenuItem.id) { // Set vehicle type - case 101: settings.carType = CAR_KIA_ENIRO_2020_64; break; - case 102: settings.carType = CAR_HYUNDAI_KONA_2020_64; break; - case 103: settings.carType = CAR_HYUNDAI_IONIQ_2018; break; - case 104: settings.carType = CAR_KIA_ENIRO_2020_39; break; - case 105: settings.carType = CAR_HYUNDAI_KONA_2020_39; break; - case 106: settings.carType = CAR_RENAULT_ZOE; break; - case 107: settings.carType = CAR_DEBUG_OBD2_KIA; break; + case 101: liveData->settings.carType = CAR_KIA_ENIRO_2020_64; break; + case 102: liveData->settings.carType = CAR_HYUNDAI_KONA_2020_64; break; + case 103: liveData->settings.carType = CAR_HYUNDAI_IONIQ_2018; break; + case 104: liveData->settings.carType = CAR_KIA_ENIRO_2020_39; break; + case 105: liveData->settings.carType = CAR_HYUNDAI_KONA_2020_39; break; + case 107: liveData->settings.carType = CAR_DEBUG_OBD2_KIA; break; // Screen orientation - case 3011: settings.displayRotation = 1; tft.setRotation(settings.displayRotation); break; - case 3012: settings.displayRotation = 3; tft.setRotation(settings.displayRotation); break; + case 3011: liveData->settings.displayRotation = 1; tft.setRotation(liveData->settings.displayRotation); break; + case 3012: liveData->settings.displayRotation = 3; tft.setRotation(liveData->settings.displayRotation); break; // Default screen - case 3021: settings.defaultScreen = 1; break; - case 3022: settings.defaultScreen = 2; break; - case 3023: settings.defaultScreen = 3; break; - case 3024: settings.defaultScreen = 4; break; - case 3025: settings.defaultScreen = 5; break; + case 3021: liveData->settings.defaultScreen = 1; break; + case 3022: liveData->settings.defaultScreen = 2; break; + case 3023: liveData->settings.defaultScreen = 3; break; + case 3024: liveData->settings.defaultScreen = 4; break; + case 3025: liveData->settings.defaultScreen = 5; break; // Debug screen off/on - case 3031: settings.debugScreen = 0; break; - case 3032: settings.debugScreen = 1; break; + case 3031: liveData->settings.debugScreen = 0; break; + case 3032: liveData->settings.debugScreen = 1; break; // Lcd brightness - case 3041: settings.lcdBrightness = 0; break; - case 3042: settings.lcdBrightness = 20; break; - case 3043: settings.lcdBrightness = 50; break; - case 3044: settings.lcdBrightness = 100; break; + case 3041: liveData->settings.lcdBrightness = 0; break; + case 3042: liveData->settings.lcdBrightness = 20; break; + case 3043: liveData->settings.lcdBrightness = 50; break; + case 3044: liveData->settings.lcdBrightness = 100; break; // Pre-drawn charg.graphs off/on - case 3051: settings.predrawnChargingGraphs = 0; break; - case 3052: settings.predrawnChargingGraphs = 1; break; + case 3051: liveData->settings.predrawnChargingGraphs = 0; break; + case 3052: liveData->settings.predrawnChargingGraphs = 1; break; // Distance - case 4011: settings.distanceUnit = 'k'; break; - case 4012: settings.distanceUnit = 'm'; break; + case 4011: liveData->settings.distanceUnit = 'k'; break; + case 4012: liveData->settings.distanceUnit = 'm'; break; // Temperature - case 4021: settings.temperatureUnit = 'c'; break; - case 4022: settings.temperatureUnit = 'f'; break; + case 4021: liveData->settings.temperatureUnit = 'c'; break; + case 4022: liveData->settings.temperatureUnit = 'f'; break; // Pressure - case 4031: settings.pressureUnit = 'b'; break; - case 4032: settings.pressureUnit = 'p'; break; + case 4031: liveData->settings.pressureUnit = 'b'; break; + case 4032: liveData->settings.pressureUnit = 'p'; break; // Pair ble device case 2: startBleScan(); return false; // Reset settings @@ -1392,7 +1405,7 @@ bool redrawScreen() { } // Lights not enabled - if (!testDataMode && params.forwardDriveMode && !params.headLights && !params.dayLights) { + if (!testDataMode && liveData->params.forwardDriveMode && !liveData->params.headLights && !liveData->params.dayLights) { spr.fillSprite(TFT_RED); spr.setFreeFont(&Orbitron_Light_32); spr.setTextColor(TFT_WHITE, TFT_RED); @@ -1407,12 +1420,12 @@ bool redrawScreen() { // 1. Auto mode = >5kpm Screen 3 - speed, other wise basic Screen2 - Main screen, if charging then Screen 5 Graph if (displayScreen == SCREEN_AUTO) { - if (params.speedKmh > 5) { + if (liveData->params.speedKmh > 5) { if (displayScreenAutoMode != 3) { displayScreenAutoMode = 3; } drawSceneSpeed(); - } else if (params.batPowerKw > 1) { + } else if (liveData->params.batPowerKw > 1) { if (displayScreenAutoMode != 5) { displayScreenAutoMode = 5; } @@ -1473,41 +1486,41 @@ bool redrawScreen() { bool doNextAtCommand() { // Restart loop with AT commands - if (commandQueueIndex >= commandQueueCount) { - commandQueueIndex = commandQueueLoopFrom; + if (liveData->commandQueueIndex >= liveData->commandQueueCount) { + liveData->commandQueueIndex = liveData->commandQueueLoopFrom; redrawScreen(); } // Send AT command to obd - commandRequest = commandQueue[commandQueueIndex]; - if (commandRequest.startsWith("ATSH")) { - currentAtshRequest = commandRequest; + liveData->commandRequest = liveData->commandQueue[liveData->commandQueueIndex]; + if (liveData->commandRequest.startsWith("ATSH")) { + liveData->currentAtshRequest = liveData->commandRequest; } Serial.print(">>> "); - Serial.println(commandRequest); - String tmpStr = commandRequest + "\r"; + Serial.println(liveData->commandRequest); + String tmpStr = liveData->commandRequest + "\r"; pRemoteCharacteristicWrite->writeValue(tmpStr.c_str(), tmpStr.length()); - commandQueueIndex++; + liveData->commandQueueIndex++; return true; } /** - Parse result from OBD, create single line responseRowMerged + Parse result from OBD, create single line liveData->responseRowMerged */ bool parseRow() { // Simple 1 line responses Serial.print(""); - Serial.println(responseRow); + Serial.println(liveData->responseRow); // Merge 0:xxxx 1:yyyy 2:zzzz to single xxxxyyyyzzzz string - if (responseRow.length() >= 2 && responseRow.charAt(1) == ':') { - if (responseRow.charAt(0) == '0') { - responseRowMerged = ""; + if (liveData->responseRow.length() >= 2 && liveData->responseRow.charAt(1) == ':') { + if (liveData->responseRow.charAt(0) == '0') { + liveData->responseRowMerged = ""; } - responseRowMerged += responseRow.substring(2); + liveData->responseRowMerged += liveData->responseRow.substring(2); } return true; @@ -1519,37 +1532,25 @@ bool parseRow() { bool parseRowMerged() { Serial.print("merged:"); - Serial.println(responseRowMerged); + Serial.println(liveData->responseRowMerged); // Catch output for debug screen if (displayScreen == SCREEN_DEBUG) { - if (debugCommandIndex == commandQueueIndex) { - debugAtshRequest = currentAtshRequest; - debugCommandRequest = commandRequest; - debugLastString = responseRowMerged; + if (debugCommandIndex == liveData->commandQueueIndex) { + debugAtshRequest = liveData->currentAtshRequest; + debugCommandRequest = liveData->commandRequest; + debugLastString = liveData->responseRowMerged; } } - if (debugTmpCharging && currentAtshRequest.equals("ATSH7E4")) { - if (commandRequest.equals("220105")) - debugTmpChargingLast05 = responseRowMerged; - if (commandRequest.equals("220106")) - debugTmpChargingLast06 = responseRowMerged; + if (debugTmpCharging && liveData->currentAtshRequest.equals("ATSH7E4")) { + if (liveData->commandRequest.equals("220105")) + debugTmpChargingLast05 = liveData->responseRowMerged; + if (liveData->commandRequest.equals("220106")) + debugTmpChargingLast06 = liveData->responseRowMerged; } - // Parse by car - if (settings.carType == CAR_KIA_ENIRO_2020_64 || settings.carType == CAR_HYUNDAI_KONA_2020_64 || - settings.carType == CAR_KIA_ENIRO_2020_39 || settings.carType == CAR_HYUNDAI_KONA_2020_39) { - parseRowMergedKiaENiro(); - } - if (settings.carType == CAR_HYUNDAI_IONIQ_2018) { - parseRowMergedHyundaiIoniq(); - } - if (settings.carType == CAR_RENAULT_ZOE) { - parseRowMergedRenaultZoe(); - } - if (settings.carType == CAR_DEBUG_OBD2_KIA) { - parseRowMergedDebugObd2Kia(); - } + // Parse by selected car interface + carInterface->parseRowMerged(); return true; } @@ -1559,21 +1560,10 @@ bool parseRowMerged() { */ bool testData() { + testDataMode = true; // skip lights off message + carInterface->loadTestData(); redrawScreen(); - - if (settings.carType == CAR_KIA_ENIRO_2020_64 || settings.carType == CAR_HYUNDAI_KONA_2020_64 || - settings.carType == CAR_KIA_ENIRO_2020_39 || settings.carType == CAR_HYUNDAI_KONA_2020_39) { - testDataMode = true; - testDataKiaENiro(); - } - if (settings.carType == CAR_HYUNDAI_IONIQ_2018) { - testDataHyundaiIoniq(); - } - if (settings.carType == CAR_RENAULT_ZOE) { - testDataRenaultZoe(); - } - - redrawScreen(); + return true; } @@ -1638,8 +1628,8 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { } }*/ - if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(BLEUUID(settings.serviceUUID)) && - (strcmp(advertisedDevice.getAddress().toString().c_str(), settings.obdMacAddress) == 0)) { + if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(BLEUUID(liveData->settings.serviceUUID)) && + (strcmp(advertisedDevice.getAddress().toString().c_str(), liveData->settings.obdMacAddress) == 0)) { Serial.println("Stop scanning. Found my BLE device."); BLEDevice::getScan()->stop(); foundMyBleDevice = new BLEAdvertisedDevice(advertisedDevice); @@ -1689,21 +1679,21 @@ static void notifyCallback (BLERemoteCharacteristic * pBLERemoteCharacteristic, char ch; // Parse multi line response to single lines - responseRow = ""; + liveData->responseRow = ""; for (int i = 0; i <= length; i++) { ch = pData[i]; if (ch == '\r' || ch == '\n' || ch == '\0') { - if (responseRow != "") + if (liveData->responseRow != "") parseRow(); - responseRow = ""; + liveData->responseRow = ""; } else { - responseRow += ch; - if (responseRow == ">") { - if (responseRowMerged != "") { + liveData->responseRow += ch; + if (liveData->responseRow == ">") { + if (liveData->responseRowMerged != "") { parseRowMerged(); } - responseRowMerged = ""; - canSendNextAtCommand = true; + liveData->responseRowMerged = ""; + liveData->canSendNextAtCommand = true; } } } @@ -1737,11 +1727,11 @@ bool connectToServer(BLEAddress pAddress) { displayMessage(" > Connecting device", "Connecting service..."); // Remote service - BLERemoteService* pRemoteService = pClient->getService(BLEUUID(settings.serviceUUID)); + BLERemoteService* pRemoteService = pClient->getService(BLEUUID(liveData->settings.serviceUUID)); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); - Serial.println(settings.serviceUUID); + Serial.println(liveData->settings.serviceUUID); displayMessage(" > Connecting device", "Unable to find service"); return false; } @@ -1749,10 +1739,10 @@ bool connectToServer(BLEAddress pAddress) { // Get characteristics displayMessage(" > Connecting device", "Connecting TxUUID..."); - pRemoteCharacteristic = pRemoteService->getCharacteristic(BLEUUID(settings.charTxUUID)); + pRemoteCharacteristic = pRemoteService->getCharacteristic(BLEUUID(liveData->settings.charTxUUID)); if (pRemoteCharacteristic == nullptr) { Serial.print("Failed to find our characteristic UUID: "); - Serial.println(settings.charTxUUID);//.toString().c_str()); + Serial.println(liveData->settings.charTxUUID);//.toString().c_str()); displayMessage(" > Connecting device", "Unable to find TxUUID"); return false; } @@ -1760,10 +1750,10 @@ bool connectToServer(BLEAddress pAddress) { // Get characteristics displayMessage(" > Connecting device", "Connecting RxUUID..."); - pRemoteCharacteristicWrite = pRemoteService->getCharacteristic(BLEUUID(settings.charRxUUID)); + pRemoteCharacteristicWrite = pRemoteService->getCharacteristic(BLEUUID(liveData->settings.charRxUUID)); if (pRemoteCharacteristicWrite == nullptr) { Serial.print("Failed to find our characteristic UUID: "); - Serial.println(settings.charRxUUID);//.toString().c_str()); + Serial.println(liveData->settings.charRxUUID);//.toString().c_str()); displayMessage(" > Connecting device", "Unable to find RxUUID"); return false; } @@ -1806,7 +1796,7 @@ bool startBleScan() { // Start scanning Serial.println("Scanning BLE devices..."); Serial.print("Looking for "); - Serial.println(settings.obdMacAddress); + Serial.println(liveData->settings.obdMacAddress); BLEScanResults foundDevices = pBLEScan->start(40, false); Serial.print("Devices found: "); Serial.println(foundDevices.getCount()); @@ -1947,6 +1937,7 @@ void setup(void) { Serial.println("Booting device..."); // + liveData = new LiveData(); initStructure(); loadSettings(); @@ -1968,8 +1959,8 @@ void setup(void) { tft.invertDisplay(true); #endif // INVERT_DISPLAY - tft.setRotation(settings.displayRotation); - analogWrite(TFT_BL, (settings.lcdBrightness == 0) ? 100 : settings.lcdBrightness); + tft.setRotation(liveData->settings.displayRotation); + analogWrite(TFT_BL, (liveData->settings.lcdBrightness == 0) ? 100 : liveData->settings.lcdBrightness); tft.fillScreen(TFT_BLACK); bool psramUsed = false; // 320x240 16bpp sprites requires psram @@ -1988,10 +1979,10 @@ void setup(void) { struct tm now; getLocalTime(&now, 0); - params.chargingStartTime = params.currentTime = mktime(&now); + liveData->params.chargingStartTime = liveData->params.currentTime = mktime(&now); // Show test data on right button during boot device - displayScreen = settings.defaultScreen; + displayScreen = liveData->settings.defaultScreen; if (digitalRead(BUTTON_RIGHT) == LOW) { testData(); } @@ -2003,12 +1994,12 @@ void setup(void) { Serial.println("SDCARD initialization done."); } /*spiSD.begin(SD_SCLK,SD_MISO,SD_MOSI,SD_CS); - if(!SD.begin( SD_CS, spiSD, 27000000)){ + if(!SD.begin( SD_CS, spiSD, 27000000)){ Serial.println("SDCARD initialization failed!"); - } else { + } else { Serial.println("SDCARD initialization done."); - }*/ - + }*/ + // Start BLE connection line = ""; Serial.println("Start BLE with PIN auth"); @@ -2043,7 +2034,7 @@ void loop() { // Connect BLE device if (bleConnect == true && foundMyBleDevice != NULL) { - pServerAddress = new BLEAddress(settings.obdMacAddress); + pServerAddress = new BLEAddress(liveData->settings.obdMacAddress); if (connectToServer(*pServerAddress)) { bleConnected = true; @@ -2074,8 +2065,8 @@ void loop() { } // Can send next command from queue to OBD - if (canSendNextAtCommand) { - canSendNextAtCommand = false; + if (liveData->canSendNextAtCommand) { + liveData->canSendNextAtCommand = false; doNextAtCommand(); } } @@ -2095,7 +2086,7 @@ void loop() { } else { if (!btnMiddlePressed) { btnMiddlePressed = true; - tft.setRotation(settings.displayRotation); + tft.setRotation(liveData->settings.displayRotation); if (menuVisible) { menuItemClick(); } else { @@ -2104,32 +2095,32 @@ void loop() { } } // LEFT - screen rotate, menu - if (digitalRead((settings.displayRotation == 1) ? BUTTON_RIGHT : BUTTON_LEFT) == HIGH) { + if (digitalRead((liveData->settings.displayRotation == 1) ? BUTTON_RIGHT : BUTTON_LEFT) == HIGH) { btnLeftPressed = false; } else { if (!btnLeftPressed) { btnLeftPressed = true; - tft.setRotation(settings.displayRotation); + tft.setRotation(liveData->settings.displayRotation); // Menu handling if (menuVisible) { menuMove(false); } else { displayScreen++; - if (displayScreen > displayScreenCount - (settings.debugScreen == 0) ? 1 : 0) + if (displayScreen > displayScreenCount - (liveData->settings.debugScreen == 0) ? 1 : 0) displayScreen = 0; // rotate screens // Turn off display on screen 0 - analogWrite(TFT_BL, (displayScreen == SCREEN_BLANK) ? 0 : (settings.lcdBrightness == 0) ? 100 : settings.lcdBrightness); + analogWrite(TFT_BL, (displayScreen == SCREEN_BLANK) ? 0 : (liveData->settings.lcdBrightness == 0) ? 100 : liveData->settings.lcdBrightness); redrawScreen(); } } } // RIGHT - menu, debug screen rotation - if (digitalRead((settings.displayRotation == 1) ? BUTTON_LEFT : BUTTON_RIGHT) == HIGH) { + if (digitalRead((liveData->settings.displayRotation == 1) ? BUTTON_LEFT : BUTTON_RIGHT) == HIGH) { btnRightPressed = false; } else { if (!btnRightPressed) { btnRightPressed = true; - tft.setRotation(settings.displayRotation); + tft.setRotation(liveData->settings.displayRotation); // Menu handling if (menuVisible) { menuMove(true); @@ -2139,8 +2130,8 @@ void loop() { displayScreenSpeedHud = !displayScreenSpeedHud; redrawScreen(); } - if (settings.debugScreen == 1 && displayScreen == SCREEN_DEBUG) { - debugCommandIndex = (debugCommandIndex >= commandQueueCount) ? commandQueueLoopFrom : debugCommandIndex + 1; + if (liveData->settings.debugScreen == 1 && displayScreen == SCREEN_DEBUG) { + debugCommandIndex = (debugCommandIndex >= liveData->commandQueueCount) ? liveData->commandQueueLoopFrom : debugCommandIndex + 1; redrawScreen(); } @@ -2151,8 +2142,8 @@ void loop() { // currentTime & 1ms delay struct tm now; getLocalTime(&now, 0); - params.currentTime = mktime(&now); + liveData->params.currentTime = mktime(&now); // Shutdown when car is off - if (params.automatickShutdownTimer != 0 && params.currentTime - params.automatickShutdownTimer > 5) + if (liveData->params.automatickShutdownTimer != 0 && liveData->params.currentTime - liveData->params.automatickShutdownTimer > 5) shutdownDevice(); } diff --git a/menu.h b/menu.h index 011b2d4..b4615e4 100644 --- a/menu.h +++ b/menu.h @@ -1,3 +1,7 @@ + +#ifndef MENU_H +#define MENU_H + // Menu id/parent/title typedef struct { int16_t id; @@ -8,7 +12,7 @@ typedef struct { char serviceUUID[40]; } MENU_ITEM; -#define menuItemsCount 79 +#define menuItemsCount 78 bool menuVisible = false; uint16_t menuCurrent = 0; uint8_t menuItemSelected = 0; @@ -32,7 +36,7 @@ MENU_ITEM menuItems[menuItemsCount] = { {103, 1, -1, "Hyundai Ioniq 2018 28kWh"}, {104, 1, -1, "Kia eNiro 2020 39kWh"}, {105, 1, -1, "Hyundai Kona 2020 39kWh"}, - {106, 1, -1, "Renault Zoe 22kWh (DEV)"}, + //{106, 1, -1, "Renault Zoe 22kWh (DEV)"}, {107, 1, -1, "Debug OBD2 Kia"}, {300, 3, 0, "<- parent menu"}, @@ -110,3 +114,6 @@ MENU_ITEM menuItems[menuItemsCount] = { {10008, 9999, -1, "-"}, {10009, 9999, -1, "-"}, }; + +// +#endif // MENU_H