mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-05 10:49:42 +02:00
More common image
This commit is contained in:
commit
901c89e03f
95 changed files with 1030 additions and 579 deletions
1
.github/workflows/compile-all-batteries.yml
vendored
1
.github/workflows/compile-all-batteries.yml
vendored
|
@ -58,6 +58,7 @@ jobs:
|
||||||
- CMFA_EV_BATTERY
|
- CMFA_EV_BATTERY
|
||||||
- DALY_BMS
|
- DALY_BMS
|
||||||
- FOXESS_BATTERY
|
- FOXESS_BATTERY
|
||||||
|
- GEELY_GEOMETRY_C_BATTERY
|
||||||
- IMIEV_CZERO_ION_BATTERY
|
- IMIEV_CZERO_ION_BATTERY
|
||||||
- JAGUAR_IPACE_BATTERY
|
- JAGUAR_IPACE_BATTERY
|
||||||
- KIA_E_GMP_BATTERY
|
- KIA_E_GMP_BATTERY
|
||||||
|
|
52
.github/workflows/compile-common-image-lilygo.yml
vendored
Normal file
52
.github/workflows/compile-common-image-lilygo.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# This is the name of the workflow, visible on GitHub UI.
|
||||||
|
name: 🔋 Compile Common Image for Lilygo
|
||||||
|
|
||||||
|
# Here we tell GitHub when to run the workflow.
|
||||||
|
on:
|
||||||
|
# The workflow is run when a commit is pushed or for a
|
||||||
|
# Pull Request.
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
# This is the list of jobs that will be run concurrently.
|
||||||
|
jobs:
|
||||||
|
# This pre-job is run to skip workflows in case a workflow is already run, i.e. because the workflow is triggered by both push and pull_request
|
||||||
|
skip-duplicate-actions:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Map a step output to a job output
|
||||||
|
outputs:
|
||||||
|
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||||
|
steps:
|
||||||
|
- id: skip_check
|
||||||
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
|
with:
|
||||||
|
# All of these options are optional, so you can remove them if you are happy with the defaults
|
||||||
|
concurrent_skipping: 'never'
|
||||||
|
skip_after_successful_duplicate: 'true'
|
||||||
|
do_not_skip: '["pull_request", "workflow_dispatch", "schedule"]'
|
||||||
|
|
||||||
|
build-common-image:
|
||||||
|
# This is the platform GitHub will use to run our workflow.
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Copy USER_SECRETS.TEMPLATE.h to USER_SECRETS.h
|
||||||
|
- name: Copy USER_SECRETS.TEMPLATE.h to USER_SECRETS.h
|
||||||
|
run: cp ./Software/USER_SECRETS.TEMPLATE.h ./Software/USER_SECRETS.h
|
||||||
|
|
||||||
|
# We use the `arduino/setup-arduino-cli` action to install and
|
||||||
|
# configure the Arduino CLI on the system.
|
||||||
|
- name: Setup Arduino CLI
|
||||||
|
uses: arduino/setup-arduino-cli@v2
|
||||||
|
|
||||||
|
# We then install the platform.
|
||||||
|
- name: Install platform
|
||||||
|
run: |
|
||||||
|
arduino-cli core update-index
|
||||||
|
arduino-cli core install esp32:esp32
|
||||||
|
|
||||||
|
- name: Compile Sketch
|
||||||
|
run: arduino-cli compile --fqbn esp32:esp32:esp32 --build-property build.partitions=min_spiffs --build-property upload.maximum_size=1966080 --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -DCOMMON_IMAGE -DHW_LILYGO" ./Software
|
|
@ -4,16 +4,134 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "RS485Battery.h"
|
#include "RS485Battery.h"
|
||||||
|
|
||||||
// These functions adapt the old C-style global functions battery-API to the
|
|
||||||
// object-oriented battery API.
|
|
||||||
|
|
||||||
// The instantiated class is defined by the pre-compiler define
|
|
||||||
// to support battery class selection at compile-time
|
|
||||||
#ifdef SELECTED_BATTERY_CLASS
|
|
||||||
|
|
||||||
Battery* battery = nullptr;
|
Battery* battery = nullptr;
|
||||||
Battery* battery2 = nullptr;
|
Battery* battery2 = nullptr;
|
||||||
|
|
||||||
|
std::vector<BatteryType> supported_battery_types() {
|
||||||
|
std::vector<BatteryType> types;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)BatteryType::Highest; i++) {
|
||||||
|
types.push_back((BatteryType)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char* name_for_type(BatteryType type) {
|
||||||
|
switch (type) {
|
||||||
|
case BatteryType::BmwI3:
|
||||||
|
return BmwI3Battery::Name;
|
||||||
|
case BatteryType::BmwIx:
|
||||||
|
return BmwIXBattery::Name;
|
||||||
|
case BatteryType::BoltAmpera:
|
||||||
|
return BoltAmperaBattery::Name;
|
||||||
|
case BatteryType::BydAtto3:
|
||||||
|
return BydAttoBattery::Name;
|
||||||
|
case BatteryType::CellPowerBms:
|
||||||
|
return CellPowerBms::Name;
|
||||||
|
case BatteryType::Chademo:
|
||||||
|
return ChademoBattery::Name;
|
||||||
|
case BatteryType::NissanLeaf:
|
||||||
|
return NissanLeafBattery::Name;
|
||||||
|
case BatteryType::TestFake:
|
||||||
|
return TestFakeBattery::Name;
|
||||||
|
case BatteryType::TeslaModel3Y:
|
||||||
|
return TeslaModel3YBattery::Name;
|
||||||
|
case BatteryType::TeslaModelSX:
|
||||||
|
return TeslaModelSXBattery::Name;
|
||||||
|
case BatteryType::None:
|
||||||
|
return "None";
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
#ifdef SELECTED_BATTERY_CLASS
|
||||||
|
#error "Compile time SELECTED_BATTERY_CLASS should not be defined with COMMON_IMAGE"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BatteryType user_selected_battery_type = BatteryType::NissanLeaf;
|
||||||
|
bool user_selected_second_battery = false;
|
||||||
|
|
||||||
|
void setup_battery() {
|
||||||
|
|
||||||
|
if (battery) {
|
||||||
|
// Let's not create the battery again.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (user_selected_battery_type) {
|
||||||
|
case BatteryType::BmwI3:
|
||||||
|
battery = new BmwI3Battery();
|
||||||
|
break;
|
||||||
|
case BatteryType::BmwIx:
|
||||||
|
battery = new BmwIXBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::BoltAmpera:
|
||||||
|
battery = new BoltAmperaBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::BydAtto3:
|
||||||
|
battery = new BydAttoBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::CellPowerBms:
|
||||||
|
battery = new CellPowerBms();
|
||||||
|
break;
|
||||||
|
case BatteryType::Chademo:
|
||||||
|
battery = new ChademoBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::CmfaEv:
|
||||||
|
battery = new CmfaEvBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::DalyBms:
|
||||||
|
battery = new DalyBms();
|
||||||
|
break;
|
||||||
|
case BatteryType::NissanLeaf:
|
||||||
|
battery = new NissanLeafBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::TeslaModel3Y:
|
||||||
|
battery = new TeslaModel3YBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::TeslaModelSX:
|
||||||
|
battery = new TeslaModelSXBattery();
|
||||||
|
break;
|
||||||
|
case BatteryType::TestFake:
|
||||||
|
battery = new TestFakeBattery();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (battery) {
|
||||||
|
battery->setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user_selected_second_battery && !battery2) {
|
||||||
|
switch (user_selected_battery_type) {
|
||||||
|
case BatteryType::NissanLeaf:
|
||||||
|
battery2 = new NissanLeafBattery(&datalayer.battery2, nullptr, can_config.battery_double);
|
||||||
|
break;
|
||||||
|
case BatteryType::BmwI3:
|
||||||
|
battery2 = new BmwI3Battery(&datalayer.battery2, &datalayer.system.status.battery2_allowed_contactor_closing,
|
||||||
|
can_config.battery_double, WUP_PIN2);
|
||||||
|
break;
|
||||||
|
case BatteryType::KiaHyundai64:
|
||||||
|
battery2 = new KiaHyundai64Battery(&datalayer.battery2, &datalayer_extended.KiaHyundai64_2,
|
||||||
|
&datalayer.system.status.battery2_allowed_contactor_closing,
|
||||||
|
can_config.battery_double);
|
||||||
|
case BatteryType::SantaFePhev:
|
||||||
|
battery2 = new SantaFePhevBattery(&datalayer.battery2, can_config.battery_double);
|
||||||
|
break;
|
||||||
|
case BatteryType::TestFake:
|
||||||
|
battery2 = new TestFakeBattery(&datalayer.battery2, can_config.battery_double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (battery2) {
|
||||||
|
battery2->setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else // Battery selection has been made at build-time
|
||||||
|
|
||||||
void setup_battery() {
|
void setup_battery() {
|
||||||
// Instantiate the battery only once just in case this function gets called multiple times.
|
// Instantiate the battery only once just in case this function gets called multiple times.
|
||||||
if (battery == nullptr) {
|
if (battery == nullptr) {
|
||||||
|
@ -40,5 +158,4 @@ void setup_battery() {
|
||||||
battery2->setup();
|
battery2->setup();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,128 +17,39 @@ void setup_can_shunt();
|
||||||
#include "BMW-SBOX.h"
|
#include "BMW-SBOX.h"
|
||||||
#include "BOLT-AMPERA-BATTERY.h"
|
#include "BOLT-AMPERA-BATTERY.h"
|
||||||
#include "BYD-ATTO-3-BATTERY.h"
|
#include "BYD-ATTO-3-BATTERY.h"
|
||||||
|
|
||||||
#ifdef CELLPOWER_BMS
|
|
||||||
#include "CELLPOWER-BMS.h"
|
#include "CELLPOWER-BMS.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CHADEMO_BATTERY
|
|
||||||
#include "CHADEMO-BATTERY.h"
|
#include "CHADEMO-BATTERY.h"
|
||||||
#include "CHADEMO-SHUNTS.h"
|
#include "CHADEMO-SHUNTS.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CMFA_EV_BATTERY
|
|
||||||
#include "CMFA-EV-BATTERY.h"
|
#include "CMFA-EV-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FOXESS_BATTERY
|
|
||||||
#include "FOXESS-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef GEELY_GEOMETRY_C_BATTERY
|
|
||||||
#include "GEELY-GEOMETRY-C-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ORION_BMS
|
|
||||||
#include "ORION-BMS.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SONO_BATTERY
|
|
||||||
#include "SONO-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef STELLANTIS_ECMP_BATTERY
|
|
||||||
#include "ECMP-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
|
||||||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JAGUAR_IPACE_BATTERY
|
|
||||||
#include "JAGUAR-IPACE-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef KIA_E_GMP_BATTERY
|
|
||||||
#include "KIA-E-GMP-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
|
||||||
#include "KIA-HYUNDAI-64-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef KIA_HYUNDAI_HYBRID_BATTERY
|
|
||||||
#include "KIA-HYUNDAI-HYBRID-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MEB_BATTERY
|
|
||||||
#include "MEB-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MG_5_BATTERY
|
|
||||||
#include "MG-5-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NISSAN_LEAF_BATTERY
|
|
||||||
#include "NISSAN-LEAF-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PYLON_BATTERY
|
|
||||||
#include "PYLON-BATTERY.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DALY_BMS
|
|
||||||
#include "DALY-BMS.h"
|
#include "DALY-BMS.h"
|
||||||
#endif
|
#include "ECMP-BATTERY.h"
|
||||||
|
#include "FOXESS-BATTERY.h"
|
||||||
#ifdef RJXZS_BMS
|
#include "GEELY-GEOMETRY-C-BATTERY.h"
|
||||||
#include "RJXZS-BMS.h"
|
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||||
#endif
|
#include "JAGUAR-IPACE-BATTERY.h"
|
||||||
|
#include "KIA-E-GMP-BATTERY.h"
|
||||||
#ifdef RANGE_ROVER_PHEV_BATTERY
|
#include "KIA-HYUNDAI-64-BATTERY.h"
|
||||||
|
#include "KIA-HYUNDAI-HYBRID-BATTERY.h"
|
||||||
|
#include "MEB-BATTERY.h"
|
||||||
|
#include "MG-5-BATTERY.h"
|
||||||
|
#include "NISSAN-LEAF-BATTERY.h"
|
||||||
|
#include "ORION-BMS.h"
|
||||||
|
#include "PYLON-BATTERY.h"
|
||||||
#include "RANGE-ROVER-PHEV-BATTERY.h"
|
#include "RANGE-ROVER-PHEV-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RENAULT_KANGOO_BATTERY
|
|
||||||
#include "RENAULT-KANGOO-BATTERY.h"
|
#include "RENAULT-KANGOO-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RENAULT_TWIZY_BATTERY
|
|
||||||
#include "RENAULT-TWIZY.h"
|
#include "RENAULT-TWIZY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RENAULT_ZOE_GEN1_BATTERY
|
|
||||||
#include "RENAULT-ZOE-GEN1-BATTERY.h"
|
#include "RENAULT-ZOE-GEN1-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RENAULT_ZOE_GEN2_BATTERY
|
|
||||||
#include "RENAULT-ZOE-GEN2-BATTERY.h"
|
#include "RENAULT-ZOE-GEN2-BATTERY.h"
|
||||||
#endif
|
#include "RJXZS-BMS.h"
|
||||||
|
|
||||||
#ifdef SANTA_FE_PHEV_BATTERY
|
|
||||||
#include "SANTA-FE-PHEV-BATTERY.h"
|
#include "SANTA-FE-PHEV-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIMPBMS_BATTERY
|
|
||||||
#include "SIMPBMS-BATTERY.h"
|
#include "SIMPBMS-BATTERY.h"
|
||||||
#endif
|
#include "SONO-BATTERY.h"
|
||||||
|
|
||||||
#if defined(TESLA_MODEL_SX_BATTERY) || defined(TESLA_MODEL_3Y_BATTERY)
|
|
||||||
#define TESLA_BATTERY
|
|
||||||
#include "TESLA-BATTERY.h"
|
#include "TESLA-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TEST_FAKE_BATTERY
|
|
||||||
#include "TEST-FAKE-BATTERY.h"
|
#include "TEST-FAKE-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VOLVO_SPA_BATTERY
|
|
||||||
#include "VOLVO-SPA-BATTERY.h"
|
#include "VOLVO-SPA-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VOLVO_SPA_HYBRID_BATTERY
|
|
||||||
#include "VOLVO-SPA-HYBRID-BATTERY.h"
|
#include "VOLVO-SPA-HYBRID-BATTERY.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
void setup_battery(void);
|
void setup_battery(void);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "BMW-I3-BATTERY.h"
|
||||||
#ifdef BMW_I3_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "BMW-I3-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* Do not change code below unless you are sure what you are doing */
|
/* Do not change code below unless you are sure what you are doing */
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ static uint8_t calculateCRC(CAN_frame rx_frame, uint8_t length, uint8_t initial_
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t increment_alive_counter(uint8_t counter) {
|
uint8_t BmwI3Battery::increment_alive_counter(uint8_t counter) {
|
||||||
counter++;
|
counter++;
|
||||||
if (counter > ALIVE_MAX_VALUE) {
|
if (counter > ALIVE_MAX_VALUE) {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
|
@ -509,7 +508,7 @@ void BmwI3Battery::transmit_can(unsigned long currentMillis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BmwI3Battery::setup(void) { // Performs one time setup at startup
|
void BmwI3Battery::setup(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "BMW i3", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
|
|
||||||
//Before we have started up and detected which battery is in use, use 60AH values
|
//Before we have started up and detected which battery is in use, use 60AH values
|
||||||
|
@ -525,5 +524,3 @@ void BmwI3Battery::setup(void) { // Performs one time setup at startup
|
||||||
pinMode(wakeup_pin, OUTPUT);
|
pinMode(wakeup_pin, OUTPUT);
|
||||||
digitalWrite(wakeup_pin, HIGH); // Wake up the battery
|
digitalWrite(wakeup_pin, HIGH); // Wake up the battery
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ class BmwI3Battery : public CanBattery {
|
||||||
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
|
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
virtual void transmit_can(unsigned long currentMillis);
|
virtual void transmit_can(unsigned long currentMillis);
|
||||||
|
static constexpr char* Name = "BMW i3";
|
||||||
|
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
|
||||||
|
@ -80,7 +81,9 @@ class BmwI3Battery : public CanBattery {
|
||||||
unsigned long previousMillis5000 = 0; // will store last time a 5000ms CAN Message was send
|
unsigned long previousMillis5000 = 0; // will store last time a 5000ms CAN Message was send
|
||||||
unsigned long previousMillis10000 = 0; // will store last time a 10000ms CAN Message was send
|
unsigned long previousMillis10000 = 0; // will store last time a 10000ms CAN Message was send
|
||||||
|
|
||||||
#define ALIVE_MAX_VALUE 14 // BMW CAN messages contain alive counter, goes from 0...14
|
static const int ALIVE_MAX_VALUE = 14; // BMW CAN messages contain alive counter, goes from 0...14
|
||||||
|
|
||||||
|
uint8_t increment_alive_counter(uint8_t counter);
|
||||||
|
|
||||||
enum BatterySize { BATTERY_60AH, BATTERY_94AH, BATTERY_120AH };
|
enum BatterySize { BATTERY_60AH, BATTERY_94AH, BATTERY_120AH };
|
||||||
BatterySize detectedBattery = BATTERY_60AH;
|
BatterySize detectedBattery = BATTERY_60AH;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "BMW-IX-BATTERY.h"
|
||||||
#ifdef BMW_IX_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "BMW-IX-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
// Function to check if a value has gone stale over a specified time period
|
// Function to check if a value has gone stale over a specified time period
|
||||||
bool BmwIXBattery::isStale(int16_t currentValue, uint16_t& lastValue, unsigned long& lastChangeTime) {
|
bool BmwIXBattery::isStale(int16_t currentValue, uint16_t& lastValue, unsigned long& lastChangeTime) {
|
||||||
|
@ -475,7 +474,7 @@ void BmwIXBattery::transmit_can(unsigned long currentMillis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BmwIXBattery::setup(void) { // Performs one time setup at startup
|
void BmwIXBattery::setup(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "BMW iX and i4-7 platform", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
|
|
||||||
//Reset Battery at bootup
|
//Reset Battery at bootup
|
||||||
|
@ -696,5 +695,3 @@ void BmwIXBattery::HandleBmwIxOpenContactorsRequest(uint16_t counter_10ms) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // BMW_IX_BATTERY
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ class BmwIXBattery : public CanBattery {
|
||||||
void request_open_contactors() { datalayer_extended.bmwix.UserRequestContactorOpen = true; }
|
void request_open_contactors() { datalayer_extended.bmwix.UserRequestContactorOpen = true; }
|
||||||
void request_close_contactors() { datalayer_extended.bmwix.UserRequestContactorClose = true; }
|
void request_close_contactors() { datalayer_extended.bmwix.UserRequestContactorClose = true; }
|
||||||
|
|
||||||
|
static constexpr char* Name = "BMW iX and i4-7 platform";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BmwIXHtmlRenderer renderer;
|
BmwIXHtmlRenderer renderer;
|
||||||
static const int MAX_PACK_VOLTAGE_DV = 4650; //4650 = 465.0V
|
static const int MAX_PACK_VOLTAGE_DV = 4650; //4650 = 465.0V
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "BMW-PHEV-BATTERY.h"
|
||||||
#ifdef BMW_PHEV_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "BMW-PHEV-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
const unsigned char crc8_table[256] =
|
const unsigned char crc8_table[256] =
|
||||||
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
|
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
|
||||||
|
@ -714,5 +713,3 @@ void BmwPhevBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include "../include.h"
|
#include "BMW-SBOX.h"
|
||||||
#ifdef BMW_SBOX
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "BMW-SBOX.h"
|
#include "../include.h"
|
||||||
|
|
||||||
uint8_t reverse_bits(uint8_t byte) {
|
uint8_t reverse_bits(uint8_t byte) {
|
||||||
uint8_t reversed = 0;
|
uint8_t reversed = 0;
|
||||||
|
@ -182,4 +181,3 @@ void BmwSbox::setup() {
|
||||||
strncpy(datalayer.system.info.shunt_protocol, "BMW SBOX", 63);
|
strncpy(datalayer.system.info.shunt_protocol, "BMW SBOX", 63);
|
||||||
datalayer.system.info.shunt_protocol[63] = '\0';
|
datalayer.system.info.shunt_protocol[63] = '\0';
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "BOLT-AMPERA-BATTERY.h"
|
||||||
#ifdef BOLT_AMPERA_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "BOLT-AMPERA-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODOs left for this implementation
|
TODOs left for this implementation
|
||||||
|
@ -645,7 +644,7 @@ void BoltAmperaBattery::transmit_can(unsigned long currentMillis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoltAmperaBattery::setup(void) { // Performs one time setup at startup
|
void BoltAmperaBattery::setup(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Chevrolet Bolt EV/Opel Ampera-e", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
datalayer.battery.info.number_of_cells = 96;
|
datalayer.battery.info.number_of_cells = 96;
|
||||||
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
||||||
|
@ -655,5 +654,3 @@ void BoltAmperaBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ class BoltAmperaBattery : public CanBattery {
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
virtual void transmit_can(unsigned long currentMillis);
|
virtual void transmit_can(unsigned long currentMillis);
|
||||||
|
|
||||||
|
static constexpr char* Name = "Chevrolet Bolt EV/Opel Ampera-e";
|
||||||
|
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "BYD-ATTO-3-BATTERY.h"
|
||||||
#ifdef BYD_ATTO_3_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "BYD-ATTO-3-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* Notes
|
/* Notes
|
||||||
SOC% by default is now ESTIMATED.
|
SOC% by default is now ESTIMATED.
|
||||||
|
@ -681,7 +680,7 @@ void BydAttoBattery::transmit_can(unsigned long currentMillis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BydAttoBattery::setup(void) { // Performs one time setup at startup
|
void BydAttoBattery::setup(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "BYD Atto 3", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
datalayer_battery->info.number_of_cells = CELLCOUNT_STANDARD;
|
datalayer_battery->info.number_of_cells = CELLCOUNT_STANDARD;
|
||||||
datalayer_battery->info.chemistry = battery_chemistry_enum::LFP;
|
datalayer_battery->info.chemistry = battery_chemistry_enum::LFP;
|
||||||
|
@ -696,5 +695,3 @@ void BydAttoBattery::setup(void) { // Performs one time setup at startup
|
||||||
SOC_method = MEASURED;
|
SOC_method = MEASURED;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -22,16 +22,6 @@
|
||||||
#define SELECTED_BATTERY_CLASS BydAttoBattery
|
#define SELECTED_BATTERY_CLASS BydAttoBattery
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CELLCOUNT_EXTENDED 126
|
|
||||||
#define CELLCOUNT_STANDARD 104
|
|
||||||
#define MAX_PACK_VOLTAGE_EXTENDED_DV 4410 //Extended range
|
|
||||||
#define MIN_PACK_VOLTAGE_EXTENDED_DV 3800 //Extended range
|
|
||||||
#define MAX_PACK_VOLTAGE_STANDARD_DV 3640 //Standard range
|
|
||||||
#define MIN_PACK_VOLTAGE_STANDARD_DV 3136 //Standard range
|
|
||||||
#define MAX_CELL_DEVIATION_MV 230
|
|
||||||
#define MAX_CELL_VOLTAGE_MV 3650 //Charging stops if one cell exceeds this value
|
|
||||||
#define MIN_CELL_VOLTAGE_MV 2800 //Discharging stops if one cell goes below this value
|
|
||||||
|
|
||||||
class BydAttoBattery : public CanBattery {
|
class BydAttoBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
// Use this constructor for the second battery.
|
// Use this constructor for the second battery.
|
||||||
|
@ -54,6 +44,8 @@ class BydAttoBattery : public CanBattery {
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
virtual void transmit_can(unsigned long currentMillis);
|
virtual void transmit_can(unsigned long currentMillis);
|
||||||
|
|
||||||
|
static constexpr char* Name = "BYD Atto 3";
|
||||||
|
|
||||||
bool supports_reset_crash() { return true; }
|
bool supports_reset_crash() { return true; }
|
||||||
|
|
||||||
void reset_crash() { datalayer_bydatto->UserRequestCrashReset = true; }
|
void reset_crash() { datalayer_bydatto->UserRequestCrashReset = true; }
|
||||||
|
@ -68,6 +60,16 @@ class BydAttoBattery : public CanBattery {
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int CELLCOUNT_EXTENDED = 126;
|
||||||
|
static const int CELLCOUNT_STANDARD = 104;
|
||||||
|
static const int MAX_PACK_VOLTAGE_EXTENDED_DV = 4410; //Extended range
|
||||||
|
static const int MIN_PACK_VOLTAGE_EXTENDED_DV = 3800; //Extended range
|
||||||
|
static const int MAX_PACK_VOLTAGE_STANDARD_DV = 3640; //Standard range
|
||||||
|
static const int MIN_PACK_VOLTAGE_STANDARD_DV = 3136; //Standard range
|
||||||
|
static const int MAX_CELL_DEVIATION_MV = 230;
|
||||||
|
static const int MAX_CELL_VOLTAGE_MV = 3650; //Charging stops if one cell exceeds this value
|
||||||
|
static const int MIN_CELL_VOLTAGE_MV = 2800; //Discharging stops if one cell goes below this value
|
||||||
|
|
||||||
BydAtto3HtmlRenderer renderer;
|
BydAtto3HtmlRenderer renderer;
|
||||||
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
||||||
DATALAYER_INFO_BYDATTO3* datalayer_bydatto;
|
DATALAYER_INFO_BYDATTO3* datalayer_bydatto;
|
||||||
|
|
|
@ -4,6 +4,53 @@
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "src/devboard/webserver/BatteryHtmlRenderer.h"
|
#include "src/devboard/webserver/BatteryHtmlRenderer.h"
|
||||||
|
|
||||||
|
enum class BatteryType {
|
||||||
|
None = 0,
|
||||||
|
BmwSbox,
|
||||||
|
BmwI3,
|
||||||
|
BmwIx,
|
||||||
|
BoltAmpera,
|
||||||
|
BydAtto3,
|
||||||
|
CellPowerBms,
|
||||||
|
Chademo,
|
||||||
|
CmfaEv,
|
||||||
|
Foxess,
|
||||||
|
GeelyGeometryC,
|
||||||
|
OrionBms,
|
||||||
|
Sono,
|
||||||
|
StellantisEcmp,
|
||||||
|
ImievCZeroIon,
|
||||||
|
JaguarIpace,
|
||||||
|
KiaEGmp,
|
||||||
|
KiaHyundai64,
|
||||||
|
KiaHyundaiHybrid,
|
||||||
|
Meb,
|
||||||
|
Mg5,
|
||||||
|
NissanLeaf,
|
||||||
|
Pylon,
|
||||||
|
DalyBms,
|
||||||
|
RjxzsBms,
|
||||||
|
RangeRoverPhev,
|
||||||
|
RenaultKangoo,
|
||||||
|
RenaultTwizy,
|
||||||
|
RenaultZoe1,
|
||||||
|
RenaultZoe2,
|
||||||
|
SantaFePhev,
|
||||||
|
SimpBms,
|
||||||
|
TeslaModel3Y,
|
||||||
|
TeslaModelSX,
|
||||||
|
TestFake,
|
||||||
|
VolvoSpa,
|
||||||
|
VolvoSpaHybrid,
|
||||||
|
Highest
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::vector<BatteryType> supported_battery_types();
|
||||||
|
extern const char* name_for_type(BatteryType type);
|
||||||
|
|
||||||
|
extern BatteryType user_selected_battery_type;
|
||||||
|
extern bool user_selected_second_battery;
|
||||||
|
|
||||||
// Abstract base class for next-generation battery implementations.
|
// Abstract base class for next-generation battery implementations.
|
||||||
// Defines the interface to call battery specific functionality.
|
// Defines the interface to call battery specific functionality.
|
||||||
class Battery {
|
class Battery {
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "CELLPOWER-BMS.h"
|
||||||
#ifdef CELLPOWER_BMS
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "CELLPOWER-BMS.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void CellPowerBms::update_values() {
|
void CellPowerBms::update_values() {
|
||||||
|
|
||||||
|
@ -230,7 +229,7 @@ void CellPowerBms::transmit_can(unsigned long currentMillis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellPowerBms::setup(void) { // Performs one time setup at startup
|
void CellPowerBms::setup(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Cellpower BMS", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
||||||
|
@ -238,5 +237,3 @@ void CellPowerBms::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CELLPOWER_BMS
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ class CellPowerBms : public CanBattery {
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
virtual void transmit_can(unsigned long currentMillis);
|
virtual void transmit_can(unsigned long currentMillis);
|
||||||
|
|
||||||
|
static constexpr char* Name = "Cellpower BMS";
|
||||||
|
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include "../include.h"
|
#include "CHADEMO-BATTERY.h"
|
||||||
#ifdef CHADEMO_BATTERY
|
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "CHADEMO-BATTERY.h"
|
#include "../include.h"
|
||||||
#include "CHADEMO-SHUNTS.h"
|
#include "CHADEMO-SHUNTS.h"
|
||||||
|
|
||||||
/* CHADEMO handling runs at 6.25 times the rate of most other code, so, rather than the
|
/* CHADEMO handling runs at 6.25 times the rate of most other code, so, rather than the
|
||||||
|
@ -939,7 +938,7 @@ void ChademoBattery::setup(void) { // Performs one time setup at startup
|
||||||
pinMode(CHADEMO_PIN_4, INPUT);
|
pinMode(CHADEMO_PIN_4, INPUT);
|
||||||
pinMode(CHADEMO_PIN_7, INPUT);
|
pinMode(CHADEMO_PIN_7, INPUT);
|
||||||
|
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Chademo V2X mode", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
|
|
||||||
CHADEMO_Status = CHADEMO_IDLE;
|
CHADEMO_Status = CHADEMO_IDLE;
|
||||||
|
@ -988,4 +987,3 @@ void ChademoBattery::setup(void) { // Performs one time setup at startup
|
||||||
|
|
||||||
setupMillis = millis();
|
setupMillis = millis();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
|
|
||||||
//Contactor control is required for CHADEMO support
|
//Contactor control is required for CHADEMO support
|
||||||
#define CONTACTOR_CONTROL
|
#define CONTACTOR_CONTROL
|
||||||
|
|
||||||
//ISA shunt is currently required for CHADEMO support
|
|
||||||
// other measurement sources may be added in the future
|
|
||||||
#define ISA_SHUNT
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ChademoBattery : public CanBattery {
|
class ChademoBattery : public CanBattery {
|
||||||
|
@ -22,6 +18,8 @@ class ChademoBattery : public CanBattery {
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
virtual void transmit_can(unsigned long currentMillis);
|
virtual void transmit_can(unsigned long currentMillis);
|
||||||
|
|
||||||
|
static constexpr char* Name = "Chademo V2X mode";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void process_vehicle_charging_minimums(CAN_frame rx_frame);
|
void process_vehicle_charging_minimums(CAN_frame rx_frame);
|
||||||
void process_vehicle_charging_maximums(CAN_frame rx_frame);
|
void process_vehicle_charging_maximums(CAN_frame rx_frame);
|
||||||
|
|
|
@ -18,12 +18,11 @@
|
||||||
* by NJbubo
|
* by NJbubo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "../include.h"
|
#include "CHADEMO-SHUNTS.h"
|
||||||
#ifdef CHADEMO_BATTERY
|
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
|
#include "../include.h"
|
||||||
#include "CHADEMO-BATTERY.h"
|
#include "CHADEMO-BATTERY.h"
|
||||||
#include "CHADEMO-SHUNTS.h"
|
|
||||||
|
|
||||||
/* Initial frames received from ISA shunts provide invalid during initialization */
|
/* Initial frames received from ISA shunts provide invalid during initialization */
|
||||||
static int framecount = 0;
|
static int framecount = 0;
|
||||||
|
@ -429,4 +428,3 @@ void ISA_getINFO(uint8_t i) {
|
||||||
|
|
||||||
transmit_can_frame(&outframe, can_config.battery);
|
transmit_can_frame(&outframe, can_config.battery);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "CMFA-EV-BATTERY.h"
|
||||||
#ifdef CMFA_EV_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "CMFA-EV-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* The raw SOC value sits at 90% when the battery is full, so we should report back 100% once this value is reached
|
/* The raw SOC value sits at 90% when the battery is full, so we should report back 100% once this value is reached
|
||||||
Same goes for low point, when 10% is reached we report 0% */
|
Same goes for low point, when 10% is reached we report 0% */
|
||||||
|
@ -951,5 +950,3 @@ void CmfaEvBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //CMFA_EV_BATTERY
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "DALY-BMS.h"
|
||||||
#ifdef DALY_BMS
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "DALY-BMS.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* Do not change code below unless you are sure what you are doing */
|
/* Do not change code below unless you are sure what you are doing */
|
||||||
|
|
||||||
|
@ -207,5 +206,3 @@ void DalyBms::receive() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -3,17 +3,9 @@
|
||||||
|
|
||||||
#include "RS485Battery.h"
|
#include "RS485Battery.h"
|
||||||
|
|
||||||
/* Tweak these according to your battery build */
|
#ifdef DALY_BMS
|
||||||
#define CELL_COUNT 14
|
|
||||||
#define MAX_PACK_VOLTAGE_DV 580 //580 = 58.0V
|
|
||||||
#define MIN_PACK_VOLTAGE_DV 460 //480 = 48.0V
|
|
||||||
#define MAX_CELL_VOLTAGE_MV 4200 //Battery is put into emergency stop if one cell goes over this value
|
|
||||||
#define MIN_CELL_VOLTAGE_MV 3200 //Battery is put into emergency stop if one cell goes below this value
|
|
||||||
#define POWER_PER_PERCENT 50 // below 20% and above 80% limit power to 50W * SOC (i.e. 150W at 3%, 500W at 10%, ...)
|
|
||||||
#define POWER_PER_DEGREE_C 60 // max power added/removed per degree above/below 0°C
|
|
||||||
#define POWER_AT_0_DEGREE_C 800 // power at 0°C
|
|
||||||
|
|
||||||
#define SELECTED_BATTERY_CLASS DalyBms
|
#define SELECTED_BATTERY_CLASS DalyBms
|
||||||
|
#endif
|
||||||
|
|
||||||
class DalyBms : public RS485Battery {
|
class DalyBms : public RS485Battery {
|
||||||
public:
|
public:
|
||||||
|
@ -23,6 +15,17 @@ class DalyBms : public RS485Battery {
|
||||||
void receive();
|
void receive();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/* Tweak these according to your battery build */
|
||||||
|
static const int CELL_COUNT = 14;
|
||||||
|
static const int MAX_PACK_VOLTAGE_DV = 580; //580 = 58.0V
|
||||||
|
static const int MIN_PACK_VOLTAGE_DV = 460; //480 = 48.0V
|
||||||
|
static const int MAX_CELL_VOLTAGE_MV = 4200; //Battery is put into emergency stop if one cell goes over this value
|
||||||
|
static const int MIN_CELL_VOLTAGE_MV = 3200; //Battery is put into emergency stop if one cell goes below this value
|
||||||
|
static const int POWER_PER_PERCENT =
|
||||||
|
50; // below 20% and above 80% limit power to 50W * SOC (i.e. 150W at 3%, 500W at 10%, ...)
|
||||||
|
static const int POWER_PER_DEGREE_C = 60; // max power added/removed per degree above/below 0°C
|
||||||
|
static const int POWER_AT_0_DEGREE_C = 800; // power at 0°C
|
||||||
|
|
||||||
int baud_rate() { return 9600; }
|
int baud_rate() { return 9600; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "ECMP-BATTERY.h"
|
||||||
#ifdef STELLANTIS_ECMP_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For More Battery Info page
|
#include "../datalayer/datalayer_extended.h" //For More Battery Info page
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "ECMP-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
This integration is still ongoing. Here is what still needs to be done in order to use this battery type
|
This integration is still ongoing. Here is what still needs to be done in order to use this battery type
|
||||||
|
@ -331,5 +330,3 @@ void EcmpBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
|
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "ECMP-HTML.h"
|
#include "ECMP-HTML.h"
|
||||||
|
|
||||||
|
#ifdef STELLANTIS_ECMP_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS EcmpBattery
|
#define SELECTED_BATTERY_CLASS EcmpBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class EcmpBattery : public CanBattery {
|
class EcmpBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "FOXESS-BATTERY.h"
|
||||||
#ifdef FOXESS_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "FOXESS-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Can bus @ 500k - all Extended ID, little endian
|
Can bus @ 500k - all Extended ID, little endian
|
||||||
|
@ -583,5 +582,3 @@ void FoxessBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "GEELY-GEOMETRY-C-BATTERY.h"
|
||||||
#ifdef GEELY_GEOMETRY_C_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "GEELY-GEOMETRY-C-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
- Contactor closing: CAN log needed from complete H-CAN of Geely Geometry C vehicle. We are not sure what needs to be sent towards the battery yet to get contactor closing working. DTC readout complains that a "Power CAN BUS Data Missing" message is still missing
|
- Contactor closing: CAN log needed from complete H-CAN of Geely Geometry C vehicle. We are not sure what needs to be sent towards the battery yet to get contactor closing working. DTC readout complains that a "Power CAN BUS Data Missing" message is still missing
|
||||||
|
@ -671,5 +670,3 @@ void GeelyGeometryCBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer_battery->info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer_battery->info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer_battery->info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer_battery->info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -10,27 +10,6 @@
|
||||||
#define SELECTED_BATTERY_CLASS GeelyGeometryCBattery
|
#define SELECTED_BATTERY_CLASS GeelyGeometryCBattery
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define POLL_SOC 0x4B35
|
|
||||||
#define POLL_CC2_VOLTAGE 0x4BCF
|
|
||||||
#define POLL_CELL_MAX_VOLTAGE_NUMBER 0x4B1E
|
|
||||||
#define POLL_CELL_MIN_VOLTAGE_NUMBER 0x4B20
|
|
||||||
#define POLL_AMOUNT_CELLS 0x4B07
|
|
||||||
#define POLL_SPECIFICIAL_VOLTAGE 0x4B05
|
|
||||||
#define POLL_UNKNOWN_1 0x4BDA //245 on two batteries
|
|
||||||
#define POLL_RAW_SOC_MAX 0x4BC3
|
|
||||||
#define POLL_RAW_SOC_MIN 0x4BC4
|
|
||||||
#define POLL_UNKNOWN_4 0xDF00 //144 (the other battery 143)
|
|
||||||
#define POLL_CAPACITY_MODULE_MAX 0x4B3D
|
|
||||||
#define POLL_CAPACITY_MODULE_MIN 0x4B3E
|
|
||||||
#define POLL_UNKNOWN_7 0x4B24 //1 (the other battery 23)
|
|
||||||
#define POLL_UNKNOWN_8 0x4B26 //16 (the other battery 33)
|
|
||||||
#define POLL_MULTI_TEMPS 0x4B0F
|
|
||||||
#define POLL_MULTI_UNKNOWN_2 0x4B10
|
|
||||||
#define POLL_MULTI_UNKNOWN_3 0x4B53
|
|
||||||
#define POLL_MULTI_UNKNOWN_4 0x4B54
|
|
||||||
#define POLL_MULTI_HARDWARE_VERSION 0x4B6B
|
|
||||||
#define POLL_MULTI_SOFTWARE_VERSION 0x4B6C
|
|
||||||
|
|
||||||
class GeelyGeometryCBattery : public CanBattery {
|
class GeelyGeometryCBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
virtual void setup(void);
|
virtual void setup(void);
|
||||||
|
@ -41,13 +20,38 @@ class GeelyGeometryCBattery : public CanBattery {
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int POLL_SOC = 0x4B35;
|
||||||
|
static const int POLL_CC2_VOLTAGE = 0x4BCF;
|
||||||
|
static const int POLL_CELL_MAX_VOLTAGE_NUMBER = 0x4B1E;
|
||||||
|
static const int POLL_CELL_MIN_VOLTAGE_NUMBER = 0x4B20;
|
||||||
|
static const int POLL_AMOUNT_CELLS = 0x4B07;
|
||||||
|
static const int POLL_SPECIFICIAL_VOLTAGE = 0x4B05;
|
||||||
|
static const int POLL_UNKNOWN_1 = 0x4BDA; //245 on two batteries
|
||||||
|
static const int POLL_RAW_SOC_MAX = 0x4BC3;
|
||||||
|
static const int POLL_RAW_SOC_MIN = 0x4BC4;
|
||||||
|
static const int POLL_UNKNOWN_4 = 0xDF00; //144 (the other battery 143)
|
||||||
|
static const int POLL_CAPACITY_MODULE_MAX = 0x4B3D;
|
||||||
|
static const int POLL_CAPACITY_MODULE_MIN = 0x4B3E;
|
||||||
|
static const int POLL_UNKNOWN_7 = 0x4B24; //1 (the other battery 23)
|
||||||
|
static const int POLL_UNKNOWN_8 = 0x4B26; //16 (the other battery 33)
|
||||||
|
static const int POLL_MULTI_TEMPS = 0x4B0F;
|
||||||
|
static const int POLL_MULTI_UNKNOWN_2 = 0x4B10;
|
||||||
|
static const int POLL_MULTI_UNKNOWN_3 = 0x4B53;
|
||||||
|
static const int POLL_MULTI_UNKNOWN_4 = 0x4B54;
|
||||||
|
static const int POLL_MULTI_HARDWARE_VERSION = 0x4B6B;
|
||||||
|
static const int POLL_MULTI_SOFTWARE_VERSION = 0x4B6C;
|
||||||
|
|
||||||
GeelyGeometryCHtmlRenderer renderer;
|
GeelyGeometryCHtmlRenderer renderer;
|
||||||
const int MAX_PACK_VOLTAGE_70_DV 4420 //70kWh
|
|
||||||
const int MIN_PACK_VOLTAGE_70_DV 2860 const int MAX_PACK_VOLTAGE_53_DV 4160 //53kWh
|
static const int MAX_PACK_VOLTAGE_70_DV = 4420; //70kWh
|
||||||
const int MIN_PACK_VOLTAGE_53_DV 2700 const int MAX_CELL_DEVIATION_MV 150 const int
|
static const int MIN_PACK_VOLTAGE_70_DV = 2860;
|
||||||
MAX_CELL_VOLTAGE_MV 4250 //Battery is put into emergency stop if one cell goes over this value
|
static const int MAX_PACK_VOLTAGE_53_DV = 4160; //53kWh
|
||||||
const int MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
static const int MIN_PACK_VOLTAGE_53_DV = 2700;
|
||||||
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
static const int MAX_CELL_DEVIATION_MV = 150;
|
||||||
|
static const int MAX_CELL_VOLTAGE_MV = 4250; //Battery is put into emergency stop if one cell goes over this value
|
||||||
|
static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value
|
||||||
|
|
||||||
|
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
||||||
DATALAYER_INFO_GEELY_GEOMETRY_C* datalayer_geometryc;
|
DATALAYER_INFO_GEELY_GEOMETRY_C* datalayer_geometryc;
|
||||||
|
|
||||||
CAN_frame GEELY_191 = {.FD = false, //PAS_APA_Status , 10ms
|
CAN_frame GEELY_191 = {.FD = false, //PAS_APA_Status , 10ms
|
||||||
|
@ -214,10 +218,7 @@ class GeelyGeometryCBattery : public CanBattery {
|
||||||
uint16_t poll_unknown7 = 0;
|
uint16_t poll_unknown7 = 0;
|
||||||
uint16_t poll_unknown8 = 0;
|
uint16_t poll_unknown8 = 0;
|
||||||
int16_t poll_temperature[6] = {0};
|
int16_t poll_temperature[6] = {0};
|
||||||
|
static const int TEMP_OFFSET = 30; //TODO, not calibrated yet, best guess
|
||||||
//TODO, not calibrated yet, best guess
|
|
||||||
static const int TEMP_OFFSET = 30;
|
|
||||||
|
|
||||||
uint8_t poll_software_version[16] = {0};
|
uint8_t poll_software_version[16] = {0};
|
||||||
uint8_t poll_hardware_version[16] = {0};
|
uint8_t poll_hardware_version[16] = {0};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
//Code still work in progress, TODO:
|
//Code still work in progress, TODO:
|
||||||
//Figure out if CAN messages need to be sent to keep the system happy?
|
//Figure out if CAN messages need to be sent to keep the system happy?
|
||||||
|
@ -200,5 +199,3 @@ void ImievCZeroIonBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS ImievCZeroIonBattery
|
#define SELECTED_BATTERY_CLASS ImievCZeroIonBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class ImievCZeroIonBattery : public CanBattery {
|
class ImievCZeroIonBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "JAGUAR-IPACE-BATTERY.h"
|
||||||
#ifdef JAGUAR_IPACE_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "JAGUAR-IPACE-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* Do not change code below unless you are sure what you are doing */
|
/* Do not change code below unless you are sure what you are doing */
|
||||||
static unsigned long previousMillisKeepAlive = 0;
|
static unsigned long previousMillisKeepAlive = 0;
|
||||||
|
@ -57,7 +56,7 @@ CAN_frame ipace_keep_alive = {.FD = false,
|
||||||
.ID = 0x59e,
|
.ID = 0x59e,
|
||||||
.data = {0x9E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};*/
|
.data = {0x9E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};*/
|
||||||
|
|
||||||
void print_units(char* header, int value, char* units) {
|
static void print_units(char* header, int value, char* units) {
|
||||||
logging.print(header);
|
logging.print(header);
|
||||||
logging.print(value);
|
logging.print(value);
|
||||||
logging.print(units);
|
logging.print(units);
|
||||||
|
@ -237,5 +236,3 @@ void JaguarIpaceBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -3,13 +3,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef JAGUAR_IPACE_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS JaguarIpaceBattery
|
#define SELECTED_BATTERY_CLASS JaguarIpaceBattery
|
||||||
|
#endif
|
||||||
#define MAX_PACK_VOLTAGE_DV 4546 //5000 = 500.0V
|
|
||||||
#define MIN_PACK_VOLTAGE_DV 3370
|
|
||||||
#define MAX_CELL_DEVIATION_MV 250
|
|
||||||
#define MAX_CELL_VOLTAGE_MV 4250 //Battery is put into emergency stop if one cell goes over this value
|
|
||||||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
|
||||||
|
|
||||||
class JaguarIpaceBattery : public CanBattery {
|
class JaguarIpaceBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
@ -17,6 +13,13 @@ class JaguarIpaceBattery : public CanBattery {
|
||||||
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
|
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
virtual void transmit_can(unsigned long currentMillis);
|
virtual void transmit_can(unsigned long currentMillis);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int MAX_PACK_VOLTAGE_DV = 4546; //5000 = 500.0V
|
||||||
|
static const int MIN_PACK_VOLTAGE_DV = 3370;
|
||||||
|
static const int MAX_CELL_DEVIATION_MV = 250;
|
||||||
|
static const int MAX_CELL_VOLTAGE_MV = 4250; //Battery is put into emergency stop if one cell goes over this value
|
||||||
|
static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "KIA-E-GMP-BATTERY.h"
|
||||||
#ifdef KIA_E_GMP_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
|
#include "../include.h"
|
||||||
#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
||||||
#include "KIA-E-GMP-BATTERY.h"
|
|
||||||
|
|
||||||
const unsigned char crc8_table[256] =
|
const unsigned char crc8_table[256] =
|
||||||
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
|
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
|
||||||
|
@ -1101,5 +1100,3 @@ void KiaEGmpBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ extern ACAN2517FD canfd;
|
||||||
|
|
||||||
#define ESTIMATE_SOC_FROM_CELLVOLTAGE
|
#define ESTIMATE_SOC_FROM_CELLVOLTAGE
|
||||||
|
|
||||||
|
#ifdef KIA_E_GMP_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS KiaEGmpBattery
|
#define SELECTED_BATTERY_CLASS KiaEGmpBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class KiaEGmpBattery : public CanBattery {
|
class KiaEGmpBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "KIA-HYUNDAI-64-BATTERY.h"
|
||||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "KIA-HYUNDAI-64-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void KiaHyundai64Battery::
|
void KiaHyundai64Battery::
|
||||||
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||||
|
@ -475,5 +474,3 @@ void KiaHyundai64Battery::setup(void) { // Performs one time setup at startup
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "KIA-HYUNDAI-64-HTML.h"
|
#include "KIA-HYUNDAI-64-HTML.h"
|
||||||
|
|
||||||
|
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS KiaHyundai64Battery
|
#define SELECTED_BATTERY_CLASS KiaHyundai64Battery
|
||||||
|
#endif
|
||||||
|
|
||||||
class KiaHyundai64Battery : public CanBattery {
|
class KiaHyundai64Battery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "KIA-HYUNDAI-HYBRID-BATTERY.h"
|
||||||
#ifdef KIA_HYUNDAI_HYBRID_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "KIA-HYUNDAI-HYBRID-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
- The HEV battery seems to turn off after 1 minute of use. When this happens SOC% stops updating.
|
- The HEV battery seems to turn off after 1 minute of use. When this happens SOC% stops updating.
|
||||||
|
@ -224,5 +223,3 @@ void KiaHyundaiHybridBattery::setup(void) { // Performs one time setup at start
|
||||||
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef KIA_HYUNDAI_HYBRID_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS KiaHyundaiHybridBattery
|
#define SELECTED_BATTERY_CLASS KiaHyundaiHybridBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class KiaHyundaiHybridBattery : public CanBattery {
|
class KiaHyundaiHybridBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#include "../include.h"
|
#include "MEB-BATTERY.h"
|
||||||
#ifdef MEB_BATTERY
|
|
||||||
#include <algorithm> // For std::min and std::max
|
#include <algorithm> // For std::min and std::max
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../communication/can/obd.h"
|
#include "../communication/can/obd.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "MEB-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO list
|
TODO list
|
||||||
|
@ -2045,5 +2044,3 @@ void MebBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "MEB-HTML.h"
|
#include "MEB-HTML.h"
|
||||||
|
|
||||||
|
#ifdef MEB_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS MebBattery
|
#define SELECTED_BATTERY_CLASS MebBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class MebBattery : public CanBattery {
|
class MebBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "MG-5-BATTERY.h"
|
||||||
#ifdef MG_5_BATTERY_H
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "MG-5-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
- Get contactor closing working
|
- Get contactor closing working
|
||||||
|
@ -122,5 +121,3 @@ void Mg5Battery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef MG_5_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS Mg5Battery
|
#define SELECTED_BATTERY_CLASS Mg5Battery
|
||||||
|
#endif
|
||||||
|
|
||||||
class Mg5Battery : public CanBattery {
|
class Mg5Battery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "../include.h"
|
|
||||||
#ifdef NISSAN_LEAF_BATTERY
|
|
||||||
#include "NISSAN-LEAF-BATTERY.h"
|
#include "NISSAN-LEAF-BATTERY.h"
|
||||||
|
#include "../include.h"
|
||||||
#ifdef MQTT
|
#ifdef MQTT
|
||||||
#include "../devboard/mqtt/mqtt.h"
|
#include "../devboard/mqtt/mqtt.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -970,7 +969,7 @@ void decodeChallengeData(unsigned int incomingChallenge, unsigned char* solvedCh
|
||||||
}
|
}
|
||||||
|
|
||||||
void NissanLeafBattery::setup(void) { // Performs one time setup at startup
|
void NissanLeafBattery::setup(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Nissan LEAF battery", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
datalayer_battery->info.number_of_cells = 96;
|
datalayer_battery->info.number_of_cells = 96;
|
||||||
datalayer_battery->info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
datalayer_battery->info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
||||||
|
@ -979,5 +978,3 @@ void NissanLeafBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer_battery->info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer_battery->info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer_battery->info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer_battery->info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //NISSAN_LEAF_BATTERY
|
|
||||||
|
|
|
@ -7,14 +7,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "NISSAN-LEAF-HTML.h"
|
#include "NISSAN-LEAF-HTML.h"
|
||||||
|
|
||||||
|
#ifdef NISSAN_LEAF_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS NissanLeafBattery
|
#define SELECTED_BATTERY_CLASS NissanLeafBattery
|
||||||
#define EXTENDED_DATA_PTR (&datalayer_extended.nissanleaf)
|
#endif
|
||||||
|
|
||||||
#define MAX_PACK_VOLTAGE_DV 4040 //5000 = 500.0V
|
|
||||||
#define MIN_PACK_VOLTAGE_DV 2600
|
|
||||||
#define MAX_CELL_DEVIATION_MV 150
|
|
||||||
#define MAX_CELL_VOLTAGE_MV 4250 //Battery is put into emergency stop if one cell goes over this value
|
|
||||||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
|
||||||
|
|
||||||
class NissanLeafBattery : public CanBattery {
|
class NissanLeafBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
@ -51,8 +46,15 @@ class NissanLeafBattery : public CanBattery {
|
||||||
}
|
}
|
||||||
|
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
static constexpr char* Name = "Nissan LEAF battery";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int MAX_PACK_VOLTAGE_DV = 4040; //5000 = 500.0V
|
||||||
|
static const int MIN_PACK_VOLTAGE_DV = 2600;
|
||||||
|
static const int MAX_CELL_DEVIATION_MV = 150;
|
||||||
|
static const int MAX_CELL_VOLTAGE_MV = 4250; //Battery is put into emergency stop if one cell goes over this value
|
||||||
|
static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value
|
||||||
|
|
||||||
NissanLeafHtmlRenderer renderer;
|
NissanLeafHtmlRenderer renderer;
|
||||||
|
|
||||||
bool is_message_corrupt(CAN_frame rx_frame);
|
bool is_message_corrupt(CAN_frame rx_frame);
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "ORION-BMS.h"
|
||||||
#ifdef ORION_BMS
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "ORION-BMS.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void findMinMaxCellvoltages(const uint16_t arr[], size_t size, uint16_t& Minimum_Cell_Voltage,
|
void findMinMaxCellvoltages(const uint16_t arr[], size_t size, uint16_t& Minimum_Cell_Voltage,
|
||||||
uint16_t& Maximum_Cell_Voltage) {
|
uint16_t& Maximum_Cell_Voltage) {
|
||||||
|
@ -124,5 +123,3 @@ void OrionBms::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef ORION_BMS
|
||||||
#define SELECTED_BATTERY_CLASS OrionBms
|
#define SELECTED_BATTERY_CLASS OrionBms
|
||||||
|
#endif
|
||||||
|
|
||||||
class OrionBms : public CanBattery {
|
class OrionBms : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "PYLON-BATTERY.h"
|
||||||
#ifdef PYLON_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "PYLON-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void PylonBattery::update_values() {
|
void PylonBattery::update_values() {
|
||||||
|
|
||||||
|
@ -144,5 +143,3 @@ void PylonBattery::setup(void) { // Performs one time setup at startup
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef PYLON_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS PylonBattery
|
#define SELECTED_BATTERY_CLASS PylonBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class PylonBattery : public CanBattery {
|
class PylonBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "RANGE-ROVER-PHEV-BATTERY.h"
|
||||||
#ifdef RANGE_ROVER_PHEV_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "RANGE-ROVER-PHEV-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
- LOG files from vehicle needed to determine CAN content needed to send towards battery!
|
- LOG files from vehicle needed to determine CAN content needed to send towards battery!
|
||||||
|
@ -216,5 +215,3 @@ void RangeRoverPhevBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //RANGE_ROVER_PHEV_BATTERY
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef RANGE_ROVER_PHEV_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS RangeRoverPhevBattery
|
#define SELECTED_BATTERY_CLASS RangeRoverPhevBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class RangeRoverPhevBattery : public CanBattery {
|
class RangeRoverPhevBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "RENAULT-KANGOO-BATTERY.h"
|
||||||
#ifdef RENAULT_KANGOO_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "RENAULT-KANGOO-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
There seems to be some values on the Kangoo that differ between the 22/33 kWh version
|
There seems to be some values on the Kangoo that differ between the 22/33 kWh version
|
||||||
|
@ -191,5 +190,3 @@ void RenaultKangooBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef RENAULT_KANGOO_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS RenaultKangooBattery
|
#define SELECTED_BATTERY_CLASS RenaultKangooBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class RenaultKangooBattery : public CanBattery {
|
class RenaultKangooBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
|
#include "RENAULT-TWIZY.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "../include.h"
|
|
||||||
#ifdef RENAULT_TWIZY_BATTERY
|
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "RENAULT-TWIZY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
int16_t max_value(int16_t* entries, size_t len) {
|
int16_t max_value(int16_t* entries, size_t len) {
|
||||||
int result = INT16_MIN;
|
int result = INT16_MIN;
|
||||||
|
@ -129,5 +128,3 @@ void RenaultTwizyBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.total_capacity_Wh = 6600;
|
datalayer.battery.info.total_capacity_Wh = 6600;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef RENAULT_TWIZY_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS RenaultTwizyBattery
|
#define SELECTED_BATTERY_CLASS RenaultTwizyBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class RenaultTwizyBattery : public CanBattery {
|
class RenaultTwizyBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "RENAULT-ZOE-GEN1-BATTERY.h"
|
||||||
#ifdef RENAULT_ZOE_GEN1_BATTERY
|
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "RENAULT-ZOE-GEN1-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||||
|
|
||||||
|
@ -567,5 +566,3 @@ void RenaultZoeGen1Battery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -4,13 +4,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "RENAULT-ZOE-GEN1-HTML.h"
|
#include "RENAULT-ZOE-GEN1-HTML.h"
|
||||||
|
|
||||||
|
#ifdef RENAULT_ZOE_GEN1_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS RenaultZoeGen1Battery
|
#define SELECTED_BATTERY_CLASS RenaultZoeGen1Battery
|
||||||
|
#endif
|
||||||
#define MAX_PACK_VOLTAGE_DV 4200 //5000 = 500.0V
|
|
||||||
#define MIN_PACK_VOLTAGE_DV 3000
|
|
||||||
#define MAX_CELL_DEVIATION_MV 150
|
|
||||||
#define MAX_CELL_VOLTAGE_MV 4250 //Battery is put into emergency stop if one cell goes over this value
|
|
||||||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
|
||||||
|
|
||||||
class RenaultZoeGen1Battery : public CanBattery {
|
class RenaultZoeGen1Battery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
@ -22,6 +18,12 @@ class RenaultZoeGen1Battery : public CanBattery {
|
||||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int MAX_PACK_VOLTAGE_DV = 4200; //5000 = 500.0V
|
||||||
|
static const int MIN_PACK_VOLTAGE_DV = 3000;
|
||||||
|
static const int MAX_CELL_DEVIATION_MV = 150;
|
||||||
|
static const int MAX_CELL_VOLTAGE_MV = 4250; //Battery is put into emergency stop if one cell goes over this value
|
||||||
|
static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value
|
||||||
|
|
||||||
RenaultZoeGen1HtmlRenderer renderer;
|
RenaultZoeGen1HtmlRenderer renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "RENAULT-ZOE-GEN2-BATTERY.h"
|
||||||
#ifdef RENAULT_ZOE_GEN2_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "RENAULT-ZOE-GEN2-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
- Add //NVROL Reset
|
- Add //NVROL Reset
|
||||||
|
@ -688,5 +687,3 @@ void RenaultZoeGen2Battery::wait_ms(int duration_ms) {
|
||||||
// Do nothing - just wait
|
// Do nothing - just wait
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "RENAULT-ZOE-GEN2-HTML.h"
|
#include "RENAULT-ZOE-GEN2-HTML.h"
|
||||||
|
|
||||||
|
#ifdef RENAULT_ZOE_GEN2_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS RenaultZoeGen2Battery
|
#define SELECTED_BATTERY_CLASS RenaultZoeGen2Battery
|
||||||
|
#endif
|
||||||
|
|
||||||
class RenaultZoeGen2Battery : public CanBattery {
|
class RenaultZoeGen2Battery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "RJXZS-BMS.h"
|
||||||
#ifdef RJXZS_BMS
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "RJXZS-BMS.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void RjxzsBms::update_values() {
|
void RjxzsBms::update_values() {
|
||||||
|
|
||||||
|
@ -525,5 +524,3 @@ void RjxzsBms::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // RJXZS_BMS
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef RJXZS_BMS
|
||||||
#define SELECTED_BATTERY_CLASS RjxzsBms
|
#define SELECTED_BATTERY_CLASS RjxzsBms
|
||||||
|
#endif
|
||||||
|
|
||||||
class RjxzsBms : public CanBattery {
|
class RjxzsBms : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "SANTA-FE-PHEV-BATTERY.h"
|
||||||
#ifdef SANTA_FE_PHEV_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "SANTA-FE-PHEV-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* Credits go to maciek16c for these findings!
|
/* Credits go to maciek16c for these findings!
|
||||||
https://github.com/maciek16c/hyundai-santa-fe-phev-battery
|
https://github.com/maciek16c/hyundai-santa-fe-phev-battery
|
||||||
|
@ -333,5 +332,3 @@ void SantaFePhevBattery::setup(void) { // Performs one time setup at startup
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef SANTA_FE_PHEV_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS SantaFePhevBattery
|
#define SELECTED_BATTERY_CLASS SantaFePhevBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class SantaFePhevBattery : public CanBattery {
|
class SantaFePhevBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include "../include.h"
|
#include "SIMPBMS-BATTERY.h"
|
||||||
#ifdef SIMPBMS_BATTERY
|
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "SIMPBMS-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void SimpBmsBattery::update_values() {
|
void SimpBmsBattery::update_values() {
|
||||||
|
|
||||||
|
@ -102,5 +101,3 @@ void SimpBmsBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef SIMPBMS_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS SimpBmsBattery
|
#define SELECTED_BATTERY_CLASS SimpBmsBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class SimpBmsBattery : public CanBattery {
|
class SimpBmsBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
#include "SONO-BATTERY.h"
|
||||||
#ifdef SONO_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "SONO-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void SonoBattery::
|
void SonoBattery::
|
||||||
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||||
|
@ -152,5 +151,3 @@ void SonoBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
datalayer.battery.info.chemistry = battery_chemistry_enum::LFP;
|
datalayer.battery.info.chemistry = battery_chemistry_enum::LFP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef SONO_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS SonoBattery
|
#define SELECTED_BATTERY_CLASS SonoBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class SonoBattery : public CanBattery {
|
class SonoBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
CanShunt* shunt = nullptr;
|
CanShunt* shunt = nullptr;
|
||||||
|
|
||||||
void setup_can_shunt() {
|
void setup_can_shunt() {
|
||||||
|
if (shunt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SELECTED_SHUNT_CLASS)
|
#if defined(SELECTED_SHUNT_CLASS)
|
||||||
shunt = new SELECTED_SHUNT_CLASS();
|
shunt = new SELECTED_SHUNT_CLASS();
|
||||||
if (shunt) {
|
if (shunt) {
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "TESLA-BATTERY.h"
|
||||||
#ifdef TESLA_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For Advanced Battery Insights webpage
|
#include "../datalayer/datalayer_extended.h" //For Advanced Battery Insights webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "TESLA-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
/* Credits: Most of the code comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */
|
/* Credits: Most of the code comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */
|
||||||
|
|
||||||
|
@ -1764,8 +1763,7 @@ void TeslaModel3YBattery::setup(void) { // Performs one time setup at startup
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TESLA_MODEL_3Y_BATTERY // Model 3/Y can be either LFP or NCM/A
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Tesla Model 3/Y", 63);
|
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
#ifdef LFP_CHEMISTRY
|
#ifdef LFP_CHEMISTRY
|
||||||
datalayer.battery.info.chemistry = battery_chemistry_enum::LFP;
|
datalayer.battery.info.chemistry = battery_chemistry_enum::LFP;
|
||||||
|
@ -1781,7 +1779,6 @@ void TeslaModel3YBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_NCA_NCM;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_NCA_NCM;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_NCA_NCM;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_NCA_NCM;
|
||||||
#endif // !LFP_CHEMISTRY
|
#endif // !LFP_CHEMISTRY
|
||||||
#endif // TESLA_MODEL_3Y_BATTERY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeslaModelSXBattery::setup(void) {
|
void TeslaModelSXBattery::setup(void) {
|
||||||
|
@ -1789,7 +1786,7 @@ void TeslaModelSXBattery::setup(void) {
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Tesla Model S/X", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_SX_NCMA;
|
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_SX_NCMA;
|
||||||
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_SX_NCMA;
|
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_SX_NCMA;
|
||||||
|
@ -1797,5 +1794,3 @@ void TeslaModelSXBattery::setup(void) {
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_NCA_NCM;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_NCA_NCM;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_NCA_NCM;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_NCA_NCM;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TESLA_BATTERY
|
|
||||||
|
|
|
@ -513,12 +513,14 @@ class TeslaModel3YBattery : public TeslaBattery {
|
||||||
operate_contactors = true;
|
operate_contactors = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
static constexpr char* Name = "Tesla Model 3/Y";
|
||||||
virtual void setup(void);
|
virtual void setup(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TeslaModelSXBattery : public TeslaBattery {
|
class TeslaModelSXBattery : public TeslaBattery {
|
||||||
public:
|
public:
|
||||||
TeslaModelSXBattery() { operate_contactors = true; }
|
TeslaModelSXBattery() { operate_contactors = true; }
|
||||||
|
static constexpr char* Name = "Tesla Model S/X";
|
||||||
virtual void setup(void);
|
virtual void setup(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "../include.h"
|
|
||||||
#ifdef TEST_FAKE_BATTERY
|
|
||||||
#include "../datalayer/datalayer.h"
|
|
||||||
#include "TEST-FAKE-BATTERY.h"
|
#include "TEST-FAKE-BATTERY.h"
|
||||||
|
#include "../datalayer/datalayer.h"
|
||||||
|
#include "../include.h"
|
||||||
|
|
||||||
void print_units(char* header, int value, char* units) {
|
static void print_units(char* header, int value, char* units) {
|
||||||
logging.print(header);
|
logging.print(header);
|
||||||
logging.print(value);
|
logging.print(value);
|
||||||
logging.print(units);
|
logging.print(units);
|
||||||
|
@ -75,7 +74,7 @@ void TestFakeBattery::transmit_can(unsigned long currentMillis) {
|
||||||
void TestFakeBattery::setup(void) { // Performs one time setup at startup
|
void TestFakeBattery::setup(void) { // Performs one time setup at startup
|
||||||
randomSeed(analogRead(0));
|
randomSeed(analogRead(0));
|
||||||
|
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Fake battery for testing purposes", 63);
|
strncpy(datalayer.system.info.battery_protocol, Name, 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
|
|
||||||
datalayer_battery->info.max_design_voltage_dV =
|
datalayer_battery->info.max_design_voltage_dV =
|
||||||
|
@ -87,5 +86,3 @@ void TestFakeBattery::setup(void) { // Performs one time setup at startup
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
|
#ifdef TEST_FAKE_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS TestFakeBattery
|
#define SELECTED_BATTERY_CLASS TestFakeBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class TestFakeBattery : public CanBattery {
|
class TestFakeBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
@ -20,6 +22,8 @@ class TestFakeBattery : public CanBattery {
|
||||||
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
|
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr char* Name = "Fake battery for testing purposes";
|
||||||
|
|
||||||
virtual void setup();
|
virtual void setup();
|
||||||
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
|
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
|
||||||
virtual void update_values();
|
virtual void update_values();
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "VOLVO-SPA-BATTERY.h"
|
||||||
#ifdef VOLVO_SPA_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "VOLVO-SPA-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void VolvoSpaBattery::
|
void VolvoSpaBattery::
|
||||||
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
||||||
|
@ -388,4 +387,3 @@ void VolvoSpaBattery::setup(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "VOLVO-SPA-HTML.h"
|
#include "VOLVO-SPA-HTML.h"
|
||||||
|
|
||||||
|
#ifdef VOLVO_SPA_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS VolvoSpaBattery
|
#define SELECTED_BATTERY_CLASS VolvoSpaBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class VolvoSpaBattery : public CanBattery {
|
class VolvoSpaBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "../include.h"
|
#include "VOLVO-SPA-HYBRID-BATTERY.h"
|
||||||
#ifdef VOLVO_SPA_HYBRID_BATTERY
|
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "VOLVO-SPA-HYBRID-BATTERY.h"
|
#include "../include.h"
|
||||||
|
|
||||||
void VolvoSpaHybridBattery::
|
void VolvoSpaHybridBattery::
|
||||||
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
update_values() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
||||||
|
@ -563,4 +562,3 @@ void VolvoSpaHybridBattery::setup(void) { //
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
#include "VOLVO-SPA-HYBRID-HTML.h"
|
#include "VOLVO-SPA-HYBRID-HTML.h"
|
||||||
|
|
||||||
|
#ifdef VOLVO_SPA_HYBRID_BATTERY
|
||||||
#define SELECTED_BATTERY_CLASS VolvoSpaHybridBattery
|
#define SELECTED_BATTERY_CLASS VolvoSpaHybridBattery
|
||||||
|
#endif
|
||||||
|
|
||||||
class VolvoSpaHybridBattery : public CanBattery {
|
class VolvoSpaHybridBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2,8 +2,42 @@
|
||||||
|
|
||||||
CanCharger* charger = nullptr;
|
CanCharger* charger = nullptr;
|
||||||
|
|
||||||
|
ChargerType user_selected_charger_type = ChargerType::None;
|
||||||
|
|
||||||
|
std::vector<ChargerType> supported_charger_types() {
|
||||||
|
std::vector<ChargerType> types;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)ChargerType::Highest; i++) {
|
||||||
|
types.push_back((ChargerType)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char* name_for_type(ChargerType type) {
|
||||||
|
switch (type) {
|
||||||
|
case ChargerType::ChevyVolt:
|
||||||
|
return ChevyVoltCharger::Name;
|
||||||
|
case ChargerType::NissanLeaf:
|
||||||
|
return NissanLeafCharger::Name;
|
||||||
|
case ChargerType::None:
|
||||||
|
return "None";
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void setup_charger() {
|
void setup_charger() {
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
switch (user_selected_charger_type) {
|
||||||
|
case ChargerType::ChevyVolt:
|
||||||
|
charger = new ChevyVoltCharger();
|
||||||
|
case ChargerType::NissanLeaf:
|
||||||
|
charger = new NissanLeafCharger();
|
||||||
|
}
|
||||||
|
#else
|
||||||
#ifdef SELECTED_CHARGER_CLASS
|
#ifdef SELECTED_CHARGER_CLASS
|
||||||
charger = new SELECTED_CHARGER_CLASS();
|
charger = new SELECTED_CHARGER_CLASS();
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ class ChevyVoltCharger : public CanCharger {
|
||||||
public:
|
public:
|
||||||
ChevyVoltCharger() : CanCharger(ChargerType::ChevyVolt) {}
|
ChevyVoltCharger() : CanCharger(ChargerType::ChevyVolt) {}
|
||||||
|
|
||||||
const char* name() { return "Chevy Volt Gen1 Charger"; }
|
const char* name() { return Name; }
|
||||||
|
static constexpr char* Name = "Chevy Volt Gen1 Charger";
|
||||||
|
|
||||||
void map_can_frame_to_variable(CAN_frame rx_frame);
|
void map_can_frame_to_variable(CAN_frame rx_frame);
|
||||||
void transmit_can(unsigned long currentMillis);
|
void transmit_can(unsigned long currentMillis);
|
||||||
|
|
|
@ -7,7 +7,12 @@
|
||||||
#include "src/communication/Transmitter.h"
|
#include "src/communication/Transmitter.h"
|
||||||
#include "src/communication/can/CanReceiver.h"
|
#include "src/communication/can/CanReceiver.h"
|
||||||
|
|
||||||
enum class ChargerType { NissanLeaf, ChevyVolt };
|
enum class ChargerType { None, NissanLeaf, ChevyVolt, Highest };
|
||||||
|
|
||||||
|
extern ChargerType user_selected_charger_type;
|
||||||
|
|
||||||
|
extern std::vector<ChargerType> supported_charger_types();
|
||||||
|
extern const char* name_for_type(ChargerType type);
|
||||||
|
|
||||||
// Generic base class for all chargers
|
// Generic base class for all chargers
|
||||||
class Charger {
|
class Charger {
|
||||||
|
|
|
@ -13,7 +13,9 @@ class NissanLeafCharger : public CanCharger {
|
||||||
public:
|
public:
|
||||||
NissanLeafCharger() : CanCharger(ChargerType::NissanLeaf) {}
|
NissanLeafCharger() : CanCharger(ChargerType::NissanLeaf) {}
|
||||||
|
|
||||||
const char* name() { return "Nissan LEAF 2013-2024 PDM charger"; }
|
const char* name() { return Name; }
|
||||||
|
static constexpr char* Name = "Nissan LEAF 2013-2024 PDM charger";
|
||||||
|
|
||||||
void map_can_frame_to_variable(CAN_frame rx_frame);
|
void map_can_frame_to_variable(CAN_frame rx_frame);
|
||||||
void transmit_can(unsigned long currentMillis);
|
void transmit_can(unsigned long currentMillis);
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,43 @@
|
||||||
#include "comm_contactorcontrol.h"
|
#include "comm_contactorcontrol.h"
|
||||||
#include "../../include.h"
|
#include "../../include.h"
|
||||||
|
|
||||||
// Parameters
|
|
||||||
#ifndef CONTACTOR_CONTROL
|
|
||||||
#ifdef PWM_CONTACTOR_CONTROL
|
|
||||||
#error CONTACTOR_CONTROL needs to be enabled for PWM_CONTACTOR_CONTROL
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONTACTOR_CONTROL
|
#ifdef CONTACTOR_CONTROL
|
||||||
|
const bool contactor_control_enabled_default = true;
|
||||||
|
#else
|
||||||
|
const bool contactor_control_enabled_default = false;
|
||||||
|
#endif
|
||||||
|
bool contactor_control_enabled = contactor_control_enabled_default;
|
||||||
|
|
||||||
|
#ifdef PWM_CONTACTOR_CONTROL
|
||||||
|
const bool pwn_contactor_control_default = true;
|
||||||
|
#else
|
||||||
|
const bool pwn_contactor_control_default = false;
|
||||||
|
#endif
|
||||||
|
bool pwm_contactor_control = pwn_contactor_control_default;
|
||||||
|
|
||||||
|
#ifdef PERIODIC_BMS_RESET
|
||||||
|
const bool periodic_bms_reset_default = true;
|
||||||
|
#else
|
||||||
|
const bool periodic_bms_reset_default = false;
|
||||||
|
#endif
|
||||||
|
bool periodic_bms_reset = periodic_bms_reset_default;
|
||||||
|
|
||||||
|
#ifdef REMOTE_BMS_RESET
|
||||||
|
const bool remote_bms_reset_default = true;
|
||||||
|
#else
|
||||||
|
const bool remote_bms_reset_default = true;
|
||||||
|
#endif
|
||||||
|
bool remote_bms_reset = remote_bms_reset_default;
|
||||||
|
|
||||||
|
// TODO: Ensure valid values at run-time
|
||||||
|
|
||||||
|
// Parameters
|
||||||
|
|
||||||
enum State { DISCONNECTED, START_PRECHARGE, PRECHARGE, POSITIVE, PRECHARGE_OFF, COMPLETED, SHUTDOWN_REQUESTED };
|
enum State { DISCONNECTED, START_PRECHARGE, PRECHARGE, POSITIVE, PRECHARGE_OFF, COMPLETED, SHUTDOWN_REQUESTED };
|
||||||
State contactorStatus = DISCONNECTED;
|
State contactorStatus = DISCONNECTED;
|
||||||
|
|
||||||
#define ON 1
|
const int ON = 1;
|
||||||
#define OFF 0
|
const int OFF = 0;
|
||||||
|
|
||||||
#ifdef NC_CONTACTORS //Normally closed contactors use inverted logic
|
#ifdef NC_CONTACTORS //Normally closed contactors use inverted logic
|
||||||
#undef ON
|
#undef ON
|
||||||
|
@ -38,7 +62,6 @@ unsigned long prechargeStartTime = 0;
|
||||||
unsigned long negativeStartTime = 0;
|
unsigned long negativeStartTime = 0;
|
||||||
unsigned long prechargeCompletedTime = 0;
|
unsigned long prechargeCompletedTime = 0;
|
||||||
unsigned long timeSpentInFaultedMode = 0;
|
unsigned long timeSpentInFaultedMode = 0;
|
||||||
#endif
|
|
||||||
unsigned long currentTime = 0;
|
unsigned long currentTime = 0;
|
||||||
unsigned long lastPowerRemovalTime = 0;
|
unsigned long lastPowerRemovalTime = 0;
|
||||||
unsigned long bmsPowerOnTime = 0;
|
unsigned long bmsPowerOnTime = 0;
|
||||||
|
@ -47,12 +70,12 @@ const unsigned long powerRemovalDuration = 30000; // 30 seconds i
|
||||||
const unsigned long bmsWarmupDuration = 3000;
|
const unsigned long bmsWarmupDuration = 3000;
|
||||||
|
|
||||||
void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
|
void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
|
||||||
#ifdef PWM_CONTACTOR_CONTROL
|
if (pwm_contactor_control) {
|
||||||
if (pwm_freq != 0xFFFF) {
|
if (pwm_freq != 0xFFFF) {
|
||||||
ledcWrite(pin, pwm_freq);
|
ledcWrite(pin, pwm_freq);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (direction == 1) {
|
if (direction == 1) {
|
||||||
digitalWrite(pin, HIGH);
|
digitalWrite(pin, HIGH);
|
||||||
} else { // 0
|
} else { // 0
|
||||||
|
@ -64,23 +87,24 @@ void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
|
||||||
|
|
||||||
void init_contactors() {
|
void init_contactors() {
|
||||||
// Init contactor pins
|
// Init contactor pins
|
||||||
#ifdef CONTACTOR_CONTROL
|
if (contactor_control_enabled) {
|
||||||
#ifdef PWM_CONTACTOR_CONTROL
|
if (pwm_contactor_control) {
|
||||||
// Setup PWM Channel Frequency and Resolution
|
// Setup PWM Channel Frequency and Resolution
|
||||||
ledcAttachChannel(POSITIVE_CONTACTOR_PIN, PWM_Freq, PWM_Res, PWM_Positive_Channel);
|
ledcAttachChannel(POSITIVE_CONTACTOR_PIN, PWM_Freq, PWM_Res, PWM_Positive_Channel);
|
||||||
ledcAttachChannel(NEGATIVE_CONTACTOR_PIN, PWM_Freq, PWM_Res, PWM_Negative_Channel);
|
ledcAttachChannel(NEGATIVE_CONTACTOR_PIN, PWM_Freq, PWM_Res, PWM_Negative_Channel);
|
||||||
// Set all pins OFF (0% PWM)
|
// Set all pins OFF (0% PWM)
|
||||||
ledcWrite(POSITIVE_CONTACTOR_PIN, PWM_OFF_DUTY);
|
ledcWrite(POSITIVE_CONTACTOR_PIN, PWM_OFF_DUTY);
|
||||||
ledcWrite(NEGATIVE_CONTACTOR_PIN, PWM_OFF_DUTY);
|
ledcWrite(NEGATIVE_CONTACTOR_PIN, PWM_OFF_DUTY);
|
||||||
#else //Normal CONTACTOR_CONTROL
|
} else {
|
||||||
pinMode(POSITIVE_CONTACTOR_PIN, OUTPUT);
|
pinMode(POSITIVE_CONTACTOR_PIN, OUTPUT);
|
||||||
set(POSITIVE_CONTACTOR_PIN, OFF);
|
set(POSITIVE_CONTACTOR_PIN, OFF);
|
||||||
pinMode(NEGATIVE_CONTACTOR_PIN, OUTPUT);
|
pinMode(NEGATIVE_CONTACTOR_PIN, OUTPUT);
|
||||||
set(NEGATIVE_CONTACTOR_PIN, OFF);
|
set(NEGATIVE_CONTACTOR_PIN, OFF);
|
||||||
#endif // Precharge never has PWM regardless of setting
|
} // Precharge never has PWM regardless of setting
|
||||||
pinMode(PRECHARGE_PIN, OUTPUT);
|
pinMode(PRECHARGE_PIN, OUTPUT);
|
||||||
set(PRECHARGE_PIN, OFF);
|
set(PRECHARGE_PIN, OFF);
|
||||||
#endif // CONTACTOR_CONTROL
|
}
|
||||||
|
|
||||||
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
||||||
pinMode(SECOND_POSITIVE_CONTACTOR_PIN, OUTPUT);
|
pinMode(SECOND_POSITIVE_CONTACTOR_PIN, OUTPUT);
|
||||||
set(SECOND_POSITIVE_CONTACTOR_PIN, OFF);
|
set(SECOND_POSITIVE_CONTACTOR_PIN, OFF);
|
||||||
|
@ -94,16 +118,16 @@ void init_contactors() {
|
||||||
#ifdef BMS_2_POWER //Hardware supports 2x BMS
|
#ifdef BMS_2_POWER //Hardware supports 2x BMS
|
||||||
pinMode(BMS_2_POWER, OUTPUT);
|
pinMode(BMS_2_POWER, OUTPUT);
|
||||||
digitalWrite(BMS_2_POWER, HIGH);
|
digitalWrite(BMS_2_POWER, HIGH);
|
||||||
#endif //BMS_2_POWER
|
|
||||||
#endif // HW with dedicated BMS pins
|
|
||||||
#if defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET) // User has enabled BMS reset, turn on output on start
|
|
||||||
pinMode(BMS_POWER, OUTPUT);
|
|
||||||
digitalWrite(BMS_POWER, HIGH);
|
|
||||||
#ifdef BMS_2_POWER //Hardware supports 2x BMS
|
|
||||||
pinMode(BMS_2_POWER, OUTPUT);
|
|
||||||
digitalWrite(BMS_2_POWER, HIGH);
|
|
||||||
#endif //BMS_2_POWER
|
#endif //BMS_2_POWER
|
||||||
#endif //PERIODIC_BMS_RESET
|
#endif // HW with dedicated BMS pins
|
||||||
|
if (periodic_bms_reset || remote_bms_reset) {
|
||||||
|
pinMode(BMS_POWER, OUTPUT);
|
||||||
|
digitalWrite(BMS_POWER, HIGH);
|
||||||
|
#ifdef BMS_2_POWER //Hardware supports 2x BMS
|
||||||
|
pinMode(BMS_2_POWER, OUTPUT);
|
||||||
|
digitalWrite(BMS_2_POWER, HIGH);
|
||||||
|
#endif //BMS_2_POWER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dbg_contactors(const char* state) {
|
static void dbg_contactors(const char* state) {
|
||||||
|
@ -117,6 +141,7 @@ static void dbg_contactors(const char* state) {
|
||||||
|
|
||||||
// Main functions of the handle_contactors include checking if inverter allows for closing, checking battery 2, checking BMS power output, and actual contactor closing/precharge via GPIO
|
// Main functions of the handle_contactors include checking if inverter allows for closing, checking battery 2, checking BMS power output, and actual contactor closing/precharge via GPIO
|
||||||
void handle_contactors() {
|
void handle_contactors() {
|
||||||
|
// TODO: This must be determined at run-time!
|
||||||
#if defined(SMA_BYD_H_CAN) || defined(SMA_BYD_HVS_CAN) || defined(SMA_TRIPOWER_CAN)
|
#if defined(SMA_BYD_H_CAN) || defined(SMA_BYD_HVS_CAN) || defined(SMA_TRIPOWER_CAN)
|
||||||
datalayer.system.status.inverter_allows_contactor_closing = digitalRead(INVERTER_CONTACTOR_ENABLE_PIN);
|
datalayer.system.status.inverter_allows_contactor_closing = digitalRead(INVERTER_CONTACTOR_ENABLE_PIN);
|
||||||
#endif
|
#endif
|
||||||
|
@ -127,100 +152,102 @@ void handle_contactors() {
|
||||||
handle_contactors_battery2();
|
handle_contactors_battery2();
|
||||||
#endif // CONTACTOR_CONTROL_DOUBLE_BATTERY
|
#endif // CONTACTOR_CONTROL_DOUBLE_BATTERY
|
||||||
|
|
||||||
#ifdef CONTACTOR_CONTROL
|
if (contactor_control_enabled) {
|
||||||
// First check if we have any active errors, incase we do, turn off the battery
|
// First check if we have any active errors, incase we do, turn off the battery
|
||||||
if (datalayer.battery.status.bms_status == FAULT) {
|
if (datalayer.battery.status.bms_status == FAULT) {
|
||||||
timeSpentInFaultedMode++;
|
timeSpentInFaultedMode++;
|
||||||
} else {
|
} else {
|
||||||
timeSpentInFaultedMode = 0;
|
timeSpentInFaultedMode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle contactor control SHUTDOWN_REQUESTED
|
//handle contactor control SHUTDOWN_REQUESTED
|
||||||
if (timeSpentInFaultedMode > MAX_ALLOWED_FAULT_TICKS) {
|
if (timeSpentInFaultedMode > MAX_ALLOWED_FAULT_TICKS) {
|
||||||
contactorStatus = SHUTDOWN_REQUESTED;
|
contactorStatus = SHUTDOWN_REQUESTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contactorStatus == SHUTDOWN_REQUESTED) {
|
if (contactorStatus == SHUTDOWN_REQUESTED) {
|
||||||
set(PRECHARGE_PIN, OFF);
|
set(PRECHARGE_PIN, OFF);
|
||||||
set(NEGATIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
set(NEGATIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
||||||
set(POSITIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
set(POSITIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
||||||
set_event(EVENT_ERROR_OPEN_CONTACTOR, 0);
|
set_event(EVENT_ERROR_OPEN_CONTACTOR, 0);
|
||||||
datalayer.system.status.contactors_engaged = false;
|
datalayer.system.status.contactors_engaged = false;
|
||||||
return; // A fault scenario latches the contactor control. It is not possible to recover without a powercycle (and investigation why fault occured)
|
return; // A fault scenario latches the contactor control. It is not possible to recover without a powercycle (and investigation why fault occured)
|
||||||
}
|
}
|
||||||
|
|
||||||
// After that, check if we are OK to start turning on the battery
|
// After that, check if we are OK to start turning on the battery
|
||||||
if (contactorStatus == DISCONNECTED) {
|
if (contactorStatus == DISCONNECTED) {
|
||||||
set(PRECHARGE_PIN, OFF);
|
set(PRECHARGE_PIN, OFF);
|
||||||
set(NEGATIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
set(NEGATIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
||||||
set(POSITIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
set(POSITIVE_CONTACTOR_PIN, OFF, PWM_OFF_DUTY);
|
||||||
datalayer.system.status.contactors_engaged = false;
|
datalayer.system.status.contactors_engaged = false;
|
||||||
|
|
||||||
if (datalayer.system.status.battery_allows_contactor_closing &&
|
if (datalayer.system.status.battery_allows_contactor_closing &&
|
||||||
datalayer.system.status.inverter_allows_contactor_closing && !datalayer.system.settings.equipment_stop_active) {
|
datalayer.system.status.inverter_allows_contactor_closing &&
|
||||||
contactorStatus = START_PRECHARGE;
|
!datalayer.system.settings.equipment_stop_active) {
|
||||||
|
contactorStatus = START_PRECHARGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case the inverter requests contactors to open, set the state accordingly
|
||||||
|
if (contactorStatus == COMPLETED) {
|
||||||
|
//Incase inverter (or estop) requests contactors to open, make state machine jump to Disconnected state (recoverable)
|
||||||
|
if (!datalayer.system.status.inverter_allows_contactor_closing ||
|
||||||
|
datalayer.system.settings.equipment_stop_active) {
|
||||||
|
contactorStatus = DISCONNECTED;
|
||||||
|
}
|
||||||
|
// Skip running the state machine below if it has already completed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTime = millis();
|
||||||
|
|
||||||
|
if (currentTime < INTERVAL_10_S) {
|
||||||
|
// Skip running the state machine before system has started up.
|
||||||
|
// Gives the system some time to detect any faults from battery before blindly just engaging the contactors
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle actual state machine. This first turns on Negative, then Precharge, then Positive, and finally turns OFF precharge
|
||||||
|
switch (contactorStatus) {
|
||||||
|
case START_PRECHARGE:
|
||||||
|
set(NEGATIVE_CONTACTOR_PIN, ON, PWM_ON_DUTY);
|
||||||
|
dbg_contactors("NEGATIVE");
|
||||||
|
prechargeStartTime = currentTime;
|
||||||
|
contactorStatus = PRECHARGE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRECHARGE:
|
||||||
|
if (currentTime - prechargeStartTime >= NEGATIVE_CONTACTOR_TIME_MS) {
|
||||||
|
set(PRECHARGE_PIN, ON);
|
||||||
|
dbg_contactors("PRECHARGE");
|
||||||
|
negativeStartTime = currentTime;
|
||||||
|
contactorStatus = POSITIVE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case POSITIVE:
|
||||||
|
if (currentTime - negativeStartTime >= PRECHARGE_TIME_MS) {
|
||||||
|
set(POSITIVE_CONTACTOR_PIN, ON, PWM_ON_DUTY);
|
||||||
|
dbg_contactors("POSITIVE");
|
||||||
|
prechargeCompletedTime = currentTime;
|
||||||
|
contactorStatus = PRECHARGE_OFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRECHARGE_OFF:
|
||||||
|
if (currentTime - prechargeCompletedTime >= PRECHARGE_COMPLETED_TIME_MS) {
|
||||||
|
set(PRECHARGE_PIN, OFF);
|
||||||
|
set(NEGATIVE_CONTACTOR_PIN, ON, PWM_HOLD_DUTY);
|
||||||
|
set(POSITIVE_CONTACTOR_PIN, ON, PWM_HOLD_DUTY);
|
||||||
|
dbg_contactors("PRECHARGE_OFF");
|
||||||
|
contactorStatus = COMPLETED;
|
||||||
|
datalayer.system.status.contactors_engaged = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case the inverter requests contactors to open, set the state accordingly
|
|
||||||
if (contactorStatus == COMPLETED) {
|
|
||||||
//Incase inverter (or estop) requests contactors to open, make state machine jump to Disconnected state (recoverable)
|
|
||||||
if (!datalayer.system.status.inverter_allows_contactor_closing || datalayer.system.settings.equipment_stop_active) {
|
|
||||||
contactorStatus = DISCONNECTED;
|
|
||||||
}
|
|
||||||
// Skip running the state machine below if it has already completed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentTime = millis();
|
|
||||||
|
|
||||||
if (currentTime < INTERVAL_10_S) {
|
|
||||||
// Skip running the state machine before system has started up.
|
|
||||||
// Gives the system some time to detect any faults from battery before blindly just engaging the contactors
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle actual state machine. This first turns on Negative, then Precharge, then Positive, and finally turns OFF precharge
|
|
||||||
switch (contactorStatus) {
|
|
||||||
case START_PRECHARGE:
|
|
||||||
set(NEGATIVE_CONTACTOR_PIN, ON, PWM_ON_DUTY);
|
|
||||||
dbg_contactors("NEGATIVE");
|
|
||||||
prechargeStartTime = currentTime;
|
|
||||||
contactorStatus = PRECHARGE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PRECHARGE:
|
|
||||||
if (currentTime - prechargeStartTime >= NEGATIVE_CONTACTOR_TIME_MS) {
|
|
||||||
set(PRECHARGE_PIN, ON);
|
|
||||||
dbg_contactors("PRECHARGE");
|
|
||||||
negativeStartTime = currentTime;
|
|
||||||
contactorStatus = POSITIVE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case POSITIVE:
|
|
||||||
if (currentTime - negativeStartTime >= PRECHARGE_TIME_MS) {
|
|
||||||
set(POSITIVE_CONTACTOR_PIN, ON, PWM_ON_DUTY);
|
|
||||||
dbg_contactors("POSITIVE");
|
|
||||||
prechargeCompletedTime = currentTime;
|
|
||||||
contactorStatus = PRECHARGE_OFF;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PRECHARGE_OFF:
|
|
||||||
if (currentTime - prechargeCompletedTime >= PRECHARGE_COMPLETED_TIME_MS) {
|
|
||||||
set(PRECHARGE_PIN, OFF);
|
|
||||||
set(NEGATIVE_CONTACTOR_PIN, ON, PWM_HOLD_DUTY);
|
|
||||||
set(POSITIVE_CONTACTOR_PIN, ON, PWM_HOLD_DUTY);
|
|
||||||
dbg_contactors("PRECHARGE_OFF");
|
|
||||||
contactorStatus = COMPLETED;
|
|
||||||
datalayer.system.status.contactors_engaged = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif // CONTACTOR_CONTROL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
||||||
|
@ -235,7 +262,7 @@ void handle_contactors_battery2() {
|
||||||
datalayer.system.status.contactors_battery2_engaged = false;
|
datalayer.system.status.contactors_battery2_engaged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // CONTACTOR_CONTROL_DOUBLE_BATTERY
|
#endif
|
||||||
|
|
||||||
/* PERIODIC_BMS_RESET - Once every 24 hours we remove power from the BMS_power pin for 30 seconds.
|
/* PERIODIC_BMS_RESET - Once every 24 hours we remove power from the BMS_power pin for 30 seconds.
|
||||||
REMOTE_BMS_RESET - Allows the user to remotely powercycle the BMS by sending a command to the emulator via MQTT.
|
REMOTE_BMS_RESET - Allows the user to remotely powercycle the BMS by sending a command to the emulator via MQTT.
|
||||||
|
@ -245,57 +272,57 @@ During that time we also set the emulator state to paused in order to not try an
|
||||||
Feature is only used if user has enabled PERIODIC_BMS_RESET in the USER_SETTINGS */
|
Feature is only used if user has enabled PERIODIC_BMS_RESET in the USER_SETTINGS */
|
||||||
|
|
||||||
void handle_BMSpower() {
|
void handle_BMSpower() {
|
||||||
#if defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
if (periodic_bms_reset || remote_bms_reset) {
|
||||||
// Get current time
|
// Get current time
|
||||||
currentTime = millis();
|
currentTime = millis();
|
||||||
|
|
||||||
#ifdef PERIODIC_BMS_RESET
|
if (periodic_bms_reset) {
|
||||||
// Check if 24 hours have passed since the last power removal
|
// Check if 24 hours have passed since the last power removal
|
||||||
if ((currentTime + bmsResetTimeOffset) - lastPowerRemovalTime >= powerRemovalInterval) {
|
if ((currentTime + bmsResetTimeOffset) - lastPowerRemovalTime >= powerRemovalInterval) {
|
||||||
start_bms_reset();
|
start_bms_reset();
|
||||||
}
|
}
|
||||||
#endif //PERIODIC_BMS_RESET
|
}
|
||||||
|
|
||||||
// If power has been removed for 30 seconds, restore the power
|
// If power has been removed for 30 seconds, restore the power
|
||||||
if (datalayer.system.status.BMS_reset_in_progress && currentTime - lastPowerRemovalTime >= powerRemovalDuration) {
|
if (datalayer.system.status.BMS_reset_in_progress && currentTime - lastPowerRemovalTime >= powerRemovalDuration) {
|
||||||
// Reapply power to the BMS
|
// Reapply power to the BMS
|
||||||
digitalWrite(BMS_POWER, HIGH);
|
digitalWrite(BMS_POWER, HIGH);
|
||||||
#ifdef BMS_2_POWER
|
#ifdef BMS_2_POWER
|
||||||
digitalWrite(BMS_2_POWER, HIGH); // Same for battery 2
|
digitalWrite(BMS_2_POWER, HIGH); // Same for battery 2
|
||||||
#endif
|
#endif
|
||||||
bmsPowerOnTime = currentTime;
|
bmsPowerOnTime = currentTime;
|
||||||
datalayer.system.status.BMS_reset_in_progress = false; // Reset the power removal flag
|
datalayer.system.status.BMS_reset_in_progress = false; // Reset the power removal flag
|
||||||
datalayer.system.status.BMS_startup_in_progress = true; // Set the BMS warmup flag
|
datalayer.system.status.BMS_startup_in_progress = true; // Set the BMS warmup flag
|
||||||
}
|
}
|
||||||
//if power has been restored we need to wait a couple of seconds to unpause the battery
|
//if power has been restored we need to wait a couple of seconds to unpause the battery
|
||||||
if (datalayer.system.status.BMS_startup_in_progress && currentTime - bmsPowerOnTime >= bmsWarmupDuration) {
|
if (datalayer.system.status.BMS_startup_in_progress && currentTime - bmsPowerOnTime >= bmsWarmupDuration) {
|
||||||
|
|
||||||
setBatteryPause(false, false, false, false);
|
setBatteryPause(false, false, false, false);
|
||||||
|
|
||||||
datalayer.system.status.BMS_startup_in_progress = false; // Reset the BMS warmup removal flag
|
datalayer.system.status.BMS_startup_in_progress = false; // Reset the BMS warmup removal flag
|
||||||
set_event(EVENT_PERIODIC_BMS_RESET, 0);
|
set_event(EVENT_PERIODIC_BMS_RESET, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_bms_reset() {
|
void start_bms_reset() {
|
||||||
#if defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
if (periodic_bms_reset || remote_bms_reset) {
|
||||||
if (!datalayer.system.status.BMS_reset_in_progress) {
|
if (!datalayer.system.status.BMS_reset_in_progress) {
|
||||||
lastPowerRemovalTime = currentTime; // Record the time when BMS reset was started
|
lastPowerRemovalTime = currentTime; // Record the time when BMS reset was started
|
||||||
// we are now resetting at the correct time. We don't need to offset anymore
|
// we are now resetting at the correct time. We don't need to offset anymore
|
||||||
bmsResetTimeOffset = 0;
|
bmsResetTimeOffset = 0;
|
||||||
// Set a flag to let the rest of the system know we are cutting power to the BMS.
|
// Set a flag to let the rest of the system know we are cutting power to the BMS.
|
||||||
// The battery CAN sending routine will then know not to try guto send anything towards battery while active
|
// The battery CAN sending routine will then know not to try guto send anything towards battery while active
|
||||||
datalayer.system.status.BMS_reset_in_progress = true;
|
datalayer.system.status.BMS_reset_in_progress = true;
|
||||||
|
|
||||||
// Set emulator state to paused (Max Charge/Discharge = 0 & CAN = stop)
|
// Set emulator state to paused (Max Charge/Discharge = 0 & CAN = stop)
|
||||||
// We try to keep contactors engaged during this pause, and just ramp power down to 0.
|
// We try to keep contactors engaged during this pause, and just ramp power down to 0.
|
||||||
setBatteryPause(true, false, false, false);
|
setBatteryPause(true, false, false, false);
|
||||||
|
|
||||||
digitalWrite(BMS_POWER, LOW); // Remove power by setting the BMS power pin to LOW
|
digitalWrite(BMS_POWER, LOW); // Remove power by setting the BMS power pin to LOW
|
||||||
#ifdef BMS_2_POWER
|
#ifdef BMS_2_POWER
|
||||||
digitalWrite(BMS_2_POWER, LOW); // Same for battery 2
|
digitalWrite(BMS_2_POWER, LOW); // Same for battery 2
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
#include "../../datalayer/datalayer.h"
|
#include "../../datalayer/datalayer.h"
|
||||||
#include "../../devboard/utils/events.h"
|
#include "../../devboard/utils/events.h"
|
||||||
|
|
||||||
|
// Settings that can be changed at run-time
|
||||||
|
extern bool contactor_control_enabled;
|
||||||
|
extern bool pwm_contactor_control;
|
||||||
|
extern bool periodic_bms_reset;
|
||||||
|
extern bool remote_bms_reset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle BMS power output
|
* @brief Handle BMS power output
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
#include "comm_nvm.h"
|
#include "comm_nvm.h"
|
||||||
#include "../../include.h"
|
#include "../../include.h"
|
||||||
|
#include "../contactorcontrol/comm_contactorcontrol.h"
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
Preferences settings; // Store user settings
|
Preferences settings; // Store user settings
|
||||||
|
|
||||||
// Initialization functions
|
// Initialization functions
|
||||||
|
|
||||||
|
static void begin() {
|
||||||
|
settings.begin("batterySettings", false);
|
||||||
|
}
|
||||||
|
|
||||||
void init_stored_settings() {
|
void init_stored_settings() {
|
||||||
static uint32_t temp = 0;
|
static uint32_t temp = 0;
|
||||||
// ATTENTION ! The maximum length for settings keys is 15 characters
|
// ATTENTION ! The maximum length for settings keys is 15 characters
|
||||||
settings.begin("batterySettings", false);
|
begin();
|
||||||
|
|
||||||
// Always get the equipment stop status
|
// Always get the equipment stop status
|
||||||
datalayer.system.settings.equipment_stop_active = settings.getBool("EQUIPMENT_STOP", false);
|
datalayer.system.settings.equipment_stop_active = settings.getBool("EQUIPMENT_STOP", false);
|
||||||
|
@ -69,6 +74,18 @@ void init_stored_settings() {
|
||||||
datalayer.battery.settings.max_user_set_discharge_voltage_dV = temp;
|
datalayer.battery.settings.max_user_set_discharge_voltage_dV = temp;
|
||||||
}
|
}
|
||||||
datalayer.battery.settings.user_set_voltage_limits_active = settings.getBool("USEVOLTLIMITS", false);
|
datalayer.battery.settings.user_set_voltage_limits_active = settings.getBool("USEVOLTLIMITS", false);
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
user_selected_battery_type = (BatteryType)settings.getUInt("BATTTYPE", (int)BatteryType::None);
|
||||||
|
user_selected_inverter_protocol = (InverterProtocolType)settings.getUInt("INVTYPE", (int)InverterProtocolType::None);
|
||||||
|
user_selected_charger_type = (ChargerType)settings.getUInt("CHGTYPE", (int)ChargerType::None);
|
||||||
|
user_selected_second_battery = settings.getBool("DBLBTR", false);
|
||||||
|
contactor_control_enabled = settings.getBool("CNTCTRL", false);
|
||||||
|
pwm_contactor_control = settings.getBool("PWMCNTCTRL", false);
|
||||||
|
periodic_bms_reset = settings.getBool("PERBMSRESET", false);
|
||||||
|
remote_bms_reset = settings.getBool("REMBMSRESET", false);
|
||||||
|
#endif
|
||||||
|
|
||||||
settings.end();
|
settings.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,5 +138,26 @@ void store_settings() {
|
||||||
if (!settings.putUInt("TARGETDISCHVOLT", datalayer.battery.settings.max_user_set_discharge_voltage_dV)) {
|
if (!settings.putUInt("TARGETDISCHVOLT", datalayer.battery.settings.max_user_set_discharge_voltage_dV)) {
|
||||||
set_event(EVENT_PERSISTENT_SAVE_INFO, 11);
|
set_event(EVENT_PERSISTENT_SAVE_INFO, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.end(); // Close preferences handle
|
settings.end(); // Close preferences handle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void store_uint(const char* key, uint32_t value) {
|
||||||
|
begin();
|
||||||
|
settings.putUInt(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_bool(const char* key, bool value) {
|
||||||
|
begin();
|
||||||
|
settings.putBool(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_uint(const char* key, uint32_t defaultValue) {
|
||||||
|
begin();
|
||||||
|
return settings.getUInt(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_bool(const char* key) {
|
||||||
|
begin();
|
||||||
|
return settings.getBool(key, false);
|
||||||
|
}
|
||||||
|
|
|
@ -34,4 +34,24 @@ void store_settings_equipment_stop();
|
||||||
*/
|
*/
|
||||||
void store_settings();
|
void store_settings();
|
||||||
|
|
||||||
|
class BatteryEmulatorSettingsStore {
|
||||||
|
public:
|
||||||
|
BatteryEmulatorSettingsStore() { settings.begin("batterySettings", false); }
|
||||||
|
|
||||||
|
~BatteryEmulatorSettingsStore() { settings.end(); }
|
||||||
|
|
||||||
|
BatteryType get_batterytype() { return (BatteryType)settings.getUInt("BATTTYPE", (int)BatteryType::None); }
|
||||||
|
|
||||||
|
void set_batterytype(BatteryType type) { settings.putUInt("BATTTYPE", (int)type); }
|
||||||
|
|
||||||
|
InverterProtocolType get_invertertype() {
|
||||||
|
return (InverterProtocolType)settings.getUInt("INVTYPE", (int)InverterProtocolType::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_invertertype(InverterProtocolType type) { settings.putUInt("INVTYPE", (int)type); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Preferences settings;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -320,17 +320,14 @@ typedef struct {
|
||||||
bool BMS_reset_in_progress = false;
|
bool BMS_reset_in_progress = false;
|
||||||
/** True if the BMS is starting up */
|
/** True if the BMS is starting up */
|
||||||
bool BMS_startup_in_progress = false;
|
bool BMS_startup_in_progress = false;
|
||||||
#ifdef PRECHARGE_CONTROL
|
|
||||||
/** State of automatic precharge sequence */
|
/** State of automatic precharge sequence */
|
||||||
PrechargeState precharge_status = AUTO_PRECHARGE_IDLE;
|
PrechargeState precharge_status = AUTO_PRECHARGE_IDLE;
|
||||||
#endif
|
|
||||||
} DATALAYER_SYSTEM_STATUS_TYPE;
|
} DATALAYER_SYSTEM_STATUS_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool equipment_stop_active = false;
|
bool equipment_stop_active = false;
|
||||||
#ifdef PRECHARGE_CONTROL
|
|
||||||
bool start_precharging = false;
|
bool start_precharging = false;
|
||||||
#endif
|
|
||||||
} DATALAYER_SYSTEM_SETTINGS_TYPE;
|
} DATALAYER_SYSTEM_SETTINGS_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -156,7 +156,7 @@ void update_machineryprotection() {
|
||||||
clear_event(EVENT_SOH_LOW);
|
clear_event(EVENT_SOH_LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!battery->soc_plausible()) {
|
if (battery && !battery->soc_plausible()) {
|
||||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, datalayer.battery.status.real_soc);
|
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, datalayer.battery.status.real_soc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,77 @@
|
||||||
#include "settings_html.h"
|
#include "settings_html.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "../../../src/communication/contactorcontrol/comm_contactorcontrol.h"
|
||||||
#include "../../charger/CHARGERS.h"
|
#include "../../charger/CHARGERS.h"
|
||||||
|
#include "../../communication/nvm/comm_nvm.h"
|
||||||
#include "../../datalayer/datalayer.h"
|
#include "../../datalayer/datalayer.h"
|
||||||
#include "../../include.h"
|
#include "../../include.h"
|
||||||
|
|
||||||
|
extern bool settingsUpdated;
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
String battery_options(BatteryType selected) {
|
||||||
|
String options;
|
||||||
|
|
||||||
|
auto batteries = supported_battery_types();
|
||||||
|
for (BatteryType type : batteries) {
|
||||||
|
auto name = name_for_type(type);
|
||||||
|
if (name != nullptr) {
|
||||||
|
options +=
|
||||||
|
("<option value=\"" + String(static_cast<int>(type)) + "\"" + (selected == type ? " selected" : "") + ">");
|
||||||
|
options += name;
|
||||||
|
options += "</option>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
String inverter_options(InverterProtocolType selected) {
|
||||||
|
String options;
|
||||||
|
|
||||||
|
auto inverters = supported_inverter_protocols();
|
||||||
|
|
||||||
|
for (InverterProtocolType type : inverters) {
|
||||||
|
auto name = name_for_type(type);
|
||||||
|
if (name != nullptr) {
|
||||||
|
options +=
|
||||||
|
("<option value=\"" + String(static_cast<int>(type)) + "\"" + (selected == type ? "selected" : "") + ">");
|
||||||
|
options += name;
|
||||||
|
options += "</option>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
String charger_options(ChargerType selected) {
|
||||||
|
String options;
|
||||||
|
|
||||||
|
auto chargers = supported_charger_types();
|
||||||
|
|
||||||
|
for (ChargerType type : chargers) {
|
||||||
|
auto name = name_for_type(type);
|
||||||
|
if (name != nullptr) {
|
||||||
|
options +=
|
||||||
|
("<option value=\"" + String(static_cast<int>(type)) + "\"" + (selected == type ? "selected" : "") + ">");
|
||||||
|
options += name;
|
||||||
|
options += "</option>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void render_checkbox(String& content, const char* label, bool enabled, const char* name) {
|
||||||
|
content += "<label>" + String(label) + "</label>";
|
||||||
|
content += "<input id='" + String(name) + "' name='" + String(name) +
|
||||||
|
"' type='checkbox' "
|
||||||
|
"style=\"margin-left: 0;\"";
|
||||||
|
content += (enabled ? " checked" : "");
|
||||||
|
content += " value='on'/>";
|
||||||
|
}
|
||||||
|
|
||||||
String settings_processor(const String& var) {
|
String settings_processor(const String& var) {
|
||||||
if (var == "X") {
|
if (var == "X") {
|
||||||
String content = "";
|
String content = "";
|
||||||
|
@ -27,11 +95,59 @@ String settings_processor(const String& var) {
|
||||||
"<h4 style='color: white;'>Password: ######## <span id='Password'></span> <button "
|
"<h4 style='color: white;'>Password: ######## <span id='Password'></span> <button "
|
||||||
"onclick='editPassword()'>Edit</button></h4>";
|
"onclick='editPassword()'>Edit</button></h4>";
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
BatteryEmulatorSettingsStore settings;
|
||||||
|
|
||||||
|
// It's important that we read/write settings directly to settings store instead of the run-time values
|
||||||
|
// since the run-time values may have direct effect on operation.
|
||||||
content +=
|
content +=
|
||||||
"<h4 style='color: white;'>Battery interface: <span id='Battery'>" + battery->interface_name() + "</span></h4>";
|
"<div style='background-color: #404E47; padding: 10px; margin-bottom: 10px;border-radius: 50px;'><div "
|
||||||
|
"style='max-width: 500px;'>";
|
||||||
|
content +=
|
||||||
|
"<form action='saveSettings' method='post' style='display: grid; grid-template-columns: 1fr 2fr; gap: 10px; "
|
||||||
|
"align-items: center;'>";
|
||||||
|
content += "<label>Battery: </label><select style='max-width: 250px;' name='battery'>";
|
||||||
|
content += battery_options(settings.get_batterytype());
|
||||||
|
content += "</select>";
|
||||||
|
content += "<label>Inverter protocol: </label><select style='max-width: 250px;' name='inverter'>";
|
||||||
|
content += inverter_options(settings.get_invertertype());
|
||||||
|
content += "</select>";
|
||||||
|
content += "<label>Charger: </label><select style='max-width: 250px;' name='charger'>";
|
||||||
|
content += charger_options((ChargerType)("CHGTYPE", 0));
|
||||||
|
content += "</select>";
|
||||||
|
//content += "<label>Double battery:</label>";
|
||||||
|
|
||||||
|
// TODO: Generalize settings: define settings in one place and use the definitions to render
|
||||||
|
// UI and handle load/save
|
||||||
|
render_checkbox(content, "Double battery", settings.get_doublebattery(), "dblbtr");
|
||||||
|
render_checkbox(content, "Contactor control", get_bool("CNTCTRL"), "contctrl");
|
||||||
|
render_checkbox(content, "PWM contactor control", get_bool("PWMCNTCTRL"), "pwmcontctrl");
|
||||||
|
render_checkbox(content, "Periodic BMS reset", get_bool("PERBMSRESET"), "PERBMSRESET");
|
||||||
|
render_checkbox(content, "Remote BMS reset", get_bool("REMBMSRESET"), "REMBMSRESET");
|
||||||
|
|
||||||
|
/* content +=
|
||||||
|
"<div style=\"display: flex; justify-content: flex-start;\"><input id='dblbtr' name='dblbtr' type='checkbox' "
|
||||||
|
"style=\"margin-left: 0;\"";
|
||||||
|
content += (user_selected_second_battery ? " checked" : "");
|
||||||
|
content += " value='on'/></div>";*/
|
||||||
|
content +=
|
||||||
|
"<div style='grid-column: span 2; text-align: center; padding-top: 10px;'><button "
|
||||||
|
"type='submit'>Save</button></div>";
|
||||||
|
|
||||||
|
if (settingsUpdated) {
|
||||||
|
content += "<p>Settings saved. Reboot to take the settings into use.</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
content += "</form></div></div>";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (battery) {
|
||||||
|
content += "<h4 style='color: white;'>Battery interface: <span id='Battery'>" + battery->interface_name() +
|
||||||
|
"</span></h4>";
|
||||||
|
}
|
||||||
|
|
||||||
if (battery2) {
|
if (battery2) {
|
||||||
content += "<h4 style='color: white;'>Battery #2 interface: <span id='Battery'>" + battery->interface_name() +
|
content += "<h4 style='color: white;'>Battery #2 interface: <span id='Battery'>" + battery2->interface_name() +
|
||||||
"</span></h4>";
|
"</span></h4>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,14 +205,14 @@ String settings_processor(const String& var) {
|
||||||
// Close the block
|
// Close the block
|
||||||
content += "</div>";
|
content += "</div>";
|
||||||
|
|
||||||
if (battery->supports_set_fake_voltage()) {
|
if (battery && battery->supports_set_fake_voltage()) {
|
||||||
content += "<div style='background-color: #2E37AD; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
|
content += "<div style='background-color: #2E37AD; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
|
||||||
content += "<h4 style='color: white;'>Fake battery voltage: " + String(battery->get_voltage(), 1) +
|
content += "<h4 style='color: white;'>Fake battery voltage: " + String(battery->get_voltage(), 1) +
|
||||||
" V </span> <button onclick='editFakeBatteryVoltage()'>Edit</button></h4>";
|
" V </span> <button onclick='editFakeBatteryVoltage()'>Edit</button></h4>";
|
||||||
content += "</div>";
|
content += "</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (battery->supports_manual_balancing()) {
|
if (battery && battery->supports_manual_balancing()) {
|
||||||
// Start a new block with grey background color
|
// Start a new block with grey background color
|
||||||
content += "<div style='background-color: #303E47; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
|
content += "<div style='background-color: #303E47; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
|
||||||
|
|
||||||
|
@ -281,7 +397,7 @@ String settings_processor(const String& var) {
|
||||||
"BalMaxDevCellV?value='+value,true);xhr.send();}else{alert('Invalid value. Please enter a value "
|
"BalMaxDevCellV?value='+value,true);xhr.send();}else{alert('Invalid value. Please enter a value "
|
||||||
"between 300 and 600');}}}";
|
"between 300 and 600');}}}";
|
||||||
|
|
||||||
if (battery->supports_set_fake_voltage()) {
|
if (battery && battery->supports_set_fake_voltage()) {
|
||||||
content +=
|
content +=
|
||||||
"function editFakeBatteryVoltage(){var value=prompt('Enter new fake battery "
|
"function editFakeBatteryVoltage(){var value=prompt('Enter new fake battery "
|
||||||
"voltage');if(value!==null){if(value>=0&&value<=5000){var xhr=new "
|
"voltage');if(value!==null){if(value>=0&&value<=5000){var xhr=new "
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../../../USER_SECRETS.h"
|
#include "../../../USER_SECRETS.h"
|
||||||
#include "../../battery/BATTERIES.h"
|
#include "../../battery/BATTERIES.h"
|
||||||
#include "../../battery/Battery.h"
|
#include "../../battery/Battery.h"
|
||||||
|
#include "../../communication/nvm/comm_nvm.h"
|
||||||
#include "../../datalayer/datalayer.h"
|
#include "../../datalayer/datalayer.h"
|
||||||
#include "../../datalayer/datalayer_extended.h"
|
#include "../../datalayer/datalayer_extended.h"
|
||||||
#include "../../lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
#include "../../lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
||||||
|
@ -38,6 +39,9 @@ const char get_firmware_info_html[] = R"rawliteral(%X%)rawliteral";
|
||||||
String importedLogs = ""; // Store the uploaded logfile contents in RAM
|
String importedLogs = ""; // Store the uploaded logfile contents in RAM
|
||||||
bool isReplayRunning = false; // Global flag to track replay state
|
bool isReplayRunning = false; // Global flag to track replay state
|
||||||
|
|
||||||
|
// True when user has updated settings and a reboot is needed.
|
||||||
|
bool settingsUpdated = false;
|
||||||
|
|
||||||
CAN_frame currentFrame = {.FD = true, .ext_ID = false, .DLC = 64, .ID = 0x12F, .data = {0}};
|
CAN_frame currentFrame = {.FD = true, .ext_ID = false, .DLC = 64, .ID = 0x12F, .data = {0}};
|
||||||
|
|
||||||
void handleFileUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len,
|
void handleFileUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len,
|
||||||
|
@ -382,6 +386,41 @@ void init_webserver() {
|
||||||
request->send(200, "text/html", response);
|
request->send(200, "text/html", response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
// Handles the form POST from UI to save certain settings: battery/inverter type and double battery on/off
|
||||||
|
server.on("/saveSettings", HTTP_POST, [](AsyncWebServerRequest* request) {
|
||||||
|
int params = request->params();
|
||||||
|
// dblbtr not present in form content if not checked.
|
||||||
|
bool secondBattery = false;
|
||||||
|
for (int i = 0; i < params; i++) {
|
||||||
|
auto p = request->getParam(i);
|
||||||
|
if (p->name() == "inverter") {
|
||||||
|
auto type = static_cast<InverterProtocolType>(atoi(p->value().c_str()));
|
||||||
|
store_uint("INVTYPE", (int)type);
|
||||||
|
} else if (p->name() == "battery") {
|
||||||
|
auto type = static_cast<BatteryType>(atoi(p->value().c_str()));
|
||||||
|
store_uint("BATTTYPE", (int)type);
|
||||||
|
} else if (p->name() == "charger") {
|
||||||
|
auto type = static_cast<ChargerType>(atoi(p->value().c_str()));
|
||||||
|
store_uint("CHGTYPE", (int)type);
|
||||||
|
} else if (p->name() == "dblbtr") {
|
||||||
|
store_bool("DBLBTR", p->value() == "on");
|
||||||
|
} else if (p->name() == "contctrl") {
|
||||||
|
store_bool("CNTCTRL", p->value() == "on");
|
||||||
|
} else if (p->name() == "pwmcontctrl") {
|
||||||
|
store_bool("PWMCNTCTRL", p->value() == "on");
|
||||||
|
} else if (p->name() == "PERBMSRESET") {
|
||||||
|
store_bool("PERBMSRESET", p->value() == "on");
|
||||||
|
} else if (p->name() == "REMBMSRESET") {
|
||||||
|
store_bool("REMBMSRESET", p->value() == "on");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsUpdated = true;
|
||||||
|
request->redirect("/settings");
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
// Route for editing SSID
|
// Route for editing SSID
|
||||||
server.on("/updateSSID", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/updateSSID", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
||||||
|
@ -945,20 +984,25 @@ String processor(const String& var) {
|
||||||
content += "<div style='background-color: #333; padding: 10px; margin-bottom: 10px; border-radius: 50px'>";
|
content += "<div style='background-color: #333; padding: 10px; margin-bottom: 10px; border-radius: 50px'>";
|
||||||
|
|
||||||
// Display which components are used
|
// Display which components are used
|
||||||
content += "<h4 style='color: white;'>Inverter protocol: ";
|
if (inverter) {
|
||||||
content += datalayer.system.info.inverter_protocol;
|
content += "<h4 style='color: white;'>Inverter protocol: ";
|
||||||
content += " ";
|
content += datalayer.system.info.inverter_protocol;
|
||||||
content += datalayer.system.info.inverter_brand;
|
content += " ";
|
||||||
content += "</h4>";
|
content += datalayer.system.info.inverter_brand;
|
||||||
content += "<h4 style='color: white;'>Battery protocol: ";
|
content += "</h4>";
|
||||||
content += datalayer.system.info.battery_protocol;
|
|
||||||
if (battery2) {
|
|
||||||
content += " (Double battery)";
|
|
||||||
}
|
}
|
||||||
if (datalayer.battery.info.chemistry == battery_chemistry_enum::LFP) {
|
|
||||||
content += " (LFP)";
|
if (battery) {
|
||||||
|
content += "<h4 style='color: white;'>Battery protocol: ";
|
||||||
|
content += datalayer.system.info.battery_protocol;
|
||||||
|
if (battery2) {
|
||||||
|
content += " (Double battery)";
|
||||||
|
}
|
||||||
|
if (datalayer.battery.info.chemistry == battery_chemistry_enum::LFP) {
|
||||||
|
content += " (LFP)";
|
||||||
|
}
|
||||||
|
content += "</h4>";
|
||||||
}
|
}
|
||||||
content += "</h4>";
|
|
||||||
|
|
||||||
if (shunt) {
|
if (shunt) {
|
||||||
content += "<h4 style='color: white;'>Shunt protocol: ";
|
content += "<h4 style='color: white;'>Shunt protocol: ";
|
||||||
|
@ -1106,7 +1150,7 @@ String processor(const String& var) {
|
||||||
}
|
}
|
||||||
content += "</h4>";
|
content += "</h4>";
|
||||||
|
|
||||||
if (battery->supports_real_BMS_status()) {
|
if (battery && battery->supports_real_BMS_status()) {
|
||||||
content += "<h4>Battery BMS status: ";
|
content += "<h4>Battery BMS status: ";
|
||||||
switch (datalayer.battery.status.real_bms_status) {
|
switch (datalayer.battery.status.real_bms_status) {
|
||||||
case BMS_ACTIVE:
|
case BMS_ACTIVE:
|
||||||
|
|
|
@ -171,6 +171,6 @@ void BydCanInverter::send_initial_data() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BydCanInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
void BydCanInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
||||||
strncpy(datalayer.system.info.inverter_protocol, "BYD Battery-Box Premium HVS over CAN Bus", 63);
|
strncpy(datalayer.system.info.inverter_protocol, Name, 63);
|
||||||
datalayer.system.info.inverter_protocol[63] = '\0';
|
datalayer.system.info.inverter_protocol[63] = '\0';
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class BydCanInverter : public CanInverterProtocol {
|
||||||
void transmit_can(unsigned long currentMillis);
|
void transmit_can(unsigned long currentMillis);
|
||||||
void map_can_frame_to_variable(CAN_frame rx_frame);
|
void map_can_frame_to_variable(CAN_frame rx_frame);
|
||||||
void update_values();
|
void update_values();
|
||||||
|
static constexpr char* Name = "BYD Battery-Box Premium HVS over CAN Bus";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void send_initial_data();
|
void send_initial_data();
|
||||||
|
|
|
@ -146,7 +146,7 @@ void BydModbusInverter::verify_inverter_modbus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BydModbusInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
void BydModbusInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
||||||
strncpy(datalayer.system.info.inverter_protocol, "BYD 11kWh HVM battery over Modbus RTU", 63);
|
strncpy(datalayer.system.info.inverter_protocol, Name, 63);
|
||||||
datalayer.system.info.inverter_protocol[63] = '\0';
|
datalayer.system.info.inverter_protocol[63] = '\0';
|
||||||
|
|
||||||
// Init Static data to the RTU Modbus
|
// Init Static data to the RTU Modbus
|
||||||
|
|
|
@ -12,6 +12,7 @@ class BydModbusInverter : public ModbusInverterProtocol {
|
||||||
public:
|
public:
|
||||||
void setup();
|
void setup();
|
||||||
void update_values();
|
void update_values();
|
||||||
|
static constexpr char* Name = "BYD 11kWh HVM battery over Modbus RTU";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_static_data();
|
void handle_static_data();
|
||||||
|
|
|
@ -367,6 +367,6 @@ void FerroampCanInverter::send_system_data() { //System equipment information
|
||||||
}
|
}
|
||||||
|
|
||||||
void FerroampCanInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
void FerroampCanInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
||||||
strncpy(datalayer.system.info.inverter_protocol, "Ferroamp Pylon battery over CAN bus", 63);
|
strncpy(datalayer.system.info.inverter_protocol, Name, 63);
|
||||||
datalayer.system.info.inverter_protocol[63] = '\0';
|
datalayer.system.info.inverter_protocol[63] = '\0';
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ class FerroampCanInverter : public CanInverterProtocol {
|
||||||
void transmit_can(unsigned long currentMillis);
|
void transmit_can(unsigned long currentMillis);
|
||||||
void map_can_frame_to_variable(CAN_frame rx_frame);
|
void map_can_frame_to_variable(CAN_frame rx_frame);
|
||||||
|
|
||||||
|
static constexpr char* Name = "Ferroamp Pylon battery over CAN bus";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void send_system_data();
|
void send_system_data();
|
||||||
void send_setup_info();
|
void send_setup_info();
|
||||||
|
|
|
@ -2,6 +2,65 @@
|
||||||
|
|
||||||
InverterProtocol* inverter = nullptr;
|
InverterProtocol* inverter = nullptr;
|
||||||
|
|
||||||
|
InverterProtocolType user_selected_inverter_protocol = InverterProtocolType::BydModbus;
|
||||||
|
|
||||||
|
std::vector<InverterProtocolType> supported_inverter_protocols() {
|
||||||
|
std::vector<InverterProtocolType> types;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)InverterProtocolType::Highest; i++) {
|
||||||
|
types.push_back((InverterProtocolType)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char* name_for_type(InverterProtocolType type) {
|
||||||
|
switch (type) {
|
||||||
|
case InverterProtocolType::BydCan:
|
||||||
|
return BydCanInverter::Name;
|
||||||
|
break;
|
||||||
|
case InverterProtocolType::BydModbus:
|
||||||
|
return BydModbusInverter::Name;
|
||||||
|
break;
|
||||||
|
case InverterProtocolType::FerroampCan:
|
||||||
|
return FerroampCanInverter::Name;
|
||||||
|
break;
|
||||||
|
case InverterProtocolType::None:
|
||||||
|
return "None";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
#ifdef SELECTED_INVERTER_CLASS
|
||||||
|
#error "Compile time SELECTED_INVERTER_CLASS should not be defined with COMMON_IMAGE"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setup_inverter() {
|
||||||
|
if (inverter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (user_selected_inverter_protocol) {
|
||||||
|
case InverterProtocolType::BydCan:
|
||||||
|
inverter = new BydCanInverter();
|
||||||
|
break;
|
||||||
|
case InverterProtocolType::BydModbus:
|
||||||
|
inverter = new BydModbusInverter();
|
||||||
|
break;
|
||||||
|
case InverterProtocolType::FerroampCan:
|
||||||
|
inverter = new FerroampCanInverter();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inverter) {
|
||||||
|
inverter->setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
void setup_inverter() {
|
void setup_inverter() {
|
||||||
if (inverter) {
|
if (inverter) {
|
||||||
// The inverter is setup only once.
|
// The inverter is setup only once.
|
||||||
|
@ -16,3 +75,4 @@ void setup_inverter() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
#ifndef INVERTER_PROTOCOL_H
|
#ifndef INVERTER_PROTOCOL_H
|
||||||
#define INVERTER_PROTOCOL_H
|
#define INVERTER_PROTOCOL_H
|
||||||
|
|
||||||
|
enum class InverterProtocolType { None = 0, BydCan, BydModbus, FerroampCan, Highest };
|
||||||
|
|
||||||
|
extern InverterProtocolType user_selected_inverter_protocol;
|
||||||
|
|
||||||
|
extern std::vector<InverterProtocolType> supported_inverter_protocols();
|
||||||
|
extern const char* name_for_type(InverterProtocolType type);
|
||||||
|
|
||||||
enum class InverterInterfaceType { Can, Rs485, Modbus };
|
enum class InverterInterfaceType { Can, Rs485, Modbus };
|
||||||
|
|
||||||
// The abstract base class for all inverter protocols
|
// The abstract base class for all inverter protocols
|
||||||
|
@ -14,4 +21,6 @@ class InverterProtocol {
|
||||||
virtual void update_values() = 0;
|
virtual void update_values() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern InverterProtocol* inverter;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue