/********* Pleasedontcode.com ********** Pleasedontcode thanks you for automatic code generation! Enjoy your code! - Terms and Conditions: You have a non-exclusive, revocable, worldwide, royalty-free license for personal and commercial use. Attribution is optional; modifications are allowed, but you're responsible for code maintenance. We're not liable for any loss or damage. For full terms, please visit pleasedontcode.com/termsandconditions. - Project: "ESP32 Automation" - Source Code NOT compiled for: ESP32 DevKit V1 - Source Code created on: 2024-07-17 00:16:29 ********* Pleasedontcode.com **********/ /****** SYSTEM REQUIREMENTS *****/ /****** SYSTEM REQUIREMENT 1 *****/ /* create a web server for setting sid and password */ /* and showing time on rtc once esp32 has wifi */ /* connection update rtc from nst. tun on relay1 */ /* every second and relay2 every 30 seconds using */ /* time from rtc */ /****** END SYSTEM REQUIREMENTS *****/ /****** DEFINITION OF LIBRARIES *****/ #include #include //https://github.com/NorthernWidget/DS3231 #include //https://github.com/tzapu/WiFiManager.git #include #include #include #include #include #include #ifdef ESP32 #include #endif /****** FUNCTION PROTOTYPES *****/ void setup(void); void loop(void); void updateOutputs(void); void saveConfigCallback(void); void isr_TickTock(void); void handleRoot(void); void handleNotFound(void); void updateRTCFromNTP(void); /***** DEFINITION OF DIGITAL OUTPUT PINS *****/ const uint8_t relay1_RelayModule_Signal_PIN_D4 = 4; const uint8_t relay2_RelayModule_Signal_PIN_D13 = 13; /***** DEFINITION OF I2C PINS *****/ const uint8_t rtc_DS3231_I2C_PIN_SDA_D21 = 21; const uint8_t rtc_DS3231_I2C_PIN_SCL_D22 = 22; const uint8_t rtc_DS3231_I2C_SLAVE_ADDRESS = 104; /***** DEFINITION OF OUTPUT RAW VARIABLES *****/ /***** used to store raw data *****/ bool relay1_RelayModule_Signal_PIN_D4_rawData = 0; bool relay2_RelayModule_Signal_PIN_D13_rawData = 0; /***** DEFINITION OF OUTPUT PHYSICAL VARIABLES *****/ /***** used to store data after characteristic curve transformation *****/ float relay1_RelayModule_Signal_PIN_D4_phyData = 0.0; float relay2_RelayModule_Signal_PIN_D13_phyData = 0.0; /****** DEFINITION OF LIBRARIES CLASS INSTANCES*****/ DS3231 myRTC; // Initialize DS3231 object WiFiManager wifiManager; // Initialize WiFiManager object WebServer server(80); // Initialize WebServer on port 80 WiFiUDP ntpUDP; // Initialize WiFiUDP object NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // Initialize NTPClient to get time from NTP server /****** WiFiManager Custom Parameters *****/ char mqtt_server[40]; char mqtt_port[6] = "8080"; char api_token[34] = "YOUR_API_TOKEN"; bool shouldSaveConfig = false; /****** WiFiManager Custom Parameters Instances *****/ WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40); WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6); WiFiManagerParameter custom_api_token("apikey", "API token", api_token, 32); void saveConfigCallback() { Serial.println("Should save config"); shouldSaveConfig = true; } void setup(void) { // Initialize I2C communication Wire.begin(rtc_DS3231_I2C_PIN_SDA_D21, rtc_DS3231_I2C_PIN_SCL_D22); // Initialize Serial communication for debugging Serial.begin(9600); while (!Serial); // Print initialization message Serial.println("Starting Serial"); // Initialize relay pins as outputs pinMode(relay1_RelayModule_Signal_PIN_D4, OUTPUT); pinMode(relay2_RelayModule_Signal_PIN_D13, OUTPUT); // Set Alarm 1 to fire every second myRTC.turnOffAlarm(1); myRTC.setA1Time(0, 0, 0, 0, 0b00001111, false, false, false); myRTC.turnOnAlarm(1); myRTC.checkIfAlarm(1); // Prevent Alarm 2 from interfering myRTC.setA2Time(0, 0, 0xFF, 0b01100000, false, false, false); myRTC.turnOffAlarm(2); myRTC.checkIfAlarm(2); // Attach clock interrupt pinMode(2, INPUT_PULLUP); // Assuming interrupt pin is GPIO 2 attachInterrupt(digitalPinToInterrupt(2), isr_TickTock, FALLING); // Use built-in LED to blink pinMode(LED_BUILTIN, OUTPUT); // Initialize SPIFFS if (SPIFFS.begin()) { if (SPIFFS.exists("/config.json")) { File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { size_t size = configFile.size(); std::unique_ptr buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonDocument json(1024); if (!deserializeJson(json, buf.get())) { strcpy(mqtt_server, json["mqtt_server"]); strcpy(mqtt_port, json["mqtt_port"]); strcpy(api_token, json["api_token"]); } configFile.close(); } } } // Set WiFiManager custom parameters wifiManager.setSaveConfigCallback(saveConfigCallback); wifiManager.addParameter(&custom_mqtt_server); wifiManager.addParameter(&custom_mqtt_port); wifiManager.addParameter(&custom_api_token); // Attempt to connect to WiFi if (!wifiManager.autoConnect("AutoConnectAP", "password")) { Serial.println("Failed to connect and hit timeout"); ESP.restart(); } Serial.println("Connected to WiFi"); // Save custom parameters strcpy(mqtt_server, custom_mqtt_server.getValue()); strcpy(mqtt_port, custom_mqtt_port.getValue()); strcpy(api_token, custom_api_token.getValue()); if (shouldSaveConfig) { DynamicJsonDocument json(1024); json["mqtt_server"] = mqtt_server; json["mqtt_port"] = mqtt_port; json["api_token"] = api_token; File configFile = SPIFFS.open("/config.json", "w"); if (configFile) { serializeJson(json, configFile); configFile.close(); } } Serial.println("Local IP: " + WiFi.localIP().toString()); // Initialize web server routes server.on("/", handleRoot); server.onNotFound(handleNotFound); server.begin(); // Initialize NTP client timeClient.begin(); } void loop(void) { // Handle web server server.handleClient(); // Update NTP client timeClient.update(); // Update RTC from NTP if not already updated static bool rtcUpdated = false; if (!rtcUpdated && WiFi.status() == WL_CONNECTED) { updateRTCFromNTP(); rtcUpdated = true; } updateOutputs(); // Refresh output data static byte state = false; static volatile byte tick = 1; // If alarm went off, toggle LED if (tick) { tick = 0; state = !state; digitalWrite(LED_BUILTIN, state); // Optional serial output Serial.print("Turning LED "); Serial.println(state ? "ON" : "OFF"); // Clear Alarm 1 flag myRTC.checkIfAlarm(1); } // Loop delay to emulate other running code delay(10); } void updateOutputs() { // Get current time from RTC DateTime now = myRTC.getDateTime(); // Turn on relay1 every second relay1_RelayModule_Signal_PIN_D4_rawData = (now.second % 2 == 0); // Turn on relay2 every 30 seconds relay2_RelayModule_Signal_PIN_D13_rawData = (now.second % 30 == 0); // Update relay states digitalWrite(relay1_RelayModule_Signal_PIN_D4, relay1_RelayModule_Signal_PIN_D4_rawData); digitalWrite(relay2_RelayModule_Signal_PIN_D13, relay2_RelayModule_Signal_PIN_D13_rawData); } void isr_TickTock() { // Interrupt signals to loop static volatile byte tick = 1; } void handleRoot() { String html = "

ESP32 Web Server

"; html += "

Current Time: " + myRTC.getDateTime().toString() + "

"; html += "
"; html += "SSID:
"; html += "Password:
"; html += ""; html += "
"; server.send(200, "text/html", html); } void handleNotFound() { server.send(404, "text/plain", "404: Not found"); } void updateRTCFromNTP() { // Get time from NTP time_t epochTime = timeClient.getEpochTime(); struct tm *ptm = gmtime(&epochTime); // Update RTC with NTP time myRTC.setDateTime(ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); Serial.println("RTC updated from NTP"); }