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..043feee --- /dev/null +++ b/CarKiaEniro.cpp @@ -0,0 +1,446 @@ +#ifndef CARKIAENIRO_CPP +#define CARKIAENIRO_CPP + +/* + * eNiro/Kona chargings limits depending on battery temperature (min.value of 01-04 battery module) + >= 35°C BMS allows max 180A + >= 25°C without limit (200A) + >= 15°C BMS allows max 120A + >= 5°C BMS allows max 90A + >= 1°C BMS allows max 60A + <= 0°C BMS allows max 40A + */ + +#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 65% rename from struct.h rename to LiveData.h index d24f72c..39d6d7a 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,22 +27,15 @@ #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 automatickShutdownTimer; + time_t currentTime; + time_t chargingStartTime; + time_t automatickShutdownTimer; +#ifdef SIM800L_ENABLED + time_t lastDataSent; + bool sim800l_enabled; +#endif //SIM800L_ENABLED bool ignitionOn; bool ignitionOnPrevious; bool forwardDriveMode; @@ -45,7 +47,7 @@ typedef struct { uint8_t lightInfo; uint8_t brakeLightInfo; uint8_t espState; - float batteryTotalAvailableKWh; + float batteryTotalAvailableKWh; float speedKmh; float motorRpm; float odoKm; @@ -110,19 +112,19 @@ 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 typedef struct { byte initFlag; // 183 value - byte settingsVersion; // current 4 + byte settingsVersion; // current 3 uint16_t carType; // 0 - Kia eNiro 2020, 1 - Hyundai Kona 2020, 2 - Hyudai Ioniq 2018 char obdMacAddress[20]; char serviceUUID[40]; @@ -137,41 +139,33 @@ typedef struct { byte lcdBrightness; // 0 - auto, 1 .. 100% byte debugScreen; // 0 - off, 1 - on byte predrawnChargingGraphs; // 0 - off, 1 - on - byte wifiEnable; // 0 off 1 on used for NTP datetime sync - char wifiSsid[32]; - char wifiPassword[32]; - byte sdcardAutoRecord; // 0 off 1 on - +#ifdef SIM800L_ENABLED + char gprsApn[64]; + char remoteApiSrvr[64]; + char remoteApiKey[13]; +#endif //SIM800L_ENABLED } 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 886bc36..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&) -## Release notes - -- Fixed menu -- Automatic shutdown when car goes off - -### 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 1043462..0442df7 100644 --- a/config.h +++ b/config.h @@ -1,69 +1,5 @@ -//////////////////////////////////////////////////////////// -// SELECT HARDWARE !!!! -//////////////////////////////////////////////////////////// - -//#define BOARD_TTGO_T4 -#define BOARD_M5STACK_CORE - -//////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////// - -#define USER_SETUP_LOADED 1 -#define SPI_FREQUENCY 27000000 -#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 26 -#define TFT_RST 5 -#define TFT_BL 4 -#define USE_HSPI_PORT -#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V -#define BUTTON_LEFT 38 -#define BUTTON_MIDDLE 37 -#define BUTTON_RIGHT 39 -#define SDCARD_CS 13 -#define SDCARD_MOSI 15 -#define SDCARD_MISO 2 -#define SDCARD_SCK 14 -#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 BUTTON_LEFT 37 -#define BUTTON_MIDDLE 38 -#define BUTTON_RIGHT 39 -#define SPEAKER 25 -#define INVERT_DISPLAY -#define SDCARD_CS 4 -#define SDCARD_MOSI 23 -#define SDCARD_MISO 19 -#define SDCARD_SCK 18 -#endif // BOARD_M5STACK_CORE - -///////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////// +#ifndef CONFIG_H +#define CONFIG_H // TFT COMMON #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH @@ -114,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/dist/m5stack_core1/enirodashboard.ino.bin b/dist/m5stack_core1/enirodashboard.ino.bin index 4c6f3d6..068dec3 100644 Binary files a/dist/m5stack_core1/enirodashboard.ino.bin and b/dist/m5stack_core1/enirodashboard.ino.bin differ diff --git a/dist/ttgo_t4_v13/enirodashboard.ino.bin b/dist/ttgo_t4_v13/enirodashboard.ino.bin index 0d491e3..8242bc8 100644 Binary files a/dist/ttgo_t4_v13/enirodashboard.ino.bin and b/dist/ttgo_t4_v13/enirodashboard.ino.bin differ diff --git a/enirodashboard.ino b/enirodashboard.ino index 5ba017e..a23e056 100644 --- a/enirodashboard.ino +++ b/enirodashboard.ino @@ -1,61 +1,70 @@ /* - - 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 - >= 25°C without limit (200A) - >= 15°C BMS allows max 120A - >= 5°C BMS allows max 90A - >= 1°C BMS allows max 60A - <= 0°C BMS allows max 40A +Required libraries +- esp32 board support +- tft_espi +- ArduinoJson +For SIM800L m5stack +- SIM800L.h, SoftwareSerial.h */ -#define APP_VERSION "v1.9.0" +//////////////////////////////////////////////////////////// +// SELECT HARDWARE +//////////////////////////////////////////////////////////// -#include "FS.h" -#include "SD.h" -#include "SPI.h" -#include "TFT_eSPI.h" -#include "BLEDevice.h" +//#define BOARD_TTGO_T4 +#define BOARD_M5STACK_CORE + +//#define SIM800L_ENABLED + +//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// + +#define APP_VERSION "v1.9.0" +#define APP_RELEASE_DATE "2020-11-30" + +#include +#include + +#include +#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 -#include "config.h" -#include "struct.h" +#include "LiveData.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 "CarInterface.h" +#include "CarKiaEniro.h" +#include "CarHyundaiIoniq.h" +#include "CarKiaDebugObd2.h" + +#ifdef SIM800L_ENABLED +#include +#include +#include "SIM800L.h" + +SIM800L* sim800l; +#endif //SIM800L_ENABLED // PLEASE CHANGE THIS SETTING for your BLE4 uint32_t PIN = 1234; -const char* ssid = "your-ssid"; -const char* password = "your-password"; -long timezone = 1; -byte daysavetime = 1; -// TFT +// TFT, SD SPI TFT_eSPI tft = TFT_eSPI(); TFT_eSprite spr = TFT_eSprite(&tft); +//SPIClass spiSD(HSPI); // BLUETOOTH4 static boolean bleConnect = true; @@ -99,6 +108,10 @@ String debugTmpChargingLast06 = ""; String debugTmpChargingPrevious06 = ""; String debugTmpChargingRef06 = "620106FFFFFFFF--00--########################00--28EA00"; +// Car +CarInterface* carInterface; +LiveData* liveData; + /** Clear screen a display two lines message */ @@ -111,7 +124,7 @@ bool displayMessage(const char* row1, const char* row2) { tft.setFreeFont(&Roboto_Thin_24); tft.setTextDatum(BL_DATUM); tft.drawString(row1, 0, 240 / 2, GFXFF); - spr.drawString(row2, 0, (240 / 2) + 30, GFXFF); + tft.drawString(row2, 0, (240 / 2) + 30, GFXFF); return true; } @@ -149,7 +162,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; @@ -162,8 +175,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"); @@ -182,78 +195,89 @@ bool loadSettings() { String tmpStr; // Init - settings.initFlag = 183; - settings.settingsVersion = 2; - 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, tmpStr.length() + 1); 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, tmpStr.length() + 1); tmpStr = "00002af0-0000-1000-8000-00805f9b34fb"; - tmpStr.toCharArray(settings.charTxUUID, 37); + tmpStr.toCharArray(liveData->settings.charTxUUID, tmpStr.length() + 1); tmpStr = "00002af1-0000-1000-8000-00805f9b34fb"; - tmpStr.toCharArray(settings.charRxUUID, 37); + tmpStr.toCharArray(liveData->settings.charRxUUID, tmpStr.length() + 1); - 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; + +#ifdef SIM800L_ENABLED + tmpStr = "internet.t-mobile.cz"; + tmpStr.toCharArray(liveData->settings.gprsApn, tmpStr.length() + 1); + tmpStr = "http://api.example.com"; + tmpStr.toCharArray(liveData->settings.remoteApiSrvr, tmpStr.length() + 1); + tmpStr = "example"; + tmpStr.toCharArray(liveData->settings.remoteApiKey, tmpStr.length() + 1); +#endif //SIM800L_ENABLED // 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; } @@ -263,87 +287,91 @@ bool loadSettings() { */ bool initStructure() { - params.automatickShutdownTimer = 0; - 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.automatickShutdownTimer = 0; +#ifdef SIM800L_ENABLED + liveData->params.lastDataSent = 0; + liveData->params.sim800l_enabled = false; +#endif //SIM800L_ENABLED + 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; @@ -353,21 +381,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; } /** @@ -394,13 +422,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); @@ -489,78 +517,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; @@ -586,29 +614,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; } @@ -622,17 +650,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); @@ -642,52 +670,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); @@ -704,29 +732,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); } @@ -736,25 +764,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); } @@ -830,13 +858,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); @@ -859,22 +887,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); @@ -900,102 +928,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 @@ -1006,7 +1034,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; @@ -1023,7 +1051,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); @@ -1036,7 +1064,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); @@ -1070,7 +1098,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); @@ -1078,18 +1106,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); @@ -1115,8 +1143,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); } } @@ -1154,14 +1182,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); @@ -1187,18 +1215,12 @@ String menuItemCaption(int16_t menuItemId, String title) { if (menuItemId == 10) // Version suffix = APP_VERSION; - if (menuItemId == 3071) { // sdcard info - uint64_t cardSize = SD.cardSize() / (1024 * 1024); - sprintf(tmpStr1, "%lluMB", cardSize); - suffix = String(tmpStr1); - } - 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; @@ -1310,53 +1332,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; - // Sdcard: - case 3072: SD.begin(SDCARD_CS, SDCARD_MOSI, SDCARD_MISO, SDCARD_SCK); 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 +1411,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 +1426,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 +1492,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 +1538,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 +1566,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 +1634,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 +1685,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 +1733,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 +1745,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 +1756,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 +1802,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()); @@ -1835,6 +1831,114 @@ bool startBleScan() { return true; } +/** + SIM800L +*/ +#ifdef SIM800L_ENABLED +bool sim800lSetup() { + Serial.println("Setting SIM800L module"); + SoftwareSerial* serial = new SoftwareSerial(SIM800L_RX, SIM800L_TX); + serial->begin(9600); + sim800l = new SIM800L((Stream *)serial, SIM800L_RST, 512 , 512); + + bool sim800l_ready = sim800l->isReady(); + for(uint8_t i = 0; i < 5 && !sim800l_ready; i++) { + Serial.println("Problem to initialize SIM800L module, retry in 1 sec"); + delay(1000); + sim800l_ready = sim800l->isReady(); + } + + if(!sim800l_ready) { + Serial.println("Problem to initialize SIM800L module"); + } else { + Serial.println("SIM800L module initialized"); + + Serial.print("Setting GPRS APN to: "); + Serial.println(liveData->settings.gprsApn); + + bool sim800l_gprs = sim800l->setupGPRS(liveData->settings.gprsApn); + for(uint8_t i = 0; i < 5 && !sim800l_gprs; i++) { + Serial.println("Problem to set GPRS connection, retry in 1 sec"); + delay(1000); + sim800l_gprs = sim800l->setupGPRS(liveData->settings.gprsApn); + } + + if(sim800l_gprs) { + liveData->params.sim800l_enabled = true; + Serial.println("GPRS OK"); + } else { + Serial.println("Problem to set GPRS"); + } + } + + return true; +} + +bool sendDataViaGPRS() { + Serial.println("Sending data via GPRS"); + + NetworkRegistration network = sim800l->getRegistrationStatus(); + if(network != REGISTERED_HOME && network != REGISTERED_ROAMING) { + Serial.println("SIM800L module not connected to network!"); + return false; + } + + bool connected = sim800l->connectGPRS(); + for(uint8_t i = 0; i < 5 && !connected; i++) { + delay(1000); + connected = sim800l->connectGPRS(); + } + + if(!connected) { + Serial.println("GPRS not connected! Reseting SIM800L module!"); + sim800l->reset(); + sim800lSetup(); + + return false; + } + + Serial.println("Start HTTP POST..."); + + StaticJsonDocument<250> jsonData; + + jsonData["akey"] = liveData->settings.remoteApiKey; + jsonData["soc"] = liveData->params.socPerc; + jsonData["soh"] = liveData->params.sohPerc; + jsonData["batK"] = liveData->params.batPowerKw; + jsonData["batA"] = liveData->params.batPowerAmp; + jsonData["batV"] = liveData->params.batVoltage; + jsonData["auxV"] = liveData->params.auxVoltage; + jsonData["MinC"] = liveData->params.batMinC; + jsonData["MaxC"] = liveData->params.batMaxC; + jsonData["InlC"] = liveData->params.batInletC; + jsonData["fan"] = liveData->params.batFanStatus; + jsonData["cumCh"] = liveData->params.cumulativeEnergyChargedKWh; + jsonData["cumD"] = liveData->params.cumulativeEnergyDischargedKWh; + + char payload[200]; + serializeJson(jsonData, payload); + + Serial.print("Sending payload: "); + Serial.println(payload); + + Serial.print("Remote API server: "); + Serial.println(liveData->settings.remoteApiSrvr); + + uint16_t rc = sim800l->doPost(liveData->settings.remoteApiSrvr, "application/json", payload, 10000, 10000); + if(rc == 200) { + Serial.println(F("HTTP POST successful")); + } else { + // Failed... + Serial.print(F("HTTP POST error: ")); + Serial.println(rc); + } + + sim800l->disconnectGPRS(); + + return true; +} +#endif //SIM800L_ENABLED + /** Setup device */ @@ -1845,6 +1949,8 @@ void setup(void) { Serial.println(""); Serial.println("Booting device..."); + // + liveData = new LiveData(); initStructure(); loadSettings(); @@ -1855,9 +1961,9 @@ void setup(void) { #ifdef BOARD_M5STACK_CORE // mute speaker - dacWrite(25, 0); + Serial.println("Mute speaker for m5stack"); + dacWrite(SPEAKER_PIN, 0); #endif // BOARD_M5STACK_C - // Init display Serial.println("Init TFT display"); tft.begin(); @@ -1866,8 +1972,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 @@ -1875,37 +1981,10 @@ void setup(void) { if (psramFound()) psramUsed = true; #endif - // if (!psramUsed) { - // displayMessage("SRAM support required", "Compile with ESP32 Wrover CPU"); - // delay(60000); - // ESP.restart(); - // } spr.setColorDepth((psramUsed) ? 16 : 8); spr.createSprite(320, 240); redrawScreen(); - // Init SDCARD - if (!SD.begin(SDCARD_CS, SDCARD_MOSI, SDCARD_MISO, SDCARD_SCK)) { - Serial.println("Card Mount Failed"); - } - uint8_t cardType = SD.cardType(); - if (cardType == CARD_NONE) { - Serial.println("No SD card attached"); - } - Serial.print("SD Card Type: "); - if (cardType == CARD_MMC) { - Serial.println("MMC"); - } else if (cardType == CARD_SD) { - Serial.println("SDSC"); - } else if (cardType == CARD_SDHC) { - Serial.println("SDHC"); - } else { - Serial.println("UNKNOWN"); - } - - uint64_t cardSize = SD.cardSize() / (1024 * 1024); - Serial.printf("SD Card Size: %lluMB\n", cardSize); - // Init time library struct timeval tv; tv.tv_sec = 1589011873; @@ -1913,14 +1992,27 @@ 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(); } + // Init SDCARD + if (!SD.begin(SD_CS, SD_MOSI, SD_MISO, SD_SCLK)) { + Serial.println("SDCARD initialization failed!"); + } else { + Serial.println("SDCARD initialization done."); + } + /*spiSD.begin(SD_SCLK,SD_MISO,SD_MOSI,SD_CS); + if(!SD.begin( SD_CS, spiSD, 27000000)){ + Serial.println("SDCARD initialization failed!"); + } else { + Serial.println("SDCARD initialization done."); + }*/ + // Start BLE connection line = ""; Serial.println("Start BLE with PIN auth"); @@ -1940,6 +2032,10 @@ void setup(void) { startBleScan(); } +#ifdef SIM800L_ENABLED + sim800lSetup(); +#endif //SIM800L_ENABLED + // End Serial.println("Device setup completed"); } @@ -1951,7 +2047,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; @@ -1982,12 +2078,19 @@ void loop() { } // Can send next command from queue to OBD - if (canSendNextAtCommand) { - canSendNextAtCommand = false; + if (liveData->canSendNextAtCommand) { + liveData->canSendNextAtCommand = false; doNextAtCommand(); } } +#ifdef SIM800L_ENABLED + if(liveData->params.lastDataSent + SIM800L_TIMER < liveData->params.currentTime && liveData->params.sim800l_enabled) { + sendDataViaGPRS(); + liveData->params.lastDataSent = liveData->params.currentTime; + } +#endif //SIM800L_ENABLED + /////////////////////////////////////////////////////////////////////// // Handle buttons // MIDDLE - menu select @@ -1996,7 +2099,7 @@ void loop() { } else { if (!btnMiddlePressed) { btnMiddlePressed = true; - tft.setRotation(settings.displayRotation); + tft.setRotation(liveData->settings.displayRotation); if (menuVisible) { menuItemClick(); } else { @@ -2005,32 +2108,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); @@ -2040,8 +2143,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(); } @@ -2052,8 +2155,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 4a639b9..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"}, @@ -41,8 +45,8 @@ MENU_ITEM menuItems[menuItemsCount] = { {303, 3, -1, "Debug screen off/on"}, {304, 3, -1, "LCD brightness"}, {305, 3, -1, "Pre-drawn ch.graphs 0/1"}, - {306, 3, -1, "WiFi network"}, - {307, 3, -1, "SD card"}, + {306, 3, -1, "[DEV] WiFi network"}, + {307, 3, -1, "[DEV] SD card"}, {400, 4, 0, "<- parent menu"}, {401, 4, -1, "Distance"}, @@ -110,3 +114,6 @@ MENU_ITEM menuItems[menuItemsCount] = { {10008, 9999, -1, "-"}, {10009, 9999, -1, "-"}, }; + +// +#endif // MENU_H