first commit
This commit is contained in:
1438
ESP8266_BATTERIE_INJECTION/ESP8266_BATTERIE_INJECTION.ino
Normal file
1438
ESP8266_BATTERIE_INJECTION/ESP8266_BATTERIE_INJECTION.ino
Normal file
File diff suppressed because it is too large
Load Diff
73
ESP8266_BATTERIE_INJECTION/common.h
Normal file
73
ESP8266_BATTERIE_INJECTION/common.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// =======================
|
||||
// WIFI
|
||||
// =======================
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
ESP8266WebServer server(80);
|
||||
|
||||
#elif defined(ESP32)
|
||||
#include "WebServer.h"
|
||||
#include <HardwareSerial.h>
|
||||
#include <SoftwareSerial.h>
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
WebServer server(80);
|
||||
|
||||
#endif
|
||||
|
||||
void handleRoot();
|
||||
void stopCharge();
|
||||
void charge();
|
||||
void injection();
|
||||
void stopInjection();
|
||||
void setPwm(int pwm);
|
||||
|
||||
double conso_apparente = 0;
|
||||
double production = 0;
|
||||
String last_message = "";
|
||||
// String getParamFromGet(String to_search)
|
||||
// {
|
||||
// String message = "Number of args received:";
|
||||
//
|
||||
// message += server.args();
|
||||
//
|
||||
// for (int i = 0; i < server.args(); i++) {
|
||||
// message = message + ("Arg nº" + String(i) + " –> ");
|
||||
// message = message + (server.argName(i) + ": ");
|
||||
// message = message + (server.arg(i) + "\n");
|
||||
// if (to_search.equals(String(server.argName(i)))) {
|
||||
// Serial.println(message);
|
||||
//
|
||||
// return String(server.arg(i));
|
||||
// }
|
||||
// }
|
||||
// Serial.println(message);
|
||||
// return String("");
|
||||
// }
|
||||
|
||||
String getParamFromGet(String to_search)
|
||||
{
|
||||
// String message = "Number of args received:";
|
||||
//
|
||||
// message += server.args();
|
||||
|
||||
for (int i = 0; i < server.args(); i++) {
|
||||
// message = message + ("Arg nº" + String(i) + " –> ");
|
||||
// message = message + (server.argName(i) + ": ");
|
||||
// message = message + (server.arg(i) + "\n");
|
||||
if (to_search.equals(String(server.argName(i)))) {
|
||||
// Serial.println(message);
|
||||
|
||||
return String(server.arg(i));
|
||||
}
|
||||
}
|
||||
// Serial.println(message);
|
||||
return String("");
|
||||
}
|
||||
|
||||
// Fonction pour vérifier si l'adresse IP est locale
|
||||
bool isLocalIP(IPAddress ip) {
|
||||
return (ip[0] == 192 && ip[1] == 168) || (ip[0] == 10) || (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31);
|
||||
}
|
||||
396
ESP8266_BATTERIE_INJECTION/config.h
Normal file
396
ESP8266_BATTERIE_INJECTION/config.h
Normal file
@@ -0,0 +1,396 @@
|
||||
const int maxSize = 60; // Taille du tableau
|
||||
|
||||
//--------------------------- SETUP -------------------------------------
|
||||
|
||||
#define MPPT_100_20 // Define used Victron Device
|
||||
|
||||
// Supported:
|
||||
// "MPPT 75 | 10"
|
||||
// "MPPT 75 | 15" tested with FW 1.56
|
||||
// "MPPT 100 | 20" tested with FW 1.5 / 1.56
|
||||
// "MPPT 100 | 30" tested with FW 1.59
|
||||
|
||||
//--------------------------- SETUP -------------------------------------
|
||||
|
||||
|
||||
|
||||
// MPPT 75 | 10
|
||||
#ifdef MPPT_75_10
|
||||
#define MAX_AMPERAGE 10
|
||||
|
||||
const byte buffsize = 32;
|
||||
const byte value_bytes = 33;
|
||||
const byte label_bytes = 9;
|
||||
const byte num_keywords = 18;
|
||||
|
||||
char keywords[num_keywords][label_bytes] = {
|
||||
"PID",
|
||||
"FW",
|
||||
"SER#",
|
||||
"V",
|
||||
"I",
|
||||
"VPV",
|
||||
"PPV",
|
||||
"CS",
|
||||
"ERR",
|
||||
"LOAD",
|
||||
"IL",
|
||||
"H19",
|
||||
"H20",
|
||||
"H21",
|
||||
"H22",
|
||||
"H23",
|
||||
"HSDS",
|
||||
"Checksum"
|
||||
};
|
||||
#define PID 0
|
||||
#define FW 1
|
||||
#define SER 2 // Offically SER# but # does not play that well as macro
|
||||
#define V 3 // ScV
|
||||
#define I 4 // ScI
|
||||
#define VPV 5 // PVV
|
||||
#define PPV 6 // PVI = PVV / VPV
|
||||
#define CS 7 // ScS
|
||||
#define ERR 8 // ScERR
|
||||
#define LOAD 9 // SLs
|
||||
#define IL 10 // SLI
|
||||
#define H19 11
|
||||
#define H20 12
|
||||
#define H21 13
|
||||
#define H22 14
|
||||
#define H23 15
|
||||
#define HSDS 16
|
||||
#define CHECKSUM 17
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// MPPT 75 | 15
|
||||
#ifdef MPPT_75_15
|
||||
#define MAX_AMPERAGE 15
|
||||
|
||||
const byte buffsize = 32;
|
||||
const byte value_bytes = 33;
|
||||
const byte label_bytes = 9;
|
||||
const byte num_keywords = 19;
|
||||
|
||||
char keywords[num_keywords][label_bytes] = {
|
||||
"PID",
|
||||
"FW",
|
||||
"SER#",
|
||||
"V",
|
||||
"I",
|
||||
"VPV",
|
||||
"PPV",
|
||||
"CS",
|
||||
"MPPT",
|
||||
"ERR",
|
||||
"LOAD",
|
||||
"IL",
|
||||
"H19",
|
||||
"H20",
|
||||
"H21",
|
||||
"H22",
|
||||
"H23",
|
||||
"HSDS",
|
||||
"Checksum"
|
||||
};
|
||||
#define PID 0
|
||||
#define FW 1
|
||||
#define SER 2 // Offically SER# but # does not play that well as macro
|
||||
#define V 3 // ScV
|
||||
#define I 4 // ScI
|
||||
#define VPV 5 // PVV
|
||||
#define PPV 6 // PVI = PVV / VPV
|
||||
#define CS 7 // ScS
|
||||
#define MPPT 8
|
||||
#define ERR 9 // ScERR
|
||||
#define LOAD 10 // SLs
|
||||
#define IL 11 // SLI
|
||||
#define H19 12
|
||||
#define H20 13
|
||||
#define H21 14
|
||||
#define H22 15
|
||||
#define H23 16
|
||||
#define HSDS 17
|
||||
#define CHECKSUM 18
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// MPPT 100 | 20
|
||||
#ifdef MPPT_100_20
|
||||
#define MAX_AMPERAGE 20
|
||||
|
||||
const byte buffsize = 32;
|
||||
const byte value_bytes = 33;
|
||||
const byte label_bytes = 9;
|
||||
const byte num_keywords = 20;
|
||||
|
||||
char keywords[num_keywords][label_bytes] = {
|
||||
"PID",
|
||||
"FW",
|
||||
"SER#",
|
||||
"V",
|
||||
"I",
|
||||
"VPV",
|
||||
"PPV",
|
||||
"CS",
|
||||
"MPPT",
|
||||
"OR",
|
||||
"ERR",
|
||||
"LOAD",
|
||||
"IL",
|
||||
"H19",
|
||||
"H20",
|
||||
"H21",
|
||||
"H22",
|
||||
"H23",
|
||||
"HSDS",
|
||||
"Checksum"
|
||||
};
|
||||
#define PID 0
|
||||
#define FW 1
|
||||
#define SER 2
|
||||
#define V 3
|
||||
#define I 4
|
||||
#define VPV 5
|
||||
#define PPV 6
|
||||
#define MPPT 7
|
||||
#define OR 8
|
||||
#define CS 9
|
||||
#define ERR 10
|
||||
#define LOAD 11
|
||||
#define IL 12
|
||||
#define H19 13
|
||||
#define H20 14
|
||||
#define H21 15
|
||||
#define H22 16
|
||||
#define H23 17
|
||||
#define HSDS 18
|
||||
#define CHECKSUM 19
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// MPPT 100 | 30
|
||||
#ifdef MPPT_100_30
|
||||
#define MAX_AMPERAGE 30
|
||||
|
||||
const byte buffsize = 32;
|
||||
const byte value_bytes = 33;
|
||||
const byte label_bytes = 9;
|
||||
const byte num_keywords = 20;
|
||||
|
||||
char keywords[num_keywords][label_bytes] = {
|
||||
"PID",
|
||||
"FW",
|
||||
"SER#",
|
||||
"V",
|
||||
"I",
|
||||
"VPV",
|
||||
"PPV",
|
||||
"CS",
|
||||
"MPPT",
|
||||
"OR",
|
||||
"ERR",
|
||||
"LOAD",
|
||||
"IL",
|
||||
"H19",
|
||||
"H20",
|
||||
"H21",
|
||||
"H22",
|
||||
"H23",
|
||||
"HSDS",
|
||||
"Checksum"
|
||||
};
|
||||
#define PID 0
|
||||
#define FW 1
|
||||
#define SER 2
|
||||
#define V 3
|
||||
#define I 4
|
||||
#define VPV 5
|
||||
#define PPV 6
|
||||
#define MPPT 7
|
||||
#define OR 8
|
||||
#define CS 9
|
||||
#define ERR 10
|
||||
#define LOAD 11
|
||||
#define IL 12
|
||||
#define H19 13
|
||||
#define H20 14
|
||||
#define H21 15
|
||||
#define H22 16
|
||||
#define H23 17
|
||||
#define HSDS 18
|
||||
#define CHECKSUM 19
|
||||
|
||||
#endif
|
||||
|
||||
struct ErrorCode {
|
||||
const char* code;
|
||||
const char* label;
|
||||
};
|
||||
|
||||
ErrorCode errorCodes[] = {
|
||||
{"0", "No error"},
|
||||
{"2", "Battery voltage too high"},
|
||||
{"17", "Charger temperature too high"},
|
||||
{"18", "Charger over current"},
|
||||
{"19", "Charger current reversed"},
|
||||
{"20", "Bulk time limit exceeded"},
|
||||
{"21", "Current sensor issue (sensor bias/sensor broken)"},
|
||||
{"26", "Terminals overheated"},
|
||||
{"33", "Input voltage too high (solar panel)"},
|
||||
{"34", "Input current too high (solar panel)"},
|
||||
{"38", "Input shutdown (due to excessive battery voltage)"},
|
||||
{"116", "Factory calibration data lost"},
|
||||
{"117", "Invalid/incompatible firmware"},
|
||||
{"119", "User settings invalid"}
|
||||
};
|
||||
const int errorCodesSize = sizeof(errorCodes) / sizeof(errorCodes[0]);
|
||||
|
||||
|
||||
struct OperationState {
|
||||
const char* code;
|
||||
const char* label;
|
||||
};
|
||||
|
||||
OperationState operationStates[] = {
|
||||
{"0", "Off"},
|
||||
{"1", "Low power"},
|
||||
{"2", "Fault"},
|
||||
{"3", "Bulk"},
|
||||
{"4", "Absorption"},
|
||||
{"5", "Float"},
|
||||
{"9", "Inverting (on)"}
|
||||
};
|
||||
const int operationStatesSize = sizeof(operationStates) / sizeof(operationStates[0]);
|
||||
|
||||
struct LabelDescription {
|
||||
const char* code;
|
||||
const char* label;
|
||||
};
|
||||
|
||||
struct OffReason {
|
||||
const char* code;
|
||||
const char* label;
|
||||
};
|
||||
|
||||
OffReason offReasons[] = {
|
||||
{"0x00000100", "No input power"},
|
||||
{"0x00000080", "Switched off (power switch)"},
|
||||
{"0x00000040", "Switched off (device mode register)"},
|
||||
{"0x00000020", "Remote input"},
|
||||
{"0x00000010", "Protection active"},
|
||||
{"0x00000008", "Paygo"},
|
||||
{"0x00000004", "BMS"},
|
||||
{"0x00000002", "Engine shutdown detection"},
|
||||
{"0x00000001", "Analysing input voltage"},
|
||||
{"0x00000000", "Working"}
|
||||
};
|
||||
const int offReasonsSize = sizeof(offReasons) / sizeof(offReasons[0]);
|
||||
|
||||
|
||||
LabelDescription mpptData[] = {
|
||||
{"V", "Voltage batterie mV"},
|
||||
{"VPV", "Voltage panneau mV"},
|
||||
{"PPV", "Puissance panneau W"},
|
||||
{"I", "Intensité batterie mA"},
|
||||
{"IL", "Intensité décharge mA"},
|
||||
{"OR", "Raison non fonctionnement"},
|
||||
{"LOAD", "Etat sortie On/Off"},
|
||||
{"H19", "Quantité d'énergie totale"},
|
||||
{"H20", "Quantité d'énergie totale aujourd'hui"},
|
||||
{"H21", "Puissance maximale aujourd'hui"},
|
||||
{"H22", "Quantité d'énergie totale hier"},
|
||||
{"H23", "Puissance maximale hier"},
|
||||
{"ERR", "Code d'erreur"},
|
||||
{"CS", "État de fonctionnement"},
|
||||
{"FW", "Version du firmware (16 bits)"},
|
||||
{"PID", "ID du produit"},
|
||||
{"SER#", "Numéro de série"},
|
||||
{"HSDS", "Numéro de la séquence du jour (0..364)"},
|
||||
{"MPPT", "Mode de fonctionnement du tracker"}
|
||||
};
|
||||
const int mpptDataSize = sizeof(mpptData) / sizeof(mpptData[0]);
|
||||
|
||||
struct MPPTState {
|
||||
const char* code;
|
||||
const char* label;
|
||||
};
|
||||
|
||||
MPPTState mpptStates[] = {
|
||||
{"0", "Off"},
|
||||
{"1", "Voltage or current limited"},
|
||||
{"2", "Actif"}
|
||||
};
|
||||
const int mpptStatesSize = sizeof(mpptStates) / sizeof(mpptStates[0]);
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Storage
|
||||
//////////////////////////////////////////
|
||||
struct Configuration {
|
||||
int max_current_charge;
|
||||
int max_current_injection;
|
||||
int voltage_charge;
|
||||
int voltage_injection;
|
||||
boolean configured;
|
||||
};
|
||||
|
||||
Configuration config;
|
||||
|
||||
|
||||
struct To_Store {
|
||||
int total_elements;
|
||||
int hour[maxSize];
|
||||
int min[maxSize];
|
||||
int tensions[maxSize];
|
||||
};
|
||||
To_Store to_store;
|
||||
#define TO_STORE_ADDRESS sizeof(Configuration) // commence après la configuration
|
||||
|
||||
const int EEPROM_SIZE = 1024;
|
||||
const int CONFIG_START = 0; // Start address in EEPROM
|
||||
|
||||
|
||||
double getFloatParam(String param)
|
||||
{
|
||||
return String(server.arg(param).c_str()).toFloat();
|
||||
}
|
||||
|
||||
void readConfiguration() {
|
||||
|
||||
EEPROM.get(CONFIG_START, config);
|
||||
|
||||
Serial.println("Configuration Loaded:");
|
||||
Serial.println("Charge: " + String(config.max_current_charge));
|
||||
Serial.println("Injection: " + String(config.max_current_injection));
|
||||
|
||||
}
|
||||
void handleSave() {
|
||||
if (getFloatParam("max_current_charge") && getFloatParam("max_current_injection")
|
||||
&& getFloatParam("voltage_charge") && getFloatParam("voltage_injection")
|
||||
) {
|
||||
|
||||
config.max_current_charge = getFloatParam("max_current_charge");
|
||||
config.max_current_injection = getFloatParam("max_current_injection");
|
||||
config.voltage_charge = getFloatParam("voltage_charge");
|
||||
config.voltage_injection = getFloatParam("voltage_injection");
|
||||
|
||||
config.configured = true;
|
||||
// // Sauvegarde des paramètres dans l'EEPROM
|
||||
EEPROM.put(CONFIG_START, config);
|
||||
EEPROM.commit();
|
||||
server.send(200, "text/plain", "Configuration saved");
|
||||
} else {
|
||||
config.configured = false;
|
||||
EEPROM.put(CONFIG_START, config);
|
||||
EEPROM.commit();
|
||||
server.send(400, "text/plain", "Invalid request");
|
||||
}
|
||||
}
|
||||
56
ESP8266_BATTERIE_INJECTION/dimmer.h
Normal file
56
ESP8266_BATTERIE_INJECTION/dimmer.h
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
#ifdef PIN_DIMMER_OUTPUT
|
||||
//pwm functions - if pwm is set to 1/-1 it will in-/decrease pwmCounter in loop()
|
||||
void exact() {
|
||||
int value_to_set = getParamFromGet("value").toInt();
|
||||
|
||||
pwm = value_to_set;
|
||||
|
||||
Serial.println(pwm);
|
||||
setPwm(pwm);
|
||||
}
|
||||
void plus() {
|
||||
int value_to_set = getParamFromGet("value").toInt();
|
||||
if (value_to_set <= 0) {
|
||||
value_to_set = 5;
|
||||
}
|
||||
pwm += value_to_set;
|
||||
setPwm(pwm);
|
||||
}
|
||||
|
||||
void minus() {
|
||||
int value_to_set = getParamFromGet("value").toInt();
|
||||
if (value_to_set <= 0) {
|
||||
value_to_set = 5;
|
||||
}
|
||||
pwm -= value_to_set;
|
||||
|
||||
setPwm(pwm);
|
||||
}
|
||||
|
||||
void stopPWM() {
|
||||
dimmer.setState(ON_OFF_typedef::OFF);
|
||||
pwm = 0;
|
||||
setPwm(pwm);
|
||||
}
|
||||
|
||||
void setPwm(int pwm)
|
||||
{
|
||||
if (pwm > 100) pwm = 100;
|
||||
if (pwm <= 1) {
|
||||
pwm = 0;
|
||||
}
|
||||
|
||||
Serial.println(pwm);
|
||||
|
||||
if (pwm <= 0) {
|
||||
dimmer.setState(ON_OFF_typedef::OFF);
|
||||
}
|
||||
else {
|
||||
dimmer.setState(ON_OFF_typedef::ON);
|
||||
}
|
||||
dimmer.setPower(pwm);
|
||||
blink(); server.sendHeader("Location", "/?message='Arret effectué'");
|
||||
server.send(302, "text/plain", "Redirection vers la page principale");
|
||||
}
|
||||
#endif
|
||||
137
ESP8266_BATTERIE_INJECTION/hall.h
Normal file
137
ESP8266_BATTERIE_INJECTION/hall.h
Normal file
@@ -0,0 +1,137 @@
|
||||
#ifdef PIN_HALL
|
||||
|
||||
//int mVperAmp = 66; // 185 pour 5A, use 100 for 20A Module and 66 for 30A Module
|
||||
int RawValue= 0;
|
||||
//int ACSoffset = 2500;
|
||||
//double mp_offset = 0.040;
|
||||
//double Voltage = 0;
|
||||
//double Amps = 0;
|
||||
|
||||
void getHall();
|
||||
float getVPP();
|
||||
|
||||
int mVperAmp = 48; // 185 pour 5, use 100 for 20A Module and 66 for 30A Module
|
||||
|
||||
double VRMS = 0;
|
||||
double Amps = 0;
|
||||
|
||||
//void getHall()
|
||||
//{
|
||||
// double Voltage = getVPP();
|
||||
// Serial.print(Voltage);
|
||||
// Serial.print(" mv ");
|
||||
// VRMS = (Voltage / 2.0) * 0.707; //root 2 is 0.707
|
||||
// Amps = (VRMS * 1000) / mVperAmp;
|
||||
// Serial.print();
|
||||
// Serial.println(" Amps RMS");
|
||||
//}
|
||||
//
|
||||
//float getVPP()
|
||||
//{
|
||||
// float result;
|
||||
// int readValue; //value read from the sensor
|
||||
// int maxValue = 0; // store max value here
|
||||
// int minValue = 1024; // store min value here
|
||||
//
|
||||
// uint32_t start_time = millis();
|
||||
// while ((millis() - start_time) < 1000) //sample for 1 Sec
|
||||
// {
|
||||
// readValue = analogRead(PIN_HALL);
|
||||
// // see if you have a new maxValue
|
||||
// if (readValue > maxValue)
|
||||
// {
|
||||
// /*record the maximum sensor value*/
|
||||
// maxValue = readValue;
|
||||
// }
|
||||
// if (readValue < minValue)
|
||||
// {
|
||||
// /*record the minimum sensor value*/
|
||||
// minValue = readValue;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Subtract min from max
|
||||
// result = ((maxValue - minValue) * 5.0) / 1024.0 - 0.06;
|
||||
//
|
||||
// return result;
|
||||
//}
|
||||
|
||||
//
|
||||
//#ifdef PIN_HALL
|
||||
void getHall(){
|
||||
|
||||
int i = 0;
|
||||
RawValue = 0;
|
||||
// Somme du courant alternatif pendant 20 ms ==> 50hz
|
||||
// Détermination du max et max pour hauteur de crete
|
||||
int vmin = 4096;
|
||||
int vmax = 0;
|
||||
int sum = 0;
|
||||
const int bcl = 2000;
|
||||
for (i = 0; i < bcl; i++) {
|
||||
int value = analogRead(PIN_HALL);
|
||||
if (value >= 0) {
|
||||
RawValue += value;
|
||||
vmax = max(value,vmax);
|
||||
vmin = min(value,vmin);
|
||||
sum += value;
|
||||
} else {
|
||||
i--;
|
||||
}
|
||||
delayMicroseconds(100);;
|
||||
|
||||
}
|
||||
// Serial.print("Raw Value = " );
|
||||
// Serial.print(RawValue);
|
||||
Serial.print("min = " );
|
||||
Serial.print(vmin);
|
||||
Serial.print(" max = " );
|
||||
Serial.print(vmax);
|
||||
|
||||
// Serial.print(" i =" );Amps
|
||||
// Serial.print(i);
|
||||
// RawValue = RawValue / i;
|
||||
|
||||
|
||||
// Tension continue
|
||||
// Voltage = (RawValue / 1023.0) * 5000; // Gets you mV
|
||||
// Amps = ((Voltage - ACSoffset) / mVperAmp);
|
||||
|
||||
|
||||
// La valeur maxi * racine carrée de 2 pour obtenir la tension "réelle"
|
||||
// La tension efficace pour l'effet Hall étant réduite d'un facteur 0,707
|
||||
//VRMS = ((vmax - vmin) / 430.0) * 5000;
|
||||
double average = sum / bcl;
|
||||
VRMS = 1000 * (((average) / 4095.0) * 3.3 - 2.43);
|
||||
|
||||
//Amps = max(5.5 * (vmax - vmin) / 473.0 -0.0580, 0.0); // <= pour le bruit
|
||||
Amps = (VRMS / mVperAmp);
|
||||
|
||||
// Serial.print(" Raw Value = " ); // shows pre-scaled value
|
||||
// Serial.print(RawValue);
|
||||
Serial.print("\t mV = "); // shows the voltage measured
|
||||
Serial.print(VRMS,3); // the '3' after voltage allows you to display 3 digits after decimal point
|
||||
Serial.print("\t Amps = "); // shows the voltage measured
|
||||
Serial.print(Amps,3); // the '3' after voltage allows you to display 3 digits after decimal point
|
||||
Serial.print("\t Watt = "); // shows the voltage measured
|
||||
Serial.print(Amps * 220,3);
|
||||
Serial.print("\t WattH = "); // shows the voltage measured
|
||||
Serial.println(Amps * 220 / 1200,3);
|
||||
|
||||
|
||||
// long sum = 0;
|
||||
// for (int i = 0; i < numSamples; i++) {
|
||||
// int sample = analogRead(PIN_HALL);
|
||||
// sum += sample;
|
||||
// delayMicroseconds(100);
|
||||
// }
|
||||
//
|
||||
// float average = sum / numSamples;
|
||||
// VRMS = (average / 4095.0) * 3.3; // Convertir l'échantillon ADC en tension (ESP32 utilise 3.3V référence ADC)
|
||||
// float currentOffset = VRMS - offset; // Calculer l'offset du courant
|
||||
// Amps = currentOffset / sensitivity; // Calculer le courant en utilisant la sensibilité de l'ACS712
|
||||
|
||||
}
|
||||
//#endif
|
||||
|
||||
#endif
|
||||
459
ESP8266_BATTERIE_INJECTION/html.h
Normal file
459
ESP8266_BATTERIE_INJECTION/html.h
Normal file
@@ -0,0 +1,459 @@
|
||||
|
||||
// Linear Regression Equation: y = 80.9356x + -2086.7172
|
||||
// R^2 for Linear Regression: 0.8820
|
||||
// Polynomial Regression (Degree 2) Equation: y = 65.2734x^2 + -3353.2872x + 43075.5362
|
||||
// R^2 for Polynomial Regression (Degree 2): 0.9724
|
||||
// Polynomial Regression (Degree 3) Equation: y = -71.35479595x^3 + 5699.68320483x^2 + -151636.19028283x + 1343695.66923927
|
||||
// R^2 for Polynomial Regression (Degree 3): 0.9821
|
||||
|
||||
|
||||
String to_include = R"=(
|
||||
<SCRIPT>
|
||||
|
||||
var xmlHttp01=createXmlHttpObject();
|
||||
var chart;
|
||||
|
||||
// Fonction pour envoyer la valeur du slider au serveur
|
||||
function sendSliderValue(sliderId, value) {
|
||||
fetch('/update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ slider: sliderId, value: value })
|
||||
})
|
||||
//.then(response => response.json())
|
||||
.then(data => {showNotification('Consigne mise à jour'); console.log('Succès:', data)})
|
||||
.catch(error => console.error('Erreur:', error));
|
||||
}
|
||||
|
||||
function createXmlHttpObject(){
|
||||
if(window.XMLHttpRequest){
|
||||
xmlHttp=new XMLHttpRequest();
|
||||
}else{
|
||||
xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');
|
||||
}
|
||||
return xmlHttp;
|
||||
}
|
||||
function getCurrentTimeString() {
|
||||
var now = new Date();
|
||||
var hours = now.getHours().toString().padStart(2, '0');
|
||||
var minutes = now.getMinutes().toString().padStart(2, '0');
|
||||
var seconds = now.getSeconds().toString().padStart(2, '0');
|
||||
|
||||
var currentTime = hours + ':' + minutes + ':' + seconds;
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
|
||||
function process(){
|
||||
if(xmlHttp01.readyState==0 || xmlHttp01.readyState==4){
|
||||
xmlHttp01.open('GET','getVictron',true);
|
||||
xmlHttp01.onreadystatechange=handleServerResponse;
|
||||
xmlHttp01.send(null);
|
||||
}
|
||||
setTimeout('process()', 5000);
|
||||
}
|
||||
function handleServerResponse(){
|
||||
var field = document.getElementById('response_items');
|
||||
if(field && xmlHttp01.readyState == 4 && xmlHttp01.status == 200){
|
||||
const json_obj = JSON.parse(xmlHttp01.response);
|
||||
console.log(xmlHttp01.response);
|
||||
|
||||
// Vérifiez si la table existe déjà, sinon créez-en une
|
||||
var table = document.getElementById('response_table');
|
||||
if (!table) {
|
||||
table = document.createElement('table');
|
||||
table.id = 'response_table';
|
||||
// Insérez une seule ligne pour les données
|
||||
var dataRow = table.insertRow();
|
||||
dataRow.id = 'data_row';
|
||||
document.getElementById('response_items').appendChild(table);
|
||||
// Ajoutez les id
|
||||
dataRow.insertCell().innerHTML = "Date";
|
||||
for (var i = 3; i < json_obj.length - 1; i++){
|
||||
var obj = json_obj[i];
|
||||
dataRow.insertCell().innerHTML = obj.key_label ? obj.key_label : obj.id;
|
||||
}
|
||||
}
|
||||
var dataRow = table.insertRow(1);
|
||||
dataRow.id = 'data_row';
|
||||
document.getElementById('response_items').appendChild(table);
|
||||
|
||||
// Initialiser le graphique
|
||||
var field_chart = document.getElementById('chartCanvas');
|
||||
// Ajoutez les nouvelles données dans la même ligne
|
||||
dataRow.insertCell().innerHTML = getCurrentTimeString();
|
||||
var time_field = document.getElementById('hour');
|
||||
time_field.textContent= getCurrentTimeString();
|
||||
|
||||
var tensions = "";
|
||||
for (var i = 3; i < json_obj.length - 1; i++){
|
||||
var obj = json_obj[i];
|
||||
|
||||
if (obj.id == "tensions") {
|
||||
if (field_chart && chart) {
|
||||
var tensions = obj.value.split(',');
|
||||
var numerictensions = tensions.map(Number);
|
||||
var labels = obj.labels.split(',');
|
||||
|
||||
chart.data.labels = labels;
|
||||
chart.data.datasets[0].data = numerictensions;
|
||||
|
||||
// var ctx = chart.ctx;
|
||||
// var yAxis = chart.scales.y;
|
||||
// var yValues = [25.7, 26.12, 26.42, 26.44, 26.46, 26.56, 26.66, 26.7, 26.74, 26.92 ];
|
||||
// var yPercentages = ["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"];
|
||||
//
|
||||
// ctx.save();
|
||||
// ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
|
||||
// ctx.lineWidth = 1;
|
||||
// yValues.forEach(function(value, index) {
|
||||
// var y = yAxis.getPixelForValue(value);
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(chart.chartArea.left, y);
|
||||
// ctx.lineTo(chart.chartArea.right, y);
|
||||
// ctx.stroke();
|
||||
// ctx.fillStyle = 'white';
|
||||
// ctx.fillText(yPercentages[index], chart.chartArea.right + 5, y + 3);
|
||||
// });
|
||||
// ctx.restore();
|
||||
chart.update();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//dataRow.insertCell().innerHTML = obj.id;
|
||||
dataRow.insertCell().innerHTML = obj.label ? obj.label : obj.value;
|
||||
|
||||
var field = document.getElementById(obj.id);
|
||||
if (field) {
|
||||
field.textContent = obj.value ;
|
||||
}
|
||||
field = document.getElementById("IND_" + obj.id);
|
||||
if (field) {
|
||||
field.textContent = obj.value ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Conservez uniquement les 10 dernières entrées
|
||||
while (table.rows.length > 31) { // 1 pour l'en-tête + 10 pour les données
|
||||
table.deleteRow(-1); // Supprime la dernière ligne
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (field_chart && !chart) {
|
||||
var ctx = field_chart.getContext('2d');
|
||||
chart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['25 mai', '24 mai', '23 mai', '22 mai', '21 mai', '20 mai', '19 mai', '18 mai', '17 mai', '16 mai'],
|
||||
datasets: [{
|
||||
label: 'Tensions (mV)',
|
||||
data: [20, 10, 5, 0, 0, 0, 0, 0, 0, 0],
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.6)',
|
||||
borderColor: 'rgba(255, 255, 255, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
color: 'white',
|
||||
font: {
|
||||
size: 30
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDraw: function(chart) {
|
||||
var ctx = chart.ctx;
|
||||
var yAxis = chart.scales.y;
|
||||
var yValues = [25.7, 25.87, 26.04, 26.21, 26.38, 26.55, 26.72, 26.89];
|
||||
var yPercentages = ["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"];
|
||||
|
||||
ctx.save();
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
|
||||
ctx.lineWidth = 1;
|
||||
yValues.forEach(function(value, index) {
|
||||
var y = yAxis.getPixelForValue(value);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(chart.chartArea.left, y);
|
||||
ctx.lineTo(chart.chartArea.right, y);
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillText(yPercentages[index], chart.chartArea.right + 5, y + 3);
|
||||
});
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
ticks: {
|
||||
color: 'white',
|
||||
beginAtZero: false
|
||||
},
|
||||
afterBuildTicks: function(scale) {
|
||||
return [25.7, 25.87, 26.04, 26.21, 26.38, 26.55, 26.72, 26.89];
|
||||
}
|
||||
},
|
||||
x: {
|
||||
ticks: {
|
||||
color: 'white'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// function updateChart(newLabels, newData) {
|
||||
// if (chart) {
|
||||
// chart.data.labels = newLabels;
|
||||
// chart.data.datasets[0].data = newData;
|
||||
// chart.update();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Example of updating the chart with new values
|
||||
// setTimeout(function() {
|
||||
// var newLabels = ['26 mai', '25 mai', '24 mai', '23 mai', '22 mai', '21 mai', '20 mai', '19 mai', '18 mai', '17 mai'];
|
||||
// var newData = [15, 20, 10, 5, 0, 0, 0, 0, 0, 0];
|
||||
// updateChart(newLabels, newData);
|
||||
// }, 5000);
|
||||
//
|
||||
|
||||
});
|
||||
|
||||
|
||||
// document.getElementById('slider2').addEventListener('change', function() {
|
||||
// sendSliderValue('slider2', this.value);
|
||||
// });
|
||||
|
||||
</SCRIPT>
|
||||
)=";
|
||||
|
||||
|
||||
String webpage = R"=(
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>Controle des batteries : MPPT 100/20 48V</h1>
|
||||
<div class="header_info">
|
||||
<h2>@@IP@@</h2>
|
||||
<h2 id="hour">@@TIME@@</h2>
|
||||
<div>
|
||||
<span class="connection-indicator">@@CONNECTION_INDICATOR@@</span>
|
||||
<button onclick="location.href='/settings'">Paramétrage</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="tab-buttons">
|
||||
<div class="tab-button" onclick="showTab('main-section')">Main</div>
|
||||
<div class="tab-button" onclick="showTab('graph-section')">Graph</div>
|
||||
<div class="tab-button" onclick="showTab('data-section')">Data</div>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<div id="main-section" class="tab">
|
||||
<div class="buttons_section">
|
||||
@@BUTTONS@@
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<div class="slider-wrapper">
|
||||
<span class="slider-label">Courant charge:</span>
|
||||
<input type="range" class="slider" id="sliderCurrent" min="0" max="20" value="@@CC@@">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<div class="slider-wrapper">
|
||||
<span class="slider-label">Courant injection:</span>
|
||||
<input type="range" class="slider" id="sliderCurrent2" min="0" max="20" value="@@CC2@@">
|
||||
</div>
|
||||
</div>
|
||||
<ul class="power-displays">
|
||||
@@INDICATORS@@
|
||||
</ul>
|
||||
<aside>
|
||||
<div class="status">
|
||||
<h2>Statut</h2>
|
||||
<div class="status-section">
|
||||
<h3>Solaire</h3>
|
||||
e<p><span>Tension:</span> <span id="VPV">@@VPV@@</span><span> mV</span></p>
|
||||
<p><span>Courant:</span> <span id="PPV">@@PPV@@</span><span> mA</span></p>
|
||||
</div>
|
||||
<div class="status-section">
|
||||
<h3>Batterie</h3>
|
||||
<p><span>Tension:</span> <span id="V">@@V@@</span><span> mV</span></p>
|
||||
<p><span>Courant:</span> <span id="I">@@I@@</span><span> mA</span></p>
|
||||
<p><span>État:</span> <span id="CS">Absorption</span></p>
|
||||
</div>
|
||||
<div class="status-section">
|
||||
<h3>Sortie de charge</h3>
|
||||
<p><span>État:</span> <span id="LOAD">@@LOAD@@</span></p>
|
||||
<p><span>Courant:</span> <span id="IL">@@IL@@</span><span> mA</span></p>
|
||||
<p><span>Puissance:</span> <span id="output-power">3</span><span> W</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
<div id="graph-section" class="tab">
|
||||
<div class="chart">
|
||||
<h2>5 dernières heures</h2>
|
||||
<canvas id="chartCanvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div id="data-section" class="tab">
|
||||
<div class='victron_data'>
|
||||
<span><A id='response_items'></A>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
</div>
|
||||
)=";
|
||||
|
||||
String indicator = R"=(
|
||||
<li class="power-display">
|
||||
<div class="power-indicator">
|
||||
<div id="@@KEY@@" class="power-value">@@VALUE@@</div>
|
||||
<div id="power-source" class="power-source">@@LABEL@@</div>
|
||||
</div>
|
||||
</li>
|
||||
)=";
|
||||
|
||||
|
||||
String end_script_to_add = R"=(
|
||||
|
||||
<script>
|
||||
function showTab(tabId) {
|
||||
var tabs = document.getElementsByClassName('tab');
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
tabs[i].style.display = 'none';
|
||||
}
|
||||
var tab = document.getElementById(tabId)
|
||||
|
||||
if (tab) {
|
||||
tab.style.display = 'block';
|
||||
|
||||
|
||||
var tabButtons = document.getElementsByClassName('tab-button');
|
||||
for (var i = 0; i < tabButtons.length; i++) {
|
||||
tabButtons[i].classList.remove('active');
|
||||
}
|
||||
tab.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
showTab('main-section'); // Affiche le premier onglet par défaut
|
||||
});
|
||||
|
||||
// // Ajouter un écouteur d'événement pour chaque slider
|
||||
// document.getElementById('sliderCurrent').addEventListener('change', function() {
|
||||
// sendSliderValue('sliderCurrent', this.value);
|
||||
// });
|
||||
// // Ajouter un écouteur d'événement pour chaque slider
|
||||
// document.getElementById('sliderCurrent2').addEventListener('change', function() {
|
||||
// sendSliderValue('sliderCurrent2', this.value);
|
||||
// });
|
||||
</script>
|
||||
)=";
|
||||
|
||||
|
||||
void handleSettings() {
|
||||
String html = "<html>\
|
||||
<head>\
|
||||
<style>\
|
||||
body {\
|
||||
font-family: Arial, sans-serif;\
|
||||
background-color: #f4f4f4;\
|
||||
display: flex;\
|
||||
justify-content: center;\
|
||||
align-items: center;\
|
||||
height: 100vh;\
|
||||
margin: 0;\
|
||||
}\
|
||||
.form-container {\
|
||||
background-color: #fff;\
|
||||
padding: 20px;\
|
||||
border-radius: 8px;\
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\
|
||||
width: 600px;\
|
||||
}\
|
||||
h2 {\
|
||||
color: #333;\
|
||||
text-align: center;\
|
||||
}\
|
||||
.form-content {\
|
||||
display: flex;\
|
||||
justify-content: space-between;\
|
||||
}\
|
||||
.column {\
|
||||
display: flex;\
|
||||
flex-direction: column;\
|
||||
width: 48%;\
|
||||
}\
|
||||
label {\
|
||||
margin-bottom: 5px;\
|
||||
font-weight: bold;\
|
||||
color: #555;\
|
||||
}\
|
||||
input[type='text'] {\
|
||||
padding: 10px;\
|
||||
margin-bottom: 15px;\
|
||||
border: 1px solid #ccc;\
|
||||
border-radius: 4px;\
|
||||
font-size: 16px;\
|
||||
}\
|
||||
input[type='submit'] {\
|
||||
background-color: #28a745;\
|
||||
color: white;\
|
||||
border: none;\
|
||||
padding: 10px;\
|
||||
border-radius: 4px;\
|
||||
cursor: pointer;\
|
||||
font-size: 16px;\
|
||||
margin-top: 10px;\
|
||||
width: 100%;\
|
||||
}\
|
||||
input[type='submit']:hover {\
|
||||
background-color: #218838;\
|
||||
}\
|
||||
</style>\
|
||||
</head>\
|
||||
<body>\
|
||||
<div class=\"form-container\">\
|
||||
<h2>Configuration</h2>\
|
||||
<form action=\"/save\" method=\"POST\">\
|
||||
<div class=\"form-content\">\
|
||||
<div class=\"column\">\
|
||||
<label for=\"max_current_charge\">MAX CHARGE :</label>\
|
||||
<input type=\"number\" id=\"max_current_charge\" name=\"max_current_charge\" min=\"0\" max=\"20\" value=\"" + String(config.max_current_charge) + "\">\
|
||||
<label for=\"voltage_charge\">VOLTAGE CHARGE :</label>\
|
||||
<input type=\"number\" id=\"voltage_charge\" name=\"voltage_charge\" min=\"0\" max=\"48\" step=\"0.1\" value=\"" + String(config.voltage_charge) + "\">\
|
||||
<label for=\"max_current_injection\">MAX INJECTION :</label>\
|
||||
<input type=\"number\" id=\"max_current_injection\" name=\"max_current_injection\" min=\"0\" max=\"20\" value=\"" + String(config.max_current_injection) + "\">\
|
||||
<label for=\"voltage_injection\">VOLTAGE INJECTION :</label>\
|
||||
<input type=\"number\" id=\"voltage_injection\" name=\"voltage_injection\" min=\"0\" max=\"48\" step=\"0.1\" value=\"" + String(config.voltage_injection) + "\">\
|
||||
<label for=\"configured\">Configuré :</label>\
|
||||
<input type=\"checkbox\" id=\"configured\" name=\"configured\" readonly=\"readonly\" @@checked@@>\
|
||||
</div>\
|
||||
</div>\
|
||||
<input type=\"submit\" value=\"Save\">\
|
||||
</form>\
|
||||
</div>\
|
||||
</body>\
|
||||
</html>";
|
||||
|
||||
html.replace("@@checked@@", (config.configured ? "checked" : ""));
|
||||
|
||||
server.send(200, "text/html", html);
|
||||
}
|
||||
58
ESP8266_BATTERIE_INJECTION/pinout.h
Normal file
58
ESP8266_BATTERIE_INJECTION/pinout.h
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
// ______________________________
|
||||
// | L T L T L T L T L T L T |
|
||||
// | |
|
||||
// RST| 1|TX HSer
|
||||
// A0| 3|RX HSer
|
||||
// D0|16 5|D1
|
||||
// D5|14 4|D2
|
||||
// D6|12 10kPUP_0|D3
|
||||
//RX SSer/HSer swap D7|13 LED_10kPUP_2|D4
|
||||
//TX SSer/HSer swap D8|15 |GND
|
||||
// 3V3|__ |5V
|
||||
// | |
|
||||
// |___________________________|
|
||||
|
||||
|
||||
// ESP 32 gauche
|
||||
// 1. 3V3 | 3.3V Power Output
|
||||
// 2. EN | Enable (Reset)
|
||||
// 3. D36 | GPIO36 / VP / ADC1_0
|
||||
// 4. D39 | GPIO39 / VN / ADC1_3
|
||||
// 5. D34 | GPIO34 / ADC1_6
|
||||
// 6. D35 | GPIO35 / ADC1_7
|
||||
// 7. D32 | GPIO32 / XTAL_32 / TOUCH9 / ADC1_4
|
||||
// 8. D33 | GPIO33 / XTAL_32 / TOUCH8 / ADC1_5
|
||||
// 9. D25 | GPIO25 / DAC1
|
||||
// 10. D26 | GPIO26 / DAC2
|
||||
// 11. D27 | GPIO27 / TOUCH7
|
||||
// 12. D14 | GPIO14 / HSPI_CLK / TOUCH6
|
||||
// 13. D12 | GPIO12 / HSPI_MISO / TOUCH5 / ADC2_5
|
||||
// 14. D13 | GPIO13 / HSPI_MOSI / TOUCH4 / ADC2_4
|
||||
// 15. GND | Ground
|
||||
// 16. D9 | GPIO9 / SD_DATA2
|
||||
// 17. D10 | GPIO10 / SD_DATA3 / HSPI_WP
|
||||
// 18. D11 | GPIO11 / CMD / HSPI_HD
|
||||
// 19. 5V | 5V Power Input
|
||||
|
||||
|
||||
// ESP32 droit
|
||||
// 1. GND | Ground
|
||||
// 2. D23 | GPIO23 / VSPI_MOSI
|
||||
// 3. D22 | GPIO22 / I2C_SCL
|
||||
// 4. TXD0 | GPIO1 / U0TXD
|
||||
// 5. RXD0 | GPIO3 / U0RXD
|
||||
// 6. D21 | GPIO21 / I2C_SDA
|
||||
// 7. D19 | GPIO19 / VSPI_MISO
|
||||
// 8. D18 | GPIO18 / VSPI_CLK
|
||||
// 9. D5 | GPIO5 / VSPI_CS
|
||||
// 10. D17 | GPIO17 / U2TXD
|
||||
// 11. D16 | GPIO16 / U2RXD
|
||||
// 12. D4 | GPIO4 / HSPI_CS / SD_DATA1
|
||||
// 13. D0 | GPIO0 / CLK_OUT1 / TOUCH1 / ADC2_0
|
||||
// 14. D2 | GPIO2 / TOUCH2 / ADC2_2
|
||||
// 15. D15 | GPIO15 / HSPI_CS / TOUCH3 / ADC2_3
|
||||
// 16. D8 | GPIO8 / SD_DATA0
|
||||
// 17. D7 | GPIO7 / SD_CLK
|
||||
// 18. D6 | GPIO6 / SD_CMD
|
||||
// 19. GND | Ground
|
||||
1
ESP8266_BATTERIE_INJECTION/pzem.h
Normal file
1
ESP8266_BATTERIE_INJECTION/pzem.h
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
56
ESP8266_BATTERIE_INJECTION/regulation.h
Normal file
56
ESP8266_BATTERIE_INJECTION/regulation.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifdef PIN_REGULATION
|
||||
|
||||
void setReg(int speed_to_set)
|
||||
{
|
||||
current_regulation = speed_to_set;
|
||||
if (current_regulation > 100) current_regulation = 100;
|
||||
if (current_regulation <= 1) {
|
||||
current_regulation = 0;
|
||||
}
|
||||
|
||||
Serial.println(current_regulation);
|
||||
|
||||
analogWrite(PIN_REGULATION, current_regulation * 2.55);// send current_regulation value to motor
|
||||
|
||||
blink(); server.sendHeader("Location", "/?message='Régulation modifiée'");
|
||||
server.send(302, "text/plain", "Redirection vers la page principale");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void exact_reg() {
|
||||
int value_to_set = getParamFromGet("value").toInt();
|
||||
|
||||
current_regulation = value_to_set;
|
||||
if (current_regulation > 100) current_regulation = 100;
|
||||
if (current_regulation < 0) {
|
||||
current_regulation = 0;
|
||||
}
|
||||
|
||||
setReg(current_regulation);
|
||||
|
||||
}
|
||||
void plus_reg() {
|
||||
int value_to_set = getParamFromGet("value").toInt();
|
||||
if (value_to_set <= 0) {
|
||||
value_to_set = 5;
|
||||
}
|
||||
current_regulation += value_to_set;
|
||||
setReg(current_regulation);
|
||||
|
||||
}
|
||||
|
||||
void minus_reg() {
|
||||
int value_to_set = getParamFromGet("value").toInt();
|
||||
if (value_to_set <= 0) {
|
||||
value_to_set = 5;
|
||||
}
|
||||
current_regulation -= value_to_set;
|
||||
setReg(current_regulation);
|
||||
}
|
||||
|
||||
void stop_reg() {
|
||||
current_regulation = 0;
|
||||
setReg(current_regulation);
|
||||
}
|
||||
#endif
|
||||
174
ESP8266_BATTERIE_INJECTION/settings.h
Normal file
174
ESP8266_BATTERIE_INJECTION/settings.h
Normal file
@@ -0,0 +1,174 @@
|
||||
struct DomoticzConfig {
|
||||
char domoticz_ip[40];
|
||||
char domoticz_port[6]; // 5 Caractères + \0
|
||||
char domoticz_user[32];
|
||||
char domoticz_password[32];
|
||||
};
|
||||
|
||||
DomoticzConfig config;
|
||||
|
||||
struct To_Store {
|
||||
int total_elements;
|
||||
int hour[maxSize];
|
||||
int min[maxSize];
|
||||
int tensions[maxSize];
|
||||
};
|
||||
To_Store to_store;
|
||||
|
||||
|
||||
void handleSettings() {
|
||||
String html = "<html>\
|
||||
<body>\
|
||||
<h2>Domoticz Configuration</h2>\
|
||||
<form action=\"/save\" method=\"POST\">\
|
||||
<label for=\"domoticz_ip\">Domoticz IP:</label><br>\
|
||||
<input type=\"text\" id=\"domoticz_ip\" name=\"domoticz_ip\" value=\"" + String(config.domoticz_ip) + "\"><br>\
|
||||
<label for=\"domoticz_port\">Domoticz Port:</label><br>\
|
||||
<input type=\"text\" id=\"domoticz_port\" name=\"domoticz_port\" value=\"" + String(config.domoticz_port) + "\"><br>\
|
||||
<label for=\"domoticz_user\">Domoticz User:</label><br>\
|
||||
<input type=\"text\" id=\"domoticz_user\" name=\"domoticz_user\" value=\"" + String(config.domoticz_user) + "\"><br>\
|
||||
<label for=\"domoticz_password\">Domoticz Password:</label><br>\
|
||||
<input type=\"password\" id=\"domoticz_password\" name=\"domoticz_password\" value=\"" + String(config.domoticz_password) + "\"><br><br>\
|
||||
<input type=\"submit\" value=\"Save\">\
|
||||
</form>\
|
||||
</body>\
|
||||
</html>";
|
||||
|
||||
server.send(200, "text/html", html);
|
||||
}
|
||||
|
||||
|
||||
void readConfig() {
|
||||
|
||||
EEPROM.get(DOMOTICZ_CONFIG_START, config);
|
||||
|
||||
Serial.println("Configuration Loaded:");
|
||||
Serial.println("IP: " + String(config.domoticz_ip));
|
||||
Serial.println("Port: " + String(config.domoticz_port));
|
||||
Serial.println("User: " + String(config.domoticz_user));
|
||||
Serial.println("Password: " + String(config.domoticz_password));
|
||||
}
|
||||
|
||||
|
||||
bool testDomoticzConnection() {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String url = String("http://") + config.domoticz_ip + ":" + config.domoticz_port + "/json.htm?type=command¶m=getversion";
|
||||
|
||||
#ifdef ESP8266
|
||||
HTTPClient http;
|
||||
http.begin(url);
|
||||
#else
|
||||
HTTPClient http;
|
||||
http.begin(url.c_str());
|
||||
#endif
|
||||
|
||||
int httpCode = http.GET();
|
||||
if (httpCode > 0) {
|
||||
String payload = http.getString();
|
||||
Serial.println(payload);
|
||||
http.end();
|
||||
return true;
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
http.end();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleTestConnection() {
|
||||
String result = testDomoticzConnection() ? "Connection successful" : "Connection failed";
|
||||
server.send(200, "text/plain", result);
|
||||
}
|
||||
|
||||
void handleSave() {
|
||||
if (server.hasArg("domoticz_ip") && server.hasArg("domoticz_port") && server.hasArg("domoticz_user") && server.hasArg("domoticz_password")) {
|
||||
strcpy(config.domoticz_ip, server.arg("domoticz_ip").c_str());
|
||||
strcpy(config.domoticz_port, server.arg("domoticz_port").c_str());
|
||||
strcpy(config.domoticz_user, server.arg("domoticz_user").c_str());
|
||||
strcpy(config.domoticz_password, server.arg("domoticz_password").c_str());
|
||||
|
||||
// Sauvegarde des paramètres dans l'EEPROM
|
||||
EEPROM.put(DOMOTICZ_CONFIG_START, config);
|
||||
EEPROM.commit();
|
||||
readConfig();
|
||||
server.send(200, "text/plain", "Configuration saved");
|
||||
} else {
|
||||
server.send(400, "text/plain", "Invalid request");
|
||||
}
|
||||
}
|
||||
|
||||
void handleTestConnection() {
|
||||
String result = testDomoticzConnection() ? "Connection successful" : "Connection failed";
|
||||
server.send(200, "text/plain", result);
|
||||
}
|
||||
|
||||
bool testDomoticzConnection() {
|
||||
if (WiFi.status() != WL_CONNECTED && String(config.domoticz_port).toInt() > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String url = String("http://") + config.domoticz_ip + ":" + config.domoticz_port + "/json.htm?type=command¶m=getversion";
|
||||
|
||||
#ifdef ESP8266
|
||||
HTTPClient http;
|
||||
http.begin(url);
|
||||
#else
|
||||
HTTPClient http;
|
||||
http.begin(url.c_str());
|
||||
#endif
|
||||
|
||||
int httpCode = http.GET();
|
||||
if (httpCode > 0) {
|
||||
String payload = http.getString();
|
||||
Serial.println(payload);
|
||||
http.end();
|
||||
return true;
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
http.end();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//void handleSettings() {
|
||||
// String html = "<html>\
|
||||
// <body>\
|
||||
// <h2>Domoticz Configuration</h2>\
|
||||
// <form action=\"/save\" method=\"POST\">\
|
||||
// <label for=\"domoticz_ip\">Domoticz IP:</label><br>\
|
||||
// <input type=\"text\" id=\"domoticz_ip\" name=\"domoticz_ip\" value=\"" + String(config.domoticz_ip) + "\"><br>\
|
||||
// <label for=\"domoticz_port\">Domoticz Port:</label><br>\
|
||||
// <input type=\"text\" id=\"domoticz_port\" name=\"domoticz_port\" value=\"" + String(config.domoticz_port) + "\"><br>\
|
||||
// <label for=\"domoticz_user\">Domoticz User:</label><br>\
|
||||
// <input type=\"text\" id=\"domoticz_user\" name=\"domoticz_user\" value=\"" + String(config.domoticz_user) + "\"><br>\
|
||||
// <label for=\"domoticz_password\">Domoticz Password:</label><br>\
|
||||
// <input type=\"password\" id=\"domoticz_password\" name=\"domoticz_password\" value=\"" + String(config.domoticz_password) + "\"><br><br>\
|
||||
// <input type=\"submit\" value=\"Save\">\
|
||||
// </form>\
|
||||
// </body>\
|
||||
// </html>";
|
||||
//
|
||||
// server.send(200, "text/html", html);
|
||||
//}
|
||||
//
|
||||
//
|
||||
//void handleSave() {
|
||||
// if (server.hasArg("domoticz_ip") && server.hasArg("domoticz_port") && server.hasArg("domoticz_user") && server.hasArg("domoticz_password")) {
|
||||
// strcpy(config.domoticz_ip, server.arg("domoticz_ip").c_str());
|
||||
// strcpy(config.domoticz_port, server.arg("domoticz_port").c_str());
|
||||
// strcpy(config.domoticz_user, server.arg("domoticz_user").c_str());
|
||||
// strcpy(config.domoticz_password, server.arg("domoticz_password").c_str());
|
||||
//
|
||||
// // Sauvegarde des paramètres dans l'EEPROM
|
||||
// EEPROM.put(DOMOTICZ_CONFIG_START, config);
|
||||
// EEPROM.commit();
|
||||
// readConfig();
|
||||
// server.send(200, "text/plain", "Configuration saved");
|
||||
// } else {
|
||||
// server.send(400, "text/plain", "Invalid request");
|
||||
// }
|
||||
//}
|
||||
189
ESP8266_BATTERIE_INJECTION/tuya.h
Normal file
189
ESP8266_BATTERIE_INJECTION/tuya.h
Normal file
@@ -0,0 +1,189 @@
|
||||
|
||||
void tick();
|
||||
void getConsoApparente();
|
||||
|
||||
//Ticker timer(tick, 10000);
|
||||
|
||||
|
||||
void tick() {
|
||||
}
|
||||
void traitement()
|
||||
{
|
||||
#ifdef TUYA
|
||||
getConsoApparente();
|
||||
#endif
|
||||
#ifdef SERIAL_XY6020L
|
||||
//if (slider_on == false) {
|
||||
// double cc_tmp = abs(conso_apparente / TENSION_CHARGE) / 3.0;
|
||||
double cc_tmp = abs(conso_apparente) > 3.0 * TENSION_CHARGE
|
||||
? abs(conso_apparente / TENSION_CHARGE) / 3.0
|
||||
: abs(conso_apparente / TENSION_CHARGE);
|
||||
|
||||
boolean en_charge = (digitalRead(PIN_CHARGE) == HIGH);
|
||||
delay(10);
|
||||
|
||||
boolean en_injection = (digitalRead(PIN_INJECTION) == HIGH);
|
||||
delay(10);
|
||||
|
||||
last_message = String(lastTimeRead) + " CHG=" + String(en_charge) + " INJ=" + String(en_injection);
|
||||
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
#define START_INJECTION 15
|
||||
#define STOP_INJECTION -15
|
||||
#else
|
||||
#define START_INJECTION 230
|
||||
#define STOP_INJECTION (production > 50 ? -15 : -60)
|
||||
#endif
|
||||
|
||||
if ((conso_apparente < STOP_INJECTION || tension_batterie <= 24.8) && en_injection && cc2 <= 0) {
|
||||
last_message += " stopInjection";
|
||||
//stopInjection();
|
||||
cc2 = 0;
|
||||
digitalWrite(PIN_INJECTION, LOW);
|
||||
}
|
||||
else if (conso_apparente < -15 && !en_charge && !en_injection && production > 15) {
|
||||
// charge();
|
||||
last_message += " début charge";
|
||||
cc2 = 0;
|
||||
// digitalWrite(PIN_INJECTION, LOW);
|
||||
digitalWrite(PIN_CHARGE, HIGH);
|
||||
}
|
||||
else if (conso_apparente > 15 && en_charge && cc <= 0) {
|
||||
// stopCharge();
|
||||
last_message += " fin charge";
|
||||
cc = 0;
|
||||
digitalWrite(PIN_CHARGE, LOW);
|
||||
}
|
||||
else if (conso_apparente > START_INJECTION && !en_injection && tension_batterie > 25.2 && !en_charge) {
|
||||
// injection();
|
||||
last_message += " début injection";
|
||||
|
||||
digitalWrite(PIN_INJECTION, HIGH);
|
||||
// digitalWrite(PIN_CHARGE, LOW);
|
||||
|
||||
cc = 0;
|
||||
}
|
||||
else {
|
||||
//last_message += " aucune action"; // + String(START_INJECTION) + " " + String(tension_batterie) + " " + String(conso_apparente > START_INJECTION);
|
||||
}
|
||||
en_charge = (digitalRead(PIN_CHARGE) == HIGH);
|
||||
delay(10);
|
||||
|
||||
en_injection = (digitalRead(PIN_INJECTION) == HIGH);
|
||||
Serial.print("en_charge="); Serial.print(en_charge); Serial.print(" en_injection="); Serial.println(en_injection);
|
||||
|
||||
delay(10);
|
||||
|
||||
// Conso > 10 Conso < -10
|
||||
// cc > 0 cc - cc +
|
||||
// cc = 0 cc +
|
||||
// cc2 > 0 cc2 + cc2 -
|
||||
// cc2 = 0 cc2 +
|
||||
|
||||
// boolean en_charge = cc > 0 || (cc == 0 && conso_apparente < -10);
|
||||
// boolean en_injection = cc == 0 && (cc2 > 0 && conso_apparente > 10);
|
||||
|
||||
if (en_charge) {
|
||||
if (conso_apparente > 10 && cc > 0) {
|
||||
cc -= cc_tmp;
|
||||
last_message += " cc-=" + String(cc, 2) + " " + String(cc_tmp, 2);
|
||||
|
||||
setCC(xy, cc);
|
||||
} else if (conso_apparente < -10) {
|
||||
last_message += " cc+=" + String(cc, 2) + " " + String(cc_tmp, 2);
|
||||
|
||||
cc += cc_tmp;
|
||||
setCC(xy, cc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setCC(xy, 0);
|
||||
}
|
||||
Serial.print("cc="); Serial.println(cc);
|
||||
|
||||
#endif
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
|
||||
// double cc_tmp2 = abs(conso_apparente / TENSION_INJECTION) / 3.0;
|
||||
|
||||
double cc_tmp2 = abs(conso_apparente) > 3.0 * TENSION_INJECTION
|
||||
? abs(conso_apparente / TENSION_INJECTION) / 3.0
|
||||
: abs(conso_apparente / TENSION_INJECTION);
|
||||
if (en_injection) {
|
||||
if (conso_apparente > 10) {
|
||||
cc2 += cc_tmp2;
|
||||
last_message += " cc2+=" + String(cc2, 2) + " " + String(cc_tmp2, 2);
|
||||
|
||||
setCC2(xy2, cc2);
|
||||
} else if (conso_apparente < -10 && cc2 > 0) {
|
||||
cc2 -= cc_tmp2;
|
||||
last_message += " cc2-=" + String(cc2, 2) + " " + String(cc_tmp2, 2);
|
||||
|
||||
setCC2(xy2, cc2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setCC2(xy2, 0);
|
||||
}
|
||||
Serial.print("cc2="); Serial.println(cc2);
|
||||
|
||||
#endif
|
||||
|
||||
// }
|
||||
// else {
|
||||
// last_message = "Slider is on";
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void getConsoApparente()
|
||||
{
|
||||
double conso = 0;
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
String url = String(MICRO_SERVICE_ADDRESS);
|
||||
#ifdef ESP8266
|
||||
HTTPClient http;
|
||||
http.begin(url);
|
||||
#else
|
||||
HTTPClient http;
|
||||
http.begin(url.c_str());
|
||||
#endif
|
||||
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
|
||||
String json = "{\"action\":\"on\"}"; // ou "{\"action\":\"off\"}"
|
||||
|
||||
int httpResponseCode = http.POST(json);
|
||||
|
||||
if (httpResponseCode > 0) {
|
||||
String response = http.getString();
|
||||
Serial.println(httpResponseCode);
|
||||
Serial.println(response);
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// Parse le JSON
|
||||
DeserializationError error = deserializeJson(doc, response);
|
||||
if (error) {
|
||||
Serial.print(F("Failed to parse JSON: "));
|
||||
Serial.println(error.f_str());
|
||||
//return 0.0;
|
||||
}
|
||||
// if (String(doc["conso_apparente"]).toFloat() < 0 && abs(String(doc["conso_apparente"]).toFloat()) > String(doc["production"]).toFloat()) {
|
||||
// Serial.println("Erreur de retour Tuya");
|
||||
// }
|
||||
// else {
|
||||
if (String(doc["conso_apparente"]).toFloat() != 0 || String(doc["production"]).toFloat() != 0) {
|
||||
conso_apparente = String(doc["conso_apparente"]).toFloat(); //[0];
|
||||
production = String(doc["production"]).toFloat(); //[0];
|
||||
}
|
||||
// }
|
||||
Serial.println(conso);
|
||||
} else {
|
||||
Serial.print("Erreur lors de l'envoi de la requête POST: ");
|
||||
Serial.println(httpResponseCode);
|
||||
}
|
||||
|
||||
http.end();
|
||||
}
|
||||
|
||||
}
|
||||
427
ESP8266_BATTERIE_INJECTION/victron.h
Normal file
427
ESP8266_BATTERIE_INJECTION/victron.h
Normal file
@@ -0,0 +1,427 @@
|
||||
char receivedChars[buffsize]; // an array to store the received data
|
||||
char tempChars[buffsize]; // an array to manipulate the received data
|
||||
char recv_label[num_keywords][label_bytes] = {0}; // {0} tells the compiler to initalize it with 0.
|
||||
char recv_value[num_keywords][value_bytes] = {0}; // That does not mean it is filled with 0's
|
||||
char value[num_keywords][value_bytes] = {0}; // The array that holds the verified data
|
||||
static byte blockindex = 0;
|
||||
bool blockend = false;
|
||||
double tension_batterie;
|
||||
|
||||
double intensite_decharge = 0;
|
||||
int outVal = 0;
|
||||
bool new_data = false;
|
||||
|
||||
long temps = 0;
|
||||
String last_serial_string = "";
|
||||
//
|
||||
//// ===================================================================
|
||||
//struct DataPair {
|
||||
// char key[10];
|
||||
// char value[20];
|
||||
//};
|
||||
//DataPair data[num_keywords]; // Tableau pour stocker les paires
|
||||
//int currentIndex = 0;
|
||||
//
|
||||
//
|
||||
//void storeDataPair(String line) {
|
||||
// int delimiterIndex = line.indexOf('\t'); // Trouver la position de la tabulation
|
||||
// if (delimiterIndex > 0 && currentIndex < num_keywords) {
|
||||
// // Extraire la clé et la valeur de la ligne
|
||||
// String key = line.substring(0, delimiterIndex);
|
||||
// String value = line.substring(delimiterIndex + 1);
|
||||
//
|
||||
// // Stocker la clé et la valeur dans le tableau
|
||||
// key.toCharArray(data[currentIndex].key, sizeof(data[currentIndex].key));
|
||||
// value.toCharArray(data[currentIndex].value, sizeof(data[currentIndex].value));
|
||||
// currentIndex++;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//void processReceivedData(String data) {
|
||||
// currentIndex = 0; // Réinitialiser l'index pour les nouvelles données
|
||||
// int start = 0;
|
||||
// while (start < data.length()) {
|
||||
// int end = data.indexOf('\n', start);
|
||||
// if (end == -1) {
|
||||
// break;
|
||||
// }
|
||||
// String line = data.substring(start, end);
|
||||
// storeDataPair(line);
|
||||
// start = end + 1;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//
|
||||
//bool receivingData = false; // Indicateur pour savoir si nous sommes en train de recevoir des données
|
||||
//String receivedData = "";
|
||||
//// ===============================================================================
|
||||
|
||||
|
||||
|
||||
void addTension( struct tm* timeinfo, int value) {
|
||||
|
||||
if(value > 30000) {
|
||||
return;
|
||||
}
|
||||
// Si le tableau est plein, décaler toutes les valeurs vers la gauche
|
||||
if (to_store.total_elements >= maxSize) {
|
||||
for (int i = 1; i < maxSize; i++) {
|
||||
to_store.hour[i - 1] = to_store.hour[i];
|
||||
to_store.min[i - 1] = to_store.min[i];
|
||||
to_store.tensions[i - 1] = to_store.tensions[i];
|
||||
}
|
||||
to_store.hour[maxSize - 1] = timeinfo->tm_hour;
|
||||
to_store.min[maxSize - 1] = timeinfo->tm_min;
|
||||
to_store.tensions[maxSize - 1] = value; // Ajouter la nouvelle valeur à la fin
|
||||
} else {
|
||||
// Ajouter la nouvelle valeur à la fin
|
||||
//hour.toCharArray(to_store.hour[to_store.total_elements], sizeof(to_store.hour));
|
||||
to_store.hour[to_store.total_elements] = timeinfo->tm_hour;
|
||||
to_store.min[to_store.total_elements] = timeinfo->tm_min;
|
||||
to_store.tensions[to_store.total_elements] = value;
|
||||
to_store.total_elements++;
|
||||
}
|
||||
to_store.total_elements %= maxSize;
|
||||
|
||||
EEPROM.put(TO_STORE_ADDRESS, to_store);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
// Serial Handling
|
||||
// ---
|
||||
// This block handles the serial reception of the data in a
|
||||
// non blocking way. It checks the Serial line for characters and
|
||||
// parses them in fields. If a block of data is send, which always ends
|
||||
// with "Checksum" field, the whole block is checked and if deemed correct
|
||||
// copied to the 'value' array.
|
||||
|
||||
void recvWithEndMarker() {
|
||||
static byte ndx = 0;
|
||||
char endMarker = '\n';
|
||||
char rc;
|
||||
// new_data = false;
|
||||
#ifdef ESP8266
|
||||
while (victronSerial.available() > 0 && new_data == false) {
|
||||
rc = victronSerial.read();
|
||||
#else
|
||||
while (Serial1.available() > 0 && new_data == false) {
|
||||
rc = Serial1.read();
|
||||
#endif
|
||||
last_serial_string += rc;
|
||||
if (rc != endMarker) {
|
||||
receivedChars[ndx] = rc;
|
||||
ndx++;
|
||||
if (ndx >= buffsize) {
|
||||
ndx = buffsize - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
receivedChars[ndx] = '\0'; // terminate the string
|
||||
ndx = 0;
|
||||
new_data = true;
|
||||
}
|
||||
last_serial_string = String(receivedChars);
|
||||
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void parseData() {
|
||||
char * strtokIndx; // this is used by strtok() as an index
|
||||
strtokIndx = strtok(tempChars,"\t"); // get the first part - the label
|
||||
// The last field of a block is always the Checksum
|
||||
if (strcmp(strtokIndx, "Checksum") == 0) {
|
||||
blockend = true;
|
||||
}
|
||||
strcpy(recv_label[blockindex], strtokIndx); // copy it to label
|
||||
|
||||
// Now get the value
|
||||
strtokIndx = strtok(NULL, "\r"); // This continues where the previous call left off until '/r'.
|
||||
if (strtokIndx != NULL) { // We need to check here if we don't receive NULL.
|
||||
strcpy(recv_value[blockindex], strtokIndx);
|
||||
}
|
||||
blockindex++;
|
||||
|
||||
if (blockend) {
|
||||
// We got a whole block into the received data.
|
||||
// Check if the data received is not corrupted.
|
||||
// Sum off all received bytes should be 0;
|
||||
byte checksum = 0;
|
||||
for (int x = 0; x < blockindex; x++) {
|
||||
// Loop over the labels and value gotten and add them.
|
||||
// Using a byte so the the % 256 is integrated.
|
||||
char *v = recv_value[x];
|
||||
char *l = recv_label[x];
|
||||
while (*v) {
|
||||
checksum += *v;
|
||||
v++;
|
||||
}
|
||||
while (*l) {
|
||||
checksum+= *l;
|
||||
l++;
|
||||
}
|
||||
// Because we strip the new line(10), the carriage return(13) and
|
||||
// the horizontal tab(9) we add them here again.
|
||||
checksum += 32;
|
||||
}
|
||||
// Checksum should be 0, so if !0 we have correct data.
|
||||
if (!checksum) {
|
||||
// Since we are getting blocks that are part of a
|
||||
// keyword chain, but are not certain where it starts
|
||||
// we look for the corresponding label. This loop has a trick
|
||||
// that will start searching for the next label at the start of the last
|
||||
// hit, which should optimize it.
|
||||
int start = 0;
|
||||
for (int i = 0; i < blockindex; i++) {
|
||||
for (int j = start; (j - start) < num_keywords; j++) {
|
||||
if (strcmp(recv_label[i], keywords[j % num_keywords]) == 0) {
|
||||
// found the label, copy it to the value array
|
||||
strcpy(value[j], recv_value[i]);
|
||||
start = (j + 1) % num_keywords; // start searching the next one at this hit +1
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reset the block index, and make sure we clear blockend.
|
||||
blockindex = 0;
|
||||
blockend = false;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanValues() {
|
||||
// new_data = false;
|
||||
// strcpy("RESET", recv_value[CHECKSUM]);
|
||||
// for (int i = 0; i < num_keywords; i++){
|
||||
// strcpy("", recv_value[i]);
|
||||
// }
|
||||
}
|
||||
|
||||
void printValues() {
|
||||
for (int i = 0; i < num_keywords; i++){
|
||||
Serial.print(keywords[i]);
|
||||
Serial.print("=");
|
||||
Serial.print(value[i]);
|
||||
Serial.print("|");
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
void printData() {
|
||||
static unsigned long prev_millis;
|
||||
if (millis() - prev_millis > PRINT_EVERY_SECONDS * 1000) {
|
||||
printValues();
|
||||
prev_millis = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void handleNewData() {
|
||||
|
||||
// We have gotten a field of data
|
||||
if (new_data == true) {
|
||||
//Copy it to the temp array because parseData will alter it.
|
||||
strcpy(tempChars, receivedChars);
|
||||
parseData();
|
||||
new_data = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Méthode pour gérer la requête '/getData'
|
||||
void handleVictron() {
|
||||
blink();
|
||||
|
||||
#ifdef PIN_HALL
|
||||
getHall();
|
||||
#endif
|
||||
|
||||
#ifdef PIN_DALLAS
|
||||
// Command all devices on bus to read temperature
|
||||
// Serial.print("Temperature is: ");
|
||||
temperature = printTemperature(Probe);
|
||||
//Serial.println();
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_XY6020L
|
||||
printMem();
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
printMem2();
|
||||
#endif
|
||||
|
||||
String JSON = F("[");
|
||||
for (int i = 0; i < num_keywords; i++){
|
||||
// String key = data[i].key; //String(keywords[i]);
|
||||
// String val = data[i].value; //String(value[i]);
|
||||
String key = String(keywords[i]);
|
||||
String val = String(value[i]);
|
||||
String label = "";
|
||||
String key_label = "";
|
||||
// if (key.equals("CS")) {
|
||||
// label = "Etat";
|
||||
// val = operationStates[val.toInt()].label;
|
||||
// }
|
||||
|
||||
for (int i = 0; i < mpptDataSize; i++) {
|
||||
if (key.equals(mpptData[i].code)) {
|
||||
key_label= key + " " + mpptData[i].label;
|
||||
}
|
||||
}
|
||||
if (key.equals("OR")) {
|
||||
for (int i = 0; i < offReasonsSize; i++) {
|
||||
if (val.equals(offReasons[i].code)) {
|
||||
label = offReasons[i].label;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals("CS")) {
|
||||
for (int i = 0; i < operationStatesSize; i++) {
|
||||
if (val.equals(operationStates[i].code)) {
|
||||
label = operationStates[i].label;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals("MPPT")) {
|
||||
for (int i = 0; i < mpptStatesSize; i++) {
|
||||
if (val.equals(mpptStates[i].code)) {
|
||||
label = mpptStates[i].label;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals("ERR")) {
|
||||
for (int i = 0; i < errorCodesSize; i++) {
|
||||
if (val.equals(errorCodes[i].code)) {
|
||||
label = errorCodes[i].label;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals("IL")) {
|
||||
intensite_decharge = val.toFloat() / 1000;
|
||||
}
|
||||
if (key.equals("V")) {
|
||||
tension_batterie = val.toFloat() / 1000;
|
||||
|
||||
}
|
||||
if (key.equals("Checksum")) {
|
||||
String tensions = "";
|
||||
String labels = "";
|
||||
for (int i = 0; i < maxSize; i++) {
|
||||
if (i == 0) {
|
||||
tensions = String(to_store.tensions[i]);
|
||||
labels = String(to_store.hour[i]) + ":" + String(to_store.min[i]);
|
||||
}
|
||||
else {
|
||||
tensions += "," + String(to_store.tensions[i]);
|
||||
labels += "," + String((to_store.hour[i] < 10 ? "0" : "") + String(to_store.hour[i]))
|
||||
+ ":"
|
||||
+ String((to_store.min[i] < 10 ? "0" : "") + String(to_store.min[i])) ;
|
||||
|
||||
}
|
||||
}
|
||||
JSON += "{\"id\":\"output-power\", \"value\":\"" + String(tension_batterie * intensite_decharge,1) + "\"},";
|
||||
|
||||
#ifdef TUYA
|
||||
JSON += "{\"id\":\"CONSO\", \"value\":\"" + String(String(conso_apparente).toFloat(),1) + "\"},";
|
||||
JSON += "{\"id\":\"PROD\", \"value\":\"" + String(String(production).toFloat(),1) + "\"},";
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PIN_DALLAS
|
||||
JSON += "{\"id\":\"TEMPERATURE\", \"value\":\"" + String(temperature,1) + "\"},";
|
||||
#endif
|
||||
|
||||
#ifdef PIN_REGULATION
|
||||
JSON += "{\"id\":\"REGULATION\", \"value\":\"" + String(current_regulation) + "\"},";
|
||||
#endif
|
||||
|
||||
#ifdef PIN_DIMMER_OUTPUT
|
||||
JSON += "{\"id\":\"RADIATEUR\", \"value\":\"" + String(pwm) + "\"},";
|
||||
#endif
|
||||
#ifdef PIN_HALL
|
||||
getHall();
|
||||
JSON += "{\"id\":\"HALL_V\", \"value\":\"" + String(VRMS) + "\"},";
|
||||
JSON += "{\"id\":\"HALL_I\", \"value\":\"" + String(Amps) + "\"},";
|
||||
JSON += "{\"id\":\"HALL_W\", \"value\":\"" + String(Amps * 230) + "\"},";
|
||||
#endif
|
||||
#ifdef SERIAL_XY6020L
|
||||
if(xy.HRegUpdated()) {
|
||||
xy.ReadAllHRegs();
|
||||
}
|
||||
|
||||
JSON += "{\"id\":\"CHRG\", \"value\":\"" + String(digitalRead(PIN_CHARGE)) + "\"},";
|
||||
JSON += "{\"id\":\"XY_ON\", \"value\":\"" + String(xy.getOutputOn()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_inV\", \"value\":\"" + String(xy.getInV()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_V\", \"value\":\"" + String(xy.getCV()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_C\", \"value\":\"" + String(xy.getCC()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_T\", \"value\":\"" + String(xy.getTemp()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_AV\", \"value\":\"" + String(xy.getActV()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_AC\", \"value\":\"" + String(xy.getActC()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_AW\", \"value\":\"" + String(xy.getActP()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_CHG\", \"value\":\"" + String(xy.getCharge()) + "\"},";
|
||||
JSON += "{\"id\":\"XY_NRJ\", \"value\":\"" + String(xy.getEnergy()) + "\"},";
|
||||
#endif
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
if(xy2.HRegUpdated()) {
|
||||
xy2.ReadAllHRegs();
|
||||
}
|
||||
JSON += "{\"id\":\"INJC\", \"value\":\"" + String(digitalRead(PIN_INJECTION)) + "\"},";
|
||||
|
||||
JSON += "{\"id\":\"XY2_ON\", \"value\":\"" + String(xy2.getOutputOn()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_inV\", \"value\":\"" + String(xy2.getInV()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_V\", \"value\":\"" + String(xy2.getCV()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_C\", \"value\":\"" + String(xy2.getCC()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_T\", \"value\":\"" + String(xy2.getTemp()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_AV\", \"value\":\"" + String(xy2.getActV()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_AC\", \"value\":\"" + String(xy2.getActC()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_AW\", \"value\":\"" + String(xy2.getActP()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_CHG\", \"value\":\"" + String(xy2.getCharge()) + "\"},";
|
||||
JSON += "{\"id\":\"XY2_NRJ\", \"value\":\"" + String(xy2.getEnergy()) + "\"},";
|
||||
#endif
|
||||
JSON += "{\"id\":\"MESSAGE\", \"value\":\"" + last_message + "\"},";
|
||||
|
||||
JSON += "{\"id\":\"tensions\", \"value\":\"" + tensions + "\",\"labels\":\"" + labels + "\"},";
|
||||
|
||||
// #ifndef SERIAL_BLUE_SOLAR
|
||||
// JSON += "{\"id\":\"" + key + "\",\"key_label\":\"" + key_label + "\",\"label\":\"" + label + "\", \"value\":\"" + val + "\"},";
|
||||
// #endif
|
||||
}
|
||||
else {
|
||||
// if (i == ERR) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// #ifdef SERIAL_BLUE_SOLAR
|
||||
JSON += "{\"id\":\"" + key + "\",\"key_label\":\"" + key_label + "\",\"label\":\"" + label + "\", \"value\":\"" + val + "\"},";
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
//to_store.tensions
|
||||
//JSON += "{\"id\":\"last_serial_string\", \"value\":\"" + last_serial_string + "\"},";
|
||||
|
||||
|
||||
JSON += "{\"id\":\"end\", \"value\":\"end\"}";
|
||||
JSON += "]";
|
||||
blink();
|
||||
server.send(200, "application/json", JSON);
|
||||
|
||||
// // Créer un objet JSON
|
||||
// DynamicJsonDocument doc(200);
|
||||
//
|
||||
// for (int i = 0; i < num_keywords; i++){
|
||||
// doc[String(keywords[i])] = String(value[i]);
|
||||
// }
|
||||
//
|
||||
// // Convertir l'objet jsonData en chaîne
|
||||
// String jsonData;
|
||||
// serializeJson(doc, jsonData);
|
||||
//
|
||||
// // Envoyer la réponse JSON au client
|
||||
// server.send(200, "application/json", jsonData);
|
||||
}
|
||||
|
||||
void handleDebug() {
|
||||
// Envoyer la réponse au client
|
||||
server.send(200, "text/plain", last_serial_string);
|
||||
}
|
||||
192
ESP8266_BATTERIE_INJECTION/xy.h
Normal file
192
ESP8266_BATTERIE_INJECTION/xy.h
Normal file
@@ -0,0 +1,192 @@
|
||||
#include "xy6020l.h"
|
||||
void setCC(xy6020l xy_tmp, double value);
|
||||
|
||||
|
||||
double cc = 0.0;
|
||||
double cc2 = 0.0;
|
||||
|
||||
boolean slider_on = false;
|
||||
|
||||
#define TENSION_CHARGE 35.0 // Volts
|
||||
#define TENSION_INJECTION 22.0
|
||||
#ifdef SERIAL_XY6020L
|
||||
byte MemIdx = 2;
|
||||
void printMem();
|
||||
void printMem2();
|
||||
|
||||
tMemory Mem;
|
||||
|
||||
#ifdef ESP32
|
||||
xy6020l xy(Serial2, 0x01, 50, XY6020_OPT_SKIP_SAME_HREG_VALUE | XY6020_OPT_NO_HREG_UPDATE);
|
||||
// xy6020l xy3(Serial3, 0x01, 50, XY6020_OPT_SKIP_SAME_HREG_VALUE | XY6020_OPT_NO_HREG_UPDATE);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
#ifdef ESP32
|
||||
// Définir le port UART logiciel
|
||||
SoftwareSerial Serial3(PIN_SOFTWARE_SERIAL_RX3, PIN_SOFTWARE_SERIAL_TX3); // RX, TX pour SoftwareSerial
|
||||
tMemory Mem2;
|
||||
xy6020l xy2(Serial3, 0x01, 50, XY6020_OPT_SKIP_SAME_HREG_VALUE | XY6020_OPT_NO_HREG_UPDATE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_XY6020L
|
||||
void printMem()
|
||||
{
|
||||
int vDiff;
|
||||
char tmpBuf[30]; // text buffer for serial messages
|
||||
word tmpW1, tmpW2;
|
||||
|
||||
// xy.ReadAllHRegs();
|
||||
// while (!xy.HRegUpdated()) {
|
||||
// xy.task();
|
||||
// }
|
||||
// sprintf( tmpBuf, "\nM:%04X V:%04X\n", xy.getModel(), xy.getVersion() );
|
||||
// Serial.print(tmpBuf);
|
||||
|
||||
|
||||
Mem.Nr = MemIdx;
|
||||
if ( xy.GetMemory(&Mem) )
|
||||
{
|
||||
xy.PrintMemory(Mem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
void printMem2()
|
||||
{
|
||||
int vDiff;
|
||||
char tmpBuf[30]; // text buffer for serial messages
|
||||
word tmpW1, tmpW2;
|
||||
|
||||
// xy.ReadAllHRegs();
|
||||
// while (!xy.HRegUpdated()) {
|
||||
// xy.task();
|
||||
// }
|
||||
// sprintf( tmpBuf, "\nM:%04X V:%04X\n", xy2.getModel(), xy2.getVersion() );
|
||||
// Serial.print(tmpBuf);
|
||||
|
||||
|
||||
Mem2.Nr = MemIdx;
|
||||
if ( xy2.GetMemory(&Mem2) )
|
||||
{
|
||||
xy2.PrintMemory(Mem2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void setCC(xy6020l xy_tmp, double value)
|
||||
{
|
||||
cc = value;
|
||||
// if (slider_on == false) {
|
||||
if (cc <= 0) {
|
||||
cc = 0;
|
||||
xy.setOutput(false);
|
||||
xy.setCV(0);
|
||||
xy.setCC(0);
|
||||
}
|
||||
else {
|
||||
if (cc > 17.0) {
|
||||
cc = 17.0;
|
||||
}
|
||||
xy.setOutput(true);
|
||||
xy.setCV(TENSION_CHARGE * 100.0);
|
||||
// xy.setCC(MAX_AMPERAGE * current_regulation);
|
||||
xy.setCC(cc * 100.0);
|
||||
}
|
||||
// }
|
||||
}
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
|
||||
void setCC2(xy6020l xy_tmp, double value)
|
||||
{
|
||||
cc2 = value;
|
||||
// if (slider_on == false) {
|
||||
if (cc2 <= 0) {
|
||||
cc2 = 0;
|
||||
xy2.setOutput(false);
|
||||
xy2.setCV(0);
|
||||
xy2.setCC(0);
|
||||
}
|
||||
else {
|
||||
if (cc2 > 10.0) {
|
||||
cc2 = 10.0;
|
||||
}
|
||||
xy2.setOutput(true);
|
||||
xy2.setCV(TENSION_INJECTION * 100.0);
|
||||
// xy.setCC(MAX_AMPERAGE * current_regulation);
|
||||
xy2.setCC(cc2 * 100.0);
|
||||
}
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fonction pour gérer la requête POST /update
|
||||
void handleUpdate() {
|
||||
// Créer un tampon pour stocker le JSON entrant
|
||||
const size_t capacity = JSON_OBJECT_SIZE(2) + 60;
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
// Lire le corps de la requête HTTP
|
||||
String json = server.arg("plain"); // 'plain' est utilisé pour lire le corps brut de la requête
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
|
||||
// Vérifier s'il y a des erreurs de désérialisation
|
||||
if (error) {
|
||||
server.send(400, "text/plain", "Invalid JSON");
|
||||
return;
|
||||
}
|
||||
|
||||
// Extraire les valeurs du JSON
|
||||
String slider = doc["slider"];
|
||||
int value = doc["value"];
|
||||
|
||||
// Vérifier la validité des valeurs reçues
|
||||
if (slider.equals("sliderCurrent")) {
|
||||
if (slider.length() > 0 && value > 0) {
|
||||
// Logique de charge ici
|
||||
// slider_on = true;
|
||||
charge();
|
||||
// xy.setOutput(true);
|
||||
// xy.setCV(TENSION_CHARGE * 100);
|
||||
setCC(xy, value);
|
||||
|
||||
server.send(200, "text/plain", "Slider saved");
|
||||
} else {
|
||||
slider_on = false;
|
||||
stopCharge();
|
||||
cc = 0;
|
||||
setCC(xy, 0);
|
||||
server.send(200, "text/plain", "Slider stopped");
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_XY6020L_2
|
||||
|
||||
else if (slider.equals("sliderCurrent2")) {
|
||||
if (slider.length() > 0 && value > 0) {
|
||||
// Logique de charge ici
|
||||
injection();
|
||||
// slider_on = true;
|
||||
// xy.setOutput(true);
|
||||
// xy.setCV(TENSION_CHARGE * 100);
|
||||
setCC2(xy2, value);
|
||||
|
||||
server.send(200, "text/plain", "Slider saved");
|
||||
} else {
|
||||
slider_on = false;
|
||||
stopInjection();
|
||||
cc2 = 0;
|
||||
setCC2(xy2, 0);
|
||||
server.send(200, "text/plain", "Slider stopped");
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
else {
|
||||
server.send(400, "text/plain", "Invalid request " + slider);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user