mirror of
https://github.com/lumapu/ahoy.git
synced 2025-04-28 17:56:21 +02:00
0.8.48
* merge PR: pin selection for ESP-32 S2 #1334 * merge PR: enhancement: power graph display option #1330
This commit is contained in:
parent
42926c4d26
commit
3c5be9ae35
6 changed files with 234 additions and 246 deletions
15
.github/workflows/compile_development.yml
vendored
15
.github/workflows/compile_development.yml
vendored
|
@ -147,8 +147,6 @@ jobs:
|
|||
with:
|
||||
merge-multiple: true
|
||||
path: firmware
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R firmware
|
||||
|
||||
- name: Get Version from code
|
||||
id: version_name
|
||||
|
@ -161,19 +159,6 @@ jobs:
|
|||
env:
|
||||
VERSION: ${{ steps.version_name.outputs.name }}
|
||||
|
||||
# - name: Create Manifest
|
||||
# working-directory: src
|
||||
# run: python ../scripts/buildManifest.py
|
||||
#
|
||||
# - name: Create Artifact
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: ahoydtu_dev
|
||||
# path: |
|
||||
# src/firmware/*
|
||||
# src/User_Manual.md
|
||||
# src/install.html
|
||||
|
||||
- name: Rename firmware directory
|
||||
run: mv firmware ${{ steps.version_name.outputs.name }}
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# Development Changes
|
||||
|
||||
## 0.8.48 - 2024-01-07
|
||||
* merge PR: pin selection for ESP-32 S2 #1334
|
||||
* merge PR: enhancement: power graph display option #1330
|
||||
|
||||
## 0.8.47 - 2024-01-06
|
||||
* reduce GxEPD2 lib to compile faster
|
||||
* upgraded GxEPD2 lib to `1.5.3`
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//-------------------------------------
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 8
|
||||
#define VERSION_PATCH 47
|
||||
#define VERSION_PATCH 48
|
||||
|
||||
//-------------------------------------
|
||||
typedef struct {
|
||||
|
|
|
@ -22,256 +22,255 @@
|
|||
#include "../../utils/timemonitor.h"
|
||||
|
||||
class DisplayMono {
|
||||
public:
|
||||
DisplayMono() {};
|
||||
public:
|
||||
DisplayMono() {};
|
||||
|
||||
virtual void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) = 0;
|
||||
virtual void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum, uint8_t graph_ratio, uint8_t graph_size) = 0;
|
||||
virtual void disp(void) = 0;
|
||||
virtual void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) = 0;
|
||||
virtual void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum, uint8_t graph_ratio, uint8_t graph_size) = 0;
|
||||
virtual void disp(void) = 0;
|
||||
|
||||
// Common loop function, manages display on/off functions for powersave and screensaver with motionsensor
|
||||
// can be overridden by subclasses
|
||||
virtual bool loop(uint8_t lum, bool motion) {
|
||||
// Common loop function, manages display on/off functions for powersave and screensaver with motionsensor
|
||||
// can be overridden by subclasses
|
||||
virtual bool loop(uint8_t lum, bool motion) {
|
||||
|
||||
bool dispConditions = (!mEnPowerSave || (mDisplayData->nrProducing > 0)) &&
|
||||
((mScreenSaver != 2) || motion); // screensaver 2 .. motionsensor
|
||||
bool dispConditions = (!mEnPowerSave || (mDisplayData->nrProducing > 0)) &&
|
||||
((mScreenSaver != 2) || motion); // screensaver 2 .. motionsensor
|
||||
|
||||
if (mDisplayActive) {
|
||||
if (!dispConditions) {
|
||||
if (mDisplayTime.isTimeout()) { // switch display off after timeout
|
||||
mDisplayActive = false;
|
||||
mDisplay->setPowerSave(true);
|
||||
DBGPRINTLN("**** Display off ****");
|
||||
if (mDisplayActive) {
|
||||
if (!dispConditions) {
|
||||
if (mDisplayTime.isTimeout()) { // switch display off after timeout
|
||||
mDisplayActive = false;
|
||||
mDisplay->setPowerSave(true);
|
||||
DBGPRINTLN("**** Display off ****");
|
||||
}
|
||||
}
|
||||
else
|
||||
mDisplayTime.reStartTimeMonitor(); // keep display on
|
||||
}
|
||||
else {
|
||||
if (dispConditions) {
|
||||
mDisplayActive = true;
|
||||
mDisplayTime.reStartTimeMonitor(); // switch display on
|
||||
mDisplay->setPowerSave(false);
|
||||
DBGPRINTLN("**** Display on ****");
|
||||
}
|
||||
}
|
||||
else
|
||||
mDisplayTime.reStartTimeMonitor(); // keep display on
|
||||
}
|
||||
else {
|
||||
if (dispConditions) {
|
||||
mDisplayActive = true;
|
||||
mDisplayTime.reStartTimeMonitor(); // switch display on
|
||||
mDisplay->setPowerSave(false);
|
||||
DBGPRINTLN("**** Display on ****");
|
||||
}
|
||||
}
|
||||
|
||||
if(mLuminance != lum) {
|
||||
mLuminance = lum;
|
||||
if(mLuminance != lum) {
|
||||
mLuminance = lum;
|
||||
mDisplay->setContrast(mLuminance);
|
||||
}
|
||||
|
||||
return(monoMaintainDispSwitchState());
|
||||
}
|
||||
|
||||
protected:
|
||||
enum class DispSwitchState {
|
||||
TEXT,
|
||||
GRAPH
|
||||
};
|
||||
|
||||
protected:
|
||||
U8G2* mDisplay;
|
||||
DisplayData *mDisplayData;
|
||||
|
||||
float *mPgData = nullptr;
|
||||
uint8_t mPgWidth = 0;
|
||||
uint8_t mPgHeight = 0;
|
||||
float mPgMaxPwr = 0.0;
|
||||
uint32_t mPgPeriod = 0; // seconds
|
||||
uint32_t mPgTimeOfDay = 0;
|
||||
uint8_t mPgLastPos = 0;
|
||||
|
||||
uint8_t mType;
|
||||
uint16_t mDispWidth;
|
||||
uint16_t mDispHeight;
|
||||
|
||||
bool mEnPowerSave;
|
||||
uint8_t mScreenSaver = 1; // 0 .. off; 1 .. pixelShift; 2 .. motionsensor
|
||||
uint8_t mLuminance;
|
||||
uint8_t mGraphRatio;
|
||||
uint8_t mGraphSize;
|
||||
|
||||
uint8_t mLoopCnt;
|
||||
uint8_t mLineXOffsets[5] = {};
|
||||
uint8_t mLineYOffsets[5] = {};
|
||||
|
||||
uint8_t mExtra;
|
||||
int8_t mPixelshift=0;
|
||||
TimeMonitor mDisplayTime = TimeMonitor(1000 * DISP_DEFAULT_TIMEOUT, true);
|
||||
TimeMonitor mDispSwitchTime = TimeMonitor();
|
||||
DispSwitchState mDispSwitchState = DispSwitchState::TEXT;
|
||||
bool mDisplayActive = true; // always start with display on
|
||||
char mFmtText[DISP_FMT_TEXT_LEN];
|
||||
|
||||
// Common initialization function to be called by subclasses
|
||||
void monoInit(U8G2* display, uint8_t type, DisplayData *displayData) {
|
||||
mDisplay = display;
|
||||
mType = type;
|
||||
mDisplayData = displayData;
|
||||
mDisplay->begin();
|
||||
mDisplay->setPowerSave(false); // always start with display on
|
||||
mDisplay->setContrast(mLuminance);
|
||||
}
|
||||
mDisplay->clearBuffer();
|
||||
mDispWidth = mDisplay->getDisplayWidth();
|
||||
mDispHeight = mDisplay->getDisplayHeight();
|
||||
mDispSwitchTime.stopTimeMonitor();
|
||||
if (mGraphRatio == 100) // if graph ratio is 100% start in graph mode
|
||||
mDispSwitchState = DispSwitchState::GRAPH;
|
||||
else if (mGraphRatio != 0)
|
||||
mDispSwitchTime.startTimeMonitor(150 * (100 - mGraphRatio)); // start display mode change only if ratio is neither 0 nor 100
|
||||
}
|
||||
|
||||
return(monoMaintainDispSwitchState());
|
||||
}
|
||||
|
||||
protected:
|
||||
U8G2* mDisplay;
|
||||
DisplayData *mDisplayData;
|
||||
|
||||
float *mPgData=nullptr;
|
||||
uint8_t mPgWidth=0;
|
||||
uint8_t mPgHeight=0;
|
||||
float mPgMaxPwr=0.0;
|
||||
// float mPgMaxAvailPower = 0.0;
|
||||
uint32_t mPgPeriod=0; // seconds
|
||||
uint32_t mPgTimeOfDay=0;
|
||||
uint8_t mPgLastPos=0;
|
||||
|
||||
uint8_t mType;
|
||||
uint16_t mDispWidth;
|
||||
uint16_t mDispHeight;
|
||||
|
||||
bool mEnPowerSave;
|
||||
uint8_t mScreenSaver = 1; // 0 .. off; 1 .. pixelShift; 2 .. motionsensor
|
||||
uint8_t mLuminance;
|
||||
uint8_t mGraphRatio;
|
||||
uint8_t mGraphSize;
|
||||
|
||||
uint8_t mLoopCnt;
|
||||
uint8_t mLineXOffsets[5] = {};
|
||||
uint8_t mLineYOffsets[5] = {};
|
||||
|
||||
uint8_t mExtra;
|
||||
int8_t mPixelshift=0;
|
||||
TimeMonitor mDisplayTime = TimeMonitor(1000 * DISP_DEFAULT_TIMEOUT, true);
|
||||
TimeMonitor mDispSwitchTime = TimeMonitor();
|
||||
uint8_t mDispSwitchState;
|
||||
bool mDisplayActive = true; // always start with display on
|
||||
char mFmtText[DISP_FMT_TEXT_LEN];
|
||||
|
||||
enum _dispSwitchState {
|
||||
d_POWER_TEXT = 0,
|
||||
d_POWER_GRAPH = 1,
|
||||
};
|
||||
|
||||
// Common initialization function to be called by subclasses
|
||||
void monoInit(U8G2* display, uint8_t type, DisplayData *displayData) {
|
||||
mDisplay = display;
|
||||
mType = type;
|
||||
mDisplayData = displayData;
|
||||
mDisplay->begin();
|
||||
mDisplay->setPowerSave(false); // always start with display on
|
||||
mDisplay->setContrast(mLuminance);
|
||||
mDisplay->clearBuffer();
|
||||
mDispWidth = mDisplay->getDisplayWidth();
|
||||
mDispHeight = mDisplay->getDisplayHeight();
|
||||
mDispSwitchTime.stopTimeMonitor();
|
||||
mDispSwitchState = d_POWER_TEXT;
|
||||
if (mGraphRatio == 100) // if graph ratio is 100% start in graph mode
|
||||
mDispSwitchState = d_POWER_GRAPH;
|
||||
else if (mGraphRatio != 0)
|
||||
mDispSwitchTime.startTimeMonitor(150 * (100 - mGraphRatio)); // start display mode change only if ratio is neither 0 nor 100
|
||||
}
|
||||
|
||||
bool monoMaintainDispSwitchState(void) {
|
||||
bool change = false;
|
||||
switch(mDispSwitchState) {
|
||||
case d_POWER_TEXT:
|
||||
if (mDispSwitchTime.isTimeout()) {
|
||||
mDispSwitchState = d_POWER_GRAPH;
|
||||
mDispSwitchTime.startTimeMonitor(150 * mGraphRatio); // mGraphRatio: 0-100 Gesamtperiode 15000 ms
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
case d_POWER_GRAPH:
|
||||
if (mDispSwitchTime.isTimeout()) {
|
||||
mDispSwitchState = d_POWER_TEXT;
|
||||
mDispSwitchTime.startTimeMonitor(150 * (100 - mGraphRatio));
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
void initPowerGraph(uint8_t width, uint8_t height) {
|
||||
mPgWidth = width;
|
||||
mPgHeight = height;
|
||||
mPgData = new float[mPgWidth];
|
||||
//memset(mPgData, 0, mPgWidth);
|
||||
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];
|
||||
bool monoMaintainDispSwitchState(void) {
|
||||
bool change = false;
|
||||
switch(mDispSwitchState) {
|
||||
case DispSwitchState::TEXT:
|
||||
if (mDispSwitchTime.isTimeout()) {
|
||||
mDispSwitchState = DispSwitchState::GRAPH;
|
||||
mDispSwitchTime.startTimeMonitor(150 * mGraphRatio); // mGraphRatio: 0-100 Gesamtperiode 15000 ms
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
case DispSwitchState::GRAPH:
|
||||
if (mDispSwitchTime.isTimeout()) {
|
||||
mDispSwitchState = DispSwitchState::TEXT;
|
||||
mDispSwitchTime.startTimeMonitor(150 * (100 - mGraphRatio));
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBGPRINTLN("max. Power = " + String(mPgMaxAvailPower));*/
|
||||
}
|
||||
|
||||
void resetPowerGraph() {
|
||||
if (mPgData != nullptr) {
|
||||
mPgMaxPwr = 0.0;
|
||||
mPgLastPos = 0;
|
||||
for (uint8_t i = 0; i < mPgWidth; i++)
|
||||
mPgData[i] = 0.0;
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sss2pgpos(uint seconds_since_start) {
|
||||
return(seconds_since_start * (mPgWidth - 1) / (mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime));
|
||||
}
|
||||
|
||||
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
|
||||
void initPowerGraph(uint8_t width, uint8_t height) {
|
||||
mPgWidth = width;
|
||||
mPgHeight = height;
|
||||
mPgData = new float[mPgWidth];
|
||||
//memset(mPgData, 0, mPgWidth);
|
||||
resetPowerGraph();
|
||||
mPgLastPos = std::min((uint8_t) (mPgTimeOfDay * (mPgWidth - 1) / mPgPeriod), (uint8_t) (mPgWidth - 1)); // current datapoint based on currenct time of day
|
||||
}
|
||||
|
||||
void addPowerGraphEntry(float val) {
|
||||
if (mDisplayData->utcTs > 0) { // precondition: 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
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getPowerGraphXpos(uint8_t p) { //
|
||||
if ((p <= mPgLastPos) && (mPgLastPos > 0))
|
||||
return((p * (mPgWidth - 1)) / mPgLastPos); // scaling of x-axis
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint8_t getPowerGraphYpos(uint8_t p) {
|
||||
if (p < mPgWidth)
|
||||
//return(((uint32_t) mPgData[p] * (uint32_t) mPgMaxAvailPower) * (uint32_t) mPgHeight / mPgMaxPwr / 255); // scaling of normalized data (0-255) to graph height
|
||||
return((mPgData[p] * (uint32_t) mPgHeight / mPgMaxPwr)); // scaling of data to graph height
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
void plotPowerGraph(uint8_t xoff, uint8_t yoff) {
|
||||
// draw axes
|
||||
mDisplay->drawLine(xoff, yoff, xoff, yoff - mPgHeight); // vertical axis
|
||||
mDisplay->drawLine(xoff, yoff, xoff + mPgWidth, yoff); // horizontal axis
|
||||
|
||||
// draw X scale
|
||||
tmElements_t tm;
|
||||
breakTime(mDisplayData->pGraphEndTime, tm);
|
||||
uint8_t endHourPg = tm.Hour;
|
||||
breakTime(mDisplayData->utcTs, tm);
|
||||
uint8_t endHour = std::min(endHourPg, tm.Hour);
|
||||
breakTime(mDisplayData->pGraphStartTime, tm);
|
||||
tm.Hour += 1;
|
||||
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
|
||||
mDisplay->drawPixel(xoff + x_pos_screen, yoff - 1);
|
||||
/*
|
||||
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));*/
|
||||
}
|
||||
|
||||
// draw Y scale
|
||||
uint16_t scale_y = 10;
|
||||
uint32_t maxpwr_int = static_cast<uint8_t>(std::round(mPgMaxPwr));
|
||||
if (maxpwr_int > 100)
|
||||
scale_y = 100;
|
||||
for (uint32_t i = scale_y; i <= maxpwr_int; i += scale_y) {
|
||||
uint8_t ypos = yoff - static_cast<uint8_t>(std::round(i * (float) mPgHeight / mPgMaxPwr)); // scale vertical axis
|
||||
mDisplay->drawPixel(xoff + 1, ypos);
|
||||
void resetPowerGraph() {
|
||||
if (mPgData != nullptr) {
|
||||
mPgMaxPwr = 0.0;
|
||||
mPgLastPos = 0;
|
||||
for (uint8_t i = 0; i < mPgWidth; i++)
|
||||
mPgData[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// 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));
|
||||
uint8_t sss2pgpos(uint seconds_since_start) {
|
||||
return(seconds_since_start * (mPgWidth - 1) / (mDisplayData->pGraphEndTime - mDisplayData->pGraphStartTime));
|
||||
}
|
||||
|
||||
// print max power value
|
||||
mDisplay->setFont(u8g2_font_4x6_tr);
|
||||
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%dW", static_cast<uint16_t>(std::round(mPgMaxPwr)));
|
||||
mDisplay->drawStr(xoff + 3, yoff - mPgHeight + 5, mFmtText);
|
||||
}
|
||||
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();
|
||||
mPgLastPos = std::min((uint8_t) (mPgTimeOfDay * (mPgWidth - 1) / mPgPeriod), (uint8_t) (mPgWidth - 1)); // current datapoint based on currenct time of day
|
||||
}
|
||||
|
||||
// pixelshift screensaver with wipe effect
|
||||
void calcPixelShift(int range) {
|
||||
int8_t mod = (millis() / 10000) % ((range >> 1) << 2);
|
||||
mPixelshift = mScreenSaver == 1 ? ((mod < range) ? mod - (range >> 1) : -(mod - range - (range >> 1) + 1)) : 0;
|
||||
}
|
||||
void addPowerGraphEntry(float val) {
|
||||
if (mDisplayData->utcTs > 0) { // precondition: 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
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getPowerGraphXpos(uint8_t p) { //
|
||||
if ((p <= mPgLastPos) && (mPgLastPos > 0))
|
||||
return((p * (mPgWidth - 1)) / mPgLastPos); // scaling of x-axis
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint8_t getPowerGraphYpos(uint8_t p) {
|
||||
if (p < mPgWidth)
|
||||
//return(((uint32_t) mPgData[p] * (uint32_t) mPgMaxAvailPower) * (uint32_t) mPgHeight / mPgMaxPwr / 255); // scaling of normalized data (0-255) to graph height
|
||||
return((mPgData[p] * (uint32_t) mPgHeight / mPgMaxPwr)); // scaling of data to graph height
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
void plotPowerGraph(uint8_t xoff, uint8_t yoff) {
|
||||
// draw axes
|
||||
mDisplay->drawLine(xoff, yoff, xoff, yoff - mPgHeight); // vertical axis
|
||||
mDisplay->drawLine(xoff, yoff, xoff + mPgWidth, yoff); // horizontal axis
|
||||
|
||||
// draw X scale
|
||||
tmElements_t tm;
|
||||
breakTime(mDisplayData->pGraphEndTime, tm);
|
||||
uint8_t endHourPg = tm.Hour;
|
||||
breakTime(mDisplayData->utcTs, tm);
|
||||
uint8_t endHour = std::min(endHourPg, tm.Hour);
|
||||
breakTime(mDisplayData->pGraphStartTime, tm);
|
||||
tm.Hour += 1;
|
||||
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
|
||||
mDisplay->drawPixel(xoff + x_pos_screen, yoff - 1);
|
||||
}
|
||||
|
||||
// draw Y scale
|
||||
uint16_t scale_y = 10;
|
||||
uint32_t maxpwr_int = static_cast<uint8_t>(std::round(mPgMaxPwr));
|
||||
if (maxpwr_int > 100)
|
||||
scale_y = 100;
|
||||
for (uint32_t i = scale_y; i <= maxpwr_int; i += scale_y) {
|
||||
uint8_t ypos = yoff - static_cast<uint8_t>(std::round(i * (float) mPgHeight / mPgMaxPwr)); // scale vertical axis
|
||||
mDisplay->drawPixel(xoff + 1, ypos);
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// print max power value
|
||||
mDisplay->setFont(u8g2_font_4x6_tr);
|
||||
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%dW", static_cast<uint16_t>(std::round(mPgMaxPwr)));
|
||||
mDisplay->drawStr(xoff + 3, yoff - mPgHeight + 5, mFmtText);
|
||||
}
|
||||
|
||||
// pixelshift screensaver with wipe effect
|
||||
void calcPixelShift(int range) {
|
||||
int8_t mod = (millis() / 10000) % ((range >> 1) << 2);
|
||||
mPixelshift = mScreenSaver == 1 ? ((mod < range) ? mod - (range >> 1) : -(mod - range - (range >> 1) + 1)) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* adapted 5x8 Font for low-res displays with symbols
|
||||
Symbols:
|
||||
\x80 ... antenna
|
||||
\x81 ... WiFi
|
||||
\x82 ... suncurve
|
||||
\x83 ... sum/sigma
|
||||
\x84 ... antenna crossed
|
||||
\x85 ... WiFi crossed
|
||||
\x86 ... sun
|
||||
\x87 ... moon
|
||||
\x88 ... calendar/day
|
||||
\x89 ... MQTT */
|
||||
\x80 ... antenna
|
||||
\x81 ... WiFi
|
||||
\x82 ... suncurve
|
||||
\x83 ... sum/sigma
|
||||
\x84 ... antenna crossed
|
||||
\x85 ... WiFi crossed
|
||||
\x86 ... sun
|
||||
\x87 ... moon
|
||||
\x88 ... calendar/day
|
||||
\x89 ... MQTT */
|
||||
const uint8_t u8g2_font_5x8_symbols_ahoy[1049] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") =
|
||||
"j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\0 \5\0\304\11!\7a\306"
|
||||
"\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m"
|
||||
|
|
|
@ -176,7 +176,7 @@ class DisplayMono128X64 : public DisplayMono {
|
|||
printText(mFmtText, l_YieldTotal, 0xff);
|
||||
}
|
||||
|
||||
if (mDispSwitchState == d_POWER_GRAPH) {
|
||||
if (mDispSwitchState == DispSwitchState::GRAPH) {
|
||||
// plot power graph
|
||||
plotPowerGraph((mDispWidth - mPgWidth) / 2 + mPixelshift, mLineYOffsets[graph_last_line] - 1);
|
||||
}
|
||||
|
@ -274,6 +274,6 @@ class DisplayMono128X64 : public DisplayMono {
|
|||
}
|
||||
|
||||
bool showLine(uint8_t line) {
|
||||
return ((mDispSwitchState == d_POWER_TEXT) || ((line < graph_first_line) || (line > graph_last_line)));
|
||||
return ((mDispSwitchState == DispSwitchState::TEXT) || ((line < graph_first_line) || (line > graph_last_line)));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -137,7 +137,7 @@ class DisplayMono84X48 : public DisplayMono {
|
|||
printText(mFmtText, l_YieldTotal, 0xff);
|
||||
}
|
||||
|
||||
if (mDispSwitchState == d_POWER_GRAPH) {
|
||||
if (mDispSwitchState == DispSwitchState::GRAPH) {
|
||||
// plot power graph
|
||||
plotPowerGraph(8, mLineYOffsets[graph_last_line] - 1);
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ class DisplayMono84X48 : public DisplayMono {
|
|||
}
|
||||
|
||||
bool showLine(uint8_t line) {
|
||||
return ((mDispSwitchState == d_POWER_TEXT) || ((line < graph_first_line) || (line > graph_last_line)));
|
||||
return ((mDispSwitchState == DispSwitchState::TEXT) || ((line < graph_first_line) || (line > graph_last_line)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue