/********* 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: "Web Server" - Source Code NOT compiled for: ESP32 DevKit V1 - Source Code created on: 2024-10-22 10:02:09 ********* Pleasedontcode.com **********/ /****** SYSTEM REQUIREMENTS *****/ /****** SYSTEM REQUIREMENT 1 *****/ /* merge code. */ /****** END SYSTEM REQUIREMENTS *****/ /* START CODE */ /****** DEFINITION OF LIBRARIES *****/ #include #include "ACS712.h" #include #include #include #include #include #include #include #include "X9C10X.h" /****** FUNCTION PROTOTYPES *****/ void setup(void); void loop(void); // Access Point credentials char ssid[] = "pleasedontcode.com"; // your network SSID (name) char pass[] = "prova1234"; // your network password (use for WPA, or use as key for WEP) // Create an instance of the web server AsyncWebServer server(80); TinyGPSPlus gps; #define VELOCITA_SOGLIA_HIGH 75.0 //km/h #define VELOCITA_SOGLIA_LOW 65.0 //km/h #define VELOCITA_SOGLIA_0A_HIGH 20.0 //km/h - soglia sotto 15km/h si spegne l'erogazione corrente #define VELOCITA_SOGLIA_0A_LOW 10.0 //km/h //PINS const int water_level_pin = 18; const int voltage_pin = 35; const int current_pin = 34; const int tempSensor1_pin = 33; const int tempSensor2_pin = 32; const int ONE_WIRE_BUS_Temp1 = 19; //sonda temp 1 const int ONE_WIRE_BUS_Temp2 = 21; //sonda temp 2 const int DIGPOT_INC = 4; // pin INC - X9C103S const int DIGPOT_UD = 5; // pin UD - X9C103S const int DIGPOT_CS = 15; // pin CS - X9C103S const float PWM_output_percentage_0A = 0.0; //0% const float PWM_output_percentage_9A = 20.0; //20% --> 1V/5V const float PWM_output_percentage_5A = 13.0; //13% --> 0,65V/5V // DATI globali da trasferire float PWM_output_percentage = 0.0; float velocita = 0.0; float voltage_output_value = 0.0; bool waterLevelEmpty = true; float voltage = 0.0; float current = 0.0; float temperature1 = 0.0; float temperature2 = 0.0; unsigned long powerOnTime = 0; //minutes boolean startRegeneration = false; unsigned int set_current = 0; unsigned int set_timer = 0; //configurazione ACS712 da 30A unsigned int ADC_Offset = 1930; ACS712 ACS(current_pin, 3.3, 4095, 40); //pin 34 per acquisizione sensore corrente; l'alimentazione sensore è 3.3V X9C10X pot(10000); // 10KΩ - potenziometro digitale X9C103S da 10kΩ void printWiFiStatus(); void printWebPage(); void checkClientRequest(String currentLine); bool ReplyWebPageContent = true; bool ReplyResetTime = false; bool postUpdateData = false; static const int GPSBaud = 9600; // The serial connection to the GPS device #define ss Serial2 unsigned long TEMPO_ATTESA_VISUALIZZAZIONE_VELOCITA = 300; unsigned long SpeedShowTimer = 0; // Counter to track seconds unsigned long secondsCounter = 0; unsigned long previousMillis = millis(); // Variable to store the previous millis value unsigned long currentMillis = millis(); unsigned long minutesCounter = 0; // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire1(ONE_WIRE_BUS_Temp1); OneWire oneWire2(ONE_WIRE_BUS_Temp2); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensor1(&oneWire1); DallasTemperature sensor2(&oneWire2); /****** DEFINITION OF ANALOG INPUTS CHARACTERISTIC CURVES *****/ const uint8_t SEGMENT_POINTS_voltage_Temperature = 10; const float voltage_Temperature_lookup[2][SEGMENT_POINTS_voltage_Temperature] = { {0.0, 1.2, 1.9, 5.0, 10.0, 14.5, 17.0, 20.0, 30.0, 35.0}, // corrente [V] {0.0, 5.0, 7.0, 13.0, 22.0, 29.0, 33.0, 37.0, 56.0, 65.0} // percentuale [°C] }; // Initialize SPIFFS for file storage void initSPIFFS() { if (!SPIFFS.begin(true)) { Serial.println("An error occurred while mounting SPIFFS"); return; } Serial.println("SPIFFS mounted successfully"); } void setup() { // Start Serial for debugging Serial.begin(115200); delay(1000); Serial.println("ciao"); pot.begin(DIGPOT_INC, DIGPOT_UD, DIGPOT_CS); // pulse, direction, select // INC = 4, UD = 5, CS = 15 //NON TOGLIERE - SERVE PER NON FAR SBARELLARE LA MACCHINA for(int i=0; i<10;i++) { setCurrentOutput(0); delay(20); setCurrentOutput(100); delay(20); } setCurrentOutput(PWM_output_percentage); readMinutesCounterFromEEPROM(); ss.begin(GPSBaud); Serial.println("ciao2"); sensor1.begin(); sensor2.begin(); smartDelay(1000); ACS.setMidPoint(ADC_Offset); Serial.println(F("Access Point Web Server")); // Initialize SPIFFS initSPIFFS(); WiFi.mode(WIFI_AP); // Set the ESP32 to access point mode if (!WiFi.softAP(ssid, pass)) { Serial.println("Soft AP creation failed."); while(1); } // Print the IP address of the access point IPAddress IP = WiFi.softAPIP(); Serial.print("Access Point IP Address: "); Serial.println(IP); // Serve the JPEG image server.on("/background.jpg", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("0"); request->send(SPIFFS, "/background.jpg", "image/jpeg"); }); // Serve the HTML page server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("1"); request->send(SPIFFS, "/index.html", "text/html"); }); server.on("/UPDATEDATA", HTTP_POST, [](AsyncWebServerRequest *request) { // Log post request handling //Serial.println("postUpdateData"); // Allocate a temporary JsonDocument StaticJsonDocument<512> doc; // Gather data and populate JSON updateData(doc); // Convert the JSON document to string and send it in response String response; serializeJsonPretty(doc, response); request->send(200, "application/json", response); }); // Start the server server.begin(); } void loop() { // No logic in the loop; the server works asynchronously readGPSAndCheckSpeed(); readCurrent(); readVoltage(); readWaterTank(); readTemp1(); readTemp2(); updateMinutesCounter(); checkRegeneration(); } // The updateData function to generate the JSON payload void updateData(JsonDocument &doc) { if (velocita > 0.0) { doc["speed"] = String(velocita) + String(F(" km/h")); } else { doc["speed"] = String(F("ERROR")); } doc["voltageCommandOut"] = String(F("Tensione uscita comando: ")) + String(voltage_output_value) + String(F("/3.3 [V]")); doc["percentageCommandOut"] = String(F("Uscita comando PWM: ")) + String(PWM_output_percentage) + String(F(" [%]")); doc["waterTankLevel"] = waterLevelEmpty ? String(F("VUOTO")) : String(F("PIENO")); doc["powerOnTime"] = String(powerOnTime) + String(F(" min")); doc["current"] = String(current) + String(F(" A")); doc["voltage"] = String(voltage) + String(F(" V")); doc["temperature1"] = String(temperature1) + String(F(" °C")); doc["temperature2"] = String(temperature2) + String(F(" °C")); doc["set_timer"] = String(F("Timer : ")) + String(set_timer) + String(F(" min")); } void checkRegeneration() { if(set_timer == 0) { startRegeneration = false; } } void readMinutesCounterFromEEPROM() { // Read the counter value from EEPROM unsigned long max_minutesCounter = 0UL - 1UL; EEPROM.begin(sizeof(powerOnTime)); EEPROM.get( 0, powerOnTime ); if(powerOnTime == max_minutesCounter) { powerOnTime = 0; Serial.println("Minutes Counter reinitialized"); saveMinutesCounterInEEPROM(); } Serial.print("powerOnTime: "); Serial.println(powerOnTime); } void updateMinutesCounter() { currentMillis = millis(); if( (currentMillis - previousMillis) > 1000) { previousMillis = currentMillis; secondsCounter++; if(secondsCounter % 60 == 0) { secondsCounter = 0; minutesCounter++; powerOnTime++; if(minutesCounter % 10 == 0) { //salva contatore in EEPROM ogni 10 minuti saveMinutesCounterInEEPROM(); } Serial.print("cumulatedMinutesCounter:"); Serial.println(powerOnTime); if(set_timer > 0) { set_timer--; } } } } void saveMinutesCounterInEEPROM() { EEPROM.put(0, powerOnTime); EEPROM.commit(); } void readGPSAndCheckSpeed() { if(startRegeneration == false) { while (ss.available() > 0) { if (gps.encode(ss.read())) { checkSpeed(); } } if (millis() > 5000 && gps.charsProcessed() < 10) { velocita = -1.0; PWM_output_percentage = PWM_output_percentage_0A; setCurrentOutput(PWM_output_percentage); } } else { PWM_output_percentage = lookup_phyData_from_voltage(set_current, SEGMENT_POINTS_voltage_Temperature, &(voltage_Temperature_lookup[0][0])); setCurrentOutput(PWM_output_percentage); } } void setCurrentOutput(float PWM_outputPercentage) { pot.setPosition(PWM_outputPercentage); // position voltage_output_value = PWM_outputPercentage*5.0/100.0; } void readCurrent(){ int mA = ACS.mA_DC(30); //30 acquisizioni di media float tempCurrent = float(mA)/1000; current = current*0.7 + tempCurrent*0.3; } void readVoltage() { // Floats for ADC voltage & Input voltage float adc_voltage = 0.0; // Floats for resistor values in divider (in ohms) float R1 = 30000.0; float R2 = 7500.0; // Float for Reference Voltage float ref_voltage = 3.3; // Read the Analog Input float adc_value = analogRead(voltage_pin); // Determine voltage at ADC input adc_voltage = (adc_value * ref_voltage) / 4096.0; // Calculate voltage at divider input voltage = adc_voltage*(R1+R2)/R2; } void readWaterTank() { waterLevelEmpty = digitalRead(water_level_pin); } void checkSpeed() { if (gps.location.isValid()) { velocita = gps.speed.kmph(); if(millis() - SpeedShowTimer > TEMPO_ATTESA_VISUALIZZAZIONE_VELOCITA) { if(velocita > VELOCITA_SOGLIA_HIGH) { PWM_output_percentage = PWM_output_percentage_9A; setCurrentOutput(PWM_output_percentage); } else if(velocita > VELOCITA_SOGLIA_0A_HIGH && velocita < VELOCITA_SOGLIA_LOW) { PWM_output_percentage = PWM_output_percentage_5A; setCurrentOutput(PWM_output_percentage); } else if(velocita < VELOCITA_SOGLIA_0A_LOW) { PWM_output_percentage = PWM_output_percentage_0A; setCurrentOutput(PWM_output_percentage); } SpeedShowTimer = millis(); } } else { Serial.println(F("NO GPS FIX!")); velocita = -1.0; PWM_output_percentage = PWM_output_percentage_0A; setCurrentOutput(PWM_output_percentage); } } void displayInfo() { Serial.print(F("Location: ")); printInt(gps.satellites.value(), gps.satellites.isValid(), 5); printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1); printFloat(gps.location.lat(), gps.location.isValid(), 11, 6); printFloat(gps.location.lat(), gps.location.isValid(), 11, 6); printFloat(gps.location.lng(), gps.location.isValid(), 12, 6); while(1); Serial.print(gps.location.lat(), 6); Serial.print(F(",")); Serial.print(gps.location.lng(), 6); Serial.print(gps.date.month()); Serial.print(F("/")); Serial.print(gps.date.day()); Serial.print(F("/")); Serial.print(gps.date.year()); if (gps.location.isValid()) { Serial.print(gps.location.lat(), 6); Serial.print(F(",")); Serial.print(gps.location.lng(), 6); } else { Serial.print(F("INVALID")); } Serial.print(F(" Date/Time: ")); if (gps.date.isValid()) { Serial.print(gps.date.month()); Serial.print(F("/")); Serial.print(gps.date.day()); Serial.print(F("/")); Serial.print(gps.date.year()); } else { Serial.print(F("INVALID")); } Serial.print(F(" ")); if (gps.time.isValid()) { if (gps.time.hour() < 10) Serial.print(F("0")); Serial.print(gps.time.hour()); Serial.print(F(":")); if (gps.time.minute() < 10) Serial.print(F("0")); Serial.print(gps.time.minute()); Serial.print(F(":")); if (gps.time.second() < 10) Serial.print(F("0")); Serial.print(gps.time.second()); Serial.print(F(".")); if (gps.time.centisecond() < 10) Serial.print(F("0")); Serial.print(gps.time.centisecond()); } else { Serial.print(F("INVALID")); } Serial.println(); } static void printFloat(float val, bool valid, int len, int prec) { if (!valid) { while (len-- > 1) Serial.print('*'); Serial.print(' '); } else { Serial.print(val, prec); int vi = abs((int)val); int flen = prec + (val < 0.0 ? 2 : 1); // . and - flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1; for (int i=flen; i 0) sz[len-1] = ' '; Serial.print(sz); smartDelay(0); } // This custom version of delay() ensures that the gps object // is being "fed". static void smartDelay(unsigned long ms) { unsigned long start = millis(); do { while (ss.available()) gps.encode(ss.read()); } while (millis() - start < ms); } void resetDataRegeneration() { PWM_output_percentage = PWM_output_percentage_0A; setCurrentOutput(PWM_output_percentage); startRegeneration = false; set_current = 0; set_timer = 0; } void extractSubstring(String str, char delimiter) { int startIndex = 0; int endIndex = str.indexOf(delimiter); int counter = 0; while(endIndex != -1) { String part = str.substring(startIndex, endIndex); Serial.println(part); if(counter == 0) { counter++; // qui c'è 'POST' } else if (counter == 1) { set_current = part.toInt(); counter++; } else if (counter == 2) { set_timer = part.toInt(); counter++; } startIndex = endIndex + 1; endIndex = str.indexOf(delimiter, startIndex); } } float lookup_phyData_from_voltage(float voltage, int segment_points, const float* voltage_phyData_lookup) { // Search table for appropriate value. uint8_t index = 0; const float *voltagePointer = &voltage_phyData_lookup[0]; const float *phyDataPointer = &voltage_phyData_lookup[segment_points]; // Perform minimum and maximum voltage saturation based on characteristic curve voltage = min(voltage, voltagePointer[segment_points-1]); voltage = max(voltage, voltagePointer[0]); while( voltagePointer[index] <= voltage && index < segment_points ) index++; // If index is zero, physical value is smaller than our table range if( index==0 ) { return map_f( voltage, voltagePointer[0], // X1 voltagePointer[1], // X2 phyDataPointer[0], // Y1 phyDataPointer[1] ); // Y2 } // If index is maxed out, phyisical value is larger than our range. else if( index==segment_points ) { return map_f( voltage, voltagePointer[segment_points-2], // X1 voltagePointer[segment_points-1], // X2 phyDataPointer[segment_points-2], // Y1 phyDataPointer[segment_points-1] ); // Y2 } // index is between 0 and max, just right else { return map_f( voltage, voltagePointer[index-1], // X1 voltagePointer[index], // X2 phyDataPointer[index-1], // Y1 phyDataPointer[index] ); // Y2 } } float map_f(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } static float voltage_average_temp1 = 0.0; static float voltage_average_temp2 = 0.0; void readTemp1() { sensor1.requestTemperatures(); // Send the command to get temperatures temperature1 =sensor1.getTempCByIndex(0); if(temperature1 == DEVICE_DISCONNECTED_C) { temperature1 = -100; } } void readTemp2() { sensor2.requestTemperatures(); // Send the command to get temperatures temperature2 =sensor2.getTempCByIndex(0); if(temperature2 == DEVICE_DISCONNECTED_C) { temperature2 = -100; } } /* END CODE */