diff --git a/lib/obp60task/OBPDataOperations.cpp b/lib/obp60task/OBPDataOperations.cpp index eca2fe9..ad04e50 100644 --- a/lib/obp60task/OBPDataOperations.cpp +++ b/lib/obp60task/OBPDataOperations.cpp @@ -83,24 +83,26 @@ bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal, { double stw, hdt, ctw; double twd, tws, twa; + double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor static const double DBL_MIN = std::numeric_limits::lowest(); + Serial.println("\ncalcTrueWind: HDT: " + String(*hdtVal) + ", HDM: " + String(*hdmVal) + ", VAR: " + String(*varVal) + ", SOG: " + String(*sogVal) + ", COG: " + String(*cogVal)); if (*hdtVal != DBL_MIN) { hdt = *hdtVal; // Use HDT if available } else { - if (*hdmVal != DBL_MIN && *varVal != DBL_MIN) { - hdt = *hdmVal + *varVal; // Use corrected HDM if HDT is not available + if (*hdmVal != DBL_MIN) { + hdt = *hdmVal + (*varVal != DBL_MIN ? *varVal : 0.0); // Use corrected HDM if HDT is not available (or just HDM if VAR is not available) hdt = to2PI(hdt); - } else if (*cogVal != DBL_MIN) { - hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available + } else if (*cogVal != DBL_MIN && *sogVal >= minSogVal) { + hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available, and SOG is not data noise } else { return false; // Cannot calculate without valid HDT or HDM+VAR or COG } } - if (*cogVal != DBL_MIN) { - ctw = *cogVal; // Use COG as CTW if available - // ctw = *cogVal + ((*cogVal - hdt) / 2); // Estimate CTW from COG + if (*cogVal != DBL_MIN && *sogVal >= minSogVal ) { // if SOG is data noise, we don't trust COG + + ctw = *cogVal; // Use COG for CTW if available } else { ctw = hdt; // 2nd approximation for CTW; hdt must exist if we reach this part of the code } @@ -113,6 +115,7 @@ bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal, // If STW and SOG are not available, we cannot calculate true wind return false; } + Serial.println("\ncalcTrueWind: HDT: " + String(hdt) + ", CTW: " + String(ctw) + ", STW: " + String(stw)); if ((*awaVal == DBL_MIN) || (*awsVal == DBL_MIN)) { // Cannot calculate true wind without valid AWA, AWS; other checks are done earlier @@ -140,15 +143,12 @@ void HstryBuf::fillWndBufSimData(tBoatHstryData& hstryBufs) } } -/* double genTwdSimDat() +/* void HstryBuf::simWndDir(double &wndDir) { - simTwd += random(-20, 20); - if (simTwd < 0.0) - simTwd += 360.0; - if (simTwd >= 360.0) - simTwd -= 360.0; + wndDir += random(-20, 20); + wndDir = WindUtils::to360(wndDir); - int16_t z = static_cast(DegToRad(simTwd) * 1000.0); + int16_t z = static_cast(DegToRad(wndDir) * 1000.0); pageData.boatHstry.twdHstry->add(z); // Fill the buffer with some test data simTws += random(-200, 150) / 10.0; // TWS value in knots diff --git a/lib/obp60task/PageWindPlot.cpp b/lib/obp60task/PageWindPlot.cpp index 5255320..f1f056a 100644 --- a/lib/obp60task/PageWindPlot.cpp +++ b/lib/obp60task/PageWindPlot.cpp @@ -118,7 +118,7 @@ public: GwConfigHandler* config = commonData->config; GwLog* logger = commonData->logger; - float twsValue; // TWS value in chart area +// float twsValue; // TWS value in chart area static String twdName, twdUnit; // TWD name and unit static int updFreq; // Update frequency for TWD static int16_t twdLowest, twdHighest; // TWD range @@ -161,7 +161,7 @@ public: static int wndRight; // chart wind right value position static int chrtRng; // Range of wind values from mid wind value to min/max wind value in degrees int diffRng; // Difference between mid and current wind value - static const int dfltRng = 40; // Default range for chart + static const int dfltRng = 60; // Default range for chart int midWndDir; // New value for wndCenter after chart start / shift static int simTwd; // Simulation value for TWD static float simTws; // Simulation value for TWS @@ -189,7 +189,7 @@ public: numNoData = 0; simTwd = pageData.boatHstry.twdHstry->getLast() / 1000.0 * radToDeg; simTws = 0; - twsValue = 0; +// twsValue = 0; bufStart = 0; oldDataIntv = 0; numAddedBufVals, currIdx, lastIdx = 0; @@ -264,6 +264,7 @@ public: } else if (diffRng + 10 < chrtRng) { // Reduce chart range for higher resolution if possible chrtRng = max(dfltRng, int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10); } + LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Range adjust: wndCenter: %d, diffRng: %d, chrtRng: %d", wndCenter, diffRng, chrtRng); } chrtScl = float(width) / float(chrtRng) / 2.0; // Chart scale: pixels per degree wndLeft = wndCenter - chrtRng; @@ -331,8 +332,7 @@ public: x = ((chrtVal - wndLeft + 360) % 360) * chrtScl; y = yOffset + cHeight - i; // Position in chart area -// if (i >= (numWndVals / dataIntv) - 10) - if (i >= (numWndVals / dataIntv) - 1) + if (i >= (numWndVals / dataIntv) - 1) // log chart data for 1 or more lines LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %d, bufStart: %d, count: %d, linesToShow: %d", i, chrtVal, bufStart, count, (numWndVals / dataIntv)); if ((i == 0) || (chrtPrevVal == INT16_MIN)) { @@ -367,8 +367,11 @@ public: int minWndDir = pageData.boatHstry.twdHstry->getMin(numWndVals) / 1000.0 * radToDeg; int maxWndDir = pageData.boatHstry.twdHstry->getMax(numWndVals) / 1000.0 * radToDeg; LOG_DEBUG(GwLog::DEBUG, "PageWindPlot FreeTop: Minimum: %d, Maximum: %d, OldwndCenter: %d", minWndDir, maxWndDir, wndCenter); -// if ((minWndDir + 540 >= wndCenter + 540) || (maxWndDir + 540 <= wndCenter + 540)) { - if (((minWndDir - wndCenter >= 0) && (minWndDir - wndCenter < 180)) || ((maxWndDir - wndCenter <= 0) && (maxWndDir - wndCenter >=180))) { + // if (((minWndDir - wndCenter >= 0) && (minWndDir - wndCenter < 180)) || ((maxWndDir - wndCenter <= 0) && (maxWndDir - wndCenter >=180))) { + if ((wndRight > wndCenter && (minWndDir >= wndCenter && minWndDir <= wndRight)) || + (wndRight <= wndCenter && (minWndDir >= wndCenter || minWndDir <= wndRight)) || + (wndLeft < wndCenter && (maxWndDir <= wndCenter && maxWndDir >= wndLeft)) || + (wndLeft >= wndCenter && (maxWndDir <= wndCenter || maxWndDir >= wndLeft))) { // Check if all wind value are left or right of center value -> optimize chart range midWndDir = pageData.boatHstry.twdHstry->getMid(numWndVals) / 1000.0 * radToDeg; if (midWndDir != INT16_MIN) { @@ -396,7 +399,7 @@ public: int xPosTws; static const int yPosTws = yOffset + 40; - twsValue = pageData.boatHstry.twsHstry->getLast() / 10.0 * 1.94384; // TWS value in knots +// twsValue = pageData.boatHstry.twsHstry->getLast() / 10.0 * 1.94384; // TWS value in knots xPosTws = flipTws ? 20 : width - 138; currentZone = (y >= yPosTws - 38) && (y <= yPosTws + 6) && (x >= xPosTws - 4) && (x <= xPosTws + 146) ? 1 : 0; // Define current zone for TWS value @@ -424,12 +427,12 @@ public: } getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(xPosTws + 82, yPosTws - 14); -// getdisplay().print("TWS"); // Name + // getdisplay().print("TWS"); // Name getdisplay().print(BDataName[1]); // Name getdisplay().setFont(&Ubuntu_Bold8pt8b); -// getdisplay().setCursor(xPosTws + 78, yPosTws + 1); + // getdisplay().setCursor(xPosTws + 78, yPosTws + 1); getdisplay().setCursor(xPosTws + 82, yPosTws + 1); -// getdisplay().printf(" kn"); // Unit + // getdisplay().printf(" kn"); // Unit getdisplay().print(BDataUnit[1]); // Unit } @@ -472,7 +475,7 @@ PageDescription registerPageWindPlot( createPage, // Action 0, // Number of bus values depends on selection in Web configuration { "TWD", "TWS" }, // Bus values we need in the page -// {}, // Bus values we need in the page + // {}, // Bus values we need in the page true // Show display header on/off ); diff --git a/lib/obp60task/obp60task.cpp b/lib/obp60task/obp60task.cpp index 3ee638b..3c65cf0 100644 --- a/lib/obp60task/obp60task.cpp +++ b/lib/obp60task/obp60task.cpp @@ -404,7 +404,7 @@ bool addTrueWind(GwApi* api, BoatValueList* boatValues) { hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MIN; hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MIN; varVal = varBVal->valid ? varBVal->value : DBL_MIN; - api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.1f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852, + api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.2f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852, cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, sogBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG); isCalculated = WindUtils::calcTrueWind(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twd, &tws, &twa); @@ -423,7 +423,7 @@ bool addTrueWind(GwApi* api, BoatValueList* boatValues) { twaBVal->valid = true; } } - api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: TWD_Valid %d, isCalculated %d, TWD %.1f, TWA %.1f, TWS %.1f", twdBVal->valid, isCalculated, twdBVal->value * RAD_TO_DEG, + api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: TWD_isValid %d, isCalculated %d, TWD %.1f, TWA %.1f, TWS %.1f", twdBVal->valid, isCalculated, twdBVal->value * RAD_TO_DEG, twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852); return isCalculated; @@ -463,8 +463,8 @@ void handleHstryBuf(GwApi* api, BoatValueList* boatValues, tBoatHstryData hstryB GwApi::BoatValue *twsBVal = boatValues->findValueOrCreate(hstryBufList.twsHstry->getName()); GwApi::BoatValue *twaBVal = boatValues->findValueOrCreate("TWA"); - api->getLogger()->logDebug(GwLog::DEBUG,"obp60task handleHstryBuf: twdBVal: %.1f, twaBVal: %.1f, twsBVal: %.1f, TWD_isValid? %d", twdBVal->value * RAD_TO_DEG, - twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852, twdBVal->valid); + api->getLogger()->logDebug(GwLog::DEBUG,"obp60task handleHstryBuf: TWD_isValid? %d, twdBVal: %.1f, twaBVal: %.1f, twsBVal: %.1f", twdBVal->valid, twdBVal->value * RAD_TO_DEG, + twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852); calBVal = new GwApi::BoatValue("TWD"); // temporary solution for calibration of history buffer values calBVal->setFormat(twdBVal->getFormat()); if (twdBVal->valid) {