mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2026-08-18 18:32:30 +02:00
Merge branch 'norbert-walter:master' into TrueWind-opt
This commit is contained in:
+11
-2
@@ -2,6 +2,9 @@
|
|||||||
#define _GWWIFI_H
|
#define _GWWIFI_H
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <GWConfig.h>
|
#include <GWConfig.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/semphr.h>
|
||||||
|
|
||||||
class GwWifi{
|
class GwWifi{
|
||||||
private:
|
private:
|
||||||
const GwConfigHandler *config;
|
const GwConfigHandler *config;
|
||||||
@@ -16,15 +19,21 @@ class GwWifi{
|
|||||||
bool apActive=false;
|
bool apActive=false;
|
||||||
bool fixedApPass=true;
|
bool fixedApPass=true;
|
||||||
bool clientIsConnected=false;
|
bool clientIsConnected=false;
|
||||||
|
SemaphoreHandle_t wifiMutex=nullptr;
|
||||||
|
static const TickType_t WIFI_MUTEX_TIMEOUT=pdMS_TO_TICKS(1000);
|
||||||
|
bool acquireMutex();
|
||||||
|
void releaseMutex();
|
||||||
public:
|
public:
|
||||||
const char *AP_password = "esp32nmea2k";
|
const char *AP_password = "esp32nmea2k";
|
||||||
GwWifi(const GwConfigHandler *config,GwLog *log, bool fixedApPass=true);
|
GwWifi(const GwConfigHandler *config,GwLog *log, bool fixedApPass=true);
|
||||||
|
~GwWifi();
|
||||||
void setup();
|
void setup();
|
||||||
void loop();
|
void loop();
|
||||||
bool clientConnected();
|
bool clientConnected();
|
||||||
bool connectClient();
|
bool connectClient(); // Blocking version
|
||||||
|
bool connectClientAsync(); // Non-blocking version for other tasks
|
||||||
String apIP();
|
String apIP();
|
||||||
bool isApActive(){return apActive;}
|
bool isApActive(){return apActive;}
|
||||||
bool isClientActive(){return wifiClient->asBoolean();}
|
bool isClientActive(){return wifiClient->asBoolean();}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
+65
-2
@@ -1,7 +1,6 @@
|
|||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
#include "GWWifi.h"
|
#include "GWWifi.h"
|
||||||
|
|
||||||
|
|
||||||
GwWifi::GwWifi(const GwConfigHandler *config,GwLog *log, bool fixedApPass){
|
GwWifi::GwWifi(const GwConfigHandler *config,GwLog *log, bool fixedApPass){
|
||||||
this->config=config;
|
this->config=config;
|
||||||
this->logger=log;
|
this->logger=log;
|
||||||
@@ -9,6 +8,28 @@ GwWifi::GwWifi(const GwConfigHandler *config,GwLog *log, bool fixedApPass){
|
|||||||
wifiSSID=config->getConfigItem(config->wifiSSID,true);
|
wifiSSID=config->getConfigItem(config->wifiSSID,true);
|
||||||
wifiPass=config->getConfigItem(config->wifiPass,true);
|
wifiPass=config->getConfigItem(config->wifiPass,true);
|
||||||
this->fixedApPass=fixedApPass;
|
this->fixedApPass=fixedApPass;
|
||||||
|
wifiMutex=xSemaphoreCreateMutex();
|
||||||
|
if (wifiMutex==nullptr){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"GwWifi: unable to create mutex");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GwWifi::~GwWifi(){
|
||||||
|
if (wifiMutex!=nullptr){
|
||||||
|
vSemaphoreDelete(wifiMutex);
|
||||||
|
wifiMutex=nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GwWifi::acquireMutex(){
|
||||||
|
if (wifiMutex==nullptr) return false;
|
||||||
|
return xSemaphoreTake(wifiMutex,WIFI_MUTEX_TIMEOUT)==pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwWifi::releaseMutex(){
|
||||||
|
if (wifiMutex!=nullptr){
|
||||||
|
xSemaphoreGive(wifiMutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void GwWifi::setup(){
|
void GwWifi::setup(){
|
||||||
LOG_DEBUG(GwLog::LOG,"Wifi setup");
|
LOG_DEBUG(GwLog::LOG,"Wifi setup");
|
||||||
@@ -85,8 +106,14 @@ bool GwWifi::connectInternal(){
|
|||||||
if (wifiClient->asBoolean()){
|
if (wifiClient->asBoolean()){
|
||||||
clientIsConnected=false;
|
clientIsConnected=false;
|
||||||
LOG_DEBUG(GwLog::LOG,"creating wifiClient ssid=%s",wifiSSID->asString().c_str());
|
LOG_DEBUG(GwLog::LOG,"creating wifiClient ssid=%s",wifiSSID->asString().c_str());
|
||||||
|
// CRITICAL SECTION: WiFi-Operationen müssen serialisiert werden
|
||||||
|
if (!acquireMutex()){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in connectInternal");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
WiFi.setAutoReconnect(false); //#102
|
WiFi.setAutoReconnect(false); //#102
|
||||||
wl_status_t rt=WiFi.begin(wifiSSID->asCString(),wifiPass->asCString());
|
wl_status_t rt=WiFi.begin(wifiSSID->asCString(),wifiPass->asCString());
|
||||||
|
releaseMutex();
|
||||||
LOG_DEBUG(GwLog::LOG,"wifiClient connect returns %d",(int)rt);
|
LOG_DEBUG(GwLog::LOG,"wifiClient connect returns %d",(int)rt);
|
||||||
lastConnectStart=millis();
|
lastConnectStart=millis();
|
||||||
return true;
|
return true;
|
||||||
@@ -104,9 +131,16 @@ void GwWifi::loop(){
|
|||||||
if (lastConnectStart > now || (lastConnectStart + RETRY_MILLIS) < now)
|
if (lastConnectStart > now || (lastConnectStart + RETRY_MILLIS) < now)
|
||||||
{
|
{
|
||||||
LOG_DEBUG(GwLog::LOG,"wifiClient: retry connect to %s", wifiSSID->asCString());
|
LOG_DEBUG(GwLog::LOG,"wifiClient: retry connect to %s", wifiSSID->asCString());
|
||||||
|
// CRITICAL SECTION: WiFi-Operationen müssen serialisiert werden
|
||||||
|
if (acquireMutex()){
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
|
releaseMutex();
|
||||||
connectInternal();
|
connectInternal();
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in loop");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (! clientIsConnected){
|
if (! clientIsConnected){
|
||||||
@@ -127,10 +161,39 @@ void GwWifi::loop(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool GwWifi::clientConnected(){
|
bool GwWifi::clientConnected(){
|
||||||
return WiFi.status() == WL_CONNECTED;
|
// CRITICAL SECTION: WiFi.status() muss geschützt werden
|
||||||
|
if (!acquireMutex()){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in clientConnected");
|
||||||
|
return false; // Conservative: nehme an, nicht verbunden
|
||||||
|
}
|
||||||
|
bool result = WiFi.status() == WL_CONNECTED;
|
||||||
|
releaseMutex();
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
bool GwWifi::connectClient(){
|
bool GwWifi::connectClient(){
|
||||||
|
// CRITICAL SECTION: Disconnect und Connect müssen atomar sein
|
||||||
|
if (!acquireMutex()){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in connectClient");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
|
releaseMutex();
|
||||||
|
return connectInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GwWifi::connectClientAsync(){
|
||||||
|
// Non-blocking version: Versuche Mutex zu nehmen, gib aber sofort auf
|
||||||
|
// Ideal für Tasks, die nicht blockieren dürfen
|
||||||
|
if (wifiMutex==nullptr){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex not initialized in connectClientAsync");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (xSemaphoreTake(wifiMutex, 0)!=pdTRUE){
|
||||||
|
LOG_DEBUG(GwLog::LOG,"GwWifi: connectClientAsync skipped - WiFi busy");
|
||||||
|
return false; // WiFi ist aktuell busy, versuche es später nochmal
|
||||||
|
}
|
||||||
|
WiFi.disconnect();
|
||||||
|
xSemaphoreGive(wifiMutex);
|
||||||
return connectInternal();
|
return connectInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// General hardware definitions
|
// General hardware definitions
|
||||||
// CAN and RS485 bus pin definitions see obp60task.h
|
// CAN and RS485 bus pin definitions see obp60task.h
|
||||||
|
|
||||||
#ifdef HARDWARE_V21
|
#if defined HARDWARE_V20 || HARDWARE_V21
|
||||||
// Direction pin for RS485 NMEA0183
|
// Direction pin for RS485 NMEA0183
|
||||||
#define OBP_DIRECTION_PIN 18
|
#define OBP_DIRECTION_PIN 18
|
||||||
// I2C
|
// I2C
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ void initKeys(CommonData &commonData) {
|
|||||||
commonData.keydata[5].h = height;
|
commonData.keydata[5].h = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HARDWARE_V21
|
#if defined HARDWARE_V20 || HARDWARE_V21
|
||||||
// Keypad functions for original OBP60 hardware
|
// Keypad functions for original OBP60 hardware
|
||||||
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
|
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,13 @@
|
|||||||
#include "OBP60Extensions.h"
|
#include "OBP60Extensions.h"
|
||||||
#include "NetworkClient.h" // Network connection
|
#include "NetworkClient.h" // Network connection
|
||||||
#include "ImageDecoder.h" // Image decoder for navigation map
|
#include "ImageDecoder.h" // Image decoder for navigation map
|
||||||
|
#include "GWWifi.h" // WiFi management (thread-safe)
|
||||||
|
|
||||||
#include "Logo_OBP_400x300_sw.h"
|
#include "Logo_OBP_400x300_sw.h"
|
||||||
|
|
||||||
|
// Extern declaration of global WiFi instance
|
||||||
|
extern GwWifi gwWifi;
|
||||||
|
|
||||||
// Defines for reading of navigation map
|
// Defines for reading of navigation map
|
||||||
#define JSON_BUFFER 30000 // Max buffer size for JSON content (30 kB picture + values)
|
#define JSON_BUFFER 30000 // Max buffer size for JSON content (30 kB picture + values)
|
||||||
NetworkClient net(JSON_BUFFER); // Define network client
|
NetworkClient net(JSON_BUFFER); // Define network client
|
||||||
@@ -25,6 +29,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
int imageBackupHeight = 0;
|
int imageBackupHeight = 0;
|
||||||
size_t imageBackupSize = 0;
|
size_t imageBackupSize = 0;
|
||||||
bool hasImageBackup = false;
|
bool hasImageBackup = false;
|
||||||
|
static bool wifiConnectRequested; // Track if WiFi connection was requested
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageNavigation(CommonData &common){
|
PageNavigation(CommonData &common){
|
||||||
@@ -55,12 +60,15 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
}
|
}
|
||||||
return 0; // Commit the key
|
return 0; // Commit the key
|
||||||
}
|
}
|
||||||
// Code for zoom -
|
// Code for zoom +
|
||||||
if(key == 2){
|
if(key == 2){
|
||||||
zoom ++; // Zoom +
|
zoom ++; // Zoom +
|
||||||
if(zoom >17){
|
if(zoom >17){
|
||||||
zoom = 17;
|
zoom = 17;
|
||||||
}
|
}
|
||||||
|
// Optional: Versuche WiFi-Verbindung nach Zoom-Änderung
|
||||||
|
// Dies ermöglicht eine neue Kartendarstellung
|
||||||
|
gwWifi.connectClientAsync();
|
||||||
return 0; // Commit the key
|
return 0; // Commit the key
|
||||||
}
|
}
|
||||||
if(key == 5){
|
if(key == 5){
|
||||||
@@ -95,6 +103,13 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
zoom = zoomLevel; // Over write zoom level with setup value
|
zoom = zoomLevel; // Over write zoom level with setup value
|
||||||
showValues = showValuesMap; // Over write showValues with setup value
|
showValues = showValuesMap; // Over write showValues with setup value
|
||||||
firstRun = false; // Restet variable
|
firstRun = false; // Restet variable
|
||||||
|
|
||||||
|
// Versuche beim ersten Laden eine WiFi-Verbindung herzustellen (non-blocking)
|
||||||
|
// Dies ist thread-safe und blockiert das UI nicht
|
||||||
|
if (!gwWifi.clientConnected()) {
|
||||||
|
LOG_DEBUG(GwLog::LOG, "PageNavigation: Initiating WiFi connection for map download");
|
||||||
|
gwWifi.connectClientAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local variables
|
// Local variables
|
||||||
@@ -344,6 +359,16 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
// Load navigation map
|
// Load navigation map
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
|
// Prüfe WiFi-Verbindung (Thread-Safe)
|
||||||
|
// Diese Methode ist synchronisiert und blockiert maximal 1 Sekunde
|
||||||
|
bool wifiConnected = gwWifi.clientConnected();
|
||||||
|
|
||||||
|
if (!wifiConnected && !wifiConnectRequested) {
|
||||||
|
LOG_DEBUG(GwLog::LOG, "PageNavigation: WiFi not connected, attempting async connect");
|
||||||
|
gwWifi.connectClientAsync();
|
||||||
|
wifiConnectRequested = true;
|
||||||
|
}
|
||||||
|
|
||||||
// URL to OBP Maps Converter
|
// URL to OBP Maps Converter
|
||||||
// For more details see: https://github.com/norbert-walter/maps-converter
|
// For more details see: https://github.com/norbert-walter/maps-converter
|
||||||
String url = String("http://") + server + ":" + port + // OBP Server
|
String url = String("http://") + server + ":" + port + // OBP Server
|
||||||
@@ -375,7 +400,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
getdisplay().setTextColor(commonData->fgcolor);
|
getdisplay().setTextColor(commonData->fgcolor);
|
||||||
|
|
||||||
// If a network connection to URL then load the navigation map
|
// If a network connection to URL then load the navigation map
|
||||||
if (net.fetchAndDecompressJson(url)) {
|
if (wifiConnected && net.fetchAndDecompressJson(url)) {
|
||||||
|
wifiConnectRequested = false; // Reset flag after successful connection
|
||||||
|
|
||||||
auto& json = net.json(); // Extract JSON content
|
auto& json = net.json(); // Extract JSON content
|
||||||
int numPix = json["number_pixels"] | 0; // Read number of pixels
|
int numPix = json["number_pixels"] | 0; // Read number of pixels
|
||||||
@@ -442,6 +468,12 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
}
|
}
|
||||||
|
|
||||||
lostCounter++; // Increment lost counter
|
lostCounter++; // Increment lost counter
|
||||||
|
|
||||||
|
// Nur einmal pro Sekunde einen neuen Verbindungsversuch machen
|
||||||
|
if (!wifiConnectRequested) {
|
||||||
|
gwWifi.connectClientAsync();
|
||||||
|
wifiConnectRequested = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -488,6 +520,9 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Initialize static member variable
|
||||||
|
bool PageNavigation::wifiConnectRequested = false;
|
||||||
|
|
||||||
static Page *createPage(CommonData &common){
|
static Page *createPage(CommonData &common){
|
||||||
return new PageNavigation(common);
|
return new PageNavigation(common);
|
||||||
}/**
|
}/**
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
# PlatformIO extra script for obp60task
|
# PlatformIO extra script for obp60task
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
patching = False
|
||||||
|
|
||||||
epdtype = "unknown"
|
epdtype = "unknown"
|
||||||
pcbvers = "unknown"
|
pcbvers = "unknown"
|
||||||
for x in env["BUILD_FLAGS"]:
|
for x in env["BUILD_FLAGS"]:
|
||||||
if x.startswith("-D HARDWARE_"):
|
if not x.startswith('-D'):
|
||||||
|
continue
|
||||||
|
opt = x[2:].strip()
|
||||||
|
if opt.startswith("HARDWARE_"):
|
||||||
pcbvers = x.split('_')[1]
|
pcbvers = x.split('_')[1]
|
||||||
if x.startswith("-D DISPLAY_"):
|
elif opt.startswith("DISPLAY_"):
|
||||||
epdtype = x.split('_')[1]
|
epdtype = x.split('_')[1]
|
||||||
|
elif opt == 'ENABLE_PATCHES':
|
||||||
|
patching = True
|
||||||
|
|
||||||
propfilename = os.path.join(env["PROJECT_LIBDEPS_DIR"], env["PIOENV"], "GxEPD2/library.properties")
|
propfilename = os.path.join(env["PROJECT_LIBDEPS_DIR"], env["PIOENV"], "GxEPD2/library.properties")
|
||||||
properties = {}
|
properties = {}
|
||||||
@@ -28,3 +37,20 @@ except:
|
|||||||
env["CPPDEFINES"].extend([("BOARD", env["BOARD"]), ("EPDTYPE", epdtype), ("PCBVERS", pcbvers), ("GXEPD2VERS", gxepd2vers)])
|
env["CPPDEFINES"].extend([("BOARD", env["BOARD"]), ("EPDTYPE", epdtype), ("PCBVERS", pcbvers), ("GXEPD2VERS", gxepd2vers)])
|
||||||
|
|
||||||
print("added hardware info to CPPDEFINES")
|
print("added hardware info to CPPDEFINES")
|
||||||
|
|
||||||
|
if patching:
|
||||||
|
# apply patches to gateway code
|
||||||
|
print("applying gateway patches")
|
||||||
|
patchdir = os.path.join(os.path.dirname(script), "patches")
|
||||||
|
if not os.path.isdir(patchdir):
|
||||||
|
print("patchdir not found, no patches applied")
|
||||||
|
else:
|
||||||
|
patchfiles = [f for f in os.listdir(patchdir)]
|
||||||
|
for p in patchfiles:
|
||||||
|
patch = os.path.join(patchdir, p)
|
||||||
|
print(f"applying {patch}")
|
||||||
|
res = subprocess.run(["git", "apply", patch], capture_output=True, text=True)
|
||||||
|
if res.returncode != 0:
|
||||||
|
print(res.stderr)
|
||||||
|
else:
|
||||||
|
print("no patches found")
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ void OBP60Task(GwApi *api){
|
|||||||
// return;
|
// return;
|
||||||
GwLog *logger=api->getLogger();
|
GwLog *logger=api->getLogger();
|
||||||
GwConfigHandler *config=api->getConfig();
|
GwConfigHandler *config=api->getConfig();
|
||||||
#ifdef HARDWARE_V21
|
#if defined HARDWARE_V20 || HARDWARE_V21
|
||||||
startLedTask(api);
|
startLedTask(api);
|
||||||
#endif
|
#endif
|
||||||
PageList allPages;
|
PageList allPages;
|
||||||
@@ -341,7 +341,7 @@ void OBP60Task(GwApi *api){
|
|||||||
commonData.logger=logger;
|
commonData.logger=logger;
|
||||||
commonData.config=config;
|
commonData.config=config;
|
||||||
|
|
||||||
#ifdef HARDWARE_V21
|
#if defined HARDWARE_V20 || HARDWARE_V21
|
||||||
// Keyboard coordinates for page footer
|
// Keyboard coordinates for page footer
|
||||||
initKeys(commonData);
|
initKeys(commonData);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ build_flags=
|
|||||||
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm - medium
|
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm - medium
|
||||||
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm - bad (burn in effects)
|
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm - bad (burn in effects)
|
||||||
# -D DISPLAY_ZJY400300-042CAAMFGN #alternativ E-Ink display from ZZE Technology, R10 2.2 ohm - very good
|
# -D DISPLAY_ZJY400300-042CAAMFGN #alternativ E-Ink display from ZZE Technology, R10 2.2 ohm - very good
|
||||||
|
# -D ENABLE_PATCHES #enable patching of gateway code
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
||||||
upload_port = /dev/ttyACM0 #OBP60 download via USB-C direct
|
upload_port = /dev/ttyACM0 #OBP60 download via USB-C direct
|
||||||
@@ -108,6 +109,7 @@ build_flags=
|
|||||||
#-D DISPLAY_ZJY400300-042CAAMFGN #alternativ E-Ink display from ZZE Technology, R10 2.2 ohm - very good
|
#-D DISPLAY_ZJY400300-042CAAMFGN #alternativ E-Ink display from ZZE Technology, R10 2.2 ohm - very good
|
||||||
-D LIPO_ACCU_1200 #Hardware extension, LiPo accu 3,7V 1200mAh
|
-D LIPO_ACCU_1200 #Hardware extension, LiPo accu 3,7V 1200mAh
|
||||||
-D VOLTAGE_SENSOR #Hardware extension, LiPo voltage sensor with two resistors
|
-D VOLTAGE_SENSOR #Hardware extension, LiPo voltage sensor with two resistors
|
||||||
|
#-D ENABLE_PATCHES #enable patching of gateway code
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
upload_port = /dev/ttyUSB0 #OBP40 download via external USB/Serail converter
|
upload_port = /dev/ttyUSB0 #OBP40 download via external USB/Serail converter
|
||||||
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
|
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
|
||||||
|
|||||||
Reference in New Issue
Block a user