Skip to content

Commit

Permalink
add fonts with symbols to ahoy project and add WLAN RSSI bar to 84x48
Browse files Browse the repository at this point in the history
  • Loading branch information
You69Man committed Sep 10, 2023
1 parent f1bff0b commit bf0f118
Show file tree
Hide file tree
Showing 26 changed files with 2,292 additions and 60 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ This work is licensed under a

This repository offers hardware and software solutions for communicating with Hoymiles inverters via radio. With our system, you can easily obtain real-time values such as power, current, and daily energy. Additionally, you can set parameters like the power limit of your inverter to achieve zero export. You can access these functionalities through our user-friendly web interface, MQTT, or JSON. Whether you're monitoring your solar panel system's performance or fine-tuning its settings, our solutions make it easy to achieve your goals.

This fork aims to improve the display layouts of several low-res displays, starting with the Nokia5110.

Current status of progress:
- improved layout with additional fixed headline for day of week, date and time, and centered text (already merged in lumapu >=0.7.34)
- improved 5x8 pixel font (some glyphes like dot and zero were deformed) and enhanced by ahoy specific symbols
- added sun and moon symbols with values that show number of producing and sleeping inverters (working)
- added calender and sigma symbols for YieldDay and YieldTotal
- added symbol for WiFi and MQTT that indicates WiFi and MQTT connection status (working)
- added RSSI bar for WiFi (working)
- added symbol für NRF24 that indicates if radio board is connected (working)
- added RSSI bar for NRF24 (basically working but currently only fed by inverter status due to missing RSSI value of NRF24. This should be improved in the future by using transition package heuristics)

![alt text](https://github.com/You69Man/ahoy/blob/feature/fancy_nokia/pics/PXL_20230824_204200660.jpg?raw=true)


There is also already a working implementation for OLED 128x64, with a bit of a higher font and symbol resolution.
The reason why this is not published at the moment is that OLEDs tend to quickly burn-in. Moving the screen content is no option for this layout because the layout is very well optimized and so pixels would quickly move off-screen. The only option would be to limit the on-time of the display by a means to activate it, e.g. a button or a sensor. This however would require a free GPIO pin, which are already rare on EPS8266... Other Ideas welcome!

![alt text](https://github.com/You69Man/ahoy/blob/feature/fancy_nokia/pics/PXL_20230901_061927908.jpg?raw=true)



Table of approaches:

| Board | MI | HM | HMS/HMT | comment | HowTo start |
Expand Down
Binary file added pics/PXL_20230824_204200660.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pics/PXL_20230901_061927908.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 13 additions & 7 deletions src/plugins/Display/Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class Display {
if (mMono != NULL)
mMono->loop(mCfg->contrast);

if (mNewPayload || (((++mLoopCnt) % 30) == 0)) {
if (mNewPayload || (((++mLoopCnt) % 10) == 0)) {
mNewPayload = false;
mLoopCnt = 0;
DataScreen();
Expand All @@ -85,7 +85,8 @@ class Display {
float totalYieldDay = 0;
float totalYieldTotal = 0;

uint8_t isprod = 0;
uint8_t nrprod = 0;
uint8_t nrsleep = 0;

Inverter<> *iv;
record_t<> *rec;
Expand All @@ -96,21 +97,26 @@ class Display {
continue;

if (iv->isProducing())
isprod++;
nrprod++;
else
nrsleep++;

totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec);
}

// prepare display data
mDisplayData.isProducing = isprod;
mDisplayData.nrProducing = nrprod;
mDisplayData.nrSleeping = nrsleep;
mDisplayData.totalPower = totalPower;
mDisplayData.totalYieldDay = totalYieldDay;
mDisplayData.totalYieldTotal = totalYieldTotal;
mDisplayData.RadioSymbol = mHmRadio->isChipConnected();
mDisplayData.wifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN;
mDisplayData.WiFiSymbol = (WiFi.status() == WL_CONNECTED);
mDisplayData.WifiSymbol = (WiFi.status() == WL_CONNECTED);
mDisplayData.MQTTSymbol = mApp->getMqttIsConnected();
mDisplayData.RadioRSSI = (0 < mDisplayData.nrProducing) ? 0 : SCHAR_MIN; // Workaround as NRF24 has no RSSI. Could be approximated by transmisson error heuristic in the future
mDisplayData.WifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN;
mDisplayData.ipAddress = WiFi.localIP();
time_t utc= mApp->getTimestamp();
if (year(utc) > 2020)
Expand All @@ -123,7 +129,7 @@ class Display {
}
#if defined(ESP32)
else if (mCfg->type == 10) {
mEpaper.loop(totalPower, totalYieldDay, totalYieldTotal, isprod);
mEpaper.loop(totalPower, totalYieldDay, totalYieldTotal, nrprod);
mRefreshCycle++;
}

Expand Down
68 changes: 67 additions & 1 deletion src/plugins/Display/Display_Mono.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,70 @@ class DisplayMono {
mDispWidth = mDisplay->getDisplayWidth();
mDispHeight = mDisplay->getDisplayHeight();
}
};
};

/* 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 */
const uint8_t u8g2_font_5x8_symbols_ahoy[1052] 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\3 \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"
"I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b"
"\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244"
"\60\2,\7\63\275\32\245\4-\6\24\324\212!.\6\42\305\212!/\10d\304\272R[\6\60\14d"
"\304\32%R\206DJ\24\0\61\10c\305\232Dj\31\62\13d\304\32%\312\22%\33\2\63\13d\304"
"\212!\212D)Q\0\64\13d\304\252H\251\14Q\226\0\65\12d\304\212A\33\245D\1\66\13d\304"
"\32%[\42)Q\0\67\13d\304\212!\213\262(\213\0\70\14d\304\32%J\224HJ\24\0\71\13"
"d\304\32%\222\222-Q\0:\10R\305\212!\32\2;\10c\275\32\243R\2<\10c\305\252\244\224"
"\25=\10\64\314\212!\34\2>\11c\305\212\254\224\224\0?\11c\305\232\246$M\0@\15\205\274*"
")\222\226DI\244\252\2A\12d\304\32%\222\206I\12B\14d\304\212%\32\222H\32\22\0C\12"
"d\304\32%\322J\211\2D\12d\304\212%r\32\22\0E\12d\304\212A[\262l\10F\12d\304"
"\212A[\262\32\0G\13d\304\32%\322\222)Q\0H\12d\304\212H\32&S\0I\10c\305\212"
"%j\31J\12d\304\232)\253\224\42\0K\13d\304\212HI\244\244S\0L\10d\304\212\254\333\20"
"M\12d\304\212h\70D\246\0N\12d\304\212h\31\226I\12O\12d\304\32%rJ\24\0P\13"
"d\304\212%\222\206$\313\0Q\12t\274\32%\222\26\307\0R\13d\304\212%\222\206$\222\2S\14"
"d\304\32%J\302$J\24\0T\11e\304\212A\12;\1U\11d\304\212\310S\242\0V\12d\304"
"\212\310)\221\24\0W\12d\304\212\310\64\34\242\0X\13d\304\212HJ$%\222\2Y\12e\304\212"
"LKja\11Z\12d\304\212!\213\332\206\0[\10c\305\212!j\32\134\10d\304\212,l\13]"
"\10c\305\212\251i\10^\6#\345\232\6_\6\24\274\212!`\6\42\345\212(a\11D\304\232!\222"
"\222\1b\13d\304\212,[\42iH\0c\7C\305\232)\23d\12d\304\272\312\20I\311\0e\11"
"D\304\32%\31\262\1f\12d\304\252Ji\312\42\0g\12T\274\32%J\266D\1h\12d\304\212"
",[\42S\0i\10c\305\232P\252\14j\12s\275\252\64\212\224\12\0k\12d\304\212\254\64$\221"
"\24l\10c\305\12\251\313\0m\12E\304\12\245EI\224\2n\10D\304\212%\62\5o\11D\304\32"
"%\222\22\5p\12T\274\212%\32\222,\3q\11T\274\232!J\266\2r\11D\304\212$\261e\0"
"s\10C\305\232![\0t\13d\304\232,\232\262$J\0u\10D\304\212\310\224\14v\10C\305\212"
"\304R\1w\12E\304\212LI\224.\0x\11D\304\212(\221\224(y\13T\274\212HJ\206(Q"
"\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61"
"\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f"
"D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220"
"\26\207A\204\16\205\274\212,)%Y\230%QR\13\205\17\206<\213\60\31\22\311\66D\245!\11\3"
"\206\20\210<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w"
"<\214\203RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0";


const uint8_t u8g2_font_ncenB08_symbols8_ahoy[173] U8G2_FONT_SECTION("u8g2_font_ncenB08_symbols8_ahoy") =
"\13\0\3\2\4\4\1\2\5\10\11\0\0\10\0\10\0\0\0\0\0\0\224A\14\207\305\70H\321\222H"
"k\334\6B\20\230\305\32\262\60\211\244\266\60T\243\34\326\0C\20\210\305S\243\60\312\302(\214\302("
"L\342\0D\16\210\315\70(i\224#\71\20W\207\3E\15\207\305xI\206\323\232nIS\1F\25"
"\230\305H\206\244\230$C\22\15Y\242\204j\224\205I$\5G\17\210\305*\16\321%\214\302d:\204"
"Q\4H\14w\307\215Uq\33\16\321\20\1I\21\227\305\311\222aP\245H\221\244H\212\324a\20J"
"\5\0\275\0K\5\0\315\0\0\0\0";

const uint8_t u8g2_font_ncenB10_symbols10_ahoy[207] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") =
"\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\266A\15\267\212q\220\42\251\322"
"\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243"
"\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\22\267\212\361\222\14I\242"
"\14\332\232\216[RJ\232\12F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30"
"\273\312W\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210"
"\16\354\300<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x"
"\10J\5\0\232\1K\5\0\232\1\0\0\0";

10 changes: 5 additions & 5 deletions src/plugins/Display/Display_Mono_128X32.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class DisplayMono128X32 : public DisplayMono {
if (3 != mType)
mDisplay->setContrast(mLuminance);

if ((mDisplayData->totalPower > 0) && (mDisplayData->isProducing > 0)) {
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (mDisplayData->totalPower > 999)
Expand All @@ -78,7 +78,7 @@ class DisplayMono128X32 : public DisplayMono {
if (!(mExtra % 10) && (ip))
printText(ip.toString().c_str(), 3);
else if (!(mExtra % 5)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", mDisplayData->isProducing);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", mDisplayData->nrProducing);
printText(mFmtText, 3);
} else if (0 != mDisplayData->utcTs)
printText(ah::getTimeStr(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), 3);
Expand Down Expand Up @@ -106,13 +106,13 @@ class DisplayMono128X32 : public DisplayMono {
inline void setFont(uint8_t line) {
switch (line) {
case 0:
mDisplay->setFont(u8g2_font_9x15_tf);
mDisplay->setFont(u8g2_font_9x15_tr);
break;
case 3:
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf);
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tr);
break;
default:
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf);
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tr);
break;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/Display/Display_Mono_128X64.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class DisplayMono128X64 : public DisplayMono {
// set Contrast of the Display to raise the lifetime
mDisplay->setContrast(mLuminance);

if ((mDisplayData->totalPower > 0) && (mDisplayData->isProducing > 0)) {
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);

Expand All @@ -88,7 +88,7 @@ class DisplayMono128X64 : public DisplayMono {
if (!(mExtra % 10) && (ip))
printText(ip.toString().c_str(), 3);
else if (!(mExtra % 5)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", mDisplayData->isProducing);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", mDisplayData->nrProducing);
printText(mFmtText, 3);
} else if (0 != mDisplayData->utcTs)
printText(ah::getDateTimeStr(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), 3);
Expand All @@ -115,7 +115,7 @@ class DisplayMono128X64 : public DisplayMono {
mDisplay->setFont(u8g2_font_ncenB14_tr);
break;
case 3:
mDisplay->setFont(u8g2_font_5x8_tr);
mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);
break;
default:
mDisplay->setFont(u8g2_font_ncenB10_tr);
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/Display/Display_Mono_64X48.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class DisplayMono64X48 : public DisplayMono {
// set Contrast of the Display to raise the lifetime
mDisplay->setContrast(mLuminance);

if ((mDisplayData->totalPower > 0) && (mDisplayData->isProducing > 0)) {
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);

Expand All @@ -79,7 +79,7 @@ class DisplayMono64X48 : public DisplayMono {
if (!(mExtra % 10) && (ip))
printText(ip.toString().c_str(), 3);
else if (!(mExtra % 5)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "active Inv: %d", mDisplayData->isProducing);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "active Inv: %d", mDisplayData->nrProducing);
printText(mFmtText, 3);
} else if (0 != mDisplayData->utcTs)
printText(ah::getTimeStr(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), 3);
Expand All @@ -102,11 +102,11 @@ class DisplayMono64X48 : public DisplayMono {
inline void setFont(uint8_t line) {
switch (line) {
case 0:
mDisplay->setFont(u8g2_font_fur11_tf);
mDisplay->setFont(u8g2_font_fur11_tr);
break;
case 1:
case 2:
mDisplay->setFont(u8g2_font_6x10_tf);
mDisplay->setFont(u8g2_font_6x10_tr);
break;
case 3:
mDisplay->setFont(u8g2_font_4x6_tr);
Expand Down
Loading

0 comments on commit bf0f118

Please sign in to comment.