-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6a54c44
Showing
26 changed files
with
3,338 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#ifndef CHADEMO_H_ | ||
#define CHADEMO_H_ | ||
#include <Arduino.h> | ||
#include "Globals.h" | ||
#include <ACAN_ESP32.h> | ||
|
||
enum CHADEMOSTATE | ||
{ | ||
STARTUP, | ||
SEND_INITIAL_PARAMS, | ||
WAIT_FOR_EVSE_PARAMS, | ||
SET_CHARGE_BEGIN, | ||
WAIT_FOR_BEGIN_CONFIRMATION, | ||
CLOSE_CONTACTORS, | ||
WAIT_FOR_PRECHARGE, | ||
RUNNING, | ||
CEASE_CURRENT, | ||
WAIT_FOR_ZERO_CURRENT, | ||
OPEN_CONTACTOR, | ||
FAULTED, | ||
STOPPED, | ||
LIMBO | ||
}; | ||
|
||
typedef struct | ||
{ | ||
uint8_t supportWeldCheck; | ||
uint16_t availVoltage; | ||
uint8_t availCurrent; | ||
uint16_t thresholdVoltage; //evse calculates this. It is the voltage at which it'll abort charging to save the battery pack in case we asked for something stupid | ||
} EVSE_PARAMS; | ||
|
||
typedef struct | ||
{ | ||
uint16_t presentVoltage; | ||
uint8_t presentCurrent; | ||
uint8_t status; | ||
uint16_t remainingChargeSeconds; | ||
} EVSE_STATUS; | ||
|
||
typedef struct | ||
{ | ||
uint16_t targetVoltage; //what voltage we want the EVSE to put out | ||
uint8_t targetCurrent; //what current we'd like the EVSE to provide | ||
uint8_t remainingKWH; //report # of KWh in the battery pack (charge level) | ||
uint8_t battOverVolt : 1; //we signal that battery or a cell is too high of a voltage | ||
uint8_t battUnderVolt : 1; //we signal that battery is too low | ||
uint8_t currDeviation : 1; //we signal that measured current is not the same as EVSE is reporting | ||
uint8_t battOverTemp : 1; //we signal that battery is too hot | ||
uint8_t voltDeviation : 1; //we signal that we measure a different voltage than EVSE reports | ||
uint8_t chargingEnabled : 1; //ask EVSE to enable charging | ||
uint8_t notParked : 1; //advise EVSE that we're not in park. | ||
uint8_t chargingFault : 1; //signal EVSE that we found a fault | ||
uint8_t contactorOpen : 1; //tell EVSE whether we've closed the charging contactor | ||
uint8_t stopRequest : 1; //request that the charger cease operation before we really get going | ||
} CARSIDE_STATUS; | ||
|
||
//The IDs for chademo comm - both carside and EVSE side so we know what to listen for | ||
//as well. | ||
#define CARSIDE_BATT_ID 0x100 | ||
#define CARSIDE_CHARGETIME_ID 0x101 | ||
#define CARSIDE_CONTROL_ID 0x102 | ||
|
||
#define EVSE_PARAMS_ID 0x108 | ||
#define EVSE_STATUS_ID 0x109 | ||
|
||
#define CARSIDE_FAULT_OVERV 1 //over voltage | ||
#define CARSIDE_FAULT_UNDERV 2 //Under voltage | ||
#define CARSIDE_FAULT_CURR 4 //current mismatch | ||
#define CARSIDE_FAULT_OVERT 8 //over temperature | ||
#define CARSIDE_FAULT_VOLTM 16 //voltage mismatch | ||
|
||
#define CARSIDE_STATUS_CHARGE 1 //charging enabled | ||
#define CARSIDE_STATUS_NOTPARK 2 //shifter not in safe state | ||
#define CARSIDE_STATUS_MALFUN 4 //vehicle did something dumb | ||
#define CARSIDE_STATUS_CONTOP 8 //main contactor open | ||
#define CARSIDE_STATUS_CHSTOP 16 //charger stop before even charging | ||
|
||
#define EVSE_STATUS_CHARGE 1 //charger is active | ||
#define EVSE_STATUS_ERR 2 //something went wrong | ||
#define EVSE_STATUS_CONNLOCK 4 //connector is currently locked | ||
#define EVSE_STATUS_INCOMPAT 8 //parameters between vehicle and charger not compatible | ||
#define EVSE_STATUS_BATTERR 16 //something wrong with battery?! | ||
#define EVSE_STATUS_STOPPED 32 //charger is stopped | ||
|
||
class CHADEMO | ||
{ | ||
public: | ||
CHADEMO(); | ||
void setDelayedState(int newstate, uint16_t delayTime); | ||
CHADEMOSTATE getState(); | ||
EVSE_PARAMS getEVSEParams(); | ||
EVSE_STATUS getEVSEStatus(); | ||
|
||
void setTargetAmperage(uint8_t t_amp); | ||
void setTargetVoltage(uint16_t t_volt); | ||
void loop(); | ||
void doProcessing(); | ||
void handleCANFrame(CANMessage &frame); | ||
void setChargingFault(); | ||
void setBattOverTemp(); | ||
void setStateOfCharge(uint8_t stateofcharge); | ||
|
||
//these need to be accessed quickly in tight spots so they're public in an attempt at efficiency | ||
uint8_t bChademoMode; //accessed but not modified in ISR so it should be OK non-volatile | ||
uint8_t bChademoSendRequests; //should we be sending periodic status updates? | ||
volatile uint8_t bChademoRequest; //is it time to send one of those updates? | ||
|
||
protected: | ||
private: | ||
uint8_t bStartedCharge; //we have started a charge since the plug was inserted. Prevents attempts to restart charging if it stopped previously | ||
uint8_t bChademo10Protocol; //can we use 1.0 protocol? | ||
//target values are what we send with periodic frames and can be changed. | ||
uint8_t askingAmps; //how many amps to ask for. Trends toward targetAmperage | ||
uint8_t bListenEVSEStatus; //should we pay attention to stop requests and such yet? | ||
uint8_t bDoMismatchChecks; //should we be checking for voltage and current mismatches? | ||
uint8_t bConnectorLocked; //is the EVSE saying the connector is locked | ||
uint8_t vMismatchCount; //count # of consecutive voltage mismatches. Don't trigger until we get enough | ||
uint8_t cMismatchCount; //same but for current | ||
uint8_t vCapCount; //# of EVSE voltage capacity checks that have failed in a row. | ||
uint8_t vOverFault; //over volt fault counter like above. | ||
uint8_t faultCount; //force faults to count up a bit before we actually fault. | ||
uint32_t mismatchStart; | ||
const uint16_t mismatchDelay = 10000; //don't start mismatch checks for 10 seconds | ||
uint32_t stateMilli; | ||
uint16_t stateDelay; | ||
uint32_t insertionTime; | ||
uint32_t lastCommTime; | ||
const uint16_t lastCommTimeout = 1000; //allow up to 1 second of comm fault before getting angry | ||
uint8_t soc; //BMS reported SoC | ||
|
||
CHADEMOSTATE chademoState; | ||
CHADEMOSTATE stateHolder; | ||
EVSE_PARAMS evse_params; | ||
EVSE_STATUS evse_status; | ||
CARSIDE_STATUS carStatus; | ||
|
||
void sendCANStatus(); | ||
void sendCANBattSpecs(); | ||
void sendCANChargingTime(); | ||
}; | ||
|
||
extern CHADEMO chademo; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#include "ChademoWebServer.h" | ||
#include <SPIFFS.h> | ||
#include <EEPROM.h> | ||
|
||
AsyncWebServer server(80); | ||
AsyncWebSocket ws("/ws"); | ||
AsyncEventSource events("/events"); | ||
|
||
ChademoWebServer::ChademoWebServer(EESettings& s) : settings{ s } { | ||
} | ||
|
||
AsyncWebSocket& ChademoWebServer::getWebSocket() { | ||
return ws; | ||
} | ||
void ChademoWebServer::execute() { | ||
ws.cleanupClients(); | ||
} | ||
|
||
void ChademoWebServer::broadcast(const char * message) { | ||
ws.printfAll(message); | ||
} | ||
|
||
void ChademoWebServer::setup() | ||
{ | ||
// ws.onEvent(onWsEvent); | ||
server.addHandler(&ws); | ||
|
||
server.on("/wifi", [&] (AsyncWebServerRequest *request) { | ||
bool updated = true; | ||
if(request->hasParam("apSSID", true) && request->hasParam("apPW", true)) | ||
{ | ||
WiFi.softAP(request->arg("apSSID").c_str(), request->arg("apPW").c_str()); | ||
} | ||
else if(request->hasParam("staSSID", true) && request->hasParam("staPW", true)) | ||
{ | ||
WiFi.mode(WIFI_AP_STA); | ||
WiFi.begin(request->arg("staSSID").c_str(), request->arg("staPW").c_str()); | ||
} | ||
else | ||
{ | ||
File file = SPIFFS.open("/wifi.html", "r"); | ||
String html = file.readString(); | ||
file.close(); | ||
html.replace("%staSSID%", WiFi.SSID()); | ||
html.replace("%apSSID%", WiFi.softAPSSID()); | ||
html.replace("%staIP%", WiFi.localIP().toString()); | ||
request->send(200, "text/html", html); | ||
updated = false; | ||
} | ||
|
||
if (updated) | ||
{ | ||
request->send(SPIFFS, "/wifi-updated.html"); | ||
} | ||
}); | ||
|
||
server.on("/settings", HTTP_GET, [&] (AsyncWebServerRequest *request) { | ||
AsyncResponseStream *response = request->beginResponseStream("application/json"); | ||
DynamicJsonDocument json(2048); | ||
toJson(settings, json); | ||
serializeJson(json, *response); | ||
request->send(response); | ||
}); | ||
|
||
server.on( | ||
"/settings", | ||
HTTP_POST, | ||
[](AsyncWebServerRequest * request){}, | ||
NULL, | ||
[&](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) { | ||
Serial.println("settings POST"); | ||
const size_t JSON_DOC_SIZE = 1024U; | ||
DynamicJsonDocument jsonDoc(JSON_DOC_SIZE); | ||
|
||
if (DeserializationError::Ok == deserializeJson(jsonDoc, (const char*)data)) | ||
{ | ||
JsonObject obj = jsonDoc.as<JsonObject>(); | ||
fromJson(settings, obj); | ||
EEPROM.put(0, settings); | ||
EEPROM.commit(); | ||
request->send(200, "application/json", "success"); | ||
|
||
} else { | ||
request->send(200, "application/json", "DeserializationError"); | ||
} | ||
}); | ||
|
||
server.on("/edit", | ||
HTTP_POST, | ||
[](AsyncWebServerRequest * request){}, | ||
[&](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { | ||
if (!index) { | ||
// open the file on first call and store the file handle in the request object | ||
request->_tempFile = SPIFFS.open("/" + filename, "w"); | ||
|
||
} | ||
|
||
if (len) { | ||
// stream the incoming chunk to the opened file | ||
request->_tempFile.write(data, len); | ||
} | ||
|
||
if (final) { | ||
// close the file handle as the upload is now done | ||
request->_tempFile.close(); | ||
|
||
if (filename.substring(filename.lastIndexOf(".")).equals("bin")) { | ||
Serial.println("Firmware uploaded, restarting"); | ||
request->send(200, "application/json", "restarting"); | ||
ESP.restart(); | ||
} | ||
request->redirect("/"); | ||
} | ||
} | ||
|
||
); | ||
|
||
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html"); | ||
|
||
|
||
// Start server | ||
Serial.println("Starting Web Server"); | ||
|
||
server.begin(); | ||
} | ||
|
||
void ChademoWebServer::toJson(EESettings& settings, DynamicJsonDocument &root) { | ||
root["useBms"] = settings.useBms; | ||
root["ampHours"] = settings.ampHours; | ||
root["packSizeKWH"] = settings.packSizeKWH; | ||
root["maxChargeVoltage"] = settings.maxChargeVoltage; | ||
root["targetChargeVoltage"] = settings.targetChargeVoltage; | ||
root["maxChargeAmperage"] = settings.maxChargeAmperage; | ||
root["minChargeAmperage"] = settings.minChargeAmperage; | ||
root["capacity"] = settings.capacity; | ||
root["debuggingLevel"] = settings.debuggingLevel; | ||
} | ||
|
||
void ChademoWebServer::fromJson(EESettings& settings, JsonObject &doc) { | ||
|
||
settings.useBms = doc["useBms"]; | ||
settings.ampHours = doc["ampHours"]; | ||
settings.packSizeKWH = doc["packSizeKWH"]; | ||
settings.maxChargeVoltage = doc["maxChargeVoltage"]; | ||
settings.targetChargeVoltage = doc["targetChargeVoltage"]; | ||
settings.maxChargeAmperage = doc["maxChargeAmperage"]; | ||
settings.minChargeAmperage = doc["minChargeAmperage"]; | ||
settings.capacity = doc["capacity"]; | ||
settings.debuggingLevel = doc["debuggingLevel"]; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#ifndef CHADEMO_WEB_SERVER_H | ||
#define CHADEMO_WEB_SERVER_H | ||
#include <Arduino.h> | ||
#include "Globals.h" | ||
#include "ESPAsyncWebServer.h" | ||
#include "ArduinoJson.h" | ||
|
||
class ChademoWebServer | ||
{ | ||
public: | ||
ChademoWebServer(EESettings& settings); | ||
void setup(); | ||
void execute(); | ||
void broadcast(const char * message); | ||
AsyncWebSocket& getWebSocket(); | ||
private: | ||
void toJson(EESettings& settings, DynamicJsonDocument &root); | ||
void fromJson(EESettings& settings, JsonObject &doc); | ||
EESettings& settings; | ||
}; | ||
#endif |
Oops, something went wrong.