diff --git a/src/plugins/Display/Display_Mono.h b/src/plugins/Display/Display_Mono.h index c8d25f8b..e0a03c61 100644 --- a/src/plugins/Display/Display_Mono.h +++ b/src/plugins/Display/Display_Mono.h @@ -81,7 +81,7 @@ class DisplayMono { mDispWidth = mDisplay->getDisplayWidth(); mDispHeight = mDisplay->getDisplayHeight(); mDispSwitchTime.stopTimeMonitor(); - if (mCfg->graph_ratio == 100) // if graph ratio is 100% start in graph mode + if (100 == mCfg->graph_ratio) // if graph ratio is 100% start in graph mode mDispSwitchState = DispSwitchState::GRAPH; else if (mCfg->graph_ratio != 0) mDispSwitchTime.startTimeMonitor(150 * (100 - mCfg->graph_ratio)); // start display mode change only if ratio is neither 0 nor 100 @@ -90,39 +90,70 @@ class DisplayMono { // pixelshift screensaver with wipe effect void calcPixelShift(int range) { int8_t mod = (millis() / 10000) % ((range >> 1) << 2); - mPixelshift = mCfg->screenSaver == 1 ? ((mod < range) ? mod - (range >> 1) : -(mod - range - (range >> 1) + 1)) : 0; + mPixelshift = (1 == mCfg->screenSaver) ? ((mod < range) ? mod - (range >> 1) : -(mod - range - (range >> 1) + 1)) : 0; } + protected: + enum class PowerGraphState { + NO_TIME_SYNC, + IN_PERIOD, + WAIT_4_NEW_PERIOD, + WAIT_4_RESTART + }; + + // initialize power graph and allocate data buffer based on pixel width void initPowerGraph(uint8_t width, uint8_t height) { DBGPRINTLN(F("---- Init Power Graph ----")); mPgWidth = width; mPgHeight = height; mPgData = new float[mPgWidth]; + mPgState = PowerGraphState::NO_TIME_SYNC; resetPowerGraph(); -/* - Inverter<> *iv; - mPgMaxAvailPower = 0; - uint8_t nInv = mSys->getNumInverters(); - for (uint8_t i = 0; i < nInv; i++) { - iv = mSys->getInverterByPos(i); - if (iv == NULL) - continue; - for (uint8_t ch = 0; ch < 6; ch++) { - mPgMaxAvailPower += iv->config->chMaxPwr[ch]; - } - } - DBGPRINTLN("max. Power = " + String(mPgMaxAvailPower));*/ } + // add new value to power graph and maintain state engine for period times void addPowerGraphEntry(float val) { - if ((nullptr != mPgData) && (mDisplayData->utcTs > 0)) { // precondition: power graph initialized and utc time available - calcPowerGraphValues(); - //mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], (uint8_t) (val * 255.0 / mPgMaxAvailPower)); // normalizing of data to 0-255 - mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], val); - mPgMaxPwr = std::max(mPgMaxPwr, val); // max value of stored data for scaling of y-axis + if (nullptr == mPgData) // power graph not initialized + return; + + bool store_entry = false; + switch(mPgState) { + case PowerGraphState::NO_TIME_SYNC: + if ((mDisplayData->pGraphStartTime > 0) && (mDisplayData->pGraphEndTime > 0) && // wait until period data is available ... + (mDisplayData->utcTs >= mDisplayData->pGraphStartTime) && (mDisplayData->utcTs < mDisplayData->pGraphEndTime)) { // and current time is in period + storeStartEndTimes(); // period was received -> store + store_entry = true; + mPgState = PowerGraphState::IN_PERIOD; + } + break; + case PowerGraphState::IN_PERIOD: + if (mDisplayData->utcTs > mPgEndTime) // check if end of day is reached ... + mPgState = PowerGraphState::WAIT_4_NEW_PERIOD; // then wait for new period setting + else + store_entry = true; + break; + case PowerGraphState::WAIT_4_NEW_PERIOD: + if ((mPgStartTime != mDisplayData->pGraphStartTime) || (mPgEndTime != mDisplayData->pGraphEndTime)) { // wait until new time period was received ... + storeStartEndTimes(); // and store it for next period + mPgState = PowerGraphState::WAIT_4_RESTART; + } + break; + case PowerGraphState::WAIT_4_RESTART: + if ((mDisplayData->utcTs >= mPgStartTime) && (mDisplayData->utcTs < mPgEndTime)) { // wait until current time is in period again ... + resetPowerGraph(); // then reset power graph data + store_entry = true; + mPgState = PowerGraphState::IN_PERIOD; + } + break; + } + if (store_entry) { + mPgLastPos = std::min((uint8_t) sss2PgPos(mDisplayData->utcTs - mPgStartTime), (uint8_t) (mPgWidth - 1)); // current datapoint based on seconds since start + mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], val); // update current datapoint to maximum of all seen values + mPgMaxPwr = std::max(mPgMaxPwr, val); // update max value of stored data for scaling of y-axis } } + // plot power graph to given display offset void plotPowerGraph(uint8_t xoff, uint8_t yoff) { if (nullptr == mPgData) // power graph not initialized return; @@ -146,7 +177,7 @@ class DisplayMono { tm.Minute = 0; tm.Second = 0; for (; tm.Hour <= endHour; tm.Hour++) { - uint8_t x_pos_screen = getPowerGraphXpos(sss2pgpos((uint32_t) makeTime(tm) - mDisplayData->pGraphStartTime)); // scale horizontal axis + uint8_t x_pos_screen = getPowerGraphXpos(sss2PgPos((uint32_t) makeTime(tm) - mDisplayData->pGraphStartTime)); // scale horizontal axis mDisplay->drawPixel(xoff + x_pos_screen, yoff - 1); } @@ -163,8 +194,8 @@ class DisplayMono { // draw curve for (uint8_t i = 1; i <= mPgLastPos; i++) { - mDisplay->drawLine(xoff + getPowerGraphXpos(i - 1), yoff - getPowerGraphYpos(i - 1), - xoff + getPowerGraphXpos(i), yoff - getPowerGraphYpos(i)); + mDisplay->drawLine(xoff + getPowerGraphXpos(i - 1), yoff - getPowerGraphValueYpos(i - 1), + xoff + getPowerGraphXpos(i), yoff - getPowerGraphValueYpos(i)); } // print max power value @@ -195,6 +226,7 @@ class DisplayMono { return change; } + // reset power graph void resetPowerGraph() { if (mPgData != nullptr) { mPgMaxPwr = 0.0; @@ -205,34 +237,35 @@ class DisplayMono { } } - uint8_t sss2pgpos(uint seconds_since_start) { - uint32_t diff = (mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime); - if(diff) - return (seconds_since_start * (mPgWidth - 1) / diff); - return 0; + // store start and end times of current time period and calculate period length + void storeStartEndTimes() { + mPgStartTime = mDisplayData->pGraphStartTime; + mPgEndTime = mDisplayData->pGraphEndTime; + mPgPeriod = mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime; // time period of power graph in sec for scaling of x-axis } - void calcPowerGraphValues() { - mPgPeriod = mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime; // length of power graph for scaling of x-axis - uint32_t oldTimeOfDay = mPgTimeOfDay; - mPgTimeOfDay = (mDisplayData->utcTs > mDisplayData->pGraphStartTime) ? mDisplayData->utcTs - mDisplayData->pGraphStartTime : 0; // current time of day with respect to current sunrise time - if (oldTimeOfDay > mPgTimeOfDay) // new day -> reset old data - resetPowerGraph(); - if(0 == mPgPeriod) - mPgPeriod = 1; - mPgLastPos = std::min((uint8_t) (mPgTimeOfDay * (mPgWidth - 1) / mPgPeriod), (uint8_t) (mPgWidth - 1)); // current datapoint based on currenct time of day + // get power graph datapoint index, scaled to current time period, by seconds since start + uint8_t sss2PgPos(uint seconds_since_start) { + if(mPgPeriod) + return (seconds_since_start * (mPgWidth - 1) / mPgPeriod); + else + return 0; } - uint8_t getPowerGraphXpos(uint8_t p) { + // get X-position of power graph, scaled to lastpos, by according data point index + uint8_t getPowerGraphXpos(uint8_t p) { if ((p <= mPgLastPos) && (mPgLastPos > 0)) return((p * (mPgWidth - 1)) / mPgLastPos); // scaling of x-axis - return 0; + else + return 0; } - uint8_t getPowerGraphYpos(uint8_t p) { + // get Y-position of power graph, scaled to maximum value, by according datapoint index + uint8_t getPowerGraphValueYpos(uint8_t p) { if ((p < mPgWidth) && (mPgMaxPwr > 0)) return((mPgData[p] * (uint32_t) mPgHeight / mPgMaxPwr)); // scaling of data to graph height - return 0; + else + return 0; } protected: @@ -254,9 +287,11 @@ class DisplayMono { float *mPgData = nullptr; uint8_t mPgHeight = 0; float mPgMaxPwr = 0.0; - uint32_t mPgPeriod = 0; // seconds - uint32_t mPgTimeOfDay = 0; + uint32_t mPgStartTime = 0; + uint32_t mPgEndTime = 0; + uint32_t mPgPeriod = 0; // seconds uint8_t mPgLastPos = 0; + PowerGraphState mPgState = PowerGraphState::NO_TIME_SYNC; uint16_t mDispHeight; uint8_t mLuminance; diff --git a/src/plugins/Display/Display_Mono_128X64.h b/src/plugins/Display/Display_Mono_128X64.h index 34f35834..b4aa08cc 100644 --- a/src/plugins/Display/Display_Mono_128X64.h +++ b/src/plugins/Display/Display_Mono_128X64.h @@ -89,9 +89,8 @@ class DisplayMono128X64 : public DisplayMono { calcPixelShift(pixelShiftRange); // add new power data to power graph - if (mDisplayData->nrProducing > 0) { + if (mDisplayData->nrProducing > 0) addPowerGraphEntry(mDisplayData->totalPower); - } // print Date and time if (0 != mDisplayData->utcTs)