#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3 #include "Pagedata.h" #include "OBP60Extensions.h" class PageBattery2 : public Page { static constexpr int8_t LEFT = 0; static constexpr int8_t CENTER = 1; static constexpr int8_t RIGHT = 2; bool init = false; // Marker for init done int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s bool trend = true; // Trend indicator [0|1], 0=off, 1=on double raw = 0; public: PageBattery2(CommonData &common){ commonData = &common; common.logger->logDebug(GwLog::LOG,"Instantiate PageBattery2"); } virtual void setupKeys(){ Page::setupKeys(); commonData->keydata[0].label = "AVG"; } virtual int handleKey(int key){ // Change average if(key == 1){ average ++; average = average % 4; // Modulo 4 return 0; // Commit the key } // Trend indicator if(key == 5){ trend = !trend; return 0; // Commit the key } // Code for keylock if(key == 11){ commonData->keylock = !commonData->keylock; return 0; // Commit the key } return key; } int displayPage(PageData &pageData) { GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; // Polynominal coefficients second order for battery energy level calculation // index 0 = Pb, 1 = Gel, 2 = AGM, 3 = LiFePo4 float x0[4] = {+3082.5178, +1656.1571, +1316.8766, +14986.9336}; // Offset float x1[4] = {-603.7478, -351.6503, -298.1454, -2432.1985}; // X float x2[4] = {+29.0340, +17.9000, +15.8196, +98.6132}; // X² int batPercentage = 0; // Battery level float batRange = 0; // Range in hours // Get config data bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); String batVoltage = config->getString(config->batteryVoltage); int batCapacity = config->getInt(config->batteryCapacity); String batType = config->getString(config->batteryType); String backlightMode = config->getString(config->backlight); String powerSensor = config->getString(config->usePowSensor1); bool smallDecimals = config->getBool(config->smallDecimals); double value1 = 0; // Battery voltage double value2 = 0; // Battery current double value3 = 0; // Battery power consumption double valueTrend = 0; // Average over 10 values // Get voltage value String name1 = "VBat"; // Create trend value if(init == false){ // Load start values for first page run valueTrend = commonData->data.batteryVoltage10; init = true; } else{ // Reading trend value valueTrend = commonData->data.batteryVoltage10; } // Get raw value for trend indicator raw = commonData->data.batteryVoltage; // Live data // Switch average values switch (average) { case 0: value1 = commonData->data.batteryVoltage; // Live data value2 = commonData->data.batteryCurrent; value3 = commonData->data.batteryPower; break; case 1: value1 = commonData->data.batteryVoltage10; // Average 10s value2 = commonData->data.batteryCurrent10; value3 = commonData->data.batteryPower10; break; case 2: value1 = commonData->data.batteryVoltage60; // Average 60s value2 = commonData->data.batteryCurrent60; value3 = commonData->data.batteryPower60; break; case 3: value1 = commonData->data.batteryVoltage300; // Average 300s value2 = commonData->data.batteryCurrent300; value3 = commonData->data.batteryPower300; break; default: value1 = commonData->data.batteryVoltage; // Default value2 = commonData->data.batteryCurrent; value3 = commonData->data.batteryPower; break; } bool valid1 = true; // Battery energy level calculation if(String(batType) == "Pb"){ batPercentage = (value1 * value1 * x2[0]) + (value1 * x1[0]) + x0[0]; } if(String(batType) == "Gel"){ batPercentage = (value1 * value1 * x2[1]) + (value1 * x1[1]) + x0[1]; } if(String(batType) == "AGM"){ batPercentage = (value1 * value1 * x2[2]) + (value1 * x1[2]) + x0[2]; } if(String(batType) == "LiFePo4"){ batPercentage = (value1 * value1 * x2[3]) + (value1 * x1[3]) + x0[3]; } // Limits for battery level if(batPercentage < 0) batPercentage = 0; if(batPercentage > 99) batPercentage = 99; // Battery range calculation if(value2 <= 0) value2 = 0.0000001; // Limiting current batRange = batCapacity * batPercentage / 100 / value2; // Limits for battery range if(batRange < 0) batRange = 0; if(batRange > 99) batRange = 99; // Optical warning by limit violation if(String(flashLED) == "Limit Violation"){ // Limits for Pb battery if(String(batType) == "Pb" && (raw < 11.8 || raw > 14.8)){ setBlinkingLED(true); } if(String(batType) == "Pb" && (raw >= 11.8 && raw <= 14.8)){ setBlinkingLED(false); setFlashLED(false); } // Limits for Gel battery if(String(batType) == "Gel" && (raw < 11.8 || raw > 14.4)){ setBlinkingLED(true); } if(String(batType) == "Gel" && (raw >= 11.8 && raw <= 14.4)){ setBlinkingLED(false); setFlashLED(false); } // Limits for AGM battery if(String(batType) == "AGM" && (raw < 11.8 || raw > 14.7)){ setBlinkingLED(true); } if(String(batType) == "AGM" && (raw >= 11.8 && raw <= 14.7)){ setBlinkingLED(false); setFlashLED(false); } // Limits for LiFePo4 battery if(String(batType) == "LiFePo4" && (raw < 12.0 || raw > 14.6)){ setBlinkingLED(true); } if(String(batType) == "LiFePo4" && (raw >= 12.0 && raw <= 14.6)){ setBlinkingLED(false); setFlashLED(false); } } // Logging voltage value LOG_DEBUG(GwLog::LOG,"Drawing at PageBattery2, Type:%s %s:=%f", batType.c_str(), name1.c_str(), raw); // Draw page //*********************************************************** // Set display in partial refresh mode displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update getdisplay().setTextColor(commonData->fgcolor); // Show name getdisplay().setFont(&Ubuntu_Bold20pt8b); getdisplay().setCursor(10, 65); getdisplay().print("Bat."); // Show battery type getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(90, 65); getdisplay().print(batType); // Show voltage type int bvoltage = 0; if(String(batVoltage) == "12V") bvoltage = 12; else bvoltage = 24; printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show battery capacity String svalueCapacity = (batCapacity <= 999) ? String(batCapacity) : String(float(batCapacity/1000.0), 1); printBoatValue(svalueCapacity, 10, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); if(batCapacity <= 999) getdisplay().print("Ah"); if(batCapacity > 999) getdisplay().print("kAh"); // Show info getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(10, 235); getdisplay().print("Installed"); getdisplay().setCursor(10, 255); getdisplay().print("Battery Type"); // Show battery with fill level batteryGraphic(150, 45, batPercentage, commonData->fgcolor, commonData->bgcolor); // Show average settings getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(150, 145); switch (average) { case 0: getdisplay().print("Avg: 1s"); break; case 1: getdisplay().print("Avg: 10s"); break; case 2: getdisplay().print("Avg: 60s"); break; case 3: getdisplay().print("Avg: 300s"); break; default: getdisplay().print("Avg: 1s"); break; } // Show fill level in percent printBoatValue(String(batPercentage), 150, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("%"); // Show time to full discharge String svalueRange; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ svalueRange = (batRange < 9.9) ? String(batRange, 1) : String(batRange, 0); } else{ svalueRange = "--"; } printBoatValue(svalueRange, 150, 260, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("h"); // Show sensor type info String i2cAddr = ""; getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(270, 60); if(powerSensor == "off") getdisplay().print("Internal"); if(powerSensor == "INA219"){ getdisplay().print("INA219"); } if(powerSensor == "INA226"){ getdisplay().print("INA226"); i2cAddr = " (0x" + String(INA226_I2C_ADDR1, HEX) + ")"; } getdisplay().print(i2cAddr); getdisplay().setCursor(270, 80); getdisplay().print("Sensor Modul"); // Reading bus data or using simulation data String svalue1; // Check for valid real data, display also if hold values activated if(valid1 == true || holdvalues == true){ svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData); } else { svalue1 = "---"; // Missing bus data } printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show actual current in A String svalue2; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData); } else{ svalue2 = "---"; } printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("A"); // Show actual consumption in W String svalue3; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData); } else{ svalue3 = "---"; } printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("W"); return PAGE_UPDATE; }; }; static Page *createPage(CommonData &common){ return new PageBattery2(common); } /** * with the code below we make this page known to the PageTask * we give it a type (name) that can be selected in the config * we define which function is to be called * and we provide the number of user parameters we expect (0 here) * and will will provide the names of the fixed values we need */ PageDescription registerPageBattery2( "Battery2", // Name of page createPage, // Action 0, // Number of bus values depends on selection in Web configuration {}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h) true // Show display header on/off ); #endif