sdcard logs

This commit is contained in:
Lubos Petrovic
2020-12-06 21:29:34 +01:00
parent 1eaff543ff
commit 94ebdc6653
14 changed files with 210 additions and 66 deletions

View File

@@ -2,10 +2,11 @@
#define BOARD320_240_CPP
#include <SD.h>
#include <FS.h>
#include <analogWrite.h>
#include <TFT_eSPI.h>
#include <WiFi.h>
#include <WiFiClient.h>
//#include <WiFi.h>
//#include <WiFiClient.h>
#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

View File

@@ -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];

View File

@@ -1,6 +1,9 @@
#ifndef BOARDINTERFACE_CPP
#define BOARDINTERFACE_CPP
#define ARDUINOJSON_USE_LONG_LONG 1
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <BLEDevice.h>
#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

View File

@@ -1,6 +1,7 @@
#ifndef BOARDINTERFACE_H
#define BOARDINTERFACE_H
#include <FS.h>
#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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -3,8 +3,8 @@
#include <BLEDevice.h>
#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 */

Binary file not shown.

Binary file not shown.

View File

@@ -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 <mySD.h>
//#include <SD.h>
#endif
#include <sys/time.h>
#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");
}

9
menu.h
View File

@@ -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];