diff --git a/Board320_240.cpp b/Board320_240.cpp index 2bb2ba2..f40733c 100644 --- a/Board320_240.cpp +++ b/Board320_240.cpp @@ -2,10 +2,11 @@ #define BOARD320_240_CPP #include +#include #include #include -#include -#include +//#include +//#include #include "config.h" #include "BoardInterface.h" #include "Board320_240.h" @@ -35,14 +36,6 @@ void Board320_240::initBoard() { #endif spr.setColorDepth((psramUsed) ? 16 : 8); spr.createSprite(320, 240); - - // Wifi - if (liveData->settings.wifiEnabled == 1) { - Serial.println("WiFi init..."); - //WiFi.mode(WIFI_STA); - //WiFi.begin(liveData->settings.wifiSsid, liveData->settings.wifiPassword); - Serial.println("WiFi init completed..."); - } } /** @@ -55,6 +48,27 @@ void Board320_240::afterSetup() { if (digitalRead(pinButtonRight) == LOW) { loadTestData(); } + + // Wifi + // Starting Wifi after BLE prevents reboot loop + if (liveData->settings.wifiEnabled == 1) { + + /*Serial.print("memReport(): MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM bytes free. "); + Serial.println(heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM)); + + Serial.println("WiFi init..."); + WiFi.enableSTA(true); + WiFi.mode(WIFI_STA); + WiFi.begin(liveData->settings.wifiSsid, liveData->settings.wifiPassword); + Serial.println("WiFi init completed...");*/ + } + + // SD card + if (liveData->settings.sdcardEnabled == 1) { + if (sdcardMount() && liveData->settings.sdcardAutstartLog == 1) { + sdcardToggleRecording(); + } + } } /** @@ -847,7 +861,9 @@ String Board320_240::menuItemCaption(int16_t menuItemId, String title) { case 106: prefix = (liveData->settings.carType == CAR_RENAULT_ZOE) ? ">" : ""; break; case 107: prefix = (liveData->settings.carType == CAR_DEBUG_OBD2_KIA) ? ">" : ""; break; // - case MENU_WIFI: switch (WiFi.status()) { + /*case MENU_WIFI: + suffix = "n/a"; + switch (WiFi.status()) { WL_CONNECTED: suffix = "CONNECTED"; break; WL_NO_SHIELD: suffix = "NO_SHIELD"; break; WL_IDLE_STATUS: suffix = "IDLE_STATUS"; break; @@ -856,9 +872,9 @@ WL_CONNECT_FAILED: suffix = "CONNECT_FAILED"; break; WL_CONNECTION_LOST: suffix = "CONNECTION_LOST"; break; WL_DISCONNECTED: suffix = "DISCONNECTED"; break; } - break; - case MENU_GPRS: sprintf(tmpStr1, "[%s] %s", (liveData->settings.gprsEnabled == 1) ? "[on]" : "[off]", liveData->settings.gprsApn); suffix = tmpStr1; break; - case MENU_SDCARD: sprintf(tmpStr1, "[%s]", (liveData->params.sdcardRecording) ? "RECORDING" : (liveData->settings.sdcardEnabled == 1) ? "on" : "off"); suffix = tmpStr1; break; + break;*/ + case MENU_GPRS: sprintf(tmpStr1, "[%s] %s", (liveData->settings.gprsEnabled == 1) ? "on" : "off", liveData->settings.gprsApn); suffix = tmpStr1; break; + case MENU_SDCARD: sprintf(tmpStr1, "[%d] %lluMB", SD.cardType(), SD.cardSize() / (1024 * 1024)); suffix = tmpStr1; break; case MENU_SCREEN_ROTATION: suffix = (liveData->settings.displayRotation == 1) ? "[vertical]" : "[normal]"; break; case MENU_DEFAULT_SCREEN: sprintf(tmpStr1, "[%d]", liveData->settings.defaultScreen); suffix = tmpStr1; break; case MENU_SCREEN_BRIGHTNESS: sprintf(tmpStr1, "[%d%%]", liveData->settings.lcdBrightness); suffix = (liveData->settings.lcdBrightness == 0) ? "[auto]" : tmpStr1; break; @@ -868,7 +884,9 @@ WL_DISCONNECTED: suffix = "DISCONNECTED"; break; // case MENU_SDCARD_ENABLED: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 1) ? "on" : "off"); suffix = tmpStr1; break; case MENU_SDCARD_AUTOSTARTLOG: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 0) ? "n/a" : (liveData->settings.sdcardAutstartLog == 1) ? "on" : "off"); suffix = tmpStr1; break; - case MENU_SDCARD_MOUNT_STATUS: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 0) ? "n/a" : (liveData->params.sdcardInit) ? "READY" : "MOUNT"); suffix = tmpStr1; break; + case MENU_SDCARD_MOUNT_STATUS: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 0) ? "n/a" : + (strlen(liveData->params.sdcardFilename) != 0) ? liveData->params.sdcardFilename : + (liveData->params.sdcardInit) ? "READY" : "MOUNT"); suffix = tmpStr1; break; case MENU_SDCARD_REC: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 0) ? "n/a" : (liveData->params.sdcardRecording) ? "STOP" : "START"); suffix = tmpStr1; break; // case MENU_WIFI_ENABLED: suffix = (liveData->settings.wifiEnabled == 1) ? "[on]" : "[off]"; break; @@ -1144,8 +1162,16 @@ void Board320_240::redrawScreen() { // SDCARD recording /*liveData->params.sdcardRecording*/ if (liveData->settings.sdcardEnabled == 1) { - spr.fillCircle(310, 10, 7, TFT_BLACK); - spr.fillCircle(310, 10, 6, TFT_RED); + spr.fillCircle(310, 10, 4, TFT_BLACK); + + spr.fillCircle(310, 10, 3, + (liveData->params.sdcardInit == 1) ? + (liveData->params.sdcardRecording) ? + TFT_BLUE : + TFT_GREEN + : + TFT_YELLOW + ); } // BLE not connected @@ -1242,6 +1268,36 @@ void Board320_240::mainLoop() { if (digitalRead(pinButtonLeft) == LOW && digitalRead(pinButtonRight) == LOW) { hideMenu(); } + + // SD card recording + if (liveData->params.sdcardInit && liveData->params.sdcardRecording && liveData->params.sdcardCanNotify) { + // create filename + if (liveData->params.operationTimeSec > 0) { + sprintf(liveData->params.sdcardFilename, "/%llu.json", uint64_t(liveData->params.operationTimeSec / 60)); + Serial.println("Log filename: "); + Serial.println(liveData->params.sdcardFilename); + } + + // append buffer, clear buffer & notify state + if (strlen(liveData->params.sdcardFilename) != 0) { + + liveData->params.sdcardCanNotify = false; + File file = SD.open(liveData->params.sdcardFilename, FILE_APPEND); + if (!file) { + Serial.println("Failed to open file for appending"); + File file = SD.open(liveData->params.sdcardFilename, FILE_WRITE); + } + if (!file) { + Serial.println("Failed to create file"); + } + if (file) { + Serial.println("Save buffer to SD card"); + serializeParamsToJson(file); + file.print(",\n"); + file.close(); + } + } + } } /** @@ -1261,22 +1317,38 @@ bool Board320_240::sdcardMount() { return true; } - int8_t countdown = 10; + int8_t countdown = 3; while (1) { Serial.print("Initializing SD card..."); - /* - if (SD.begin(pinSdcardCs, pinSdcardMosi, pinSdcardMiso, pinSdcardSclk)) { - Serial.println("SD card found."); - liveData->params.sdcardInit = true; - return true; + + if (SD.begin(pinSdcardCs)) { + + uint8_t cardType = SD.cardType(); + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return false; } - */ - //SPI.begin(); - if (SD.begin(pinSdcardCs, SPI, SPI_FREQUENCY)) { + Serial.println("SD card found."); liveData->params.sdcardInit = true; + + 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); + return true; } + Serial.println("Initialization failed!"); countdown--; if (countdown <= 0) { @@ -1293,6 +1365,17 @@ bool Board320_240::sdcardMount() { */ void Board320_240::sdcardToggleRecording() { + if (!liveData->params.sdcardInit) + return; + + Serial.println("Toggle SD card recording..."); + liveData->params.sdcardRecording = !liveData->params.sdcardRecording; + if (liveData->params.sdcardRecording) { + liveData->params.sdcardCanNotify = true; + } else { + String tmpStr = ""; + tmpStr.toCharArray(liveData->params.sdcardFilename, tmpStr.length() + 1); + } } #endif // BOARD320_240_CPP diff --git a/Board320_240.h b/Board320_240.h index 7d048d3..a8db8ec 100644 --- a/Board320_240.h +++ b/Board320_240.h @@ -22,6 +22,7 @@ class Board320_240 : public BoardInterface { // TFT, SD SPI TFT_eSPI tft = TFT_eSPI(); TFT_eSprite spr = TFT_eSprite(&tft); + //SPIClass spiSD(HSPI); char tmpStr1[20]; char tmpStr2[20]; char tmpStr3[20]; diff --git a/BoardInterface.cpp b/BoardInterface.cpp index aefd472..daa7d28 100644 --- a/BoardInterface.cpp +++ b/BoardInterface.cpp @@ -1,6 +1,9 @@ #ifndef BOARDINTERFACE_CPP #define BOARDINTERFACE_CPP +#define ARDUINOJSON_USE_LONG_LONG 1 + +#include #include #include #include "BoardInterface.h" @@ -204,4 +207,67 @@ void BoardInterface::customConsoleCommand(String cmd) { if (key == "remoteApiKey") value.toCharArray(liveData->settings.remoteApiKey, value.length() + 1); } +/** + * Serialize parameters + */ +bool BoardInterface::serializeParamsToJson(File file) { + + StaticJsonDocument<1024> jsonData; + + jsonData["apiKey"] = liveData->settings.remoteApiKey; + jsonData["carType"] = liveData->settings.carType; + jsonData["batTotalKwh"] = liveData->params.batteryTotalAvailableKWh; + jsonData["currTime"] = liveData->params.currentTime; + jsonData["opTime"] = liveData->params.operationTimeSec; + + jsonData["socPerc"] = liveData->params.socPerc; + jsonData["sohPerc"] = liveData->params.sohPerc; + jsonData["powKwh100"] = liveData->params.batPowerKwh100; + jsonData["speedKmh"] = liveData->params.speedKmh; + jsonData["motorRpm"] = liveData->params.motorRpm; + jsonData["odoKm"] = liveData->params.odoKm; + + jsonData["batPowKw"] = liveData->params.batPowerKw; + jsonData["batPowA"] = liveData->params.batPowerAmp; + jsonData["batV"] = liveData->params.batVoltage; + jsonData["cecKwh"] = liveData->params.cumulativeEnergyChargedKWh; + jsonData["cedKwh"] = liveData->params.cumulativeEnergyDischargedKWh; + jsonData["maxChKw"] = liveData->params.availableChargePower; + jsonData["maxDisKw"] = liveData->params.availableDischargePower; + + jsonData["cellMinV"] = liveData->params.batCellMinV; + jsonData["cellMaxV"] = liveData->params.batCellMaxV; + jsonData["bMinC"] = round(liveData->params.batMinC); + jsonData["baxC"] = round(liveData->params.batMaxC); + jsonData["bHeatC"] = round(liveData->params.batHeaterC); + jsonData["bInletC"] = round(liveData->params.batInletC); + jsonData["bFanSt"] = liveData->params.batFanStatus; + jsonData["bWatC"] = round(liveData->params.coolingWaterTempC); + jsonData["tmpA"] = round(liveData->params.bmsUnknownTempA); + jsonData["tmpB"] = round(liveData->params.bmsUnknownTempB); + jsonData["tmpC"] = round(liveData->params.bmsUnknownTempC); + jsonData["tmpD"] = round(liveData->params.bmsUnknownTempD); + + jsonData["auxP"] = liveData->params.auxPerc; + jsonData["auxV"] = liveData->params.auxVoltage; + jsonData["auxA"] = liveData->params.auxCurrentAmp; + + jsonData["inC"] = liveData->params.indoorTemperature; + jsonData["outC"] = liveData->params.outdoorTemperature; + jsonData["c1C"] = liveData->params.coolantTemp1C; + jsonData["c2C"] = liveData->params.coolantTemp2C; + + jsonData["tFlC"] = liveData->params.tireFrontLeftTempC; + jsonData["tFlBar"] = round(liveData->params.tireFrontLeftPressureBar * 10) / 10; + jsonData["tFrC"] = liveData->params.tireFrontRightTempC; + jsonData["tFrBar"] = round(liveData->params.tireFrontRightPressureBar * 10) / 10; + jsonData["tRlC"] = liveData->params.tireRearLeftTempC; + jsonData["tRlBar"] = round(liveData->params.tireRearLeftPressureBar * 10) / 10; + jsonData["tRrC"] = liveData->params.tireRearRightTempC; + jsonData["tRrBar"] = round(liveData->params.tireRearRightPressureBar * 10) / 10; + + serializeJson(jsonData, Serial); + serializeJson(jsonData, file); +} + #endif // BOARDINTERFACE_CPP diff --git a/BoardInterface.h b/BoardInterface.h index 86bdf85..e122768 100644 --- a/BoardInterface.h +++ b/BoardInterface.h @@ -1,6 +1,7 @@ #ifndef BOARDINTERFACE_H #define BOARDINTERFACE_H +#include #include "LiveData.h" #include "CarInterface.h" @@ -18,6 +19,7 @@ class BoardInterface { bool btnRightPressed = true; bool testDataMode = false; bool scanDevices = false; + String sdcardRecordBuffer = ""; // Debug screen - next command with right button uint16_t debugCommandIndex = 0; String debugAtshRequest = "ATSH7E4"; @@ -49,6 +51,7 @@ class BoardInterface { // Sdcard virtual bool sdcardMount() {return false; }; virtual void sdcardToggleRecording()=0; + bool serializeParamsToJson(File file); }; #endif // BOARDINTERFACE_H diff --git a/BoardM5stackCore.cpp b/BoardM5stackCore.cpp index 6d7b903..12bf0d9 100644 --- a/BoardM5stackCore.cpp +++ b/BoardM5stackCore.cpp @@ -21,7 +21,7 @@ void BoardM5stackCore::initBoard() { pinSdcardMosi = SDCARD_MOSI; pinSdcardMiso = SDCARD_MISO; pinSdcardSclk = SDCARD_SCLK; - + // Mute speaker //ledcWriteTone(TONE_PIN_CHANNEL, 0); digitalWrite(SPEAKER_PIN, 0); diff --git a/CarKiaEniro.cpp b/CarKiaEniro.cpp index 91abc7c..673c0ad 100644 --- a/CarKiaEniro.cpp +++ b/CarKiaEniro.cpp @@ -109,6 +109,7 @@ void CarKiaEniro::activateCommandQueue() { void CarKiaEniro::parseRowMerged() { bool tempByte; + float tempFloat; // ABS / ESP + AHB 7D1 if (liveData->currentAtshRequest.equals("ATSH7D1")) { @@ -155,7 +156,10 @@ void CarKiaEniro::parseRowMerged() { // Cluster module 7c6 if (liveData->currentAtshRequest.equals("ATSH7C6")) { if (liveData->commandRequest.equals("22B002")) { + tempFloat = liveData->params.odoKm; liveData->params.odoKm = float(strtol(liveData->responseRowMerged.substring(18, 24).c_str(), 0, 16)); + if (tempFloat != liveData->params.odoKm) + liveData->params.sdcardCanNotify = true; } } @@ -174,6 +178,7 @@ void CarKiaEniro::parseRowMerged() { // BMS 7e4 if (liveData->currentAtshRequest.equals("ATSH7E4")) { if (liveData->commandRequest.equals("220101")) { + liveData->params.operationTimeSec = liveData->hexToDec(liveData->responseRowMerged.substring(98, 106).c_str(), 4, false); liveData->params.cumulativeEnergyChargedKWh = float(strtol(liveData->responseRowMerged.substring(82, 90).c_str(), 0, 16)) / 10.0; if (liveData->params.cumulativeEnergyChargedKWhStart == -1) liveData->params.cumulativeEnergyChargedKWhStart = liveData->params.cumulativeEnergyChargedKWh; @@ -248,6 +253,8 @@ void CarKiaEniro::parseRowMerged() { liveData->params.socPercPrevious = liveData->params.socPerc; liveData->params.sohPerc = liveData->hexToDec(liveData->responseRowMerged.substring(56, 60).c_str(), 2, false) / 10.0; liveData->params.socPerc = liveData->hexToDec(liveData->responseRowMerged.substring(68, 70).c_str(), 1, false) / 2.0; + if (liveData->params.socPercPrevious != liveData->params.socPerc) + liveData->params.sdcardCanNotify = true; // Soc10ced table, record x0% CEC/CED table (ex. 90%->89%, 80%->79%) if (liveData->params.socPercPrevious - liveData->params.socPerc > 0) { diff --git a/LiveData.cpp b/LiveData.cpp index b3c0564..a8c0e40 100644 --- a/LiveData.cpp +++ b/LiveData.cpp @@ -17,9 +17,13 @@ void LiveData::initParams() { // SD card params.sdcardInit = false; params.sdcardRecording = false; + String tmpStr = ""; + tmpStr.toCharArray(params.sdcardFilename, tmpStr.length() + 1); + params.sdcardCanNotify = false; // Car data params.ignitionOn = false; params.ignitionOnPrevious = false; + params.operationTimeSec = 0; params.chargingStartTime = params.currentTime = 0; params.lightInfo = 0; params.headLights = false; diff --git a/LiveData.h b/LiveData.h index ab54bb0..5b87257 100644 --- a/LiveData.h +++ b/LiveData.h @@ -41,9 +41,12 @@ typedef struct { // SD card bool sdcardInit; bool sdcardRecording; + char sdcardFilename[32]; // Car params bool ignitionOn; bool ignitionOnPrevious; + uint64_t operationTimeSec; + bool sdcardCanNotify; bool forwardDriveMode; bool reverseDriveMode; bool parkModeOrNeutral; @@ -118,13 +121,12 @@ 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;*/ + ;*/ } PARAMS_STRUC; // Setting stored to flash diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 25e4318..3f50663 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,10 +1,12 @@ # RELEASE NOTES -### DEV +### v2.1.0 2020-12-06 - m5stack mute speaker - settings v4 (wifi/gprs/sdcard/ntp/..) - ble4 skipped if mac is not set (00:00:00:00:00:00) - improved menu (L&R buttons hides menu, parent menu now keep position) +- SD card car params logging (json format) + (note: m5stack supports max 16GB FAT16/32 microSD) - supported serial console commands serviceUUID=xxx charTxUUID=xxx diff --git a/config.h b/config.h index 1611f09..634b073 100644 --- a/config.h +++ b/config.h @@ -3,8 +3,8 @@ #include -#define APP_VERSION "v2.0.0" -#define APP_RELEASE_DATE "2020-12-02" +#define APP_VERSION "v2.1.0" +#define APP_RELEASE_DATE "2020-12-06" // TFT COLORS FOR TTGO #define TFT_BLACK 0x0000 /* 0, 0, 0 */ diff --git a/dist/m5stack_core1/evDash.ino.bin b/dist/m5stack_core1/evDash.ino.bin index 9b10c92..2e27678 100644 Binary files a/dist/m5stack_core1/evDash.ino.bin and b/dist/m5stack_core1/evDash.ino.bin differ diff --git a/dist/ttgo_t4_v13/evDash.ino.bin b/dist/ttgo_t4_v13/evDash.ino.bin index 9005db6..6adea11 100644 Binary files a/dist/ttgo_t4_v13/evDash.ino.bin and b/dist/ttgo_t4_v13/evDash.ino.bin differ diff --git a/evDash.ino b/evDash.ino index 34fa144..7a75c66 100644 --- a/evDash.ino +++ b/evDash.ino @@ -1,12 +1,11 @@ /* - 2020-12-02 Project renamed from eNiroDashboard to evDash !! 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 - Supported serial console commands + Serial console commands serviceUUID=xxx charTxUUID=xxx @@ -35,7 +34,6 @@ #define BOARD_M5STACK_CORE //#define SIM800L_ENABLED -//#define SD_ENABLED //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -51,11 +49,6 @@ #include "BoardM5stackCore.h" #endif // BOARD_M5STACK_CORE -#ifdef SD_ENABLED -#include -//#include -#endif - #include #include "config.h" #include "LiveData.h" @@ -536,6 +529,7 @@ void setup(void) { Serial.println("Booting device..."); // Init settings/params, board library + line = ""; liveData = new LiveData(); liveData->initParams(); @@ -577,27 +571,9 @@ void setup(void) { getLocalTime(&now, 0); liveData->params.chargingStartTime = liveData->params.currentTime = mktime(&now); - // Hold right button - board->afterSetup(); - -#ifdef SD_ENABLED - // 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."); - }*/ -#endif - // Start BLE connection - line = ""; Serial.println("Start BLE with PIN auth"); + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); BLEDevice::init(""); // Retrieve a Scanner and set the callback we want to use to be informed when we have detected a new device. @@ -610,8 +586,8 @@ void setup(void) { liveData->pBLEScan->setActiveScan(true); // Skip BLE scan if middle button pressed - Serial.println(liveData->settings.obdMacAddress); if (strcmp(liveData->settings.obdMacAddress, "00:00:00:00:00:00") != 0 && !board->skipAdapterScan()) { + Serial.println(liveData->settings.obdMacAddress); startBleScan(); } @@ -619,6 +595,9 @@ void setup(void) { sim800lSetup(); #endif //SIM800L_ENABLED + // Hold right button + board->afterSetup(); + // End Serial.println("Device setup completed"); } diff --git a/menu.h b/menu.h index 743befc..50e128d 100644 --- a/menu.h +++ b/menu.h @@ -24,11 +24,11 @@ MENU_ITEM menuItemsSource[100] = { {107, 1, -1, "Debug OBD2 Kia"}, {300, 3, 0, "<- parent menu"}, - {MENU_WIFI, 3, -1, "[dev] WiFi network"}, + // {MENU_WIFI, 3, -1, "[dev] WiFi network"}, {MENU_GPRS, 3, -1, "[dev] GSM/GPRS"}, - {MENU_NTP, 3, -1, "[dev] NTP"}, - {MENU_SDCARD, 3, -1, "[dev] SD card"}, {MENU_REMOTE_UPLOAD, 3, -1, "[dev] Remote upload"}, + {MENU_NTP, 3, -1, "[dev] NTP"}, + {MENU_SDCARD, 3, -1, "SD card"}, {MENU_SCREEN_ROTATION, 3, -1, "Screen rotation"}, {MENU_DEFAULT_SCREEN, 3, -1, "Default screen"}, {MENU_SCREEN_BRIGHTNESS, 3, -1, "LCD brightness"}, @@ -41,9 +41,6 @@ MENU_ITEM menuItemsSource[100] = { byte ntpEnabled; // 0/1 byte ntpTimezone; byte ntpDaySaveTime; // 0/1 - // SDcard logging - byte sdcardEnabled; // 0/1 - byte sdcardAutstartLog; // 0/1 // GPRS SIM800L byte gprsEnabled; // 0/1 char gprsApn[64];