#include "HermitCrab.h" #include "Config.h" #include "AHT2x.h" #include "NTC_10K.h" #include "ZCD.h" #include "History.h" #include "ConnectWiFi.h" #include "WiFiHost.h" #include "TimeManager.h" #include "OTA.h" #include "UI.h" #include "BLEScan.h" #include #include "esp_coexist.h" #include "hal/timer_ll.h" #define TAG_SETUP "TAG_SETUP" // Task handle TaskHandle_t TaskHandle_0; bool g_bWiFiSetupExecuted = false; bool g_bWiFiHasBeenConnected = false; extern STATUS_TYPE status; extern CHistory history; extern timg_dev_t *tg1; void setupConfig(); void setupStatus(); void restoreStatus(); void setupWiFi(); void setupPostWiFi(bool bBoot); void setupPins(); void setupSensor(); void setupZCD(); void setup_BLE(); void scanI2C(); void setup() { timer_ll_set_clock_prescale(tg1, 1, 80000); timer_ll_set_count_direction(tg1, 1, GPTIMER_COUNT_UP); tg1->hw_timer[1].loadhi.val = 0UL; tg1->hw_timer[1].loadlo.val = 0UL; tg1->hw_timer[1].load.val = 1UL; timer_ll_enable_alarm(tg1, 1, false); // No ISR needed for watchdog timer_ll_enable_counter(tg1, 1, true); // put your setup code here, to run once: #ifdef DEBUG Serial.begin(115200); #endif //esp_log_level_set("*", ESP_LOG_INFO); // Global log level //esp_log_level_set("BLE_POLL", ESP_LOG_INFO); // Module-specific level //esp_coex_preference_set(ESP_COEX_PREFER_BT); DPRINTLN(" **********************"); DPRINTF(" SETUP - Start - ver. %s type: %d\n", HC__VERSION, THIS_DEVICE_TYPE); DPRINTLN(" **********************"); g_bWiFiHasBeenConnected = false; g_bWiFiHasBeenConnected = false; g_nYear = 2024; g_nMonth = 10; g_nDay = 15; g_nHour = 0; g_nMinute = 0; g_nSecond = 0; bShowSensor = false; setupConfig(); setupStatus(); setupPins(); scanI2C(); setupSensor(); ui.setup(); ui.message(0, (char *) "WiFi..."); setupWiFi(); if (aht25.sensor() || aht10_0x39.sensor()) { ui.message(4, (char *) "Sensor... OK!"); } else { ui.message(4, (char *) "Sensor... None!"); } ui.message(5, (char *) "ZCD..."); setupZCD(); ui.message(5, (char *) "ZCD... OK!"); ui.message(6, (char *) "Setup OK!"); //if (!isWiFiConnected) delay(3000); ble.setupConnect(config.nBLESensorAddr, config.nBLESensorAddr2); // Restore Status restoreStatus(); // Create a task pinned to core 0 xTaskCreatePinnedToCore( core0Task, // Function to run as a task "Task0", // Task name 20480, // Stack size in words NULL, // Task input parameter 1, // Priority of the task &TaskHandle_0, // Task handle 0 // Core 0 ); DPRINTLN("Setup Completed\n========================\n"); } // ====================================================================== // // Setup // // ====================================================================== void setupConfig() { config.load(); history.loadPID(); config.m_nDeviceType = THIS_DEVICE_TYPE; } void setupWiFi() { // Set WiFiEvent WiFi.onEvent(WiFiEvent); strncpy(BLE_SSID, config.ssid, sizeof(BLE_SSID)); strncpy(BLE_PW, config.pw, sizeof(BLE_PW)); // Connect WiFi for OTA if (config.ssid[0] && config.pw[0]) { #if defined(ESP32) esp_wifi_set_max_tx_power(74); #elif defined(ESP8266) WiFi.setOutputPower(20.5f); pinMode(16,OUTPUT); digitalWrite(16, LOW); int c = 0; #endif DPRINTF("BOOT: Connecting to WiFi: SSID: '%s', PW: '%s'\n", config.ssid, config.pw); WiFi.mode(WIFI_STA); WiFi.begin(config.ssid, config.pw); unsigned long beginTime = millis(); while (WiFi.status() != WL_CONNECTED) { delay(250); DPRINT('.'); if (millis() - beginTime > 30000) break; } DPRINTLN(); if (WiFi.status() == WL_CONNECTED) { ledcWrite(PIN_LED_WIFI, PWM_FULL); // LED_OFF ui.message(0, (char *) "WiFi...OK!"); DPRINTLN("WiFi - Connected at SETUP"); DPRINTF("WiFi - SSID(%s) PW(%s) IP(%s)\n", config.ssid, config.pw, WiFi.localIP().toString().c_str()); g_bWiFiHasBeenConnected = true; setupPostWiFi(true); } else { DPRINTLN("WiFi - ** NOT ** Connected at SETUP."); //WiFi.disconnect(false, true, 500); } } } void setupPostWiFi(bool bBoot = false) { if (WiFi.status() == WL_CONNECTED) { // Time if (bBoot) ui.message(1, (char *) "Time..."); timeManager.begin(); vTaskDelay((bBoot ? 500 : 250)/portTICK_PERIOD_MS); timeManager.checkNTPResponse(); if (bBoot) { if (timeManager.hasNTPUpdate()) { ui.message(1, (char *) "Time...OK!"); // OTA DPRINTLN("Setup - TimeManager.begin()"); DPRINTLN("\n===============================\n"); DPRINTLN(" Trying OTA"); ui.message(2, (char *) "Update check..."); checkOTA(true); ui.message(2, (char *) "Update OK!"); DPRINTLN(" OTA Process completed!"); DPRINTLN("===============================\n"); } else { ui.message(2, (char *) "Update check SKIPPED!"); timeManager.sendNTPRequest(); } } // Host if (bBoot) ui.message(3, (char *) "Server..."); host.Setup(); DPRINTLN("Setup - host.Setup()"); if (bBoot) ui.message(3, (char *) "Server...OK!"); g_bWiFiSetupExecuted = true; } } void setupPins() { // --- Basic Digital Pin Initialization --- pinMode(PIN_HEATER1, OUTPUT); pinMode(PIN_HEATER2, OUTPUT); digitalWrite(PIN_HEATER1, HEATER_OFF); digitalWrite(PIN_HEATER2, HEATER_OFF); // --- 1. High Speed Group: Motor and Fan (~26kHz) --- // Core 2.0.17 uses APB (80MHz). 80MHz / (3 * 1024) ≈ 26kHz. ledcAttachChannel(PIN_MOTOR, PWM_26KHZ_FREQ, PWM_RESOLUTION, PWM_MOTOR_CHANNEL); ledcAttachChannel(PIN_FAN, PWM_26KHZ_FREQ, PWM_RESOLUTION, PWM_FAN_CHANNEL); // --- 2. Medium Speed Group: LED & Heaters (1221Hz) --- // 80MHz / (64 * 1024) = 1220.7Hz. ledcAttachChannel(PIN_LIGHT, PWM_1KHZ_FREQ, PWM_RESOLUTION, PWM_LIGHT_CHANNEL); ledcAttachChannel(PIN_LED_HEATER1, PWM_1KHZ_FREQ, PWM_RESOLUTION, PWM_HEATER1_CHANNEL); ledcAttachChannel(PIN_LED_HEATER2, PWM_1KHZ_FREQ, PWM_RESOLUTION, PWM_HEATER2_CHANNEL); // --- 3. Low Speed Group: Mist & WiFi LED (1.19Hz) --- // Initialized at 1Hz to bypass the slow divider calculation/WDT panic. // Must be ESP32 coer version 3.0.2 in ordre to set 1Hz ledcAttachChannel(PIN_MIST, PWM_1HZ_FREQ, PWM_RESOLUTION, PWM_MIST_CHANNEL); ledcAttachChannel(PIN_LED_WIFI, PWM_1HZ_FREQ, PWM_RESOLUTION, PWM_WIFI_LED_CHANNEL); // --- Initial State Writes --- ledcWrite(PIN_MOTOR, PWM_OFF); ledcWrite(PIN_FAN, PWM_OFF); ledcWrite(PIN_LIGHT, PWM_OFF); ledcWrite(PIN_MIST, PWM_OFF); ledcWrite(PIN_LED_WIFI, (PWM_FULL * 4) / 5); // 80% Initial Blink // Heaters (Inverted logic for MOSFET safety) ledcWrite(PIN_LED_HEATER1, PWM_FULL - PWM_OFF); ledcWrite(PIN_LED_HEATER2, PWM_FULL - PWM_OFF); } void setupStatus() { if (config.bStatusSaved) { status = config.statusSave; config.bStatusSaved = false; } // init sensor and counter status.nTemp1 = 0; status.nTemp2 = 0; status.nTemp3 = 0; status.nHumid1 = 0; status.nHumid2 = 0; status.zcdAC = 0; status.zcdLoad = 0; status.nFlags = 0x00; } void restoreStatus() { if (isWiFiConnected()) { if (timeManager.hasNTPUpdate()) { time_t now; time(&now); uint32_t gap = (uint32_t)now - config.statusSave.now; DPRINTF("Reboot within %.1f seconds after last reset... \n", gap / 1000.0f); if (gap < 60000 && config.bStatusSaved) { status = config.statusSave; status.nFlags |= (uint16_t)(config.statusSave.nFlags & 0xFF); status.nLightDuty = 0; config.bStatusSaved = false; DPRINTLN(" Status Restored!"); } else { DPRINTLN(" Status NOT Restored!"); } } } } void scanI2C() { Wire.begin(); DPRINTLN("I2C - Scanning..."); for (byte addr = 1; addr < 127; addr++) { Wire.beginTransmission(addr); if (Wire.endTransmission() == 0) { DPRINTF("I2C - Found device at address: 0x%02X\n", addr); } } DPRINTLN(" Scanning Done."); } void setupSensor() { // AHTx0 if (aht25.setup()) { delay(82); aht25.readSensor(millis()); DPRINTF("AHT25 initialized successfully at 0x38. Temp: %.2f, Humid: %.2f%%\n", aht25.getTemperature() / 100.0f, aht25.getHumidity() / 100.0f); } delay(10); if (aht10_0x39.setup(0x39)) { //begin(PIN_SCL, PIN_SDA, AHT10_ADDRESS_0X39)) { delay(82); if (aht10_0x39.readSensor(millis())) { //aht10_0x39.initBuffer(); } DPRINTF("AHTx0 initialized successfully at 0x39. Temp: %.2f, Humid: %.2f%%\n", aht10_0x39.getTemperature() / 100.0f , aht10_0x39.getHumidity() / 100.0f ); } delay(10); history.init(status.nTemp1, status.nHumid1); if (!aht25.sensor() && !aht10_0x39.sensor()) { DPRINTF("AHTx0 initialization failed. SCL:%d SDA:%d\n", PIN_SCL, PIN_SDA ); } // Temp3 - NTC ntc.setup(config.bNTCNegativePolarity); status.nTemp3 = ntc.getTemp(); }