/********* 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 */