1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2026-08-18 18:32:30 +02:00

Add smoothing option for any chart plot

This commit is contained in:
Ulrich Meine
2026-03-26 22:08:00 +01:00
parent 1f0e3cb6eb
commit 3deb80b2c6
5 changed files with 55 additions and 5 deletions
+29 -2
View File
@@ -42,6 +42,11 @@ Chart::Chart(RingBuffer<uint16_t>& dataBuf, double dfltRng, CommonData& common,
dbMAX_VAL = dataBuf.getMaxVal();
bufSize = dataBuf.getCapacity();
smoothCharts = common.config->getBool(common.config->smoothCharts);
if (smoothCharts) {
chrtAvg.begin();
}
// Initialize chart data format; shorter version of standard format indicator
if (dbFormat == "formatCourse" || dbFormat == "formatWind" || dbFormat == "formatRot") {
chrtDataFmt = WIND; // Chart is showing data of course / wind <degree> format
@@ -337,6 +342,23 @@ void Chart::drawChartLines(const char direction, const int8_t chrtIntv, const do
double chrtVal; // Current data value
Pos point, prevPoint; // current and previous chart point
if (smoothCharts) {
// prime moving average filter to ensure the first plotted point is already averaged
chrtAvg.reset();
// Feed the filter the 10 values preceding bufStart
for (int p = 10; p > 0; p--) {
// Calculate index with wrapping: (start - offset + size) % size
int primeIdx = (bufStart - (p * chrtIntv));
double primeVal = dataBuf.get(primeIdx);
if (primeVal != dbMAX_VAL) {
chrtAvg.reading(primeVal);
}
}
}
for (int i = 0; i < (numBufVals / chrtIntv); i++) {
chrtVal = dataBuf.get(bufStart + (i * chrtIntv)); // show the latest wind values in buffer; keep 1st value constant in a rolling buffer
@@ -345,6 +367,11 @@ void Chart::drawChartLines(const char direction, const int8_t chrtIntv, const do
chrtPrevVal = dbMAX_VAL;
} else {
if (smoothCharts) {
// if chart lines shall be smoothed, apply moving average filter of the last 10 values
chrtVal = chrtAvg.reading(chrtVal);
}
point = setCurrentChartPoint(i, direction, chrtVal, chrtScale);
// if (i >= (numBufVals / chrtIntv) - 5) // log chart data of 1 line (adjust for test purposes)
@@ -399,7 +426,7 @@ void Chart::drawChartLines(const char direction, const int8_t chrtIntv, const do
if (chrtDataFmt == WIND) { // degree of course or wind
recalcRngMid = true;
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: chart end: timAxis: %d, i: %d, bufStart: %d, numBufVals: %d, recalcRngCntr: %d", timAxis, i, bufStart, numBufVals, recalcRngMid);
// LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: chart end: timAxis: %d, i: %d, bufStart: %d, numBufVals: %d, recalcRngCntr: %d", timAxis, i, bufStart, numBufVals, recalcRngMid);
}
break;
}
@@ -454,7 +481,7 @@ void Chart::drawChrtTimeAxis(const char chrtDir, const int8_t chrtSz, const int8
if (chrtDir == HORIZONTAL) {
getdisplay().fillRect(0, cRoot.y, dWidth, 2, fgColor);
LOG_DEBUG(GwLog::DEBUG, "Chart::drawChrtTimeAxis: intv: %d, axSlots: %d, timAxis: %d, chrtIntv: %d", intv, axSlots, timAxis, chrtIntv);
// LOG_DEBUG(GwLog::DEBUG, "Chart::drawChrtTimeAxis: intv: %d, axSlots: %d, timAxis: %d, chrtIntv: %d", intv, axSlots, timAxis, chrtIntv);
for (int j = intv; j < timAxis - 1; j += intv) { // fill time axis with values but keep area free on right hand side for value label
// draw text with appropriate offset
+3 -2
View File
@@ -2,6 +2,7 @@
#pragma once
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "movingAvg.h"
struct Pos {
int x;
@@ -44,12 +45,11 @@ protected:
static constexpr bool NO_SIMUDATA = true; // switch off simulation feature of <formatValue> function
RingBuffer<uint16_t>& dataBuf; // Buffer to display
//char chrtDir; // Chart timeline direction: 'H' = horizontal, 'V' = vertical
//int8_t chrtSz; // Chart size: [0] = full size, [1] = half size left/top, [2] half size right/bottom
double dfltRng; // Default range of chart, e.g. 30 = [0..30]
uint16_t fgColor; // color code for any screen writing
uint16_t bgColor; // color code for screen background
bool useSimuData; // flag to indicate if simulation data is active
bool smoothCharts; // flag to indicate if charts shall be printed with smoothed gradient
String tempFormat; // user defined format for temperature
double zeroValue; // "0" SI value for temperature
@@ -84,6 +84,7 @@ protected:
bool bufDataValid = false; // Flag to indicate if buffer data is valid
int oldChrtIntv = 0; // remember recent user selection of data interval
movingAvg<double> chrtAvg{7}; // Store average of the last 7 chart values if chart gradient shall be smoothed
double chrtPrevVal; // Last data value in chart area
int x, y; // x and y coordinates for drawing
int prevX, prevY; // Last x and y coordinates for drawing
+1 -1
View File
@@ -37,7 +37,7 @@ private:
bool oldShowTruW = false; // remember recent user selection of wind data type
int8_t dataIntv = 1; // Update interval for wind history chart:
// (1)|(2)|(3)|(4)|(8) x 240 seconds for 4, 8, 12, 16, 32 min. history chart
// (1)|(2)|(3)|(4)|(8) seconds for up to 32 min. history chart
bool useSimuData;
// bool holdValues;
String flashLED;
+11
View File
@@ -230,6 +230,17 @@
"obp40": "true"
}
},
{
"name": "smoothCharts",
"label": "Smooth chart lines",
"type": "boolean",
"default": "false",
"description": "Print chart lines with a smoothed gradient",
"category": "OBP40 Settings",
"capabilities": {
"obp40": "true"
}
},
{
"name": "lengthFormat",
"label": "Length Format",
+11
View File
@@ -230,6 +230,17 @@
"obp60": "true"
}
},
{
"name": "smoothCharts",
"label": "Smooth chart lines",
"type": "boolean",
"default": "false",
"description": "Print chart lines with a smoothed gradient",
"category": "OBP60 Settings",
"capabilities": {
"obp40": "true"
}
},
{
"name": "lengthFormat",
"label": "Length Format",