From ee5077e0a517e025a88be301cd63695759574368 Mon Sep 17 00:00:00 2001 From: Norbert Walter Date: Sat, 7 Feb 2026 16:59:17 +0000 Subject: [PATCH 1/6] Add PageAutopilot --- lib/obp60task/config_obp40.json | 10 ++++++++++ lib/obp60task/config_obp60.json | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/obp60task/config_obp40.json b/lib/obp60task/config_obp40.json index 54a5409..bb58948 100644 --- a/lib/obp60task/config_obp40.json +++ b/lib/obp60task/config_obp40.json @@ -1517,6 +1517,7 @@ "default": "Voltage", "description": "Type of page for page 1", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -1847,6 +1848,7 @@ "default": "WindRose", "description": "Type of page for page 2", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2168,6 +2170,7 @@ "default": "OneValue", "description": "Type of page for page 3", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2480,6 +2483,7 @@ "default": "TwoValues", "description": "Type of page for page 4", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2783,6 +2787,7 @@ "default": "ThreeValues", "description": "Type of page for page 5", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3077,6 +3082,7 @@ "default": "FourValues", "description": "Type of page for page 6", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3362,6 +3368,7 @@ "default": "FourValues2", "description": "Type of page for page 7", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3638,6 +3645,7 @@ "default": "Clock", "description": "Type of page for page 8", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3905,6 +3913,7 @@ "default": "RollPitch", "description": "Type of page for page 9", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -4163,6 +4172,7 @@ "default": "Battery2", "description": "Type of page for page 10", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", diff --git a/lib/obp60task/config_obp60.json b/lib/obp60task/config_obp60.json index 8318af7..12d4681 100644 --- a/lib/obp60task/config_obp60.json +++ b/lib/obp60task/config_obp60.json @@ -1494,6 +1494,7 @@ "default": "Voltage", "description": "Type of page for page 1", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -1794,6 +1795,7 @@ "default": "WindRose", "description": "Type of page for page 2", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2086,6 +2088,7 @@ "default": "OneValue", "description": "Type of page for page 3", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2370,6 +2373,7 @@ "default": "TwoValues", "description": "Type of page for page 4", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2646,6 +2650,7 @@ "default": "ThreeValues", "description": "Type of page for page 5", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2914,6 +2919,7 @@ "default": "FourValues", "description": "Type of page for page 6", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3174,6 +3180,7 @@ "default": "FourValues2", "description": "Type of page for page 7", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3426,6 +3433,7 @@ "default": "Clock", "description": "Type of page for page 8", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3670,6 +3678,7 @@ "default": "RollPitch", "description": "Type of page for page 9", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3906,6 +3915,7 @@ "default": "Battery2", "description": "Type of page for page 10", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", From 99404991a3a60d9bbc3a2ff841a47a15ad8fbfac Mon Sep 17 00:00:00 2001 From: Norbert Walter Date: Sun, 8 Feb 2026 12:40:20 +0000 Subject: [PATCH 2/6] Add rudder bargraf --- lib/obp60task/OBP60Extensions.cpp | 63 ++++++++++++++++++++++++++++++- lib/obp60task/OBP60Extensions.h | 3 ++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 76c6334..57471d4 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -923,7 +923,7 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor){ } -// Generator graphic with fill level +// Generator graphic void generatorGraphic(uint x, uint y, int pcolor, int bcolor){ // Show battery int xb = x; // X position @@ -940,6 +940,67 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){ getdisplay().print("G"); } +// Display rudder position as horizontal bargraph +/-30 degrees +void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg){ + const int w = 300; + const int h = 20; + const int t = 3; // Line thickness + const int halfw = w/2; + const int halfh = h/2; + // Calculate top-left of bar (cx,cy are center of 0°) + int left = int(cx) - halfw; + int top = int(cy) - halfh; + + // Pixels per degree for +/-30° -> 60° span + const float pxPerDeg = float(w) / 60.0f; // =5.0 + + // Draw outer border (thickness t) + for (int i = 0; i < t; i++) { + getdisplay().drawRect(left + i, top + i, w - 2 * i, h - 2 * i, fg); + } + + // Fill inner area with background + getdisplay().fillRect(left + t, top + t, w - 2 * t, h - 2 * t, bg); + + // Clamp rudder position to -30..30 + if (rudderPosition > 30) rudderPosition = 30; + if (rudderPosition < -30) rudderPosition = -30; + + // Compute fill width in pixels + int fillPx = int(round(rudderPosition * pxPerDeg)); // positive -> right + + // Fill area from center to position (if non-zero) + int centerx = cx; + int innerTop = top + t; + int innerH = h - 2 * t; + if (fillPx > 0) { + // Right side + getdisplay().fillRect(centerx, innerTop, fillPx, innerH, fg); + } else if (fillPx < 0) { + // Left side + getdisplay().fillRect(centerx + fillPx, innerTop, -fillPx, innerH, fg); + } + + // Draw tick marks every 5° and labels outside the bar + getdisplay().setTextColor(fg); + getdisplay().setFont(&Ubuntu_Bold8pt8b); + for (int angle = -30; angle <= 30; angle += 5) { + int xpos = int(round(centerx + angle * pxPerDeg)); + // Vertical tick inside bar + getdisplay().drawLine(xpos, top, xpos, top + h, fg); + // Label outside: below the bar + String lbl = String(angle); + lbl += "\u00B0"; // Degree symbol + int16_t bx, by; + uint16_t bw, bh; + getdisplay().getTextBounds(lbl, 0, 0, &bx, &by, &bw, &bh); + int16_t tx = xpos - bw/2; + int16_t ty = top + h + bh + 2; // A little spacing + getdisplay().setCursor(tx, ty); + getdisplay().print(lbl); + } +} + // Function to handle HTTP image request // http://192.168.15.1/api/user/OBP60Task/screenshot void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request) { diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index 604c356..de6db20 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -128,6 +128,9 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor); // S void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic void startLedTask(GwApi *api); +// Display rudder position as horizontal bargraph +/-30 degrees +void displayRudderPosition(int rudderPosition, uint16_t x, uint16_t y, uint16_t fg, uint16_t bg); + void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request); // Icons From 4468c0555b26cf50a33cef2ec01ff1f3d3f5822e Mon Sep 17 00:00:00 2001 From: norbert-walter Date: Sun, 8 Feb 2026 14:09:10 +0100 Subject: [PATCH 3/6] Implement rudder bargraf in PageAutopilot --- lib/obp60task/OBP60Extensions.cpp | 7 +++---- lib/obp60task/PageAutopilot.cpp | 26 +++++++++++++++----------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 57471d4..5b3d278 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -942,7 +942,7 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){ // Display rudder position as horizontal bargraph +/-30 degrees void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg){ - const int w = 300; + const int w = 360; const int h = 20; const int t = 3; // Line thickness const int halfw = w/2; @@ -987,15 +987,14 @@ void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_ for (int angle = -30; angle <= 30; angle += 5) { int xpos = int(round(centerx + angle * pxPerDeg)); // Vertical tick inside bar - getdisplay().drawLine(xpos, top, xpos, top + h, fg); + getdisplay().drawLine(xpos, top, xpos, top + h + 2, fg); // Label outside: below the bar String lbl = String(angle); - lbl += "\u00B0"; // Degree symbol int16_t bx, by; uint16_t bw, bh; getdisplay().getTextBounds(lbl, 0, 0, &bx, &by, &bw, &bh); int16_t tx = xpos - bw/2; - int16_t ty = top + h + bh + 2; // A little spacing + int16_t ty = top + h + bh + 5; // A little spacing getdisplay().setCursor(tx, ty); getdisplay().print(lbl); } diff --git a/lib/obp60task/PageAutopilot.cpp b/lib/obp60task/PageAutopilot.cpp index 6cbf299..f5161f5 100644 --- a/lib/obp60task/PageAutopilot.cpp +++ b/lib/obp60task/PageAutopilot.cpp @@ -21,8 +21,9 @@ const int ShowDTW = 7; const int ShowBTW = 8; const int Compass_X0 = 200; // X center point of compass band -const int Compass_Y0 = 220; // Y position of compass lines -const int Compass_LineLength = 22; // Length of compass lines +const int Compass_Y0 = 90; // Y position of compass lines +//const int Compass_LineLength = 22; // Length of compass lines +const int Compass_LineLength = 15; // Length of compass lines const float Compass_LineDelta = 8.0;// Compass band: 1deg = 5 Pixels, 10deg = 50 Pixels class PageAutopilot : public Page @@ -38,8 +39,11 @@ class PageAutopilot : public Page virtual void setupKeys(){ Page::setupKeys(); - commonData->keydata[0].label = "CMP"; - commonData->keydata[1].label = "SRC"; + commonData->keydata[0].label = "-10"; + commonData->keydata[1].label = "-1"; + commonData->keydata[2].label = "Auto"; + commonData->keydata[3].label = "+1"; + commonData->keydata[4].label = "+10"; } virtual int handleKey(int key){ @@ -106,15 +110,13 @@ class PageAutopilot : public Page setBlinkingLED(false); setFlashLED(false); } - - if (bvalue == NULL) return PAGE_OK; // WTF why this statement? //*********************************************************** // Set display in partial refresh mode getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update getdisplay().setTextColor(commonData->fgcolor); - +/* // Horizontal line 2 pix top & bottom // Print data on top half getdisplay().fillRect(0, 130, 400, 2, commonData->fgcolor); @@ -138,7 +140,7 @@ class PageAutopilot : public Page OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value OldDataUnits[WhichDataDisplay] = DataUnits[WhichDataDisplay]; // Save the old unit } - +*/ // Now draw compass band // Get the data double TheAngle = DataValue[WhichDataCompass]; @@ -152,13 +154,13 @@ class PageAutopilot : public Page buffer[0]=0; getdisplay().setFont(&Ubuntu_Bold16pt8b); - getdisplay().setCursor(10, Compass_Y0-60); + getdisplay().setCursor(10, Compass_Y0-40); getdisplay().print(DataName[WhichDataCompass]); // Page name - // Draw compass base line and pointer getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor); - getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor); + //getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor); + getdisplay().fillTriangle(Compass_X0,Compass_Y0-30,Compass_X0-10,Compass_Y0-60,Compass_X0+10,Compass_Y0-60,commonData->fgcolor); // Draw trendlines for ( int i = 1; i < abs(TheTrend) / 2; i++){ int x1; @@ -238,6 +240,8 @@ class PageAutopilot : public Page // if ( x_test > 390) // x_test = 320; + displayRudderPosition(12, 200, 160, commonData->fgcolor, commonData->bgcolor); + return PAGE_UPDATE; }; From 71512e726285bd49d076511b7244c24b25284226 Mon Sep 17 00:00:00 2001 From: Norbert Walter Date: Sun, 8 Feb 2026 13:18:39 +0000 Subject: [PATCH 4/6] Actualize PageAutopilot --- lib/obp60task/OBP60Extensions.cpp | 20 ++++++++++++-------- lib/obp60task/OBP60Extensions.h | 5 +++-- lib/obp60task/PageAutopilot.cpp | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 5b3d278..3c4d9a2 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -940,8 +940,8 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){ getdisplay().print("G"); } -// Display rudder position as horizontal bargraph +/-30 degrees -void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg){ +// Display rudder position as horizontal bargraph with configurable +/- range (degrees) +void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg){ const int w = 360; const int h = 20; const int t = 3; // Line thickness @@ -951,8 +951,12 @@ void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_ int left = int(cx) - halfw; int top = int(cy) - halfh; - // Pixels per degree for +/-30° -> 60° span - const float pxPerDeg = float(w) / 60.0f; // =5.0 + // clamp provided range to allowed bounds [10,45] + if (rangeDeg < 10) rangeDeg = 10; + if (rangeDeg > 45) rangeDeg = 45; + + // Pixels per degree for +/-rangeDeg -> total span = 2*rangeDeg + const float pxPerDeg = float(w) / (2.0f * float(rangeDeg)); // Draw outer border (thickness t) for (int i = 0; i < t; i++) { @@ -962,9 +966,9 @@ void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_ // Fill inner area with background getdisplay().fillRect(left + t, top + t, w - 2 * t, h - 2 * t, bg); - // Clamp rudder position to -30..30 - if (rudderPosition > 30) rudderPosition = 30; - if (rudderPosition < -30) rudderPosition = -30; + // Clamp rudder position to -rangeDeg..rangeDeg + if (rudderPosition > (int)rangeDeg) rudderPosition = (int)rangeDeg; + if (rudderPosition < -((int)rangeDeg)) rudderPosition = -((int)rangeDeg); // Compute fill width in pixels int fillPx = int(round(rudderPosition * pxPerDeg)); // positive -> right @@ -984,7 +988,7 @@ void displayRudderPosition(int rudderPosition, uint16_t cx, uint16_t cy, uint16_ // Draw tick marks every 5° and labels outside the bar getdisplay().setTextColor(fg); getdisplay().setFont(&Ubuntu_Bold8pt8b); - for (int angle = -30; angle <= 30; angle += 5) { + for (int angle = -((int)rangeDeg); angle <= (int)rangeDeg; angle += 5) { int xpos = int(round(centerx + angle * pxPerDeg)); // Vertical tick inside bar getdisplay().drawLine(xpos, top, xpos, top + h + 2, fg); diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index de6db20..6d9e4a9 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -128,8 +128,9 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor); // S void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic void startLedTask(GwApi *api); -// Display rudder position as horizontal bargraph +/-30 degrees -void displayRudderPosition(int rudderPosition, uint16_t x, uint16_t y, uint16_t fg, uint16_t bg); +// Display rudder position as horizontal bargraph with configurable +/- range (degrees) +// 'rangeDeg' is unsigned and will be clamped to [10,45] +void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t x, uint16_t y, uint16_t fg, uint16_t bg); void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request); diff --git a/lib/obp60task/PageAutopilot.cpp b/lib/obp60task/PageAutopilot.cpp index f5161f5..8a698ce 100644 --- a/lib/obp60task/PageAutopilot.cpp +++ b/lib/obp60task/PageAutopilot.cpp @@ -240,7 +240,7 @@ class PageAutopilot : public Page // if ( x_test > 390) // x_test = 320; - displayRudderPosition(12, 200, 160, commonData->fgcolor, commonData->bgcolor); + displayRudderPosition(12, 20, 200, 160, commonData->fgcolor, commonData->bgcolor); return PAGE_UPDATE; }; From 7f747e9b35756f6dbde1b808fb6e4aa1299060cb Mon Sep 17 00:00:00 2001 From: norbert-walter Date: Sun, 8 Feb 2026 14:49:40 +0100 Subject: [PATCH 5/6] Add data connections for PageAutopilot --- lib/obp60task/OBP60Extensions.cpp | 4 ++++ lib/obp60task/OBP60Extensions.h | 2 +- lib/obp60task/PageAutopilot.cpp | 15 +++++++++------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 3c4d9a2..3b3ee88 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -966,6 +966,9 @@ void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, ui // Fill inner area with background getdisplay().fillRect(left + t, top + t, w - 2 * t, h - 2 * t, bg); + // Draw center line + getdisplay().drawRect(cx - 1, top + 1, 3 , h - 2, fg); + // Clamp rudder position to -rangeDeg..rangeDeg if (rudderPosition > (int)rangeDeg) rudderPosition = (int)rangeDeg; if (rudderPosition < -((int)rangeDeg)) rudderPosition = -((int)rangeDeg); @@ -985,6 +988,7 @@ void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, ui getdisplay().fillRect(centerx + fillPx, innerTop, -fillPx, innerH, fg); } + // Draw tick marks every 5° and labels outside the bar getdisplay().setTextColor(fg); getdisplay().setFont(&Ubuntu_Bold8pt8b); diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index 6d9e4a9..41e3717 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -130,7 +130,7 @@ void startLedTask(GwApi *api); // Display rudder position as horizontal bargraph with configurable +/- range (degrees) // 'rangeDeg' is unsigned and will be clamped to [10,45] -void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t x, uint16_t y, uint16_t fg, uint16_t bg); +void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg); void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request); diff --git a/lib/obp60task/PageAutopilot.cpp b/lib/obp60task/PageAutopilot.cpp index 8a698ce..09d14e2 100644 --- a/lib/obp60task/PageAutopilot.cpp +++ b/lib/obp60task/PageAutopilot.cpp @@ -5,8 +5,9 @@ // These constants have to match the declaration below in : // PageDescription registerPageAutopilot( -// {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW"}, // Bus values we need in the page -const int HowManyValues = 9; +// {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW", "RPOS", "ROT"}, // Bus values we need in the page + +const int HowManyValues = 11; const int AverageValues = 4; @@ -19,6 +20,8 @@ const int ShowDBT = 5; const int ShowXTE = 6; const int ShowDTW = 7; const int ShowBTW = 8; +const int ShowRPOS = 9; +const int ShowROT = 10; const int Compass_X0 = 200; // X center point of compass band const int Compass_Y0 = 90; // Y position of compass lines @@ -73,8 +76,8 @@ class PageAutopilot : public Page GwLog *logger = commonData->logger; // Old values for hold function - static String OldDataText[HowManyValues] = {"", "", "","", "", "","", "", ""}; - static String OldDataUnits[HowManyValues] = {"", "", "","", "", "","", "", ""}; + static String OldDataText[HowManyValues] = {"", "", "", "", "", "","", "", "", "", ""}; + static String OldDataUnits[HowManyValues] = {"", "", "", "", "", "","", "", "", "", ""}; // Get config data String lengthformat = config->getString(config->lengthFormat); @@ -240,7 +243,7 @@ class PageAutopilot : public Page // if ( x_test > 390) // x_test = 320; - displayRudderPosition(12, 20, 200, 160, commonData->fgcolor, commonData->bgcolor); + displayRudderPosition(DataValue[ShowRPOS], 20, 200, 160, commonData->fgcolor, commonData->bgcolor); return PAGE_UPDATE; }; @@ -260,7 +263,7 @@ PageDescription registerPageAutopilot( "Autopilot", // Page name createPage, // Action 0, // Number of bus values depends on selection in Web configuration - {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW"}, // Bus values we need in the page + {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW", "RPOS", "ROT"}, // Bus values we need in the page true // Show display header on/off ); From 6c7997e3694711beb6207972509d4d0c15d7b818 Mon Sep 17 00:00:00 2001 From: norbert-walter Date: Sun, 8 Feb 2026 22:00:22 +0100 Subject: [PATCH 6/6] Fix iRTC time for N2K bus --- lib/gwwifi/GwWifi.cpp | 15 +++++++++- lib/obp60task/OBPSensorTask.cpp | 53 +++++++++++++++++---------------- lib/obp60task/PageAutopilot.cpp | 2 +- lib/obp60task/config_obp40.json | 4 +-- lib/obp60task/config_obp60.json | 3 +- 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/lib/gwwifi/GwWifi.cpp b/lib/gwwifi/GwWifi.cpp index c81acec..00ae59c 100644 --- a/lib/gwwifi/GwWifi.cpp +++ b/lib/gwwifi/GwWifi.cpp @@ -104,8 +104,21 @@ void GwWifi::loop(){ if (lastConnectStart > now || (lastConnectStart + RETRY_MILLIS) < now) { LOG_DEBUG(GwLog::LOG,"wifiClient: retry connect to %s", wifiSSID->asCString()); - WiFi.disconnect(); + +//+++++++++ Old part +++++++++++++++++++++ +// WiFi.disconnect(); +// connectInternal(); +//++++++++++++++++++++++++++++++++++++++++ + +//+++++++++ New part +++++++++++++++++++++ + WiFi.disconnect(true); + delay(300); + esp_wifi_stop(); + delay(100); + esp_wifi_start(); connectInternal(); +//++++++++++++++++++++++++++++++++++++++++ + } } else{ diff --git a/lib/obp60task/OBPSensorTask.cpp b/lib/obp60task/OBPSensorTask.cpp index 25d861b..1424907 100644 --- a/lib/obp60task/OBPSensorTask.cpp +++ b/lib/obp60task/OBPSensorTask.cpp @@ -371,7 +371,7 @@ void sensorTask(void *param){ GwApi::BoatValue *hdop=new GwApi::BoatValue(GwBoatData::_HDOP); GwApi::BoatValue *valueList[]={gpsdays, gpsseconds, hdop}; - // Internal RTC with NTP init + // Internal iRTC with NTP init ESP32Time rtc(0); if (api->getConfig()->getString(api->getConfig()->timeSource) == "iRTC") { GwApi::Status status; @@ -432,17 +432,17 @@ void sensorTask(void *param){ iRTC RTC GPS N2K 0 0 0 (1) - 0 0 (1) (X) - 0 (1) 0 (X) - 0 1 <-(1) (X) - (1) 0 0 (X) - 1 0 (1) (X) - 1 ->(1) 0 (X) - 1 1 <-(1) (X) + 0 0 (1) X + 0 (1) 0 X + 0 1 <-(1) X + (1) 0 0 X + 1 0 (1) X + 1 ->(1) 0 X + 1 1 <-(1) X */ - // If RTC DS1388 ready, then copy iRTC and GPS data to RTC all 1min + // If RTC DS1388 ready, then copy iRTC and GPS data to RTC all 1 min if(millis() > starttime11 + 1*60*1000){ starttime11 = millis(); // Set RTC chip via iRTC (NTP) @@ -475,7 +475,7 @@ void sensorTask(void *param){ // Adjust RTC time as unix time value ds1388.adjust(adjusttime); } - } + } } // Set RTC chip via N2K or 183 in case the internal GPS is off (only one time) @@ -524,7 +524,7 @@ void sensorTask(void *param){ // N2K sysTime is double in n2klib double sysTime = (dt.hour() * 3600) + (dt.minute() * 60) + dt.second(); if(!isnan(daysAt1970) && !isnan(sysTime)){ - //api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); + //api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon+1, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); //api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime); SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock); api->sendN2kMessage(N2kMsg); @@ -533,25 +533,26 @@ void sensorTask(void *param){ } // Send date and time from software RTC (iRTC) if (iRTC_ready == true && RTC_ready == false && GPS_ready == false) { - // Use internal RTC feature - sensors.rtcTime = rtc.getTimeStruct(); // Save software RTC values in SensorData - // TODO implement daysAt1970 and sysTime as methods of DateTime + sensors.rtcTime = rtc.getTimeStruct(); + const short daysOfYear[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; - uint16_t switchYear = ((sensors.rtcTime.tm_year-1)-1968)/4 - ((sensors.rtcTime.tm_year-1)-1900)/100 + ((sensors.rtcTime.tm_year-1)-1600)/400; - long daysAt1970 = (sensors.rtcTime.tm_year-1970)*365 + switchYear + daysOfYear[sensors.rtcTime.tm_mon-1] + sensors.rtcTime.tm_mday-1; - // If switch year then add one day - if ((sensors.rtcTime.tm_mon > 2) && (sensors.rtcTime.tm_year % 4 == 0 && (sensors.rtcTime.tm_year % 100 != 0 || sensors.rtcTime.tm_year % 400 == 0))) { + int year = sensors.rtcTime.tm_year + 1900; + int month = sensors.rtcTime.tm_mon; + int day = sensors.rtcTime.tm_mday; + uint16_t switchYear = ((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 + ((year - 1) - 1600) / 400; + long daysAt1970 = (year - 1970) * 365L + switchYear + daysOfYear[month] + day - 1; + + // Leap day add if date is after Feb (i.e. month >= March) + if (month >= 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) { daysAt1970 += 1; } - // N2K sysTime is double in n2klib - double sysTime = (sensors.rtcTime.tm_hour * 3600) + (sensors.rtcTime.tm_min * 60) + sensors.rtcTime.tm_sec; - if(!isnan(daysAt1970) && !isnan(sysTime)){ - //api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); - //api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime); - SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock); - api->sendN2kMessage(N2kMsg); - } + double sysTime = sensors.rtcTime.tm_hour * 3600.0 + sensors.rtcTime.tm_min * 60.0 + sensors.rtcTime.tm_sec; + //api->getLogger()->logDebug(GwLog::LOG, "iRTC time: %04d/%02d/%02d %02d:%02d:%02d", year, month + 1, day, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); + //api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime); + SetN2kPGN126992(N2kMsg, 0, daysAt1970, sysTime, N2ktimes_LocalCrystalClock); + api->sendN2kMessage(N2kMsg); } + } // Send 1Wire data for all temperature sensors to N2K all 2s diff --git a/lib/obp60task/PageAutopilot.cpp b/lib/obp60task/PageAutopilot.cpp index 09d14e2..ecfc62e 100644 --- a/lib/obp60task/PageAutopilot.cpp +++ b/lib/obp60task/PageAutopilot.cpp @@ -243,7 +243,7 @@ class PageAutopilot : public Page // if ( x_test > 390) // x_test = 320; - displayRudderPosition(DataValue[ShowRPOS], 20, 200, 160, commonData->fgcolor, commonData->bgcolor); + displayRudderPosition(DataValue[ShowSOG], 20, 200, 160, commonData->fgcolor, commonData->bgcolor); return PAGE_UPDATE; }; diff --git a/lib/obp60task/config_obp40.json b/lib/obp60task/config_obp40.json index bb58948..0617c41 100644 --- a/lib/obp60task/config_obp40.json +++ b/lib/obp60task/config_obp40.json @@ -1245,8 +1245,8 @@ "name": "timeSource", "label": "Status Time Source", "type": "list", - "default": "GPS", - "description": "Data source for date and time display in status line [RTC|iRTC|GPS]", + "default": "iRTC", + "description": "Data source for date and time display in status line [iRTC|RTC|GPS]", "list": [ {"l":"Internal real time clock (iRTC)","v":"iRTC"}, {"l":"External real time clock (RTC)","v":"RTC"}, diff --git a/lib/obp60task/config_obp60.json b/lib/obp60task/config_obp60.json index 12d4681..305688f 100644 --- a/lib/obp60task/config_obp60.json +++ b/lib/obp60task/config_obp60.json @@ -1235,8 +1235,9 @@ "label": "Status Time Source", "type": "list", "default": "GPS", - "description": "Data source for date and time display in status line [RTC|GPS]", + "description": "Data source for date and time display in status line [iRTC|RTC|GPS]", "list": [ + {"l":"Internal real time clock (iRTC)","v":"iRTC"}, {"l":"Real time clock (RTC)","v":"RTC"}, {"l":"Time via bus (GPS)","v":"GPS"} ],