Browse Source

add motion sensor function for screensaver and remove redundant display code

pull/1239/head
Wusaweki 1 year ago
parent
commit
9647044e49
  1. 6
      src/config/config.h
  2. 12
      src/config/settings.h
  3. 32
      src/plugins/Display/Display.h
  4. 46
      src/plugins/Display/Display_Mono.h
  5. 29
      src/plugins/Display/Display_Mono_128X32.h
  6. 82
      src/plugins/Display/Display_Mono_128X64.h
  7. 29
      src/plugins/Display/Display_Mono_64X48.h
  8. 27
      src/plugins/Display/Display_Mono_84X48.h
  9. 3
      src/web/RestApi.h
  10. 58
      src/web/html/setup.html
  11. 3
      src/web/web.h

6
src/config/config.h

@ -98,6 +98,9 @@
#ifndef DEF_CMT_IRQ #ifndef DEF_CMT_IRQ
#define DEF_CMT_IRQ 34 #define DEF_CMT_IRQ 34
#endif #endif
#ifndef DEF_MOTION_SENSOR_PIN
#define DEF_MOTION_SENSOR_PIN DEF_PIN_OFF
#endif
#else #else
#ifndef DEF_NRF_CS_PIN #ifndef DEF_NRF_CS_PIN
#define DEF_NRF_CS_PIN 15 #define DEF_NRF_CS_PIN 15
@ -119,6 +122,9 @@
#ifndef DEF_NRF_SCLK_PIN #ifndef DEF_NRF_SCLK_PIN
#define DEF_NRF_SCLK_PIN 14 #define DEF_NRF_SCLK_PIN 14
#endif #endif
#ifndef DEF_MOTION_SENSOR_PIN
#define DEF_MOTION_SENSOR_PIN A0
#endif
#endif #endif
#ifndef DEF_LED0 #ifndef DEF_LED0
#define DEF_LED0 DEF_PIN_OFF #define DEF_LED0 DEF_PIN_OFF

12
src/config/settings.h

@ -164,7 +164,7 @@ typedef struct {
typedef struct { typedef struct {
uint8_t type; uint8_t type;
bool pwrSaveAtIvOffline; bool pwrSaveAtIvOffline;
bool pxShift; uint8_t screenSaver;
uint8_t rot; uint8_t rot;
//uint16_t wakeUp; //uint16_t wakeUp;
//uint16_t sleepAt; //uint16_t sleepAt;
@ -175,6 +175,7 @@ typedef struct {
uint8_t disp_reset; uint8_t disp_reset;
uint8_t disp_busy; uint8_t disp_busy;
uint8_t disp_dc; uint8_t disp_dc;
uint8_t pirPin;
} display_t; } display_t;
typedef struct { typedef struct {
@ -458,7 +459,7 @@ class settings {
mCfg.plugin.display.pwrSaveAtIvOffline = false; mCfg.plugin.display.pwrSaveAtIvOffline = false;
mCfg.plugin.display.contrast = 60; mCfg.plugin.display.contrast = 60;
mCfg.plugin.display.pxShift = true; mCfg.plugin.display.screenSaver = 1; // default: 1 .. pixelshift for OLED for downward compatibility
mCfg.plugin.display.rot = 0; mCfg.plugin.display.rot = 0;
mCfg.plugin.display.disp_data = DEF_PIN_OFF; // SDA mCfg.plugin.display.disp_data = DEF_PIN_OFF; // SDA
mCfg.plugin.display.disp_clk = DEF_PIN_OFF; // SCL mCfg.plugin.display.disp_clk = DEF_PIN_OFF; // SCL
@ -466,6 +467,7 @@ class settings {
mCfg.plugin.display.disp_reset = DEF_PIN_OFF; mCfg.plugin.display.disp_reset = DEF_PIN_OFF;
mCfg.plugin.display.disp_busy = DEF_PIN_OFF; mCfg.plugin.display.disp_busy = DEF_PIN_OFF;
mCfg.plugin.display.disp_dc = DEF_PIN_OFF; mCfg.plugin.display.disp_dc = DEF_PIN_OFF;
mCfg.plugin.display.pirPin = DEF_MOTION_SENSOR_PIN;
} }
void loadAddedDefaults() { void loadAddedDefaults() {
@ -672,7 +674,7 @@ class settings {
JsonObject disp = obj.createNestedObject("disp"); JsonObject disp = obj.createNestedObject("disp");
disp[F("type")] = mCfg.plugin.display.type; disp[F("type")] = mCfg.plugin.display.type;
disp[F("pwrSafe")] = (bool)mCfg.plugin.display.pwrSaveAtIvOffline; disp[F("pwrSafe")] = (bool)mCfg.plugin.display.pwrSaveAtIvOffline;
disp[F("pxShift")] = (bool)mCfg.plugin.display.pxShift; disp[F("screenSaver")] = mCfg.plugin.display.screenSaver;
disp[F("rotation")] = mCfg.plugin.display.rot; disp[F("rotation")] = mCfg.plugin.display.rot;
//disp[F("wake")] = mCfg.plugin.display.wakeUp; //disp[F("wake")] = mCfg.plugin.display.wakeUp;
//disp[F("sleep")] = mCfg.plugin.display.sleepAt; //disp[F("sleep")] = mCfg.plugin.display.sleepAt;
@ -683,11 +685,12 @@ class settings {
disp[F("reset")] = mCfg.plugin.display.disp_reset; disp[F("reset")] = mCfg.plugin.display.disp_reset;
disp[F("busy")] = mCfg.plugin.display.disp_busy; disp[F("busy")] = mCfg.plugin.display.disp_busy;
disp[F("dc")] = mCfg.plugin.display.disp_dc; disp[F("dc")] = mCfg.plugin.display.disp_dc;
disp[F("pirPin")] = mCfg.plugin.display.pirPin;
} else { } else {
JsonObject disp = obj["disp"]; JsonObject disp = obj["disp"];
getVal<uint8_t>(disp, F("type"), &mCfg.plugin.display.type); getVal<uint8_t>(disp, F("type"), &mCfg.plugin.display.type);
getVal<bool>(disp, F("pwrSafe"), &mCfg.plugin.display.pwrSaveAtIvOffline); getVal<bool>(disp, F("pwrSafe"), &mCfg.plugin.display.pwrSaveAtIvOffline);
getVal<bool>(disp, F("pxShift"), &mCfg.plugin.display.pxShift); getVal<uint8_t>(disp, F("screenSaver"), &mCfg.plugin.display.screenSaver);
getVal<uint8_t>(disp, F("rotation"), &mCfg.plugin.display.rot); getVal<uint8_t>(disp, F("rotation"), &mCfg.plugin.display.rot);
//mCfg.plugin.display.wakeUp = disp[F("wake")]; //mCfg.plugin.display.wakeUp = disp[F("wake")];
//mCfg.plugin.display.sleepAt = disp[F("sleep")]; //mCfg.plugin.display.sleepAt = disp[F("sleep")];
@ -698,6 +701,7 @@ class settings {
getVal<uint8_t>(disp, F("reset"), &mCfg.plugin.display.disp_reset); getVal<uint8_t>(disp, F("reset"), &mCfg.plugin.display.disp_reset);
getVal<uint8_t>(disp, F("busy"), &mCfg.plugin.display.disp_busy); getVal<uint8_t>(disp, F("busy"), &mCfg.plugin.display.disp_busy);
getVal<uint8_t>(disp, F("dc"), &mCfg.plugin.display.disp_dc); getVal<uint8_t>(disp, F("dc"), &mCfg.plugin.display.disp_dc);
getVal<uint8_t>(disp, F("pirPin"), &mCfg.plugin.display.pirPin);
} }
} }

32
src/plugins/Display/Display.h

@ -53,9 +53,20 @@ class Display {
default: mMono = NULL; break; default: mMono = NULL; break;
} }
if(mMono) { if(mMono) {
mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast); mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->screenSaver, mCfg->contrast);
mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, &mDisplayData); mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, &mDisplayData);
} }
// setup PIR pin for motion sensor
#ifdef ESP32
if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF))
pinMode(mCfg->pirPin, INPUT);
#endif
#ifdef ESP8266
if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF) && (mCfg->pirPin != A0))
pinMode(mCfg->pirPin, INPUT);
#endif
} }
void payloadEventListener(uint8_t cmd) { void payloadEventListener(uint8_t cmd) {
@ -64,12 +75,12 @@ class Display {
void tickerSecond() { void tickerSecond() {
if (mMono != NULL) if (mMono != NULL)
mMono->loop(mCfg->contrast); mMono->loop(mCfg->contrast, motionSensorActive());
if (mNewPayload || (((++mLoopCnt) % 5) == 0)) { if (mNewPayload || (((++mLoopCnt) % 5) == 0)) {
DataScreen();
mNewPayload = false; mNewPayload = false;
mLoopCnt = 0; mLoopCnt = 0;
DataScreen();
} }
#if defined(ESP32) #if defined(ESP32)
mEpaper.tickerSecond(); mEpaper.tickerSecond();
@ -158,6 +169,21 @@ class Display {
#endif #endif
} }
bool motionSensorActive() {
if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) {
#if defined(ESP8266)
if (mCfg->pirPin == A0)
return((analogRead(A0) >= 512));
else
return(digitalRead(mCfg->pirPin));
#elif defined(ESP32)
return(digitalRead(mCfg->pirPin));
#endif
}
else
return(false);
}
// approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) ) // approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) )
int8_t ivQuality2RadioRSSI(int8_t invQuality) { int8_t ivQuality2RadioRSSI(int8_t invQuality) {
int8_t pseudoRSSIdB; int8_t pseudoRSSIdB;

46
src/plugins/Display/Display_Mono.h

@ -18,16 +18,49 @@
#endif #endif
#include "../../utils/helper.h" #include "../../utils/helper.h"
#include "Display_data.h" #include "Display_data.h"
#include "../../utils/dbg.h"
class DisplayMono { class DisplayMono {
public: public:
DisplayMono() {}; 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 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, bool enScreenSaver, uint8_t lum) = 0; virtual void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum) = 0;
virtual void loop(uint8_t lum) = 0;
virtual void disp(void) = 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 void loop(uint8_t lum, bool motion) {
bool dispConditions = (!mEnPowerSave || (mDisplayData->nrProducing > 0)) &&
((mScreenSaver != 2) || motion); // screensaver 2 .. motionsensor
if (mDisplayActive) {
if (!dispConditions) {
if ((millis() - mStarttime) > DISP_DEFAULT_TIMEOUT * 1000ul) { // switch display off after timeout
mDisplayActive = false;
mDisplay->setPowerSave(true);
DBGPRINTLN("**** Display off ****");
}
}
else
mStarttime = millis(); // keep display on
}
else {
if (dispConditions) {
mDisplayActive = true; // switch display on
mStarttime = millis();
mDisplay->setPowerSave(false);
DBGPRINTLN("**** Display on ****");
}
}
if(mLuminance != lum) {
mLuminance = lum;
mDisplay->setContrast(mLuminance);
}
}
protected: protected:
U8G2* mDisplay; U8G2* mDisplay;
DisplayData *mDisplayData; DisplayData *mDisplayData;
@ -36,17 +69,17 @@ class DisplayMono {
uint16_t mDispWidth; uint16_t mDispWidth;
uint16_t mDispHeight; uint16_t mDispHeight;
bool mEnPowerSave, mEnScreenSaver; bool mEnPowerSave;
uint8_t mScreenSaver = 1; // 0 .. off; 1 .. pixelShift; 2 .. motionsensor
uint8_t mLuminance; uint8_t mLuminance;
uint8_t mLoopCnt; uint8_t mLoopCnt;
uint8_t mLineXOffsets[5] = {}; uint8_t mLineXOffsets[5] = {};
uint8_t mLineYOffsets[5] = {}; uint8_t mLineYOffsets[5] = {};
uint16_t mDispY;
uint8_t mExtra; uint8_t mExtra;
uint16_t mTimeout; uint32_t mStarttime = millis();
bool mDisplayActive = true; // always start with display on
char mFmtText[DISP_FMT_TEXT_LEN]; char mFmtText[DISP_FMT_TEXT_LEN];
// Common initialization function to be called by subclasses // Common initialization function to be called by subclasses
@ -55,6 +88,7 @@ class DisplayMono {
mType = type; mType = type;
mDisplayData = displayData; mDisplayData = displayData;
mDisplay->begin(); mDisplay->begin();
mDisplay->setPowerSave(false); // always start with display on
mDisplay->setContrast(mLuminance); mDisplay->setContrast(mLuminance);
mDisplay->clearBuffer(); mDisplay->clearBuffer();
mDispWidth = mDisplay->getDisplayWidth(); mDispWidth = mDisplay->getDisplayWidth();

29
src/plugins/Display/Display_Mono_128X32.h

@ -9,17 +9,12 @@
class DisplayMono128X32 : public DisplayMono { class DisplayMono128X32 : public DisplayMono {
public: public:
DisplayMono128X32() : DisplayMono() { DisplayMono128X32() : DisplayMono() {
mEnPowerSave = true;
mEnScreenSaver = true;
mLuminance = 60;
mExtra = 0; mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
} }
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) { void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave; mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver; mScreenSaver = screenSaver;
mLuminance = lum; mLuminance = lum;
} }
@ -33,18 +28,6 @@ class DisplayMono128X32 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void loop(uint8_t lum) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
if(mLuminance != lum) {
mLuminance = lum;
mDisplay->setContrast(mLuminance);
}
}
void disp(void) { void disp(void) {
mDisplay->clearBuffer(); mDisplay->clearBuffer();
@ -53,8 +36,6 @@ class DisplayMono128X32 : public DisplayMono {
mDisplay->setContrast(mLuminance); mDisplay->setContrast(mLuminance);
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) { if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (mDisplayData->totalPower > 999) if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000)); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000));
else else
@ -63,9 +44,6 @@ class DisplayMono128X32 : public DisplayMono {
printText(mFmtText, 0); printText(mFmtText, 0);
} else { } else {
printText("offline", 0); printText("offline", 0);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSave);
} }
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", mDisplayData->totalYieldDay); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", mDisplayData->totalYieldDay);
@ -85,7 +63,6 @@ class DisplayMono128X32 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
mDispY = 0;
mExtra++; mExtra++;
} }
@ -131,7 +108,7 @@ class DisplayMono128X32 : public DisplayMono {
void printText(const char *text, uint8_t line) { void printText(const char *text, uint8_t line) {
setFont(line); setFont(line);
uint8_t dispX = mLineXOffsets[line] + ((mEnScreenSaver) ? (mExtra % 7) : 0); uint8_t dispX = mLineXOffsets[line] + ((mScreenSaver==1) ? (mExtra % 7) : 0);
if (isTwoRowLine(line)) { if (isTwoRowLine(line)) {
String stringText = String(text); String stringText = String(text);

82
src/plugins/Display/Display_Mono_128X64.h

@ -9,17 +9,12 @@
class DisplayMono128X64 : public DisplayMono { class DisplayMono128X64 : public DisplayMono {
public: public:
DisplayMono128X64() : DisplayMono() { DisplayMono128X64() : DisplayMono() {
mEnPowerSave = true;
mEnScreenSaver = true;
mLuminance = 60;
mExtra = 0; mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
} }
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) { void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave; mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver; mScreenSaver = screenSaver;
mLuminance = lum; mLuminance = lum;
} }
@ -45,41 +40,29 @@ class DisplayMono128X64 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void loop(uint8_t lum) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
if(mLuminance != lum) {
mLuminance = lum;
mDisplay->setContrast(mLuminance);
}
}
void disp(void) { void disp(void) {
uint8_t pos, sun_pos, moon_pos; uint8_t pos, sun_pos, moon_pos;
// Test
/*
mDisplayData->isSleeping = 1;
mDisplayData->isProducing = 0;
mDisplayData->totalPower = 10000;
mDisplayData->totalYieldDay = 4998;
mDisplayData->totalYieldTotal = 5321;
*/
mDisplay->clearBuffer(); mDisplay->clearBuffer();
// Layout-Test
/*
mDisplayData->nrSleeping = 10;
mDisplayData->nrProducing = 10;
mDisplayData->totalPower = 99990;
mDisplayData->totalYieldDay = 8888;
mDisplayData->totalYieldTotal = 9999;
mDisplay->drawPixel(0, 0);
mDisplay->drawPixel(mDispWidth-1, 0);
mDisplay->drawPixel(0, mDispHeight-1);
mDisplay->drawPixel(mDispWidth-1, mDispHeight-1);
*/
// set Contrast of the Display to raise the lifetime // set Contrast of the Display to raise the lifetime
mDisplay->setContrast(mLuminance); mDisplay->setContrast(mLuminance);
// print total power // print total power
if (mDisplayData->nrProducing > 0) { if (mDisplayData->nrProducing > 0) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (mDisplayData->totalPower > 999) if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (mDisplayData->totalPower / 1000)); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (mDisplayData->totalPower / 1000));
else else
@ -87,9 +70,6 @@ class DisplayMono128X64 : public DisplayMono {
printText(mFmtText, l_TotalPower, 0xff); printText(mFmtText, l_TotalPower, 0xff);
} else { } else {
printText("offline", l_TotalPower, 0xff); printText("offline", l_TotalPower, 0xff);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSave);
} }
// print Date and time // print Date and time
@ -119,9 +99,9 @@ class DisplayMono128X64 : public DisplayMono {
} }
else { else {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2d", mDisplayData->nrProducing); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2d", mDisplayData->nrProducing);
sun_pos = mDisplay->getStrWidth(mFmtText); sun_pos = mDisplay->getStrWidth(mFmtText) + 1;
snprintf(mFmtText+2, DISP_FMT_TEXT_LEN, " %2d", mDisplayData->nrSleeping); snprintf(mFmtText+2, DISP_FMT_TEXT_LEN, " %2d", mDisplayData->nrSleeping);
moon_pos = mDisplay->getStrWidth(mFmtText); moon_pos = mDisplay->getStrWidth(mFmtText) + 1;
snprintf(mFmtText+7, DISP_FMT_TEXT_LEN, " "); snprintf(mFmtText+7, DISP_FMT_TEXT_LEN, " ");
} }
printText(mFmtText, l_Status, 0xff); printText(mFmtText, l_Status, 0xff);
@ -129,20 +109,21 @@ class DisplayMono128X64 : public DisplayMono {
pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2; pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2;
mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy); mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy);
if (sun_pos!=-1) if (sun_pos!=-1)
mDisplay->drawStr(pos+sun_pos, mLineYOffsets[l_Status], "G"); // sun mDisplay->drawStr(pos + sun_pos + pixelshift(), mLineYOffsets[l_Status], "G"); // sun
if (moon_pos!=-1) if (moon_pos!=-1)
mDisplay->drawStr(pos+moon_pos, mLineYOffsets[l_Status], "H"); // moon mDisplay->drawStr(pos + moon_pos + pixelshift(), mLineYOffsets[l_Status], "H"); // moon
} }
// print yields // print yields
mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy);
mDisplay->drawStr(15 + pixelshift(), mLineYOffsets[l_YieldDay], "I"); // day
mDisplay->drawStr(15 + pixelshift(), mLineYOffsets[l_YieldTotal], "D"); // total
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.0f Wh", mDisplayData->totalYieldDay); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, l_YieldDay, 25); printText(mFmtText, l_YieldDay, 25);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.1f kWh", mDisplayData->totalYieldTotal); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.1f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, l_YieldTotal, 25); printText(mFmtText, l_YieldTotal, 25);
mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy);
mDisplay->drawStr(11, mLineYOffsets[l_YieldDay], "I"); // day
mDisplay->drawStr(11, mLineYOffsets[l_YieldTotal], "D"); // total
if (mScreenSaver != 1 ) { // not practical for pixel shift screensaver
// draw dynamic RSSI bars // draw dynamic RSSI bars
int rssi_bar_height = 9; int rssi_bar_height = 9;
for (int i=0; i<4;i++) { for (int i=0; i<4;i++) {
@ -153,7 +134,6 @@ class DisplayMono128X64 : public DisplayMono {
if (mDisplayData->WifiRSSI > wifi_rssi_threshold) if (mDisplayData->WifiRSSI > wifi_rssi_threshold)
mDisplay->drawBox(mDispWidth-4+i, 8+(rssi_bar_height+1)*i, 4-i,rssi_bar_height); mDisplay->drawBox(mDispWidth-4+i, 8+(rssi_bar_height+1)*i, 4-i,rssi_bar_height);
} }
// draw dynamic antenna and WiFi symbols // draw dynamic antenna and WiFi symbols
mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy); mDisplay->setFont(u8g2_font_ncenB10_symbols10_ahoy);
char sym[]=" "; char sym[]=" ";
@ -166,19 +146,10 @@ class DisplayMono128X64 : public DisplayMono {
sym[0] = mDisplayData->WifiSymbol?'B':'F'; // Wifi sym[0] = mDisplayData->WifiSymbol?'B':'F'; // Wifi
mDisplay->drawStr(mDispWidth - mDisplay->getStrWidth(sym), mLineYOffsets[l_RSSI], sym); mDisplay->drawStr(mDispWidth - mDisplay->getStrWidth(sym), mLineYOffsets[l_RSSI], sym);
mDisplay->sendBuffer(); mDisplay->sendBuffer();
}
mExtra++;
/* // just for test
mDisplay->drawPixel(0, 0);
mDisplay->drawPixel(mDispWidth-1, 0);
mDisplay->drawPixel(0, mDispHeight-1);
mDisplay->drawPixel(mDispWidth-1, mDispHeight-1);
*/
mDisplay->sendBuffer(); mDisplay->sendBuffer();
mDispY = 0;
mExtra++; mExtra++;
} }
@ -218,6 +189,11 @@ class DisplayMono128X64 : public DisplayMono {
} while(l_MAX_LINES>i); } while(l_MAX_LINES>i);
} }
inline int8_t pixelshift(void) {
int8_t range = 11; // number of pixels to shift from left to right (centered)
return(mScreenSaver == 1 ? (mExtra % range - range/2) : 0);
}
inline void setLineFont(uint8_t line) { inline void setLineFont(uint8_t line) {
if ((line == l_TotalPower) || if ((line == l_TotalPower) ||
(line == l_Ahoy)) (line == l_Ahoy))
@ -232,12 +208,12 @@ class DisplayMono128X64 : public DisplayMono {
void printText(const char *text, uint8_t line, uint8_t col=0) { void printText(const char *text, uint8_t line, uint8_t col=0) {
uint8_t dispX; uint8_t dispX;
setLineFont(line); setLineFont(line);
if (0xff == col) if (0xff == col)
dispX = (mDispWidth - mDisplay->getStrWidth(text)) / 2; // center text dispX = (mDispWidth - mDisplay->getStrWidth(text)) / 2; // center text
else else
dispX = col; dispX = col;
dispX += pixelshift();
mDisplay->drawStr(dispX, mLineYOffsets[line], text); mDisplay->drawStr(dispX, mLineYOffsets[line], text);
} }
}; };

29
src/plugins/Display/Display_Mono_64X48.h

@ -9,17 +9,12 @@
class DisplayMono64X48 : public DisplayMono { class DisplayMono64X48 : public DisplayMono {
public: public:
DisplayMono64X48() : DisplayMono() { DisplayMono64X48() : DisplayMono() {
mEnPowerSave = true;
mEnScreenSaver = false;
mLuminance = 20;
mExtra = 0; mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
} }
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) { void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave; mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver; mScreenSaver = screenSaver;
mLuminance = lum; mLuminance = lum;
} }
@ -34,18 +29,6 @@ class DisplayMono64X48 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void loop(uint8_t lum) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
if(mLuminance != lum) {
mLuminance = lum;
mDisplay->setContrast(mLuminance);
}
}
void disp(void) { void disp(void) {
mDisplay->clearBuffer(); mDisplay->clearBuffer();
@ -53,9 +36,6 @@ class DisplayMono64X48 : public DisplayMono {
mDisplay->setContrast(mLuminance); mDisplay->setContrast(mLuminance);
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) { if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (mDisplayData->totalPower > 999) if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000)); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000));
else else
@ -64,9 +44,6 @@ class DisplayMono64X48 : public DisplayMono {
printText(mFmtText, 0); printText(mFmtText, 0);
} else { } else {
printText("offline", 0); printText("offline", 0);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSave);
} }
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "D: %4.0f Wh", mDisplayData->totalYieldDay); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "D: %4.0f Wh", mDisplayData->totalYieldDay);
@ -119,7 +96,7 @@ class DisplayMono64X48 : public DisplayMono {
void printText(const char *text, uint8_t line) { void printText(const char *text, uint8_t line) {
uint8_t dispX = 0; //small display, use all we have uint8_t dispX = 0; //small display, use all we have
dispX += (mEnScreenSaver) ? (mExtra % 4) : 0; dispX += (mScreenSaver==1) ? (mExtra % 4) : 0;
setFont(line); setFont(line);
mDisplay->drawStr(dispX, mLineYOffsets[line], text); mDisplay->drawStr(dispX, mLineYOffsets[line], text);
} }

27
src/plugins/Display/Display_Mono_84X48.h

@ -10,17 +10,12 @@
class DisplayMono84X48 : public DisplayMono { class DisplayMono84X48 : public DisplayMono {
public: public:
DisplayMono84X48() : DisplayMono() { DisplayMono84X48() : DisplayMono() {
mEnPowerSave = true;
mEnScreenSaver = true;
mLuminance = 140;
mExtra = 0; mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
} }
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) { void config(bool enPowerSave, uint8_t screenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave; mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver; mScreenSaver = screenSaver;
mLuminance = lum; mLuminance = lum;
} }
@ -34,18 +29,6 @@ class DisplayMono84X48 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void loop(uint8_t lum) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
if(mLuminance != lum) {
mLuminance = lum;
mDisplay->setContrast(mLuminance);
}
}
void disp(void) { void disp(void) {
mDisplay->clearBuffer(); mDisplay->clearBuffer();
@ -65,9 +48,6 @@ class DisplayMono84X48 : public DisplayMono {
// print total power // print total power
if (mDisplayData->nrProducing > 0) { if (mDisplayData->nrProducing > 0) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (mDisplayData->totalPower > 9999) if (mDisplayData->totalPower > 9999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2fkW", (mDisplayData->totalPower / 1000)); // forgo spacing between value and SI unit in favor of second position after decimal point snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2fkW", (mDisplayData->totalPower / 1000)); // forgo spacing between value and SI unit in favor of second position after decimal point
else if (mDisplayData->totalPower > 999) else if (mDisplayData->totalPower > 999)
@ -78,9 +58,6 @@ class DisplayMono84X48 : public DisplayMono {
printText(mFmtText, l_TotalPower, 0xff); printText(mFmtText, l_TotalPower, 0xff);
} else { } else {
printText("offline", l_TotalPower, 0xff); printText("offline", l_TotalPower, 0xff);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSave);
} }
// print Date and time // print Date and time

3
src/web/RestApi.h

@ -578,7 +578,7 @@ class RestApi {
void getDisplay(JsonObject obj) { void getDisplay(JsonObject obj) {
obj[F("disp_typ")] = (uint8_t)mConfig->plugin.display.type; obj[F("disp_typ")] = (uint8_t)mConfig->plugin.display.type;
obj[F("disp_pwr")] = (bool)mConfig->plugin.display.pwrSaveAtIvOffline; obj[F("disp_pwr")] = (bool)mConfig->plugin.display.pwrSaveAtIvOffline;
obj[F("disp_pxshift")] = (bool)mConfig->plugin.display.pxShift; obj[F("disp_screensaver")] = (uint8_t)mConfig->plugin.display.screenSaver;
obj[F("disp_rot")] = (uint8_t)mConfig->plugin.display.rot; obj[F("disp_rot")] = (uint8_t)mConfig->plugin.display.rot;
obj[F("disp_cont")] = (uint8_t)mConfig->plugin.display.contrast; obj[F("disp_cont")] = (uint8_t)mConfig->plugin.display.contrast;
obj[F("disp_clk")] = (mConfig->plugin.display.type == 0) ? DEF_PIN_OFF : mConfig->plugin.display.disp_clk; obj[F("disp_clk")] = (mConfig->plugin.display.type == 0) ? DEF_PIN_OFF : mConfig->plugin.display.disp_clk;
@ -587,6 +587,7 @@ class RestApi {
obj[F("disp_dc")] = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : mConfig->plugin.display.disp_dc; obj[F("disp_dc")] = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : mConfig->plugin.display.disp_dc;
obj[F("disp_rst")] = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : mConfig->plugin.display.disp_reset; obj[F("disp_rst")] = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : mConfig->plugin.display.disp_reset;
obj[F("disp_bsy")] = (mConfig->plugin.display.type < 10) ? DEF_PIN_OFF : mConfig->plugin.display.disp_busy; obj[F("disp_bsy")] = (mConfig->plugin.display.type < 10) ? DEF_PIN_OFF : mConfig->plugin.display.disp_busy;
obj[F("pir_pin")] = mConfig->plugin.display.pirPin;
} }
void getMqttInfo(JsonObject obj) { void getMqttInfo(JsonObject obj) {

58
src/web/html/setup.html

@ -278,16 +278,14 @@
<div class="col-8 col-sm-3">Turn off while inverters are offline</div> <div class="col-8 col-sm-3">Turn off while inverters are offline</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="disp_pwr"/></div> <div class="col-4 col-sm-9"><input type="checkbox" name="disp_pwr"/></div>
</div> </div>
<div class="row mb-3"> <div id="screenSaver"></div>
<div class="col-8 col-sm-3">Enable Screensaver (pixel shifting, OLED only)</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="disp_pxshift"/></div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12 col-sm-3 my-2">Luminance</div> <div class="col-12 col-sm-3 my-2">Luminance</div>
<div class="col-12 col-sm-9"><input type="number" name="disp_cont" min="0" max="255"></select></div> <div class="col-12 col-sm-9"><input type="number" name="disp_cont" min="0" max="255"></select></div>
</div> </div>
<p class="des">Pinout</p> <p class="des">Pinout</p>
<div id="dispPins"></div> <div id="dispPins"></div>
<div id="pirPin"></div>
</fieldset> </fieldset>
</div> </div>
@ -946,17 +944,17 @@
} }
function parseDisplay(obj, type, system) { function parseDisplay(obj, type, system) {
for(var i of ["disp_pwr", "disp_pxshift"]) for(var i of ["disp_pwr"])
document.getElementsByName(i)[0].checked = obj[i]; document.getElementsByName(i)[0].checked = obj[i];
var e = document.getElementById("dispPins"); var dpins_elem = document.getElementById("dispPins");
//KEEP this order !!! //KEEP this order !!!
var pins = [['clock', 'disp_clk'], ['data', 'disp_data'], ['cs', 'disp_cs'], ['dc', 'disp_dc'], ['reset', 'disp_rst']]; var pins = [['clock', 'disp_clk'], ['data', 'disp_data'], ['cs', 'disp_cs'], ['dc', 'disp_dc'], ['reset', 'disp_rst']];
/*IF_ESP32*/ /*IF_ESP32*/
pins.push(['busy', 'disp_bsy']); pins.push(['busy', 'disp_bsy']);
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
for(p of pins) { for(p of pins) {
e.append( dpins_elem.append(
ml("div", {class: "row mb-3", id: "row_" + p[1]}, [ ml("div", {class: "row mb-3", id: "row_" + p[1]}, [
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
ml("div", {class: "col-12 col-sm-9"}, ml("div", {class: "col-12 col-sm-9"},
@ -965,23 +963,18 @@
]) ])
); );
} }
// keep display types grouped // keep display types grouped
var opts = [[0, "None"], [2, "SH1106 1.3\" 128X64"], [5, "SSD1306 0.66\" 64X48 (Wemos OLED Shield)"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [6, "SSD1309 2.42\" 128X64"], [3, "Nokia5110"]]; var opts = [[0, "None"], [2, "SH1106 1.3\" 128X64"], [5, "SSD1306 0.66\" 64X48 (Wemos OLED Shield)"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [6, "SSD1309 2.42\" 128X64"], [3, "Nokia5110"]];
/*IF_ESP32*/ /*IF_ESP32*/
opts.push([10, "ePaper"]); opts.push([10, "ePaper"]);
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
var dispType = sel("disp_typ", opts, obj["disp_typ"]); var dtype_sel = sel("disp_typ", opts, obj["disp_typ"]);
document.getElementById("dispType").append( document.getElementById("dispType").append(
ml("div", {class: "row mb-3"}, [ ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-12 col-sm-3 my-2"}, "Type"), ml("div", {class: "col-12 col-sm-3 my-2"}, "Type"),
ml("div", {class: "col-12 col-sm-9"}, dispType) ml("div", {class: "col-12 col-sm-9"}, dtype_sel)
]) ])
); );
dispType.addEventListener('change', (e) => {
hideDispPins(pins, parseInt(e.target.value))
});
opts = [[0, "0&deg;"], [2, "180&deg;"]]; opts = [[0, "0&deg;"], [2, "180&deg;"]];
/*IF_ESP32*/ /*IF_ESP32*/
opts.push([1, "90&deg;"]); opts.push([1, "90&deg;"]);
@ -994,7 +987,35 @@
]) ])
); );
var opts1 = [[0, "off"], [1, "pixel shift"], [2, "motion sensor"]];
var screensaver_sel = sel("disp_screensaver", opts1, obj["disp_screensaver"]);
screensaver_sel.id = 'disp_screensaver';
document.getElementById("screenSaver").append(
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-12 col-sm-3 my-2"}, "Screensaver (OLED only)"),
ml("div", {class: "col-12 col-sm-9"}, screensaver_sel)
])
);
var esp8266pirpins = [[255, "off / default"],
[17, "A0"]];
document.getElementById("pirPin").append(
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-12 col-sm-3 my-2"}, "PIR sensor"),
ml("div", {class: "col-12 col-sm-9"}, sel("pir_pin", ("ESP8266" == type) ? esp8266pirpins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj["pir_pin"]))
])
);
document.getElementsByName("disp_cont")[0].value = obj["disp_cont"]; document.getElementsByName("disp_cont")[0].value = obj["disp_cont"];
dtype_sel.addEventListener('change', function(e) {
hideDispPins(pins, parseInt(e.target.value))
});
document.getElementById("disp_screensaver").addEventListener('change', function(e) {
hideDispPins(pins, parseInt(dtype_sel.value))
});
hideDispPins(pins, obj.disp_typ); hideDispPins(pins, obj.disp_typ);
} }
@ -1021,6 +1042,15 @@
cl.add("hide"); cl.add("hide");
} }
} }
var screenSaver = document.getElementById("disp_screensaver").value;
if (2==screenSaver) { // show pir pin only for motion screensaver
setHide("pirPin", false);
}
else { // no pir pin for all others
setHide("pirPin", true);
}
} }
function tick() { function tick() {

3
src/web/web.h

@ -565,7 +565,7 @@ class Web {
// display // display
mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("disp_pwr") == "on"); mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("disp_pwr") == "on");
mConfig->plugin.display.pxShift = (request->arg("disp_pxshift") == "on"); mConfig->plugin.display.screenSaver = request->arg("disp_screensaver").toInt();
mConfig->plugin.display.rot = request->arg("disp_rot").toInt(); mConfig->plugin.display.rot = request->arg("disp_rot").toInt();
mConfig->plugin.display.type = request->arg("disp_typ").toInt(); mConfig->plugin.display.type = request->arg("disp_typ").toInt();
mConfig->plugin.display.contrast = (mConfig->plugin.display.type == 0) ? 60 : request->arg("disp_cont").toInt(); mConfig->plugin.display.contrast = (mConfig->plugin.display.type == 0) ? 60 : request->arg("disp_cont").toInt();
@ -575,6 +575,7 @@ class Web {
mConfig->plugin.display.disp_reset = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : request->arg("disp_rst").toInt(); mConfig->plugin.display.disp_reset = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : request->arg("disp_rst").toInt();
mConfig->plugin.display.disp_dc = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : request->arg("disp_dc").toInt(); mConfig->plugin.display.disp_dc = (mConfig->plugin.display.type < 3) ? DEF_PIN_OFF : request->arg("disp_dc").toInt();
mConfig->plugin.display.disp_busy = (mConfig->plugin.display.type < 10) ? DEF_PIN_OFF : request->arg("disp_bsy").toInt(); mConfig->plugin.display.disp_busy = (mConfig->plugin.display.type < 10) ? DEF_PIN_OFF : request->arg("disp_bsy").toInt();
mConfig->plugin.display.pirPin = request->arg("pir_pin").toInt();
mApp->saveSettings((request->arg("reboot") == "on")); mApp->saveSettings((request->arg("reboot") == "on"));

Loading…
Cancel
Save