tweak diagram

This commit is contained in:
Rob0xFF 2024-05-03 22:12:38 +02:00
parent 891cc26583
commit efb38cc423
7 changed files with 136 additions and 47 deletions

61
.vscode/settings.json vendored
View File

@ -1,3 +1,60 @@
{
"C_Cpp.clang_format_style": "WebKit"
}
"C_Cpp.clang_format_style": "WebKit",
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
}
}

View File

@ -19,6 +19,7 @@ public:
private:
void averageLoop();
void dataPointLoop();
void resetDataPoints();
uint32_t getSecondsPerDot();
@ -33,4 +34,5 @@ private:
float _iRunningAverage = 0;
uint16_t _iRunningAverageCnt = 0;
uint32_t _daySeconds = 0;
};

View File

@ -11,6 +11,7 @@ public:
void init(Scheduler& scheduler);
bool isDayPeriod() const;
uint32_t dayPeriodLength() const;
bool isSunsetAvailable() const;
bool sunsetTime(struct tm* info) const;
bool sunriseTime(struct tm* info) const;

View File

@ -31,8 +31,8 @@ const uint8_t languages[] = {
static const char* const i18n_offline[] = { "Offline", "OFFLINE", "Offline" };
static const char* const i18n_current_power_w[] = { "%.1f W", "%.1f W", "%.1f W" };
static const char* const i18n_current_power_kw[] = { "%.1f kW", "%.1f kW", "%.1f kW" };
static const char* const i18n_current_power_w[] = { "%.1f W", "%.1f W", "%.1f W" };
static const char* const i18n_current_power_kw[] = { "%.1f kW", "%.1f kW", "%.1f kW" };
static const char* const i18n_yield_today_wh[] = { "today: %.0f Wh", "Heute: %.0f Wh", "auj.: %.0f Wh" };
static const char* const i18n_yield_today_kwh[] = { "today: %.1f kWh", "Heute: %.1f kWh", "auj.: %.1f kWh" };
@ -189,7 +189,7 @@ void DisplayGraphicClass::loop()
case DiagramMode_t::Fullscreen:
// Every 10 seconds
if (_mExtra % (10 * 2) < 10) {
_diagram.redraw(screenSaverOffsetX, 10, 0, _display->getDisplayWidth() - 12, _display->getDisplayHeight() - 3, true);
_diagram.redraw(screenSaverOffsetX, 0, 0, _display->getDisplayWidth(), _display->getDisplayHeight(), true);
showText = false;
}
break;

View File

@ -5,6 +5,7 @@
#include "Display_Graphic_Diagram.h"
#include "Configuration.h"
#include "Datastore.h"
#include "SunPosition.h"
#include <algorithm>
DisplayGraphicDiagramClass::DisplayGraphicDiagramClass()
@ -30,6 +31,14 @@ void DisplayGraphicDiagramClass::averageLoop()
const float currentWatts = Datastore.getTotalAcPowerEnabled(); // get the current AC production
_iRunningAverage += currentWatts;
_iRunningAverageCnt++;
if(SunPosition.dayPeriodLength() == 0) { // noch keine Uhrzeit oder ein neuer tag
_graphValuesCount = 0;
} else {
if(SunPosition.dayPeriodLength() != _daySeconds) { // neue Tageslänge
updatePeriod();
_daySeconds = SunPosition.dayPeriodLength();
}
}
}
void DisplayGraphicDiagramClass::dataPointLoop()
@ -47,20 +56,26 @@ void DisplayGraphicDiagramClass::dataPointLoop()
}
}
void DisplayGraphicDiagramClass::resetDataPoints()
{
}
uint32_t DisplayGraphicDiagramClass::getSecondsPerDot()
{
return Configuration.get().Display.Diagram.Duration / _chartWidth;
return SunPosition.dayPeriodLength() / _chartWidth;
}
void DisplayGraphicDiagramClass::updatePeriod()
{
// Calculate seconds per datapoint
_dataPointTask.setInterval(Configuration.get().Display.Diagram.Duration * TASK_SECOND / MAX_DATAPOINTS);
_dataPointTask.setInterval(SunPosition.dayPeriodLength() * TASK_SECOND / MAX_DATAPOINTS);
}
void DisplayGraphicDiagramClass::redraw(uint8_t screenSaverOffsetX, uint8_t xPos, uint8_t yPos, uint8_t width, uint8_t height, bool isFullscreen)
{
_chartWidth = width;
Serial.println(SunPosition.dayPeriodLength());
// screenSaverOffsetX expected to be in range 0..6
const uint8_t graphPosX = xPos + ((screenSaverOffsetX > 3) ? 1 : 0);
@ -69,58 +84,52 @@ void DisplayGraphicDiagramClass::redraw(uint8_t screenSaverOffsetX, uint8_t xPos
const uint8_t horizontal_line_y = graphPosY + height - 1;
const uint8_t arrow_size = 2;
const float maxWatts = Datastore.getTotalDcIrradiationInstalled();//*std::max_element(_graphValues.begin(), _graphValues.end());
// draw diagram axis
_display->drawVLine(graphPosX, graphPosY, height);
_display->drawHLine(graphPosX, horizontal_line_y, width);
//_display->drawHLine(graphPosX, horizontal_line_y, width);
if (!isFullscreen) {
_display->drawVLine(graphPosX, graphPosY, height);
// UP-arrow
_display->drawLine(graphPosX, graphPosY, graphPosX + arrow_size, graphPosY + arrow_size);
_display->drawLine(graphPosX, graphPosY, graphPosX - arrow_size, graphPosY + arrow_size);
// UP-arrow
_display->drawLine(graphPosX, graphPosY, graphPosX + arrow_size, graphPosY + arrow_size);
_display->drawLine(graphPosX, graphPosY, graphPosX - arrow_size, graphPosY + arrow_size);
// LEFT-arrow
_display->drawLine(graphPosX + width - 1, horizontal_line_y, graphPosX + width - 1 - arrow_size, horizontal_line_y - arrow_size);
_display->drawLine(graphPosX + width - 1, horizontal_line_y, graphPosX + width - 1 - arrow_size, horizontal_line_y + arrow_size);
// LEFT-arrow
_display->drawLine(graphPosX + width - 1, horizontal_line_y, graphPosX + width - 1 - arrow_size, horizontal_line_y - arrow_size);
_display->drawLine(graphPosX + width - 1, horizontal_line_y, graphPosX + width - 1 - arrow_size, horizontal_line_y + arrow_size);
// draw AC value
char fmtText[7];
const float maxWatts = *std::max_element(_graphValues.begin(), _graphValues.end());
if (maxWatts > 999) {
snprintf(fmtText, sizeof(fmtText), "%2.1fkW", maxWatts / 1000);
} else {
snprintf(fmtText, sizeof(fmtText), "%dW", static_cast<uint16_t>(maxWatts));
}
if (isFullscreen) {
_display->setFont(u8g2_font_5x8_tr);
_display->setFontDirection(3);
_display->drawStr(graphPosX - arrow_size, graphPosY + _display->getStrWidth(fmtText), fmtText);
_display->setFontDirection(0);
} else {
// 4 pixels per char
// draw AC value
char fmtText[7];
if (maxWatts > 999) {
snprintf(fmtText, sizeof(fmtText), "%2.1fkW", maxWatts / 1000);
} else {
snprintf(fmtText, sizeof(fmtText), "%dW", static_cast<uint16_t>(maxWatts));
}
_display->setFont(u8g2_font_tom_thumb_4x6_mr);
_display->drawStr(graphPosX - arrow_size - _display->getStrWidth(fmtText), graphPosY + 5, fmtText);
}
else {
float wattsToday = Datastore.getTotalAcYieldDayEnabled();
char * text = new char[10]();
if (wattsToday > 999) {
snprintf(text, 10, "%.0fkWh" , wattsToday / 1000);
} else {
snprintf(text, 10, "%.0fWh", wattsToday);
}
_display->setFont(u8g2_font_unifont_t_0_76);
_display->drawUTF8(0, 16, text);
}
// draw chart
const float scaleFactorY = maxWatts / static_cast<float>(height);
const float scaleFactorX = static_cast<float>(MAX_DATAPOINTS) / static_cast<float>(_chartWidth);
if (maxWatts > 0 && isFullscreen) {
// draw y axis ticks
const uint16_t yAxisWattPerTick = maxWatts <= 100 ? 10 : maxWatts <= 1000 ? 100
: maxWatts < 5000 ? 500
: 1000;
const uint8_t yAxisTickSizePixel = height / (maxWatts / yAxisWattPerTick);
for (int16_t tickYPos = graphPosY + height; tickYPos > graphPosY - arrow_size; tickYPos -= yAxisTickSizePixel) {
_display->drawPixel(graphPosX - 1, tickYPos);
}
}
uint8_t xAxisTicks = 1;
for (uint8_t i = 1; i < _graphValuesCount; i++) {
Serial.println(_graphValuesCount);
for (uint8_t i = 0; i < _graphValuesCount; i++) {
// draw one tick per hour to the x-axis
if (i * getSecondsPerDot() > (3600u * xAxisTicks)) {
if (!isFullscreen && i * getSecondsPerDot() > (3600u * xAxisTicks)) {
_display->drawPixel((graphPosX + 1 + i) * scaleFactorX, graphPosY + height);
xAxisTicks++;
}
@ -130,7 +139,7 @@ void DisplayGraphicDiagramClass::redraw(uint8_t screenSaverOffsetX, uint8_t xPos
}
_display->drawLine(
graphPosX + (i - 1) / scaleFactorX, horizontal_line_y - std::max<int16_t>(0, _graphValues[i - 1] / scaleFactorY - 0.5),
graphPosX + i / scaleFactorX, horizontal_line_y - std::max<int16_t>(0, _graphValues[i] / scaleFactorY - 0.5));
graphPosX + i / scaleFactorX, horizontal_line_y - std::max<int16_t>(0, _graphValues[i] / scaleFactorY - 0.5),
graphPosX + i / scaleFactorX, horizontal_line_y);
}
}

View File

@ -0,0 +1,12 @@
{
"folders": [
{
"path": "../../NerdMiner_v2"
},
{
"name": "OpenDTU",
"path": ".."
}
],
"settings": {}
}

View File

@ -39,6 +39,14 @@ bool SunPositionClass::isDayPeriod() const
return (minutesPastMidnight >= _sunriseMinutes) && (minutesPastMidnight < _sunsetMinutes);
}
uint32_t SunPositionClass::dayPeriodLength() const
{
if (!_isValidInfo) {
return 0;
}
return (60 * (_sunsetMinutes - _sunriseMinutes));
}
bool SunPositionClass::isSunsetAvailable() const
{
return _isSunsetAvailable;