Fix how chart smoothing handles angular value averages; move smoothing calculation of data from chart function to history buffer, because new method needs too much time in chart function

This commit is contained in:
Ulrich Meine
2026-07-06 22:44:52 +02:00
parent e757ac4016
commit e129b18057
3 changed files with 23 additions and 49 deletions
+13 -38
View File
@@ -28,11 +28,6 @@ Chart::Chart(RingBuffer<uint16_t>& dataBuf, CommonData& common, bool useSimuData
dHeight = getdisplay().height();
#endif
smoothCharts = commonData->config->getBool(commonData->config->smoothCharts);
if (smoothCharts) {
chrtAvg.begin();
}
init();
};
@@ -51,7 +46,7 @@ bool Chart::init()
dbMIN_VAL = dataBuf.getMinVal();
dbMAX_VAL = dataBuf.getMaxVal();
bufSize = dataBuf.getCapacity();
LOG_DEBUG(GwLog::DEBUG, "Chart Init: dbMIN_VAL: %.2f, dbMAX_VAL: %.2fd, bufSize: %d", dbMIN_VAL, dbMAX_VAL, bufSize);
// LOG_DEBUG(GwLog::DEBUG, "Chart Init: dbMIN_VAL: %.2f, dbMAX_VAL: %.2fd, bufSize: %d", dbMIN_VAL, dbMAX_VAL, bufSize);
// Initialize chart data format; shorter version of standard format indicator
if (dbFormat == "formatCourse" || dbFormat == "formatWind") {
@@ -214,7 +209,7 @@ void Chart::drawChrt(const ChrtDir chrtDir, const int8_t chrtIntv, GwApi::BoatVa
// LOG_DEBUG(GwLog::DEBUG, "Chart:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f", chrtMin, chrtMid, chrtMax, chrtRng);
calcChrtBorders(chrtMin, chrtMid, chrtMax, chrtRng);
chrtScale = double(valAxis) / chrtRng; // Chart scale: pixels per value step
LOG_DEBUG(GwLog::DEBUG, "Chart:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f, data valid: %d", chrtMin, chrtMid, chrtMax, chrtRng, currValue.valid);
// LOG_DEBUG(GwLog::DEBUG, "Chart:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f, data valid: %d", chrtMin, chrtMid, chrtMax, chrtRng, currValue.valid);
// Do we have valid buffer data?
if (dataBuf.getMax() == dbMAX_VAL) { // only <MAX_VAL> values in buffer -> no valid wind data available
@@ -285,7 +280,6 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
rngMid = 0;
} else {
rngMid = std::round(rngMid / rngStep) * rngStep; // round new center value to next <rngStep> value
}
recalcRngMid = false; // Reset flag for <rngMid> determination
@@ -359,23 +353,6 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
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
@@ -384,10 +361,6 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
chrtPrevVal = dbMAX_VAL;
} else {
if (smoothCharts) {
chrtVal = chrtAvg.reading(chrtVal); // if chart lines shall be smoothed, apply moving average filter of the last 10 values
}
point = setChartPoint(i, chrtDir, chrtVal, chrtScale);
// if (i >= (numBufVals / chrtIntv) - 5) // log chart data of x lines (adjust for test purposes)
// LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %.2f, chrtMin: %.2f, {x,y} {%d,%d}", i, chrtVal, chrtMin, point.x, point.y);
@@ -419,12 +392,14 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
}
}
// test position of chart point against chart middle
double d = WindUtils::toPI(chrtVal - chrtMid);
if (d > 0) // point is right of mid point
allLeft = false;
if (d < 0) // point is left of mid point
allRight = false;
// test position of chart point against chart middle; ignore first values which we don't show next time anyway
if (i > MIN_FREE_VALUES) {
double d = WindUtils::toPI(chrtVal - chrtMid);
if (d > 0) // point is right of mid point
allLeft = false;
if (d < 0) // point is left of mid point
allRight = false;
}
}
if (chrtDataFmt == DEPTH) {
@@ -446,11 +421,11 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
oldChrtIntv = 0; // force reset of buffer start and number of values to show in next display loop
if (chrtDataFmt == WIND) { // degree of course or wind
if (allLeft || allRight) {
if (allLeft || allRight || chrtRng == M_PI) {
recalcRngMid = true;
}
LOG_DEBUG(GwLog::DEBUG, "OBPcharts: WIND chart end: timAxis: %d, i: %d, bufStart: %d, numBufVals: %d, recalcRngCntr: %d, allLeft: %d, allRight: %d", timAxis, i, bufStart,
numBufVals, recalcRngMid, allLeft, allRight);
// LOG_DEBUG(GwLog::DEBUG, "OBPcharts: WIND chart end: timAxis: %d, i: %d, bufStart: %d, numBufVals: %d, recalcRngCntr: %d, allLeft: %d, allRight: %d", timAxis, i, bufStart,
// numBufVals, recalcRngMid, allLeft, allRight);
allLeft = true; // reset marker for all left/right chart points
allRight = true;
}
-2
View File
@@ -106,9 +106,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
// Default ranges for various boat data types
+10 -9
View File
@@ -462,6 +462,13 @@ void OBP60Task(GwApi *api){
WindUtils trueWind(&boatValues, logger); // Create helper object for true wind calculation
CalibrationData calibrationDataList(logger); // all boat data types which are supposed to be calibrated
// Read user settings from config file
bool calcTrueWnds = api->getConfig()->getBool(api->getConfig()->calcTrueWnds, false);
bool smoothCharts = api->getConfig()->getBool(api->getConfig()->smoothCharts, false);
bool useSimuData = api->getConfig()->getBool(api->getConfig()->useSimuData, false);
// Read user calibration data settings from config file
calibrationDataList.readConfig(config);
//fill the page data from config
numPages=config->getInt(config->visiblePages,1);
if (numPages < 1) numPages=1;
@@ -507,7 +514,7 @@ void OBP60Task(GwApi *api){
if (pages[i].parameters.pageName == "OneValue" || pages[i].parameters.pageName == "TwoValues"
|| pages[i].parameters.pageName == "WindPlot" || pages[i].parameters.pageName == "Weather") {
for (auto pVal : pages[i].parameters.values) {
hstryBufferList.addBuffer(pVal->getName());
hstryBufferList.addBuffer(pVal->getName(), smoothCharts);
}
}
// Add list of history buffers to page parameters
@@ -517,12 +524,6 @@ void OBP60Task(GwApi *api){
// add out of band system page (always available)
Page *syspage = allPages.pages[0]->creator(commonData);
// Read user settings from config file
bool calcTrueWnds = api->getConfig()->getBool(api->getConfig()->calcTrueWnds, false);
bool useSimuData = api->getConfig()->getBool(api->getConfig()->useSimuData, false);
// Read user calibration data settings from config file
calibrationDataList.readConfig(config);
// Display screenshot handler for HTTP request
// http://192.168.15.1/api/user/OBP60Task/screenshot
api->registerRequestHandler("screenshot", [api, &pageNumber, pages](AsyncWebServerRequest *request) {
@@ -848,12 +849,12 @@ void OBP60Task(GwApi *api){
api->getBoatDataValues(boatValues.numValues,boatValues.allBoatValues);
api->getStatus(commonData.status);
// ulong startHndl = millis();
// ulong startHandl = millis();
trueWind.handleWinds(calcTrueWnds); // calculate true wind data from apparent wind values
trueWind.setMaxWs(); // maintain MaxTWS value in any case; invalid TWS value is considered automatically
calibrationDataList.handleCalibration(&boatValues); // Process calibration for all boat data in <calibrationDataList>
hstryBufferList.handleHstryBufs(useSimuData, commonData); // Handle history buffers for certain boat data for charts and other usage
// LOG_DEBUG(GwLog::DEBUG, "obp60task: data handling: %d ms", millis() - startHndl);
// LOG_DEBUG(GwLog::DEBUG, "obp60task: data handling: %d ms", millis() - startHandl);
// Clear display
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);