SleepMode

Signed-off-by: Martin Kolací <martin.kolaci@lmc.eu>
This commit is contained in:
Martin Kolací
2020-12-28 13:10:49 +01:00
parent 6cc3c5dcf4
commit 25f31c7811
14 changed files with 170 additions and 40 deletions

View File

@@ -11,6 +11,8 @@
#include <ArduinoJson.h>
#include "SIM800L.h"
RTC_DATA_ATTR int bootCount = 0;
/**
Init board
*/
@@ -29,6 +31,29 @@ void Board320_240::initBoard() {
getLocalTime(&now, 0);
liveData->params.chargingStartTime = liveData->params.currentTime = mktime(&now);
++bootCount;
syslog->print("Boot count: ");
syslog->println(bootCount);
}
/**
After setup device
*/
void Board320_240::afterSetup() {
if (digitalRead(pinButtonRight) == LOW) {
loadTestData();
}
// Init from parent class
syslog->println("BoardInterface::afterSetup");
BoardInterface::afterSetup();
// Check if bard was sleeping
if(bootCount > 1) {
afterSleep();
}
// Init display
syslog->println("Init tft display");
tft.begin();
@@ -44,12 +69,6 @@ void Board320_240::initBoard() {
#endif
spr.setColorDepth((psramUsed) ? 16 : 8);
spr.createSprite(320, 240);
}
/**
After setup device
*/
void Board320_240::afterSetup() {
// Show test data on right button during boot device
displayScreen = liveData->settings.defaultScreen;
@@ -63,7 +82,6 @@ void Board320_240::afterSetup() {
/*syslog->print("memReport(): MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM bytes free. ");
syslog->println(heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM));
syslog->println("WiFi init...");
WiFi.enableSTA(true);
WiFi.mode(WIFI_STA);
@@ -96,10 +114,73 @@ void Board320_240::afterSetup() {
if (liveData->settings.gprsHwSerialPort <= 2) {
sim800lSetup();
}
}
// Init from parent class
syslog->println("BoardInterface::afterSetup");
BoardInterface::afterSetup();
/**
Go to Sleep for TIME_TO_SLEEP seconds
*/
void Board320_240::goToSleep() {
//Sleep MCP2515
commInterface->disconnectDevice();
//Sleep SIM800L
if(liveData->params.sim800l_enabled) {
if (sim800l->isConnectedGPRS()) {
bool disconnected = sim800l->disconnectGPRS();
for(uint8_t i = 0; i < 5 && !disconnected; i++) {
delay(1000);
disconnected = sim800l->disconnectGPRS();
}
}
if(sim800l->getPowerMode() == NORMAL) {
sim800l->setPowerMode(SLEEP);
delay(1000);
}
sim800l->enterSleepMode();
}
syslog->println("Going to sleep for " + String(TIME_TO_SLEEP) + " seconds!");
syslog->flush();
delay(1000);
//Sleep ESP32
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * 1000000ULL);
esp_deep_sleep_start();
}
/*
Wake up board from sleep
Iterate thru commands and determine if car is charging or ignition is on
*/
void Board320_240::afterSleep() {
syslog->println("Waking up from sleep mode!");
bool firstRun = true;
while(liveData->commandQueueIndex -1 > liveData->commandQueueLoopFrom || firstRun) {
if(liveData->commandQueueIndex -1 == liveData->commandQueueLoopFrom) {
firstRun = false;
}
if(millis() > 5000) {
syslog->println("Time's up (5s timeout)...");
goToSleep();
}
commInterface->mainLoop();
}
if(liveData->params.auxVoltage < 12) {
syslog->println("AuxBATT too low!");
goToSleep();
} else if(!liveData->params.ignitionOn && !liveData->params.chargingOn) {
syslog->println("Not started & Not charging.");
goToSleep();
} else {
syslog->println("Wake up conditions satisfied... Good morning!");
}
}
/**
@@ -895,7 +976,7 @@ String Board320_240::menuItemCaption(int16_t menuItemId, String title) {
case MENU_SCREEN_BRIGHTNESS: sprintf(tmpStr1, "[%d%%]", liveData->settings.lcdBrightness); suffix = (liveData->settings.lcdBrightness == 0) ? "[auto]" : tmpStr1; 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_DEBUG_SCREEN: suffix = (liveData->settings.debugScreen == 1) ? "[on]" : "[off]"; break;
case MENU_SLEEP_MODE: suffix = (liveData->settings.sleepModeEnabled == 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;
@@ -1045,7 +1126,7 @@ void Board320_240::menuItemClick() {
case 3064: liveData->settings.defaultScreen = 4; showParentMenu = true; break;
case 3065: liveData->settings.defaultScreen = 5; showParentMenu = true; break;
// Debug screen off/on
case MENU_DEBUG_SCREEN: liveData->settings.debugScreen = (liveData->settings.debugScreen == 1) ? 0 : 1; showMenu(); return; break;
case MENU_SLEEP_MODE: liveData->settings.sleepModeEnabled = (liveData->settings.sleepModeEnabled == 1) ? 0 : 1; showMenu(); return; break;
case MENU_SCREEN_BRIGHTNESS: liveData->settings.lcdBrightness += 20; if (liveData->settings.lcdBrightness > 100) liveData->settings.lcdBrightness = 0;
setBrightness((liveData->settings.lcdBrightness == 0) ? 100 : liveData->settings.lcdBrightness); showMenu(); return; break;
// Pre-drawn charg.graphs off/on
@@ -1300,7 +1381,7 @@ void Board320_240::mainLoop() {
menuMove(false);
} else {
displayScreen++;
if (displayScreen > displayScreenCount - (liveData->settings.debugScreen == 0) ? 1 : 0)
if (displayScreen > displayScreenCount - 1)
displayScreen = 0; // rotate screens
// Turn off display on screen 0
setBrightness((displayScreen == SCREEN_BLANK) ? 0 : (liveData->settings.lcdBrightness == 0) ? 100 : liveData->settings.lcdBrightness);
@@ -1392,9 +1473,21 @@ void Board320_240::mainLoop() {
}
}
// Shutdown when car is off
if (liveData->params.automaticShutdownTimer != 0 && liveData->params.currentTime - liveData->params.automaticShutdownTimer > 5)
shutdownDevice();
// Turn off display if Ignition is off for more than 10s
if(liveData->params.currentTime - liveData->params.lastIgnitionOnTime > 10
&& liveData->params.lastIgnitionOnTime != 0
&& liveData->settings.sleepModeEnabled) {
setBrightness(0);
} else {
setBrightness((liveData->settings.lcdBrightness == 0) ? 100 : liveData->settings.lcdBrightness);
}
// Go to sleep when car is off for more than 10s and not charging
if (liveData->params.currentTime - liveData->params.lastIgnitionOnTime > 10
&& !liveData->params.chargingOn
&& liveData->params.lastIgnitionOnTime != 0
&& liveData->settings.sleepModeEnabled)
goToSleep();
// Read data from BLE/CAN
commInterface->mainLoop();
@@ -1534,9 +1627,9 @@ bool Board320_240::sim800lSetup() {
gprsHwUart = new HardwareSerial(liveData->settings.gprsHwSerialPort);
gprsHwUart->begin(9600);
sim800l = new SIM800L((Stream *)gprsHwUart, SIM800L_RST, 512 , 512);
sim800l = new SIM800L((Stream *)gprsHwUart, SIM800L_RST, 768 , 128);
// SIM800L DebugMode:
//sim800l = new SIM800L((Stream *)gprsHwUart, SIM800L_RST, 512 , 512, (Stream *)&Serial);
//sim800l = new SIM800L((Stream *)gprsHwUart, SIM800L_RST, 768 , 128, (Stream *)&Serial);
bool sim800l_ready = sim800l->isReady();
for (uint8_t i = 0; i < 5 && !sim800l_ready; i++) {
@@ -1550,6 +1643,17 @@ bool Board320_240::sim800lSetup() {
} else {
syslog->println("SIM800L module initialized");
sim800l->exitSleepMode();
if(sim800l->getPowerMode() != NORMAL) {
syslog->println("SIM800L module in sleep mode - Waking up");
if(sim800l->setPowerMode(NORMAL)) {
syslog->println("SIM800L in normal power mode");
} else {
syslog->println("Failed to switch SIM800L to normal power mode");
}
}
syslog->print("Setting GPRS APN to: ");
syslog->println(liveData->settings.gprsApn);
@@ -1606,10 +1710,12 @@ bool Board320_240::sendDataViaGPRS() {
syslog->println("Start HTTP POST...");
StaticJsonDocument<512> jsonData;
StaticJsonDocument<768> jsonData;
jsonData["apikey"] = liveData->settings.remoteApiKey;
jsonData["carType"] = liveData->settings.carType;
jsonData["ignitionOn"] = liveData->params.ignitionOn;
jsonData["chargingOn"] = liveData->params.chargingOn;
jsonData["socPerc"] = liveData->params.socPerc;
jsonData["sohPerc"] = liveData->params.sohPerc;
jsonData["batPowerKw"] = liveData->params.batPowerKw;
@@ -1626,7 +1732,7 @@ bool Board320_240::sendDataViaGPRS() {
jsonData["cumulativeEnergyChargedKWh"] = liveData->params.cumulativeEnergyChargedKWh;
jsonData["cumulativeEnergyDischargedKWh"] = liveData->params.cumulativeEnergyDischargedKWh;
char payload[512];
char payload[768];
serializeJson(jsonData, payload);
syslog->print("Sending payload: ");

View File

@@ -11,6 +11,9 @@
#define SMOOTH_FONT
#define GFXFF 1 // TFT FOnts
// DEEP SLEEP
#define TIME_TO_SLEEP 60 // Sleep time in secs
//
#include <TFT_eSPI.h>
#include <TinyGPS++.h>
@@ -49,6 +52,8 @@ class Board320_240 : public BoardInterface {
void afterSetup() override;
void mainLoop() override;
bool skipAdapterScan() override;
void goToSleep();
void afterSleep();
// SD card
bool sdcardMount() override;
void sdcardToggleRecording() override;

View File

@@ -112,7 +112,7 @@ void BoardInterface::loadSettings() {
liveData->settings.pressureUnit = 'b';
liveData->settings.defaultScreen = 1;
liveData->settings.lcdBrightness = 0;
liveData->settings.debugScreen = 0;
liveData->settings.sleepModeEnabled = 0;
liveData->settings.predrawnChargingGraphs = 1;
liveData->settings.commType = COMM_TYPE_OBD2BLE4; // BLE4
liveData->settings.wifiEnabled = 0;
@@ -161,7 +161,7 @@ void BoardInterface::loadSettings() {
liveData->tmpSettings.settingsVersion = 2;
liveData->tmpSettings.defaultScreen = liveData->settings.defaultScreen;
liveData->tmpSettings.lcdBrightness = liveData->settings.lcdBrightness;
liveData->tmpSettings.debugScreen = liveData->settings.debugScreen;
liveData->tmpSettings.sleepModeEnabled = liveData->settings.sleepModeEnabled;
}
if (liveData->tmpSettings.settingsVersion == 2) {
liveData->tmpSettings.settingsVersion = 3;

View File

@@ -106,9 +106,7 @@ void CarHyundaiIoniq::parseRowMerged() {
if (liveData->params.ignitionOn) {
liveData->params.lastIgnitionOnTime = liveData->params.currentTime;
}
int32_t secDiff = liveData->params.currentTime - liveData->params.currentTime;
if (liveData->commConnected && secDiff > 30 && secDiff < MONTH_SEC && !liveData->params.ignitionOn && !liveData->params.chargingOn)
liveData->params.automaticShutdownTimer = liveData->params.currentTime;
tempByte = liveData->hexToDecFromResponse(18, 20, 1, false);
liveData->params.headLights = (bitRead(tempByte, 5) == 1);
liveData->params.dayLights = (bitRead(tempByte, 3) == 1);
@@ -185,8 +183,8 @@ void CarHyundaiIoniq::parseRowMerged() {
//liveData->params.batMaxC = liveData->hexToDecFromResponse(32, 34, 1, true);
//liveData->params.batMinC = liveData->hexToDecFromResponse(34, 36, 1, true);
tempByte = liveData->hexToDecFromResponse(104, 106, 1, false);
liveData->params.chargingOn = (bitRead(tempByte, 2) == 0);
tempByte = liveData->hexToDecFromResponse(22, 24, 1, false);
liveData->params.chargingOn = (bitRead(tempByte, 5) == 1 || bitRead(tempByte, 6) == 1); // bit 5 = AC; bit 6 = DC
// 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)
liveData->params.batInletC = liveData->hexToDecFromResponse(48, 50, 1, true);

View File

@@ -128,9 +128,6 @@ void CarKiaEniro::parseRowMerged() {
liveData->params.lastIgnitionOnTime = liveData->params.currentTime;
}
int32_t secDiff = liveData->params.currentTime - liveData->params.currentTime;
if (liveData->commConnected && secDiff > 30 && secDiff < MONTH_SEC && !liveData->params.ignitionOn && !liveData->params.chargingOn)
liveData->params.automaticShutdownTimer = liveData->params.currentTime;
tempByte = liveData->hexToDecFromResponse(18, 20, 1, false);
liveData->params.headLights = (bitRead(tempByte, 5) == 1);
liveData->params.dayLights = (bitRead(tempByte, 3) == 1);
@@ -234,8 +231,12 @@ void CarKiaEniro::parseRowMerged() {
//liveData->params.batTempC = liveData->hexToDecFromResponse(36, 38, 1, true);
//liveData->params.batMaxC = liveData->hexToDecFromResponse(34, 36, 1, true);
//liveData->params.batMinC = liveData->hexToDecFromResponse(36, 38, 1, true);
tempByte = liveData->hexToDecFromResponse(106, 108, 1, false);
liveData->params.chargingOn = (bitRead(tempByte, 2) == 1);
// Ignition Off/on
// tempByte = liveData->hexToDecFromResponse(106, 108, 1, false);
// liveData->params.chargingOn = (bitRead(tempByte, 2) == 1);
tempByte = liveData->hexToDecFromResponse(24, 26, 1, false);
liveData->params.chargingOn = (bitRead(tempByte, 5) == 1 || bitRead(tempByte, 6) == 1); // bit 5 = AC; bit 6 = DC
// 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)
liveData->params.batMinC = liveData->params.batMaxC = liveData->params.batModuleTempC[0];

View File

@@ -32,6 +32,11 @@ void CommInterface::mainLoop() {
}
}
// Drop ChargingOn when status was not updated for more than 10 seconds
if(liveData->params.currentTime - liveData->params.lastChargingOnTime > 10 && liveData->params.chargingOn) {
liveData->params.chargingOn = false;
}
// Can send next command from queue to OBD
if (liveData->canSendNextAtCommand) {
liveData->canSendNextAtCommand = false;

View File

@@ -60,6 +60,7 @@ void CommObd2Can::connectDevice() {
void CommObd2Can::disconnectDevice() {
liveData->commConnected = false;
CAN->setMode(MCP_SLEEP);
syslog->println("COMM disconnectDevice");
}

View File

@@ -15,7 +15,6 @@ void debug(String msg, uint8_t debugLevel) {
*/
void LiveData::initParams() {
params.automaticShutdownTimer = 0;
// SIM
params.lastDataSent = 0;
params.sim800l_enabled = false;

View File

@@ -45,7 +45,6 @@ typedef struct {
// System
time_t currentTime;
time_t chargingStartTime;
time_t automaticShutdownTimer;
// SIM
time_t lastDataSent;
bool sim800l_enabled;
@@ -63,6 +62,7 @@ typedef struct {
bool ignitionOn;
bool chargingOn;
time_t lastIgnitionOnTime;
time_t lastChargingOnTime;
uint64_t operationTimeSec;
bool sdcardCanNotify;
bool forwardDriveMode;
@@ -175,7 +175,7 @@ typedef struct {
// =================================
byte defaultScreen; // 1 .. 6
byte lcdBrightness; // 0 - auto, 1 .. 100%
byte debugScreen; // 0 - off, 1 - on
byte sleepModeEnabled; // 0 - off, 1 - on
byte predrawnChargingGraphs; // 0 - off, 1 - on
// === settings version 4
// =================================

View File

@@ -45,6 +45,9 @@ const char AT_CMD_CFUN0[] PROGMEM = "AT+CFUN=0"; //
const char AT_CMD_CFUN1[] PROGMEM = "AT+CFUN=1"; // Switch normal power mode
const char AT_CMD_CFUN4[] PROGMEM = "AT+CFUN=4"; // Switch sleep power mode
const char AC_CMD_CSCLK0[] PROGMEM = "AT+CSCLK=0"; // AT+CSCLK=0 command
const char AC_CMD_CSCLK2[] PROGMEM = "AT+CSCLK=2"; // AT+CSCLK=2 command
const char AT_CMD_CREG_TEST[] PROGMEM = "AT+CREG?"; // Check the network registration status
const char AT_CMD_SAPBR_GPRS[] PROGMEM = "AT+SAPBR=3,1,\"Contype\",\"GPRS\""; // Configure the GPRS bearer
const char AT_CMD_SAPBR_APN[] PROGMEM = "AT+SAPBR=3,1,\"APN\","; // Configure the APN for the GPRS
@@ -721,6 +724,16 @@ bool SIM800L::setPowerMode(PowerMode powerMode) {
return currentPowerMode == powerMode;
}
void SIM800L::exitSleepMode() {
sendCommand_P(AC_CMD_CSCLK0);
purgeSerial();
}
void SIM800L::enterSleepMode() {
sendCommand_P(AC_CMD_CSCLK2);
purgeSerial();
}
/**
* Status function: Check the strengh of the signal
*/

View File

@@ -66,6 +66,8 @@ class SIM800L {
// Define the power mode (for parameter: see PowerMode enum)
bool setPowerMode(PowerMode powerMode);
void enterSleepMode();
void exitSleepMode();
// Enable/disable GPRS
bool setupGPRS(const char *apn);

View File

@@ -79,7 +79,7 @@ typedef struct {
#define MENU_PREDRAWN_GRAPHS 308
#define MENU_REMOTE_UPLOAD 309
#define MENU_HEADLIGHTS_REMINDER 310
#define MENU_DEBUG_SCREEN 311
#define MENU_SLEEP_MODE 311
#define MENU_GPS 312
#define MENU_SERIAL_CONSOLE 313
#define MENU_DEBUG_LEVEL 314

View File

@@ -117,12 +117,12 @@ void setup(void) {
car->activateCommandQueue();
board->attachCar(car);
// Redraw screen
board->redrawScreen();
// Finish board setup
board->afterSetup();
// Redraw screen
board->redrawScreen();
// End
syslog->println("Device setup completed");
}

2
menu.h
View File

@@ -45,7 +45,7 @@ MENU_ITEM menuItemsSource[100] = {
{MENU_SCREEN_BRIGHTNESS, 3, -1, "LCD brightness"},
{MENU_PREDRAWN_GRAPHS, 3, -1, "Pre-drawn ch.graphs"},
{MENU_HEADLIGHTS_REMINDER, 3, -1, "Headlight reminder"},
// {MENU_DEBUG_SCREEN, 3, -1, "Debug screen"},
{MENU_SLEEP_MODE, 3, -1, "Debug screen"},
/*
// NTP