diff --git a/RotaxMonitor/platformio.ini b/RotaxMonitor/platformio.ini index c07cdb2..6919e02 100644 --- a/RotaxMonitor/platformio.ini +++ b/RotaxMonitor/platformio.ini @@ -27,14 +27,14 @@ monitor_port = /dev/ttyACM0 monitor_speed = 921600 build_type = release build_flags = - -DCORE_DEBUG_LEVEL=3 + -DCORE_DEBUG_LEVEL=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MODE=0 -DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 -DCONFIG_ASYNC_TCP_PRIORITY=21 - -DCONFIG_ASYNC_TCP_QUEUE_SIZE=128 + -DCONFIG_ASYNC_TCP_QUEUE_SIZE=64 -DCONFIG_ASYNC_TCP_RUNNING_CORE=1 - -DCONFIG_ASYNC_TCP_STACK_SIZE=8192 + -DCONFIG_ASYNC_TCP_STACK_SIZE=4096 [env:esp32-s3-devkitc1-n16r8-debug] board = ${env:esp32-s3-devkitc1-n16r8.board} @@ -61,6 +61,6 @@ build_flags = -DARDUINO_USB_MODE=0 -DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 -DCONFIG_ASYNC_TCP_PRIORITY=21 - -DCONFIG_ASYNC_TCP_QUEUE_SIZE=128 + -DCONFIG_ASYNC_TCP_QUEUE_SIZE=64 -DCONFIG_ASYNC_TCP_RUNNING_CORE=1 - -DCONFIG_ASYNC_TCP_STACK_SIZE=8192 + -DCONFIG_ASYNC_TCP_STACK_SIZE=4096 diff --git a/RotaxMonitor/src/datasave.h b/RotaxMonitor/src/datasave.h index b27308a..65270cd 100644 --- a/RotaxMonitor/src/datasave.h +++ b/RotaxMonitor/src/datasave.h @@ -14,8 +14,6 @@ #include "isr.h" #include "psvector.h" -const uint32_t max_history = 256; - class LITTLEFSGuard { public: diff --git a/RotaxMonitor/src/main.cpp b/RotaxMonitor/src/main.cpp index 565bec9..2b15435 100644 --- a/RotaxMonitor/src/main.cpp +++ b/RotaxMonitor/src/main.cpp @@ -16,24 +16,23 @@ #include #include -#define CH_A_ENABLE -#define CH_B_ENABLE +//#define CH_A_ENABLE +//#define CH_B_ENABLE #define CH_A_RT_ENABLE #define CH_B_RT_ENABLE -// #define I2C_ENABLE -// #define WEB_ENABLE +//#define I2C_ENABLE +#define WEB_ENABLE // Debug Defines #define WIFI_SSID "AstroRotaxMonitor" #define WIFI_PASSWORD "maledettirotax" -#define PSRAM_MAX 1024 -#define QUEUE_MAX 32 +#define PSRAM_MAX 4096 +#define QUEUE_MAX 128 void setup() { - Serial.begin(115200); + Serial.begin(921600); delay(250); - Serial.setTimeout(5000); // Setup Logger LOG_ATTACH_SERIAL(Serial); @@ -106,7 +105,7 @@ void loop() spiA_ok = SPI_A.begin(SPI_A_SCK, SPI_A_MISO, SPI_A_MOSI); SPI_A.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1 LOG_DEBUG("Init SPI_A -> OK"); - delay(500); + delay(100); LOG_DEBUG("Begin Init ADC_A"); ADS1256 ADC_A(ADC_A_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_A_CS, 2.5, &SPI_A); ADC_A.InitializeADC(); @@ -115,7 +114,7 @@ void loop() dev.m_adc_a = &ADC_A; dev.m_spi_a = &SPI_A; LOG_DEBUG("Init ADC_A -> OK"); - delay(1000); + delay(100); #endif #ifdef CH_B_ENABLE @@ -124,7 +123,7 @@ void loop() spiB_ok = SPI_B.begin(SPI_B_SCK, SPI_B_MISO, SPI_B_MOSI); SPI_B.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1 LOG_DEBUG("Init SPI_B -> OK"); - delay(500); + delay(100); LOG_DEBUG("Begin Init ADC_B"); ADS1256 ADC_B(ADC_B_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_B_CS, 2.5, &SPI_B); ADC_B.InitializeADC(); @@ -133,7 +132,7 @@ void loop() dev.m_adc_b = &ADC_B; dev.m_spi_b = &SPI_B; LOG_DEBUG("Init ADC_B -> OK"); - delay(1000); + delay(100); #endif if (!spiA_ok || !spiB_ok) @@ -159,10 +158,10 @@ void loop() esp_restart(); } LOG_DEBUG("Init I2c ok"); - Serial.readStringUntil('\n'); // Init IO Expanders - dev->m_ext_io = std::make_unique(Wire, dev->m_i2c_mutex, EXPANDER_ALL_INTERRUPT); + ExternalIO extIo(Wire, dev.m_i2c_mutex, EXPANDER_ALL_INTERRUPT); + dev.m_ext_io = &extIo; #endif //////// INIT REALTIME TASKS PARAMETERS //////// @@ -238,17 +237,17 @@ void loop() BaseType_t ignB_task_success = pdPASS; #ifdef CH_A_RT_ENABLE - auto task_A = rtIgnitionTask(taskA_params, PSRAM_MAX, QUEUE_MAX, CORE_1, fs_mutex); + auto task_A = rtIgnitionTask(taskA_params, PSRAM_MAX, QUEUE_MAX, CORE_0, fs_mutex); ignA_task_success = task_A.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL; - //tasK_A_rt = task_A.start(); - delay(1000); + tasK_A_rt = task_A.start(); + delay(100); #endif #ifdef CH_B_RT_ENABLE auto task_B = rtIgnitionTask(taskB_params, PSRAM_MAX, QUEUE_MAX, CORE_1, fs_mutex); ignB_task_success = task_B.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL; - //task_B_rt = task_B.start(); - delay(1000); + task_B_rt = task_B.start(); + delay(100); #endif // Ignition A on Core 0 @@ -275,7 +274,8 @@ void loop() bool data_a = false, data_b = false; #ifdef WEB_ENABLE AstroWebServer webPage(80, LittleFS); - delay(1000); + delay(100); + task_A.onMessage([&webPage, &json_data, &data_a](ignitionBoxStatusFiltered sts) { json_data["box_a"] = sts.toJson(); @@ -289,8 +289,8 @@ void loop() #endif #endif - // task_A.enableSave(true, "ignitionA_test.csv"); - // task_B.enableSave(true, "ignitionB_test.csv"); + task_A.enableSave(true, "ignitionA_test.csv"); + task_B.enableSave(true, "ignitionB_test.csv"); uint32_t monitor_loop = millis(); uint32_t data_loop = monitor_loop; diff --git a/RotaxMonitor/src/pins.h b/RotaxMonitor/src/pins.h index 8ed24f7..5df0fdf 100644 --- a/RotaxMonitor/src/pins.h +++ b/RotaxMonitor/src/pins.h @@ -33,16 +33,15 @@ // ===================== // SPI BUS ADC2 (HSPI) // ===================== -#define SPI_B_MOSI 36 -#define SPI_B_SCK 37 -#define SPI_B_MISO 38 +#define SPI_B_MOSI 17 +#define SPI_B_SCK 18 +#define SPI_B_MISO 8 // ===================== // I2C BUS (PCA9555) // ===================== -#define SDA 8 -#define SCL 9 -#define I2C_INT 17 +#define SDA 21 +#define SCL 38 // ===================== // ADC CONTROL @@ -50,8 +49,8 @@ #define ADC_A_CS 14 #define ADC_A_DRDY 13 -#define ADC_B_CS 21 -#define ADC_B_DRDY 47 +#define ADC_B_CS 3 +#define ADC_B_DRDY 9 // ===================== // TRIGGER INPUT INTERRUPTS @@ -81,7 +80,7 @@ // ===================== // PCA9555 I/O EXPANDER INTERRUPT (Common) // ===================== -#define EXPANDER_ALL_INTERRUPT 17 +#define EXPANDER_ALL_INTERRUPT 45 // ===================== // PCA9555 I/O EXPANDER BOX_A (OUT) diff --git a/RotaxMonitor/src/tasks.cpp b/RotaxMonitor/src/tasks.cpp index a5b6b92..6c073cf 100644 --- a/RotaxMonitor/src/tasks.cpp +++ b/RotaxMonitor/src/tasks.cpp @@ -6,7 +6,7 @@ //// GLOBAL STATIC FUNCTIONS // Timeout callback for microsecond precision -void spark_timeout_callback(void *arg) +void IRAM_ATTR spark_timeout_callback(void *arg) { TaskHandle_t handle = (TaskHandle_t)arg; xTaskNotify(handle, SPARK_FLAG_TIMEOUT, eSetValueWithOverwrite); @@ -21,10 +21,6 @@ void rtIgnitionTask::rtIgnitionTask_manager(void *pvParameters) while (cls->m_running) { cls->run(); - // if (millis() - last_loop > 2000) { - // LOG_DEBUG("TASK [", cls->m_name.c_str(), "] Alive -", count++); - // last_loop = millis(); - // } vTaskDelay(pdMS_TO_TICKS(1)); } } @@ -47,10 +43,8 @@ void rtIgnitionTask::rtIgnitionTask_realtime(void *pvParameters) QueueHandle_t rt_queue = params->rt_queue; Devices *dev = params->dev; ExternalIO *io = dev->m_ext_io; - // ADS1256 *adc = params->name == "rtIgnTask_A" ? dev->m_adc_a : dev->m_adc_b; - ADS1256 *adc = NULL; - // std::mutex &spi_mutex = params->name == "rtIgnTask_A" ? dev->m_spi_a_mutex : dev->m_spi_b_mutex; - std::mutex spi_mutex; + ADS1256 *adc = params->name == "rtIgnTask_A" ? dev->m_adc_a : dev->m_adc_b; + std::mutex &spi_mutex = params->name == "rtIgnTask_A" ? dev->m_spi_a_mutex : dev->m_spi_b_mutex; TaskStatus_t rt_task_info; vTaskGetInfo(NULL, &rt_task_info, pdFALSE, eInvalid); @@ -321,15 +315,22 @@ rtIgnitionTask::rtIgnitionTask(const rtTaskParams params, const uint32_t history else m_params.rt_queue = m_queue; - // create PSram history vectors - m_history_0 = PSHistory(history_size); - m_history_1 = PSHistory(history_size); - // assing active and writable history - m_active_history = std::unique_ptr(&m_history_0); - m_save_history = std::unique_ptr(&m_history_1); + try + { + // create PSram history vectors + m_history_0 = PSHistory(history_size); + m_history_1 = PSHistory(history_size); + // assing active and writable history + m_active_history = std::unique_ptr(&m_history_0); + m_save_history = std::unique_ptr(&m_history_1); + } + catch (std::bad_alloc &e) + { + LOG_ERROR("Task [", params.name.c_str(), "] Unable to allocate history PSRAM: ", e.what()); + return; + } m_name = (std::string("man_") + m_params.name).c_str(); - // auto task_success = pdPASS; auto task_success = xTaskCreatePinnedToCore( rtIgnitionTask_manager, m_name.c_str(), @@ -379,7 +380,7 @@ void rtIgnitionTask::run() m_partial_save = false; // reset partial save flag on new data cycle std::swap(m_active_history, m_save_history); if (m_enable_save) - // saveHistory(m_save_history, m_history_path); // directly call the save task function to save without delay + saveHistory(*m_save_history, m_history_path); // directly call the save task function to save without delay LOG_INFO("Save History"); } @@ -402,9 +403,9 @@ void rtIgnitionTask::run() if (m_counter_status > 0 && !m_partial_save) { LOG_DEBUG("Save Partial: ", m_counter_status); - // m_active_history->resize(m_counter_status); - // saveHistory(m_active_history, m_history_path); - // m_active_history->resize(m_max_history); + m_active_history->resize(m_counter_status); + saveHistory(*m_active_history, m_history_path); + m_active_history->resize(m_max_history); m_counter_status = 0; m_partial_save = true; } diff --git a/RotaxMonitor/src/tasks.h b/RotaxMonitor/src/tasks.h index 04f0af8..7b90902 100644 --- a/RotaxMonitor/src/tasks.h +++ b/RotaxMonitor/src/tasks.h @@ -41,7 +41,6 @@ static const std::map names = { class rtIgnitionTask { using PSHistory = PSRAMVector; - // using PSHistory = std::vector; public: // RT task Interrupt parameters diff --git a/RotaxMonitor/src/utils.cpp b/RotaxMonitor/src/utils.cpp index 0474abc..9674c3a 100644 --- a/RotaxMonitor/src/utils.cpp +++ b/RotaxMonitor/src/utils.cpp @@ -62,7 +62,7 @@ void printBar(Print &printer, const char *label, size_t used, size_t total, cons k += sprintf(&str[k], "-"); } - sprintf(&str[k], "] %s%6.2f%%%s (%5.3f/%5.3f)MB\n", + sprintf(&str[k], "] %s%6.2f%%%s (%5.3f/%5.3f)MB", color, perc * 100.0, COLOR_RESET, @@ -104,14 +104,14 @@ void printRunningTasksMod(Print &printer, std::function -#include - -static std::map s_webserverCommands = { - {"setTime", AstroWebServer::SET_TIME}, -}; void on_ping(TimerHandle_t xTimer) { @@ -32,6 +27,10 @@ AstroWebServer::AstroWebServer(const uint8_t port, fs::FS &filesystem) : m_port( m_websocket.enable(true); m_pingTimer = xTimerCreate("wsPingTimer", pdMS_TO_TICKS(2000), pdTRUE, (void *)&m_websocket, on_ping); + + registerWsCommand("setTime", [this](const ArduinoJson::JsonDocument &doc) + { onSetTme(doc); }); + LOG_DEBUG("Webserver Init OK"); } @@ -50,6 +49,21 @@ void AstroWebServer::sendWsData(const String &data) } } +void AstroWebServer::registerWsCommand(const std::string &cmd, const WScommand func) +{ + if (cmd.empty() || m_webserverCommands.contains(cmd)) + return; + if (!func) + return; + m_webserverCommands[cmd] = func; +} + +void AstroWebServer::unRegisterWsCommand(const std::string &cmd) +{ + if (m_webserverCommands.contains(cmd)) + m_webserverCommands.erase(cmd); +} + void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { switch (type) @@ -75,38 +89,13 @@ void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *cli LOG_ERROR("WS Client unable to deserialize Json"); return; } - if (!doc["cmd"].is() || !s_webserverCommands.contains(doc["cmd"])) + if (!doc["cmd"].is() || !m_webserverCommands.contains(doc["cmd"])) { LOG_WARN("WS Client Invalid Json command [", doc["cmd"].as().c_str(), "]"); return; } - std::string buffer; - switch (s_webserverCommands.at(doc["cmd"])) - { - case SET_TIME: - { - auto epoch = doc["time"].as(); - timeval te{ - .tv_sec = epoch, - .tv_usec = 0, - }; - timezone tz{ - .tz_minuteswest = 0, - .tz_dsttime = DST_MET, - }; - settimeofday(&te, &tz); - time_t now = time(nullptr); - struct tm *t = localtime(&now); - buffer.resize(64); - strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t); - LOG_DEBUG("WS Client set Datetime to: ", buffer.c_str()); - break; - } - - default: - // call external command callback - break; - } + // execute callback function + m_webserverCommands[doc["cmd"]](doc); } } } @@ -164,3 +153,23 @@ void AstroWebServer::onUploadHandler(AsyncWebServerRequest *request, const Strin LOG_INFO("Uploaded file to LittleFS:", filename.c_str()); } } + +void AstroWebServer::onSetTme(const ArduinoJson::JsonDocument &doc) +{ + std::string buffer; + auto epoch = doc["time"].as(); + timeval te{ + .tv_sec = epoch, + .tv_usec = 0, + }; + timezone tz{ + .tz_minuteswest = 0, + .tz_dsttime = DST_MET, + }; + settimeofday(&te, &tz); + time_t now = time(nullptr); + struct tm *t = localtime(&now); + buffer.resize(64); + strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t); + LOG_DEBUG("WS Client set Datetime to: ", buffer.c_str()); +} diff --git a/RotaxMonitor/src/webserver.h b/RotaxMonitor/src/webserver.h index c461787..c04a31e 100644 --- a/RotaxMonitor/src/webserver.h +++ b/RotaxMonitor/src/webserver.h @@ -8,11 +8,13 @@ #include #include #include - #include +#include class AstroWebServer { +public: + using WScommand = std::function; public: AstroWebServer(const uint8_t port, fs::FS &filesystem); @@ -20,6 +22,9 @@ public: void sendWsData(const String &data); + void registerWsCommand(const std::string &cmd, const WScommand func); + void unRegisterWsCommand(const std::string &cmd); + private: void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len); @@ -27,9 +32,7 @@ private: void onUploadRequest(AsyncWebServerRequest *request); void onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final); - void onStart(AsyncWebServerRequest *request); - void onStop(AsyncWebServerRequest *request); - void onDownload(AsyncWebServerRequest *request); + void onSetTme(const ArduinoJson::JsonDocument &doc); private: const uint8_t m_port = 80; @@ -39,10 +42,5 @@ private: bool m_uploadFailed = false; fs::File m_uploadFile; TimerHandle_t m_pingTimer = NULL; - -public: - enum c_commandEnum - { - SET_TIME - }; + std::map m_webserverCommands; };