Move global charger variables to datalayer (#810)

This commit is contained in:
Daniel Öster 2025-01-21 11:09:03 +03:00 committed by GitHub
parent 8886e86a14
commit ffe583d551
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 81 additions and 115 deletions

View file

@ -24,14 +24,6 @@
#include "src/devboard/utils/timer.h"
#include "src/devboard/utils/value_mapping.h"
#include "src/include.h"
#include "src/lib/YiannisBourkelis-Uptime-Library/src/uptime.h"
#include "src/lib/YiannisBourkelis-Uptime-Library/src/uptime_formatter.h"
#include "src/lib/bblanchon-ArduinoJson/ArduinoJson.h"
#include "src/lib/eModbus-eModbus/Logging.h"
#include "src/lib/eModbus-eModbus/ModbusServerRTU.h"
#include "src/lib/eModbus-eModbus/scripts/mbServerFCs.h"
#include "src/lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
#include "src/lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
#ifndef AP_PASSWORD
#error \
"Initial setup not completed, USER_SECRETS.h is missing. Please rename the file USER_SECRETS.TEMPLATE.h to USER_SECRETS.h and fill in the required credentials. This file is ignored by version control to keep sensitive information private."
@ -61,21 +53,6 @@ uint16_t intervalUpdateValues = INTERVAL_1_S; // Interval at which to update in
unsigned long previousMillis10ms = 0;
unsigned long previousMillisUpdateVal = 0;
// Common charger parameters
volatile float charger_setpoint_HV_VDC = 0.0f;
volatile float charger_setpoint_HV_IDC = 0.0f;
volatile float charger_setpoint_HV_IDC_END = 0.0f;
bool charger_HV_enabled = false;
bool charger_aux12V_enabled = false;
// Common charger statistics, instantaneous values
float charger_stat_HVcur = 0;
float charger_stat_HVvol = 0;
float charger_stat_ACcur = 0;
float charger_stat_ACvol = 0;
float charger_stat_LVcur = 0;
float charger_stat_LVvol = 0;
// Task time measurement for debugging and for setting CPU load events
int64_t core_task_time_us;
MyTimer core_task_timer_10s(INTERVAL_10_S);

View file

@ -162,17 +162,12 @@ typedef struct {
extern volatile CAN_Configuration can_config;
extern volatile uint8_t AccessPointEnabled;
extern const uint8_t wifi_channel;
extern volatile float charger_setpoint_HV_VDC;
extern volatile float charger_setpoint_HV_IDC;
extern volatile float charger_setpoint_HV_IDC_END;
extern volatile float CHARGER_SET_HV;
extern volatile float CHARGER_MAX_HV;
extern volatile float CHARGER_MIN_HV;
extern volatile float CHARGER_MAX_POWER;
extern volatile float CHARGER_MAX_A;
extern volatile float CHARGER_END_A;
extern bool charger_HV_enabled;
extern bool charger_aux12V_enabled;
#ifdef EQUIPMENT_STOP_BUTTON
typedef enum { LATCHING_SWITCH = 0, MOMENTARY_SWITCH = 1 } STOP_BUTTON_BEHAVIOR;

View file

@ -1,7 +1,6 @@
#include "../include.h"
#ifdef CHEVYVOLT_CHARGER
#include "../datalayer/datalayer.h"
#include "../devboard/utils/events.h"
#include "CHEVY-VOLT-CHARGER.h"
/* This implements Chevy Volt / Ampera charger support (2011-2015 model years).
@ -25,20 +24,6 @@ static unsigned long previousMillis30ms = 0; // 30ms cycle for keepalive fram
static unsigned long previousMillis200ms = 0; // 200ms cycle for commanding I/V targets
static unsigned long previousMillis5000ms = 0; // 5s status printout to serial
/* voltage and current settings. Validation performed to set ceiling of 3300w vol*cur */
extern volatile float charger_setpoint_HV_VDC;
extern volatile float charger_setpoint_HV_IDC;
extern volatile float charger_setpoint_HV_IDC_END;
extern bool charger_HV_enabled;
extern bool charger_aux12V_enabled;
extern float charger_stat_HVcur;
extern float charger_stat_HVvol;
extern float charger_stat_ACcur;
extern float charger_stat_ACvol;
extern float charger_stat_LVcur;
extern float charger_stat_LVvol;
enum CHARGER_MODES : uint8_t { MODE_DISABLED = 0, MODE_LV, MODE_HV, MODE_HVLV };
//Actual content messages
@ -68,26 +53,26 @@ void map_can_frame_to_variable_charger(CAN_frame rx_frame) {
//ID 0x212 conveys instantaneous DC charger stats
case 0x212:
charger_stat_HVcur_temp = (uint16_t)(rx_frame.data.u8[0] << 8 | rx_frame.data.u8[1]);
charger_stat_HVcur = (float)(charger_stat_HVcur_temp >> 3) * 0.05;
datalayer.charger.charger_stat_HVcur = (float)(charger_stat_HVcur_temp >> 3) * 0.05;
charger_stat_HVvol_temp = (uint16_t)((((rx_frame.data.u8[1] << 8 | rx_frame.data.u8[2])) >> 1) & 0x3ff);
charger_stat_HVvol = (float)(charger_stat_HVvol_temp) * .5;
datalayer.charger.charger_stat_HVvol = (float)(charger_stat_HVvol_temp) * .5;
charger_stat_LVcur_temp = (uint16_t)(((rx_frame.data.u8[2] << 8 | rx_frame.data.u8[3]) >> 1) & 0x00ff);
charger_stat_LVcur = (float)(charger_stat_LVcur_temp) * .2;
datalayer.charger.charger_stat_LVcur = (float)(charger_stat_LVcur_temp) * .2;
charger_stat_LVvol_temp = (uint16_t)(((rx_frame.data.u8[3] << 8 | rx_frame.data.u8[4]) >> 1) & 0x00ff);
charger_stat_LVvol = (float)(charger_stat_LVvol_temp) * .1;
datalayer.charger.charger_stat_LVvol = (float)(charger_stat_LVvol_temp) * .1;
break;
//ID 0x30A conveys instantaneous AC charger stats
case 0x30A:
charger_stat_ACcur_temp = (uint16_t)((rx_frame.data.u8[0] << 8 | rx_frame.data.u8[1]) >> 4);
charger_stat_ACcur = (float)(charger_stat_ACcur_temp) * 0.2;
datalayer.charger.charger_stat_ACcur = (float)(charger_stat_ACcur_temp) * 0.2;
charger_stat_ACvol_temp = (uint16_t)(((rx_frame.data.u8[1] << 8 | rx_frame.data.u8[2]) >> 4) & 0x00ff);
charger_stat_ACvol = (float)(charger_stat_ACvol_temp) * 2;
datalayer.charger.charger_stat_ACvol = (float)(charger_stat_ACvol_temp) * 2;
break;
@ -112,16 +97,16 @@ void transmit_can_charger() {
unsigned long currentMillis = millis();
uint16_t Vol_temp = 0;
uint16_t setpoint_HV_VDC = floor(charger_setpoint_HV_VDC);
uint16_t setpoint_HV_IDC = floor(charger_setpoint_HV_IDC);
uint16_t setpoint_HV_IDC_END = floor(charger_setpoint_HV_IDC_END);
uint16_t setpoint_HV_VDC = floor(datalayer.charger.charger_setpoint_HV_VDC);
uint16_t setpoint_HV_IDC = floor(datalayer.charger.charger_setpoint_HV_IDC);
uint16_t setpoint_HV_IDC_END = floor(datalayer.charger.charger_setpoint_HV_IDC_END);
uint8_t charger_mode = MODE_DISABLED;
/* Send keepalive with mode every 30ms */
if (currentMillis - previousMillis30ms >= INTERVAL_30_MS) {
previousMillis30ms = currentMillis;
if (charger_HV_enabled) {
if (datalayer.charger.charger_HV_enabled) {
charger_mode += MODE_HV;
/* disable HV if end amperage reached
@ -132,7 +117,7 @@ void transmit_can_charger() {
*/
}
if (charger_aux12V_enabled)
if (datalayer.charger.charger_aux12V_enabled)
charger_mode += MODE_LV;
charger_keepalive_frame.data.u8[0] = charger_mode;

View file

@ -1,7 +1,6 @@
#include "../include.h"
#ifdef NISSANLEAF_CHARGER
#include "../datalayer/datalayer.h"
#include "../devboard/utils/events.h"
#include "NISSAN-LEAF-CHARGER.h"
/* This implements Nissan LEAF PDM charger support. 2013-2024 Gen2/3 PDMs are supported
@ -45,20 +44,6 @@ static uint8_t OBCpower = 0;
static bool PPStatus = false;
static bool OBCwakeup = false;
/* Voltage and current settings. Validation performed to set ceiling of 3300w vol*cur */
extern volatile float charger_setpoint_HV_VDC;
extern volatile float charger_setpoint_HV_IDC;
extern volatile float charger_setpoint_HV_IDC_END;
extern bool charger_HV_enabled;
extern bool charger_aux12V_enabled;
extern float charger_stat_HVcur;
extern float charger_stat_HVvol;
extern float charger_stat_ACcur;
extern float charger_stat_ACvol;
extern float charger_stat_LVcur;
extern float charger_stat_LVvol;
//Actual content messages
static CAN_frame LEAF_1DB = {.FD = false,
.ext_ID = false,
@ -134,11 +119,11 @@ void map_can_frame_to_variable_charger(CAN_frame rx_frame) {
switch (rx_frame.ID) {
case 0x679: // This message fires once when charging cable is plugged in
OBCwakeup = true;
charger_aux12V_enabled = true; //Not possible to turn off 12V charging
datalayer.charger.charger_aux12V_enabled = true; //Not possible to turn off 12V charging on LEAF PDM
// Startout with default values, so that charging can begin right when user plugs in cable
charger_HV_enabled = true;
charger_setpoint_HV_IDC = 16; // Ampere
charger_setpoint_HV_VDC = 400; // Target voltage
datalayer.charger.charger_HV_enabled = true;
datalayer.charger.charger_setpoint_HV_IDC = 16; // Ampere
datalayer.charger.charger_setpoint_HV_VDC = 400; // Target voltage
break;
case 0x390:
OBC_Charge_Status = ((rx_frame.data.u8[5] & 0x7E) >> 1);
@ -149,17 +134,17 @@ void map_can_frame_to_variable_charger(CAN_frame rx_frame) {
}
OBC_Status_AC_Voltage = ((rx_frame.data.u8[3] & 0x18) >> 3);
if (OBC_Status_AC_Voltage == AC110) {
charger_stat_ACvol = 110;
datalayer.charger.charger_stat_ACvol = 110;
}
if (OBC_Status_AC_Voltage == AC230) {
charger_stat_ACvol = 230;
datalayer.charger.charger_stat_ACvol = 230;
}
if (OBC_Status_AC_Voltage == ABNORMAL_WAVE) {
charger_stat_ACvol = 1;
datalayer.charger.charger_stat_ACvol = 1;
}
OBC_Charge_Power = ((rx_frame.data.u8[0] & 0x01) << 8) | (rx_frame.data.u8[1]);
charger_stat_HVcur = OBC_Charge_Power;
datalayer.charger.charger_stat_HVcur = OBC_Charge_Power;
break;
default:
break;
@ -173,9 +158,7 @@ void transmit_can_charger() {
if (currentMillis - previousMillis10ms >= INTERVAL_10_MS) {
previousMillis10ms = currentMillis;
mprun10++;
if (mprun10 >= 4)
mprun10 = 0;
mprun10 = (mprun10 + 1) % 4; // mprun10 cycles between 0-1-2-3-0-1...
/* 1DB is the main control message. If LEAF battery is used, the battery controls almost everything */
// Only send these messages if Nissan LEAF battery is not used
@ -191,7 +174,7 @@ void transmit_can_charger() {
transmit_can_frame(&LEAF_1DC, can_config.charger);
#endif
OBCpowerSetpoint = ((charger_setpoint_HV_IDC * 4) + 0x64);
OBCpowerSetpoint = ((datalayer.charger.charger_setpoint_HV_IDC * 4) + 0x64);
// convert power setpoint to PDM format:
// 0xA0 = 15A (60x)
@ -204,7 +187,8 @@ void transmit_can_charger() {
// This line controls if power should flow or not
if (PPStatus &&
charger_HV_enabled) { //Charging starts when cable plugged in and User has requested charging to start via WebUI
datalayer.charger
.charger_HV_enabled) { //Charging starts when cable plugged in and User has requested charging to start via WebUI
// clamp min and max values
if (OBCpowerSetpoint > 0xA0) { //15A TODO, raise once cofirmed how to map bits into frame0 and frame1
OBCpowerSetpoint = 0xA0;
@ -242,10 +226,7 @@ void transmit_can_charger() {
if (currentMillis - previousMillis100ms >= INTERVAL_100_MS) {
previousMillis100ms = currentMillis;
mprun100++;
if (mprun100 > 3) {
mprun100 = 0;
}
mprun100 = (mprun100 + 1) % 4; // mprun100 cycles between 0-1-2-3-0-1...
// Only send these messages if Nissan LEAF battery is not used
#ifndef NISSAN_LEAF_BATTERY

View file

@ -148,6 +148,31 @@ typedef struct {
DATALAYER_BATTERY_SETTINGS_TYPE settings;
} DATALAYER_BATTERY_TYPE;
typedef struct {
/** Charger setpoint voltage */
float charger_setpoint_HV_VDC = 0;
/** Charger setpoint current */
float charger_setpoint_HV_IDC = 0;
/** Charger setpoint current at end of charge **/
float charger_setpoint_HV_IDC_END = 0;
/** Measured current from charger */
float charger_stat_HVcur = 0;
/** Measured HV from charger */
float charger_stat_HVvol = 0;
/** Measured AC current from charger **/
float charger_stat_ACcur = 0;
/** Measured AC voltage from charger **/
float charger_stat_ACvol = 0;
/** Measured LV current from charger **/
float charger_stat_LVcur = 0;
/** Measured LV voltage from charger **/
float charger_stat_LVvol = 0;
/** True if charger is enabled */
bool charger_HV_enabled = false;
/** True if the 12V DC/DC output is enabled */
bool charger_aux12V_enabled = false;
} DATALAYER_CHARGER_TYPE;
typedef struct {
/** measured voltage in deciVolts. 4200 = 420.0 V */
uint16_t measured_voltage_dV = 0;
@ -264,6 +289,7 @@ class DataLayer {
DATALAYER_BATTERY_TYPE battery;
DATALAYER_BATTERY_TYPE battery2;
DATALAYER_SHUNT_TYPE shunt;
DATALAYER_CHARGER_TYPE charger;
DATALAYER_SYSTEM_TYPE system;
};

View file

@ -144,7 +144,7 @@ String settings_processor(const String& var) {
content += "<div style='background-color: #FF6E00; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
content += "<h4 style='color: white;'>Charger HVDC Enabled: ";
if (charger_HV_enabled) {
if (datalayer.charger.charger_HV_enabled) {
content += "<span>&#10003;</span>";
} else {
content += "<span style='color: red;'>&#10005;</span>";
@ -152,17 +152,19 @@ String settings_processor(const String& var) {
content += " <button onclick='editChargerHVDCEnabled()'>Edit</button></h4>";
content += "<h4 style='color: white;'>Charger Aux12VDC Enabled: ";
if (charger_aux12V_enabled) {
if (datalayer.charger.charger_aux12V_enabled) {
content += "<span>&#10003;</span>";
} else {
content += "<span style='color: red;'>&#10005;</span>";
}
content += " <button onclick='editChargerAux12vEnabled()'>Edit</button></h4>";
content += "<h4 style='color: white;'>Charger Voltage Setpoint: " + String(charger_setpoint_HV_VDC, 1) +
" V </span> <button onclick='editChargerSetpointVDC()'>Edit</button></h4>";
content += "<h4 style='color: white;'>Charger Current Setpoint: " + String(charger_setpoint_HV_IDC, 1) +
" A </span> <button onclick='editChargerSetpointIDC()'>Edit</button></h4>";
content +=
"<h4 style='color: white;'>Charger Voltage Setpoint: " + String(datalayer.charger.charger_setpoint_HV_VDC, 1) +
" V </span> <button onclick='editChargerSetpointVDC()'>Edit</button></h4>";
content +=
"<h4 style='color: white;'>Charger Current Setpoint: " + String(datalayer.charger.charger_setpoint_HV_IDC, 1) +
" A </span> <button onclick='editChargerSetpointIDC()'>Edit</button></h4>";
// Close the block
content += "</div>";

View file

@ -551,11 +551,11 @@ void init_webserver() {
request->send(400, "text/plain", "Bad Request");
}
if (!(val * charger_setpoint_HV_IDC <= CHARGER_MAX_POWER)) {
if (!(val * datalayer.charger.charger_setpoint_HV_IDC <= CHARGER_MAX_POWER)) {
request->send(400, "text/plain", "Bad Request");
}
charger_setpoint_HV_VDC = val;
datalayer.charger.charger_setpoint_HV_VDC = val;
request->send(200, "text/plain", "Updated successfully");
});
@ -575,11 +575,11 @@ void init_webserver() {
request->send(400, "text/plain", "Bad Request");
}
if (!(val * charger_setpoint_HV_VDC <= CHARGER_MAX_POWER)) {
if (!(val * datalayer.charger.charger_setpoint_HV_VDC <= CHARGER_MAX_POWER)) {
request->send(400, "text/plain", "Bad Request");
}
charger_setpoint_HV_IDC = value.toFloat();
datalayer.charger.charger_setpoint_HV_IDC = value.toFloat();
request->send(200, "text/plain", "Updated successfully");
});
@ -590,7 +590,7 @@ void init_webserver() {
return request->requestAuthentication();
if (request->hasParam("value")) {
String value = request->getParam("value")->value();
charger_setpoint_HV_IDC_END = value.toFloat();
datalayer.charger.charger_setpoint_HV_IDC_END = value.toFloat();
request->send(200, "text/plain", "Updated successfully");
} else {
request->send(400, "text/plain", "Bad Request");
@ -603,7 +603,7 @@ void init_webserver() {
return request->requestAuthentication();
if (request->hasParam("value")) {
String value = request->getParam("value")->value();
charger_HV_enabled = (bool)value.toInt();
datalayer.charger.charger_HV_enabled = (bool)value.toInt();
request->send(200, "text/plain", "Updated successfully");
} else {
request->send(400, "text/plain", "Bad Request");
@ -616,7 +616,7 @@ void init_webserver() {
return request->requestAuthentication();
if (request->hasParam("value")) {
String value = request->getParam("value")->value();
charger_aux12V_enabled = (bool)value.toInt();
datalayer.charger.charger_aux12V_enabled = (bool)value.toInt();
request->send(200, "text/plain", "Updated successfully");
} else {
request->send(400, "text/plain", "Bad Request");
@ -1159,7 +1159,7 @@ String processor(const String& var) {
content += "<div style='background-color: #FF6E00; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
content += "<h4>Charger HV Enabled: ";
if (charger_HV_enabled) {
if (datalayer.charger.charger_HV_enabled) {
content += "<span>&#10003;</span>";
} else {
content += "<span style='color: red;'>&#10005;</span>";
@ -1167,22 +1167,22 @@ String processor(const String& var) {
content += "</h4>";
content += "<h4>Charger Aux12v Enabled: ";
if (charger_aux12V_enabled) {
if (datalayer.charger.charger_aux12V_enabled) {
content += "<span>&#10003;</span>";
} else {
content += "<span style='color: red;'>&#10005;</span>";
}
content += "</h4>";
#ifdef CHEVYVOLT_CHARGER
float chgPwrDC = static_cast<float>(charger_stat_HVcur * charger_stat_HVvol);
float chgPwrAC = static_cast<float>(charger_stat_ACcur * charger_stat_ACvol);
float chgPwrDC = static_cast<float>(datalayer.charger.charger_stat_HVcur * datalayer.charger.charger_stat_HVvol);
float chgPwrAC = static_cast<float>(datalayer.charger.charger_stat_ACcur * datalayer.charger.charger_stat_ACvol);
float chgEff = chgPwrDC / chgPwrAC * 100;
float ACcur = charger_stat_ACcur;
float ACvol = charger_stat_ACvol;
float HVvol = charger_stat_HVvol;
float HVcur = charger_stat_HVcur;
float LVvol = charger_stat_LVvol;
float LVcur = charger_stat_LVcur;
float ACcur = datalayer.charger.charger_stat_ACcur;
float ACvol = datalayer.charger.charger_stat_ACvol;
float HVvol = datalayer.charger.charger_stat_HVvol;
float HVcur = datalayer.charger.charger_stat_HVcur;
float LVvol = datalayer.charger.charger_stat_LVvol;
float LVcur = datalayer.charger.charger_stat_LVcur;
content += formatPowerValue("Charger Output Power", chgPwrDC, "", 1);
content += "<h4 style='color: white;'>Charger Efficiency: " + String(chgEff) + "%</h4>";
@ -1194,12 +1194,12 @@ String processor(const String& var) {
content += "<h4 style='color: white;'>Charger AC Input I: " + String(ACcur, 2) + " A</h4>";
#endif // CHEVYVOLT_CHARGER
#ifdef NISSANLEAF_CHARGER
float chgPwrDC = static_cast<float>(charger_stat_HVcur * 100);
charger_stat_HVcur = chgPwrDC / (datalayer.battery.status.voltage_dV / 10); // P/U=I
charger_stat_HVvol = static_cast<float>(datalayer.battery.status.voltage_dV / 10);
float ACvol = charger_stat_ACvol;
float HVvol = charger_stat_HVvol;
float HVcur = charger_stat_HVcur;
float chgPwrDC = static_cast<float>(datalayer.charger.charger_stat_HVcur * 100);
datalayer.charger.charger_stat_HVcur = chgPwrDC / (datalayer.battery.status.voltage_dV / 10); // P/U=I
datalayer.charger.charger_stat_HVvol = static_cast<float>(datalayer.battery.status.voltage_dV / 10);
float ACvol = datalayer.charger.charger_stat_ACvol;
float HVvol = datalayer.charger.charger_stat_HVvol;
float HVcur = datalayer.charger.charger_stat_HVcur;
content += formatPowerValue("Charger Output Power", chgPwrDC, "", 1);
content += "<h4 style='color: white;'>Charger HVDC Output V: " + String(HVvol, 2) + " V</h4>";