1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2026-02-24 20:53:07 +01:00

Merge branch 'autopilot2'

This commit is contained in:
norbert-walter
2026-02-20 09:43:17 +01:00
7 changed files with 165 additions and 46 deletions

View File

@@ -131,6 +131,7 @@ void GwWifi::loop(){
if (lastConnectStart > now || (lastConnectStart + RETRY_MILLIS) < now)
{
LOG_DEBUG(GwLog::LOG,"wifiClient: retry connect to %s", wifiSSID->asCString());
<<<<<<< HEAD
// CRITICAL SECTION: WiFi-Operationen müssen serialisiert werden
if (acquireMutex()){
WiFi.disconnect();
@@ -140,6 +141,23 @@ void GwWifi::loop(){
else{
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in loop");
}
=======
//+++++++++ Old part +++++++++++++++++++++
// WiFi.disconnect();
// connectInternal();
//++++++++++++++++++++++++++++++++++++++++
//+++++++++ New part +++++++++++++++++++++
WiFi.disconnect(true);
delay(300);
esp_wifi_stop();
delay(100);
esp_wifi_start();
connectInternal();
//++++++++++++++++++++++++++++++++++++++++
>>>>>>> autopilot2
}
}
else{

View File

@@ -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,74 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){
getdisplay().print("G");
}
// 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
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;
// 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++) {
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);
// 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);
// 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 = -((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);
// Label outside: below the bar
String lbl = String(angle);
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 + 5; // 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) {

View File

@@ -128,6 +128,10 @@ 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 with configurable +/- range (degrees)
// 'rangeDeg' is unsigned and will be clamped to [10,45]
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);
// Icons

View File

@@ -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

View File

@@ -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,10 +20,13 @@ 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 = 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 +42,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){
@@ -69,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);
@@ -106,15 +113,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 +143,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 +157,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 +243,8 @@ class PageAutopilot : public Page
// if ( x_test > 390)
// x_test = 320;
displayRudderPosition(DataValue[ShowSOG], 20, 200, 160, commonData->fgcolor, commonData->bgcolor);
return PAGE_UPDATE;
};
@@ -256,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
);

View File

@@ -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"},
@@ -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",

View File

@@ -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"}
],
@@ -1494,6 +1495,7 @@
"default": "Voltage",
"description": "Type of page for page 1",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -1794,6 +1796,7 @@
"default": "WindRose",
"description": "Type of page for page 2",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -2086,6 +2089,7 @@
"default": "OneValue",
"description": "Type of page for page 3",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -2370,6 +2374,7 @@
"default": "TwoValues",
"description": "Type of page for page 4",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -2646,6 +2651,7 @@
"default": "ThreeValues",
"description": "Type of page for page 5",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -2914,6 +2920,7 @@
"default": "FourValues",
"description": "Type of page for page 6",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -3174,6 +3181,7 @@
"default": "FourValues2",
"description": "Type of page for page 7",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -3426,6 +3434,7 @@
"default": "Clock",
"description": "Type of page for page 8",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -3670,6 +3679,7 @@
"default": "RollPitch",
"description": "Type of page for page 9",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",
@@ -3906,6 +3916,7 @@
"default": "Battery2",
"description": "Type of page for page 10",
"list": [
"Autopilot",
"BME280",
"Battery",
"Battery2",