GPS support (hw uart)

This commit is contained in:
Lubos Petrovic
2020-12-07 22:49:41 +01:00
parent 44c18cdba5
commit d9b7770308
9 changed files with 129 additions and 34 deletions

View File

@@ -7,6 +7,7 @@
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
//#include <WiFi.h> //#include <WiFi.h>
//#include <WiFiClient.h> //#include <WiFiClient.h>
#include <sys/time.h>
#include "config.h" #include "config.h"
#include "BoardInterface.h" #include "BoardInterface.h"
#include "Board320_240.h" #include "Board320_240.h"
@@ -63,6 +64,12 @@ void Board320_240::afterSetup() {
Serial.println("WiFi init completed...");*/ Serial.println("WiFi init completed...");*/
} }
// Init GPS
if (liveData->settings.gpsHwSerialPort <= 2) {
gpsHwUart = new HardwareSerial(liveData->settings.gpsHwSerialPort);
gpsHwUart->begin(9600);
}
// SD card // SD card
if (liveData->settings.sdcardEnabled == 1) { if (liveData->settings.sdcardEnabled == 1) {
if (sdcardMount() && liveData->settings.sdcardAutstartLog == 1) { if (sdcardMount() && liveData->settings.sdcardAutstartLog == 1) {
@@ -866,13 +873,13 @@ String Board320_240::menuItemCaption(int16_t menuItemId, String title) {
/*case MENU_WIFI: /*case MENU_WIFI:
suffix = "n/a"; suffix = "n/a";
switch (WiFi.status()) { switch (WiFi.status()) {
WL_CONNECTED: suffix = "CONNECTED"; break; WL_CONNECTED: suffix = "CONNECTED"; break;
WL_NO_SHIELD: suffix = "NO_SHIELD"; break; WL_NO_SHIELD: suffix = "NO_SHIELD"; break;
WL_IDLE_STATUS: suffix = "IDLE_STATUS"; break; WL_IDLE_STATUS: suffix = "IDLE_STATUS"; break;
WL_SCAN_COMPLETED: suffix = "SCAN_COMPLETED"; break; WL_SCAN_COMPLETED: suffix = "SCAN_COMPLETED"; break;
WL_CONNECT_FAILED: suffix = "CONNECT_FAILED"; break; WL_CONNECT_FAILED: suffix = "CONNECT_FAILED"; break;
WL_CONNECTION_LOST: suffix = "CONNECTION_LOST"; break; WL_CONNECTION_LOST: suffix = "CONNECTION_LOST"; break;
WL_DISCONNECTED: suffix = "DISCONNECTED"; break; WL_DISCONNECTED: suffix = "DISCONNECTED"; break;
} }
break;*/ break;*/
case MENU_GPRS: sprintf(tmpStr1, "[%s] %s", (liveData->settings.gprsEnabled == 1) ? "on" : "off", liveData->settings.gprsApn); suffix = tmpStr1; break; case MENU_GPRS: sprintf(tmpStr1, "[%s] %s", (liveData->settings.gprsEnabled == 1) ? "on" : "off", liveData->settings.gprsApn); suffix = tmpStr1; break;
@@ -883,6 +890,7 @@ WL_DISCONNECTED: suffix = "DISCONNECTED"; break;
case MENU_PREDRAWN_GRAPHS: suffix = (liveData->settings.predrawnChargingGraphs == 1) ? "[on]" : "[off]"; break; case MENU_PREDRAWN_GRAPHS: suffix = (liveData->settings.predrawnChargingGraphs == 1) ? "[on]" : "[off]"; break;
case MENU_HEADLIGHTS_REMINDER: suffix = (liveData->settings.headlightsReminder == 1) ? "[on]" : "[off]"; break; case MENU_HEADLIGHTS_REMINDER: suffix = (liveData->settings.headlightsReminder == 1) ? "[on]" : "[off]"; break;
case MENU_DEBUG_SCREEN: suffix = (liveData->settings.debugScreen == 1) ? "[on]" : "[off]"; break; case MENU_DEBUG_SCREEN: suffix = (liveData->settings.debugScreen == 1) ? "[on]" : "[off]"; break;
case MENU_GPS: sprintf(tmpStr1, "[HW UART=%d]", liveData->settings.gpsHwSerialPort); suffix = (liveData->settings.gpsHwSerialPort == 255) ? "[off]" : tmpStr1; break;
// //
case MENU_SDCARD_ENABLED: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 1) ? "on" : "off"); suffix = tmpStr1; 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_AUTOSTARTLOG: sprintf(tmpStr1, "[%s]", (liveData->settings.sdcardEnabled == 0) ? "n/a" : (liveData->settings.sdcardAutstartLog == 1) ? "on" : "off"); suffix = tmpStr1; break;
@@ -1029,6 +1037,7 @@ void Board320_240::menuItemClick() {
// Pre-drawn charg.graphs off/on // Pre-drawn charg.graphs off/on
case MENU_PREDRAWN_GRAPHS: liveData->settings.predrawnChargingGraphs = (liveData->settings.predrawnChargingGraphs == 1) ? 0 : 1; showMenu(); return; break; case MENU_PREDRAWN_GRAPHS: liveData->settings.predrawnChargingGraphs = (liveData->settings.predrawnChargingGraphs == 1) ? 0 : 1; showMenu(); return; break;
case MENU_HEADLIGHTS_REMINDER: liveData->settings.headlightsReminder = (liveData->settings.headlightsReminder == 1) ? 0 : 1; showMenu(); return; break; case MENU_HEADLIGHTS_REMINDER: liveData->settings.headlightsReminder = (liveData->settings.headlightsReminder == 1) ? 0 : 1; showMenu(); return; break;
case MENU_GPS: liveData->settings.gpsHwSerialPort = (liveData->settings.gpsHwSerialPort == 2) ? 255 : liveData->settings.gpsHwSerialPort + 1; showMenu(); return; break;
// Wifi menu // Wifi menu
case MENU_WIFI_ENABLED: liveData->settings.wifiEnabled = (liveData->settings.wifiEnabled == 1) ? 0 : 1; showMenu(); return; break; case MENU_WIFI_ENABLED: liveData->settings.wifiEnabled = (liveData->settings.wifiEnabled == 1) ? 0 : 1; showMenu(); return; break;
case MENU_WIFI_SSID: return; break; case MENU_WIFI_SSID: return; break;
@@ -1169,12 +1178,12 @@ void Board320_240::redrawScreen() {
spr.fillCircle(310, 10, 3, spr.fillCircle(310, 10, 3,
(liveData->params.sdcardInit == 1) ? (liveData->params.sdcardInit == 1) ?
(liveData->params.sdcardRecording) ? (liveData->params.sdcardRecording) ?
(strlen(liveData->params.sdcardFilename) != 0) ? (strlen(liveData->params.sdcardFilename) != 0) ?
TFT_GREEN /* assigned filename (opsec from bms or gsm/gps timestamp */: TFT_GREEN /* assigned filename (opsec from bms or gsm/gps timestamp */ :
TFT_BLUE /* recording started but waiting for data */ : TFT_BLUE /* recording started but waiting for data */ :
TFT_ORANGE /* sdcard init ready but recording not started*/ : TFT_ORANGE /* sdcard init ready but recording not started*/ :
TFT_YELLOW /* failed to initialize sdcard */ TFT_YELLOW /* failed to initialize sdcard */
); );
} }
// BLE not connected // BLE not connected
@@ -1272,27 +1281,50 @@ void Board320_240::mainLoop() {
hideMenu(); hideMenu();
} }
// GPS process
if (gpsHwUart != NULL) {
unsigned long start = millis();
do {
while (gpsHwUart->available())
gps.encode(gpsHwUart->read());
} while (millis() - start < 20);
//
syncGPS();
}
// currentTime
struct tm now;
getLocalTime(&now, 0);
liveData->params.currentTime = mktime(&now);
// SD card recording // SD card recording
if (liveData->params.sdcardInit && liveData->params.sdcardRecording && liveData->params.sdcardCanNotify) { if (liveData->params.sdcardInit && liveData->params.sdcardRecording && liveData->params.sdcardCanNotify) {
//Serial.println(&now, "%y%m%d%H%M");
// create filename // create filename
if (liveData->params.operationTimeSec > 0 && strlen(liveData->params.sdcardFilename) == 0) { if (liveData->params.operationTimeSec > 0 && strlen(liveData->params.sdcardFilename) == 0) {
sprintf(liveData->params.sdcardFilename, "/%llu.json", uint64_t(liveData->params.operationTimeSec / 60)); sprintf(liveData->params.sdcardFilename, "/%llu.json", uint64_t(liveData->params.operationTimeSec / 60));
Serial.println("Log filename: "); Serial.print("Log filename by opTimeSec: ");
Serial.println(liveData->params.sdcardFilename);
}
if (liveData->params.currTimeSyncWithGps && strlen(liveData->params.sdcardFilename) < 15) {
strftime(liveData->params.sdcardFilename, sizeof(liveData->params.sdcardFilename), "/%y%m%d%H%M.json", &now);
Serial.print("Log filename by GPS: ");
Serial.println(liveData->params.sdcardFilename); Serial.println(liveData->params.sdcardFilename);
} }
// append buffer, clear buffer & notify state // append buffer, clear buffer & notify state
if (strlen(liveData->params.sdcardFilename) != 0) { if (strlen(liveData->params.sdcardFilename) != 0) {
liveData->params.sdcardCanNotify = false; liveData->params.sdcardCanNotify = false;
File file = SD.open(liveData->params.sdcardFilename, FILE_APPEND); File file = SD.open(liveData->params.sdcardFilename, FILE_APPEND);
if (!file) { if (!file) {
Serial.println("Failed to open file for appending"); Serial.println("Failed to open file for appending");
File file = SD.open(liveData->params.sdcardFilename, FILE_WRITE); File file = SD.open(liveData->params.sdcardFilename, FILE_WRITE);
} }
if (!file) { if (!file) {
Serial.println("Failed to create file"); Serial.println("Failed to create file");
} }
if (file) { if (file) {
Serial.println("Save buffer to SD card"); Serial.println("Save buffer to SD card");
serializeParamsToJson(file); serializeParamsToJson(file);
@@ -1301,6 +1333,10 @@ void Board320_240::mainLoop() {
} }
} }
} }
// Shutdown when car is off
if (liveData->params.automaticShutdownTimer != 0 && liveData->params.currentTime - liveData->params.automaticShutdownTimer > 5)
shutdownDevice();
} }
/** /**
@@ -1381,4 +1417,37 @@ void Board320_240::sdcardToggleRecording() {
} }
} }
/**
Sync gps data
*/
void Board320_240::syncGPS() {
if (gps.location.isValid()) {
liveData->params.gpsLat = gps.location.lat();
liveData->params.gpsLon = gps.location.lng();
if (gps.altitude.isValid())
liveData->params.gpsAlt = gps.altitude.meters();
}
if (gps.satellites.isValid()) {
liveData->params.gpsSat = gps.satellites.value();
//Serial.print("GPS satellites: ");
//Serial.println(liveData->params.gpsSat);
}
if (!liveData->params.currTimeSyncWithGps && gps.date.isValid() && gps.time.isValid()) {
liveData->params.currTimeSyncWithGps = true;
struct tm tm;
tm.tm_year = gps.date.year() - 1900;
tm.tm_mon = gps.date.month() - 1;
tm.tm_mday = gps.date.day();
tm.tm_hour = gps.time.hour();
tm.tm_min = gps.time.minute();
tm.tm_sec = gps.time.second();
time_t t = mktime(&tm);
printf("%02d%02d%02d%02d%02d%02d\n", gps.date.year() - 2000, gps.date.month() - 1, gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second());
struct timeval now = { .tv_sec = t };
settimeofday(&now, NULL);
}
}
#endif // BOARD320_240_CPP #endif // BOARD320_240_CPP

View File

@@ -14,6 +14,7 @@
// //
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
#include <TinyGPS++.h>
#include "BoardInterface.h" #include "BoardInterface.h"
class Board320_240 : public BoardInterface { class Board320_240 : public BoardInterface {
@@ -23,6 +24,8 @@ class Board320_240 : public BoardInterface {
TFT_eSPI tft = TFT_eSPI(); TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft); TFT_eSprite spr = TFT_eSprite(&tft);
//SPIClass spiSD(HSPI); //SPIClass spiSD(HSPI);
HardwareSerial* gpsHwUart = NULL;
TinyGPSPlus gps;
char tmpStr1[20]; char tmpStr1[20];
char tmpStr2[20]; char tmpStr2[20];
char tmpStr3[20]; char tmpStr3[20];
@@ -46,6 +49,8 @@ class Board320_240 : public BoardInterface {
// SD card // SD card
bool sdcardMount() override; bool sdcardMount() override;
void sdcardToggleRecording() override; void sdcardToggleRecording() override;
// GPS
void syncGPS();
// Basic GUI // Basic GUI
void setBrightness(byte lcdBrightnessPerc) override; void setBrightness(byte lcdBrightnessPerc) override;
void displayMessage(const char* row1, const char* row2) override; void displayMessage(const char* row1, const char* row2) override;

View File

@@ -87,7 +87,7 @@ void BoardInterface::loadSettings() {
// Default settings // Default settings
liveData->settings.initFlag = 183; liveData->settings.initFlag = 183;
liveData->settings.settingsVersion = 4; liveData->settings.settingsVersion = 5;
liveData->settings.carType = CAR_KIA_ENIRO_2020_64; liveData->settings.carType = CAR_KIA_ENIRO_2020_64;
tmpStr = "00:00:00:00:00:00"; // Pair via menu (middle button) tmpStr = "00:00:00:00:00:00"; // Pair via menu (middle button)
tmpStr.toCharArray(liveData->settings.obdMacAddress, tmpStr.length() + 1); tmpStr.toCharArray(liveData->settings.obdMacAddress, tmpStr.length() + 1);
@@ -126,6 +126,7 @@ void BoardInterface::loadSettings() {
tmpStr = "not_set"; tmpStr = "not_set";
tmpStr.toCharArray(liveData->settings.remoteApiKey, tmpStr.length() + 1); tmpStr.toCharArray(liveData->settings.remoteApiKey, tmpStr.length() + 1);
liveData->settings.headlightsReminder = 0; liveData->settings.headlightsReminder = 0;
liveData->settings.gpsHwSerialPort = 255; // off
// Load settings and replace default values // Load settings and replace default values
Serial.println("Reading settings from eeprom."); Serial.println("Reading settings from eeprom.");
@@ -174,7 +175,11 @@ void BoardInterface::loadSettings() {
tmpStr.toCharArray(liveData->tmpSettings.remoteApiUrl, tmpStr.length() + 1); tmpStr.toCharArray(liveData->tmpSettings.remoteApiUrl, tmpStr.length() + 1);
tmpStr = "example"; tmpStr = "example";
tmpStr.toCharArray(liveData->tmpSettings.remoteApiKey, tmpStr.length() + 1); tmpStr.toCharArray(liveData->tmpSettings.remoteApiKey, tmpStr.length() + 1);
liveData->settings.headlightsReminder = 0; liveData->tmpSettings.headlightsReminder = 0;
}
if (liveData->tmpSettings.settingsVersion == 4) {
liveData->tmpSettings.settingsVersion = 5;
liveData->tmpSettings.gpsHwSerialPort = 255; // off
} }
// Save upgraded structure // Save upgraded structure
@@ -231,7 +236,7 @@ void BoardInterface::customConsoleCommand(String cmd) {
*/ */
bool BoardInterface::serializeParamsToJson(File file, bool inclApiKey) { bool BoardInterface::serializeParamsToJson(File file, bool inclApiKey) {
StaticJsonDocument<1024> jsonData; StaticJsonDocument<1500> jsonData;
if (inclApiKey) if (inclApiKey)
jsonData["apiKey"] = liveData->settings.remoteApiKey; jsonData["apiKey"] = liveData->settings.remoteApiKey;
@@ -240,6 +245,11 @@ bool BoardInterface::serializeParamsToJson(File file, bool inclApiKey) {
jsonData["batTotalKwh"] = liveData->params.batteryTotalAvailableKWh; jsonData["batTotalKwh"] = liveData->params.batteryTotalAvailableKWh;
jsonData["currTime"] = liveData->params.currentTime; jsonData["currTime"] = liveData->params.currentTime;
jsonData["opTime"] = liveData->params.operationTimeSec; jsonData["opTime"] = liveData->params.operationTimeSec;
jsonData["gpsSat"] = liveData->params.gpsSat;
jsonData["lat"] = liveData->params.gpsLat;
jsonData["lon"] = liveData->params.gpsLon;
jsonData["alt"] = liveData->params.gpsAlt;
jsonData["socPerc"] = liveData->params.socPerc; jsonData["socPerc"] = liveData->params.socPerc;
jsonData["sohPerc"] = liveData->params.sohPerc; jsonData["sohPerc"] = liveData->params.sohPerc;

View File

@@ -20,6 +20,12 @@ void LiveData::initParams() {
String tmpStr = ""; String tmpStr = "";
tmpStr.toCharArray(params.sdcardFilename, tmpStr.length() + 1); tmpStr.toCharArray(params.sdcardFilename, tmpStr.length() + 1);
params.sdcardCanNotify = false; params.sdcardCanNotify = false;
// Gps
params.currTimeSyncWithGps = false;
params.gpsLat = -1;
params.gpsLon = -1;
params.gpsSat = 0;
params.gpsAlt = -1;
// Car data // Car data
params.ignitionOn = false; params.ignitionOn = false;
params.ignitionOnPrevious = false; params.ignitionOnPrevious = false;

View File

@@ -42,6 +42,12 @@ typedef struct {
// SIM // SIM
time_t lastDataSent; time_t lastDataSent;
bool sim800l_enabled; bool sim800l_enabled;
// GPS
bool currTimeSyncWithGps;
float gpsLat;
float gpsLon;
byte gpsSat; // satellites count
int16_t gpsAlt;
// SD card // SD card
bool sdcardInit; bool sdcardInit;
bool sdcardRecording; bool sdcardRecording;
@@ -136,7 +142,7 @@ typedef struct {
// Setting stored to flash // Setting stored to flash
typedef struct { typedef struct {
byte initFlag; // 183 value byte initFlag; // 183 value
byte settingsVersion; // current 4 byte settingsVersion; // current 5
// === settings version 1 // === settings version 1
// ================================= // =================================
uint16_t carType; // 0 - Kia eNiro 2020, 1 - Hyundai Kona 2020, 2 - Hyudai Ioniq 2018 uint16_t carType; // 0 - Kia eNiro 2020, 1 - Hyundai Kona 2020, 2 - Hyudai Ioniq 2018
@@ -176,7 +182,10 @@ typedef struct {
char remoteApiUrl[64]; char remoteApiUrl[64];
char remoteApiKey[32]; char remoteApiKey[32];
// //
bool headlightsReminder; byte headlightsReminder;
// === settings version 5
// =================================
byte gpsHwSerialPort; // 255-off, 0,1,2 - hw serial
// //
} SETTINGS_STRUC; } SETTINGS_STRUC;

View File

@@ -2,6 +2,8 @@
### Next version ### Next version
- tech refactoring: `hexToDecFromResponse`, `decFromResponse` - tech refactoring: `hexToDecFromResponse`, `decFromResponse`
- added support for GPS module on HW UART (user HWUART=2 for m5stack NEO-M8N)
- sd card logging - added gps sat/lat/lot/alt + SD filename + time is synchronized from GPS
### v2.1.0 2020-12-06 ### v2.1.0 2020-12-06
- m5stack mute speaker - m5stack mute speaker

View File

@@ -81,6 +81,7 @@ typedef struct {
#define MENU_REMOTE_UPLOAD 309 #define MENU_REMOTE_UPLOAD 309
#define MENU_HEADLIGHTS_REMINDER 310 #define MENU_HEADLIGHTS_REMINDER 310
#define MENU_DEBUG_SCREEN 311 #define MENU_DEBUG_SCREEN 311
#define MENU_GPS 312
// //
#define MENU_DISTANCE_UNIT 401 #define MENU_DISTANCE_UNIT 401
#define MENU_TEMPERATURE_UNIT 402 #define MENU_TEMPERATURE_UNIT 402

View File

@@ -2,7 +2,7 @@
Project renamed from eNiroDashboard to evDash Project renamed from eNiroDashboard to evDash
!! working only with OBD BLE 4.0 adapters !! working only with OBD BLE 4.0 adapters
!! Supported adapter is Vgate ICar Pro (must be BLE4.0 version) !! Supported adapter is Vgate ICar Pro (must be BLE4.0 version)
!! Not working with standard BLUETOOTH 3 adapters !! Not working with standard BLUETOOTH 3 adapters
Serial console commands Serial console commands
@@ -659,14 +659,6 @@ void loop() {
#endif // SIM800L_ENABLED #endif // SIM800L_ENABLED
board->mainLoop(); board->mainLoop();
// currentTime & 1ms delay
struct tm now;
getLocalTime(&now, 0);
liveData->params.currentTime = mktime(&now);
// Shutdown when car is off
if (liveData->params.automaticShutdownTimer != 0 && liveData->params.currentTime - liveData->params.automaticShutdownTimer > 5)
board->shutdownDevice();
if (board->scanDevices) { if (board->scanDevices) {
board->scanDevices = false; board->scanDevices = false;
startBleScan(); startBleScan();

7
menu.h
View File

@@ -25,10 +25,11 @@ MENU_ITEM menuItemsSource[100] = {
{300, 3, 0, "<- parent menu"}, {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_REMOTE_UPLOAD, 3, -1, "[dev] Remote upload"},
{MENU_NTP, 3, -1, "[dev] NTP"},
{MENU_SDCARD, 3, -1, "SD card"}, {MENU_SDCARD, 3, -1, "SD card"},
{MENU_GPS, 3, -1, "GPS"},
{MENU_GPRS, 3, -1, "[dev] GSM/GPRS"},
//{MENU_REMOTE_UPLOAD, 3, -1, "[dev] Remote upload"},
//{MENU_NTP, 3, -1, "[dev] NTP"},
{MENU_SCREEN_ROTATION, 3, -1, "Screen rotation"}, {MENU_SCREEN_ROTATION, 3, -1, "Screen rotation"},
{MENU_DEFAULT_SCREEN, 3, -1, "Default screen"}, {MENU_DEFAULT_SCREEN, 3, -1, "Default screen"},
{MENU_SCREEN_BRIGHTNESS, 3, -1, "LCD brightness"}, {MENU_SCREEN_BRIGHTNESS, 3, -1, "LCD brightness"},