mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
merge
This commit is contained in:
commit
3d5f03823f
150 changed files with 8282 additions and 4683 deletions
11
.github/workflows/compile-all-batteries.yml
vendored
11
.github/workflows/compile-all-batteries.yml
vendored
|
@ -70,6 +70,7 @@ jobs:
|
|||
- RENAULT_ZOE_GEN1_BATTERY
|
||||
- RENAULT_ZOE_GEN2_BATTERY
|
||||
- SANTA_FE_PHEV_BATTERY
|
||||
- STELLANTIS_ECMP_BATTERY
|
||||
- TESLA_MODEL_3Y_BATTERY
|
||||
- TESLA_MODEL_SX_BATTERY
|
||||
- VOLVO_SPA_BATTERY
|
||||
|
@ -78,6 +79,10 @@ jobs:
|
|||
# These are the emulated inverter communication protocols for which the code will be compiled.
|
||||
inverter:
|
||||
- BYD_CAN
|
||||
# These are the supported hardware platforms for which the code will be compiled.
|
||||
hardware:
|
||||
- HW_LILYGO
|
||||
|
||||
# This is the platform GitHub will use to run our workflow.
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
@ -87,6 +92,10 @@ jobs:
|
|||
- 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
|
||||
|
@ -102,4 +111,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
|
@ -72,17 +72,20 @@ jobs:
|
|||
- BYD_CAN
|
||||
- BYD_KOSTAL_RS485
|
||||
- BYD_MODBUS
|
||||
- BYD_SMA
|
||||
- FOXESS_CAN
|
||||
- PYLON_CAN
|
||||
- PYLON_LV_CAN
|
||||
- SCHNEIDER_CAN
|
||||
- SMA_CAN
|
||||
- SMA_BYD_H_CAN
|
||||
- SMA_BYD_HVS_CAN
|
||||
- SMA_LV_CAN
|
||||
- SMA_TRIPOWER_CAN
|
||||
- SOFAR_CAN
|
||||
- SOLAX_CAN
|
||||
- SERIAL_LINK_TRANSMITTER
|
||||
# These are the supported hardware platforms for which the code will be compiled.
|
||||
hardware:
|
||||
- HW_LILYGO
|
||||
|
||||
# This is the platform GitHub will use to run our workflow.
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -93,6 +96,10 @@ jobs:
|
|||
- 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
|
||||
|
@ -108,4 +115,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
|
@ -63,6 +63,7 @@ jobs:
|
|||
- RENAULT_ZOE_GEN1_BATTERY
|
||||
- RENAULT_ZOE_GEN2_BATTERY
|
||||
- SANTA_FE_PHEV_BATTERY
|
||||
- STELLANTIS_ECMP_BATTERY
|
||||
- TESLA_MODEL_3Y_BATTERY
|
||||
- TESLA_MODEL_SX_BATTERY
|
||||
- VOLVO_SPA_BATTERY
|
||||
|
@ -73,17 +74,20 @@ jobs:
|
|||
- BYD_CAN
|
||||
- BYD_KOSTAL_RS485
|
||||
- BYD_MODBUS
|
||||
- BYD_SMA
|
||||
- FOXESS_CAN
|
||||
- PYLON_CAN
|
||||
- PYLON_LV_CAN
|
||||
- SCHNEIDER_CAN
|
||||
- SMA_CAN
|
||||
- SMA_BYD_H_CAN
|
||||
- SMA_BYD_HVS_CAN
|
||||
- SMA_LV_CAN
|
||||
- SMA_TRIPOWER_CAN
|
||||
- SOFAR_CAN
|
||||
- SOLAX_CAN
|
||||
- SERIAL_LINK_TRANSMITTER
|
||||
# These are the supported hardware platforms for which the code will be compiled.
|
||||
hardware:
|
||||
- HW_LILYGO
|
||||
|
||||
# This is the platform GitHub will use to run our workflow.
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -94,6 +98,10 @@ jobs:
|
|||
- 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
|
||||
|
@ -109,4 +117,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
93
.github/workflows/compile-all-hardware.yml
vendored
Normal file
93
.github/workflows/compile-all-hardware.yml
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
# This is the name of the workflow, visible on GitHub UI.
|
||||
name: Compile All Hardware
|
||||
|
||||
# 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"]'
|
||||
|
||||
# Since we use a build matrix, the actual number of jobs
|
||||
# started depends on how many configurations the matrix
|
||||
# will produce.
|
||||
|
||||
# This is the name of the job.
|
||||
build-hardware:
|
||||
needs: skip-duplicate-actions
|
||||
if: needs.skip-duplicate-actions.outputs.should_skip != 'true'
|
||||
|
||||
# Here we tell GitHub that the jobs must be determined
|
||||
# dynamically depending on a matrix configuration.
|
||||
strategy:
|
||||
# The matrix will produce one job for each combination of parameters.
|
||||
matrix:
|
||||
# This is the development board hardware for which the code will be compiled.
|
||||
# FBQN stands for "fully qualified board name", and is used by Arduino to define the hardware to compile for.
|
||||
fqbn:
|
||||
- esp32:esp32:esp32
|
||||
# further ESP32 chips
|
||||
#- esp32:esp32:esp32c3
|
||||
#- esp32:esp32:esp32c2
|
||||
#- esp32:esp32:esp32c6
|
||||
#- esp32:esp32:esp32h2
|
||||
#- esp32:esp32:esp32s3
|
||||
# These are the batteries for which the code will be compiled.
|
||||
battery:
|
||||
- NISSAN_LEAF_BATTERY
|
||||
# These are the emulated inverter communication protocols for which the code will be compiled.
|
||||
inverter:
|
||||
- BYD_CAN
|
||||
# These are the supported hardware platforms for which the code will be compiled.
|
||||
hardware:
|
||||
- HW_LILYGO
|
||||
- HW_STARK
|
||||
- HW_3LB
|
||||
- HW_DEVKIT
|
||||
|
||||
# This is the platform GitHub will use to run our workflow.
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# This is the list of steps this job will run.
|
||||
steps:
|
||||
# First we clone the repo using the `checkout` action.
|
||||
- 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
|
||||
|
||||
# Finally, we compile the sketch, using the FQBN that was set
|
||||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
14
.github/workflows/compile-all-inverters.yml
vendored
14
.github/workflows/compile-all-inverters.yml
vendored
|
@ -58,18 +58,22 @@ jobs:
|
|||
- BYD_CAN
|
||||
- BYD_KOSTAL_RS485
|
||||
- BYD_MODBUS
|
||||
- BYD_SMA
|
||||
- FOXESS_CAN
|
||||
- PYLON_CAN
|
||||
- PYLON_LV_CAN
|
||||
- SCHNEIDER_CAN
|
||||
- SMA_CAN
|
||||
- SMA_BYD_H_CAN
|
||||
- SMA_BYD_HVS_CAN
|
||||
- SMA_LV_CAN
|
||||
- SMA_TRIPOWER_CAN
|
||||
- SOFAR_CAN
|
||||
- SOLAX_CAN
|
||||
- SERIAL_LINK_TRANSMITTER
|
||||
- NISSANLEAF_CHARGER # Last element is not an inverter, but good to also test if the charger compiles
|
||||
# These are the supported hardware platforms for which the code will be compiled.
|
||||
hardware:
|
||||
- HW_LILYGO
|
||||
|
||||
# This is the platform GitHub will use to run our workflow.
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
@ -79,6 +83,10 @@ jobs:
|
|||
- 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
|
||||
|
@ -94,4 +102,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -22,3 +22,6 @@ compile.bat
|
|||
|
||||
# Ignore binary files
|
||||
*.bin
|
||||
|
||||
# Ignore secret file
|
||||
USER_SECRETS.h
|
10
README.md
10
README.md
|
@ -44,17 +44,19 @@ For more examples showing wiring, see each battery types own Wiki page. For inst
|
|||
3. Click `File` menu -> `Preferences` -> `Additional Development` -> `Additional Board Manager URLs` -> Enter the URL in the input box: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json` and click OK.
|
||||
4. Click `Tools` menu -> `Board: "...."` -> `Boards Manager...`, install the `esp32` package by `Espressif Systems` (not `Arduino ESP32 Boards`), then press `Close`.
|
||||
|
||||
**NOTE: The version depends on which release of Battery-Emulator you are running!**
|
||||
**NOTE: The ESP32 version depends on which release of Battery-Emulator you are running!**
|
||||
|
||||
- ⚠️ Make sure to use a 2.x.x version if you are on a release **older** than 6.0.0 (For instance ESP32 v2.0.11 when using Battery-Emulator v5.4.0)
|
||||
- ⚠️ Make sure to use a 3.x.x version if you are on a release **newer** than 6.0.0 (For instance ESP32 v3.0.0 when using Battery-Emulator v6.0.0)
|
||||
- ⚠️ Make sure to use a 3.0.x version if you are on a release **newer** than 6.0.0 (For instance ESP32 v3.0.0 when using Battery-Emulator v6.0.0)
|
||||
- ⚠️ Make sure to use a 3.1.x version if you are on a release **newer** than 8.0.0 (For instance ESP32 v3.1.0 when using Battery-Emulator v8.0.0)
|
||||
|
||||

|
||||
|
||||
5. The Arduino board should be set to `ESP32 Dev Module` (under `Tools` -> `Board` -> `ESP32 Arduino`) with the following settings:
|
||||

|
||||
6. Select which battery type you will use, along with other optional settings. This is done in the `USER_SETTINGS.h` file.
|
||||
7. Press `Verify` and `Upload` to send the sketch to the board.
|
||||
7. Copy the `USER_SECRETS.TEMPLATE.h` file to `USER_SECRETS.h` and update connectivity settings inside this file.
|
||||
8. Press `Verify` and `Upload` to send the sketch to the board.
|
||||
NOTE: In some cases, the LilyGo must be powered through the main power connector instead of USB-C
|
||||
when performing the initial firmware upload.
|
||||
NOTE: On Mac, the following USB driver may need to be installed: https://github.com/WCHSoftGroup/ch34xser_macos
|
||||
|
@ -83,7 +85,7 @@ This code uses the following excellent libraries:
|
|||
- [eModbus/eModbus](https://github.com/eModbus/eModbus) MIT-License
|
||||
- [knolleary/pubsubclient](https://github.com/knolleary/pubsubclient) MIT-License
|
||||
- [mackelec/SerialDataLink](https://github.com/mackelec/SerialDataLink)
|
||||
- [mathieucarbou/AsyncTCP](https://github.com/mathieucarbou/AsyncTCP) LGPL-3.0 license
|
||||
- [me-no-dev/AsyncTCP](https://github.com/me-no-dev/AsyncTCP) LGPL-3.0 license
|
||||
- [me-no-dev/ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer)
|
||||
- [miwagner/ESP32-Arduino-CAN](https://github.com/miwagner/ESP32-Arduino-CAN/) MIT-License
|
||||
- [pierremolinaro/acan2515](https://github.com/pierremolinaro/acan2515) MIT-License
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
/* Do not change any code below this line unless you are sure what you are doing */
|
||||
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
||||
|
||||
#include "src/include.h"
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
#include "USER_SECRETS.h"
|
||||
#include "USER_SETTINGS.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "src/charger/CHARGERS.h"
|
||||
#include "src/communication/can/comm_can.h"
|
||||
#include "src/communication/contactorcontrol/comm_contactorcontrol.h"
|
||||
#include "src/communication/equipmentstopbutton/comm_equipmentstopbutton.h"
|
||||
|
@ -18,9 +15,12 @@
|
|||
#include "src/communication/rs485/comm_rs485.h"
|
||||
#include "src/communication/seriallink/comm_seriallink.h"
|
||||
#include "src/datalayer/datalayer.h"
|
||||
#include "src/devboard/sdcard/sdcard.h"
|
||||
#include "src/devboard/utils/events.h"
|
||||
#include "src/devboard/utils/led_handler.h"
|
||||
#include "src/devboard/utils/logging.h"
|
||||
#include "src/devboard/utils/value_mapping.h"
|
||||
#include "src/include.h"
|
||||
#include "src/lib/YiannisBourkelis-Uptime-Library/src/uptime.h"
|
||||
#include "src/lib/YiannisBourkelis-Uptime-Library/src/uptime_formatter.h"
|
||||
#include "src/lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
||||
|
@ -29,7 +29,10 @@
|
|||
#include "src/lib/eModbus-eModbus/scripts/mbServerFCs.h"
|
||||
#include "src/lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "src/lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#ifndef AP_PASSWORD
|
||||
#error \
|
||||
"Initial setup not completed, USER_SECRETS.h is missing. Please rename the file USER_SECRETS.TEMPLATE.h to USER_SECRETS.h and fill in the required credentials. This file is ignored by version control to keep sensitive information private."
|
||||
#endif
|
||||
#ifdef WIFI
|
||||
#include "src/devboard/wifi/wifi.h"
|
||||
#ifdef WEBSERVER
|
||||
|
@ -77,12 +80,18 @@ MyTimer core_task_timer_10s(INTERVAL_10_S);
|
|||
int64_t connectivity_task_time_us;
|
||||
MyTimer connectivity_task_timer_10s(INTERVAL_10_S);
|
||||
|
||||
int64_t logging_task_time_us;
|
||||
MyTimer logging_task_timer_10s(INTERVAL_10_S);
|
||||
|
||||
MyTimer loop_task_timer_10s(INTERVAL_10_S);
|
||||
|
||||
MyTimer check_pause_2s(INTERVAL_2_S);
|
||||
|
||||
TaskHandle_t main_loop_task;
|
||||
TaskHandle_t connectivity_loop_task;
|
||||
TaskHandle_t logging_loop_task;
|
||||
|
||||
Logging logging;
|
||||
|
||||
// Initialization
|
||||
void setup() {
|
||||
|
@ -95,6 +104,11 @@ void setup() {
|
|||
TASK_CONNECTIVITY_PRIO, &connectivity_loop_task, WIFI_CORE);
|
||||
#endif
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, &logging_task_time_us,
|
||||
TASK_CONNECTIVITY_PRIO, &logging_loop_task, WIFI_CORE);
|
||||
#endif
|
||||
|
||||
init_events();
|
||||
|
||||
init_CAN();
|
||||
|
@ -137,6 +151,18 @@ void loop() {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
void logging_loop(void* task_time_us) {
|
||||
|
||||
init_logging_buffer();
|
||||
init_sdcard();
|
||||
|
||||
while (true) {
|
||||
write_can_frame_to_sdcard();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIFI
|
||||
void connectivity_loop(void* task_time_us) {
|
||||
|
||||
|
@ -191,13 +217,7 @@ void core_loop(void* task_time_us) {
|
|||
#endif
|
||||
|
||||
// Input, Runs as fast as possible
|
||||
receive_can_native(); // Receive CAN messages from native CAN port
|
||||
#ifdef CANFD_ADDON
|
||||
receive_canfd_addon(); // Receive CAN-FD messages.
|
||||
#endif // CANFD_ADDON
|
||||
#ifdef CAN_ADDON
|
||||
receive_can_addon(); // Receive CAN messages on add-on MCP2515 chip
|
||||
#endif // CAN_ADDON
|
||||
receive_can(); // Receive CAN messages
|
||||
#ifdef RS485_INVERTER_SELECTED
|
||||
receive_RS485(); // Process serial2 RS485 interface
|
||||
#endif // RS485_INVERTER_SELECTED
|
||||
|
@ -233,15 +253,12 @@ void core_loop(void* task_time_us) {
|
|||
update_machineryprotection(); // Check safeties (Not on serial link reciever board)
|
||||
#endif // SERIAL_LINK_RECEIVER
|
||||
update_values_inverter(); // Update values heading towards inverter
|
||||
if (DUMMY_EVENT_ENABLED) {
|
||||
set_event(EVENT_DUMMY_ERROR, (uint8_t)millis());
|
||||
}
|
||||
}
|
||||
END_TIME_MEASUREMENT_MAX(time_values, datalayer.system.status.time_values_us);
|
||||
|
||||
START_TIME_MEASUREMENT(cantx);
|
||||
// Output
|
||||
send_can(); // Send CAN messages to all components
|
||||
transmit_can(); // Send CAN messages to all components
|
||||
|
||||
END_TIME_MEASUREMENT_MAX(cantx, datalayer.system.status.time_cantx_us);
|
||||
END_TIME_MEASUREMENT_MAX(all, datalayer.system.status.core_task_10s_max_us);
|
||||
|
@ -269,7 +286,7 @@ void core_loop(void* task_time_us) {
|
|||
}
|
||||
#endif // FUNCTION_TIME_MEASUREMENT
|
||||
if (check_pause_2s.elapsed()) {
|
||||
emulator_pause_state_send_CAN_battery();
|
||||
emulator_pause_state_transmit_can_battery();
|
||||
}
|
||||
|
||||
vTaskDelayUntil(&xLastWakeTime, xFrequency);
|
||||
|
|
20
Software/USER_SECRETS.TEMPLATE.h
Normal file
20
Software/USER_SECRETS.TEMPLATE.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* This file should be renamed to USER_SECRETS.h to be able to use the software!
|
||||
It contains all the credentials that should never be made public */
|
||||
|
||||
//Password to the access point generated by the Battery-Emulator
|
||||
#define AP_PASSWORD "123456789" // Minimum of 8 characters; set to blank if you want the access point to be open
|
||||
|
||||
//Name and password of Wifi network you want the emulator to connect to
|
||||
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID" // Maximum of 63 characters
|
||||
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD" // Minimum of 8 characters
|
||||
|
||||
//Set WEBSERVER_AUTH_REQUIRED to true to require a password when accessing the webserver homepage. Improves cybersecurity.
|
||||
#define WEBSERVER_AUTH_REQUIRED false
|
||||
#define HTTP_USERNAME "admin" // Username for webserver authentication
|
||||
#define HTTP_PASSWORD "admin" // Password for webserver authentication
|
||||
|
||||
//MQTT credentials
|
||||
#define MQTT_SERVER "192.168.xxx.yyy" // MQTT server address
|
||||
#define MQTT_PORT 1883 // MQTT server port
|
||||
#define MQTT_USER NULL // MQTT username, leave blank for no authentication
|
||||
#define MQTT_PASSWORD NULL // MQTT password, leave blank for no authentication
|
|
@ -1,5 +1,6 @@
|
|||
#include "USER_SETTINGS.h"
|
||||
#include <string>
|
||||
#include "USER_SECRETS.h"
|
||||
#include "src/devboard/hal/hal.h"
|
||||
|
||||
/* This file contains all the battery settings and limits */
|
||||
|
@ -20,32 +21,25 @@ volatile CAN_Configuration can_config = {
|
|||
.shunt = CAN_NATIVE // (OPTIONAL) Which CAN is your charger connected to?
|
||||
};
|
||||
|
||||
#ifdef WIFI
|
||||
|
||||
volatile uint8_t AccessPointEnabled = true; //Set to either true/false to enable direct wifi access point
|
||||
std::string ssid = "REPLACE_WITH_YOUR_SSID"; // Maximum of 63 characters
|
||||
std::string password = "REPLACE_WITH_YOUR_PASSWORD"; // Minimum of 8 characters
|
||||
std::string ssid = WIFI_SSID; // Set in USER_SECRETS.h
|
||||
std::string password = WIFI_PASSWORD; // Set in USER_SECRETS.h
|
||||
const char* ssidAP = "Battery Emulator"; // Maximum of 63 characters, also used for device name on web interface
|
||||
const char* passwordAP = "123456789"; // Minimum of 8 characters; set to NULL if you want the access point to be open
|
||||
const char* passwordAP = AP_PASSWORD; // Set in USER_SECRETS.h
|
||||
const uint8_t wifi_channel = 0; // Set to 0 for automatic channel selection
|
||||
|
||||
#ifdef WIFICONFIG
|
||||
// Set your Static IP address
|
||||
IPAddress local_IP(192, 168, 10, 150);
|
||||
// Set your Gateway IP address
|
||||
IPAddress gateway(192, 168, 10, 1);
|
||||
// Set your Subnet IP address
|
||||
IPAddress subnet(255, 255, 255, 0);
|
||||
#endif
|
||||
#ifdef WEBSERVER
|
||||
const char* http_username = "admin"; // username to webserver authentication;
|
||||
const char* http_password = "admin"; // password to webserver authentication;
|
||||
|
||||
const char* http_username = HTTP_USERNAME; // Set in USER_SECRETS.h
|
||||
const char* http_password = HTTP_PASSWORD; // Set in USER_SECRETS.h
|
||||
// Set your Static IP address. Only used incase WIFICONFIG is set in USER_SETTINGS.h
|
||||
IPAddress local_IP(192, 168, 10, 150);
|
||||
IPAddress gateway(192, 168, 10, 1);
|
||||
IPAddress subnet(255, 255, 255, 0);
|
||||
#endif // WEBSERVER
|
||||
|
||||
// MQTT
|
||||
#ifdef MQTT
|
||||
const char* mqtt_user = "REDACTED"; // Set NULL for no username
|
||||
const char* mqtt_password = "REDACTED"; // Set NULL for no password
|
||||
const char* mqtt_user = MQTT_USER; // Set in USER_SECRETS.h
|
||||
const char* mqtt_password = MQTT_PASSWORD; // Set in USER_SECRETS.h
|
||||
#ifdef MQTT_MANUAL_TOPIC_OBJECT_NAME
|
||||
const char* mqtt_topic_name =
|
||||
"BE"; // Custom MQTT topic name. Previously, the name was automatically set to "battery-emulator_esp32-XXXXXX"
|
||||
|
@ -55,7 +49,6 @@ const char* mqtt_device_name =
|
|||
"Battery Emulator"; // Custom device name in Home Assistant. Previously, the name was automatically set to "BatteryEmulator_esp32-XXXXXX"
|
||||
#endif // MQTT_MANUAL_TOPIC_OBJECT_NAME
|
||||
#endif // USE_MQTT
|
||||
#endif // WIFI
|
||||
|
||||
#ifdef EQUIPMENT_STOP_BUTTON
|
||||
// Equipment stop button behavior. Use NC button for safety reasons.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
/* Select battery used */
|
||||
//#define BMW_I3_BATTERY
|
||||
//#define BMW_IX_BATTERY
|
||||
//#define BOLT_AMPERA_BATTERY
|
||||
//#define BYD_ATTO_3_BATTERY
|
||||
//#define CELLPOWER_BMS
|
||||
//#define CHADEMO_BATTERY //NOTE: inherently enables CONTACTOR_CONTROL below
|
||||
|
@ -30,6 +31,7 @@
|
|||
//#define RENAULT_ZOE_GEN1_BATTERY
|
||||
//#define RENAULT_ZOE_GEN2_BATTERY
|
||||
//#define SANTA_FE_PHEV_BATTERY
|
||||
//#define STELLANTIS_ECMP_BATTERY
|
||||
//#define TESLA_MODEL_3Y_BATTERY
|
||||
//#define TESLA_MODEL_SX_BATTERY
|
||||
//#define VOLVO_SPA_BATTERY
|
||||
|
@ -41,21 +43,22 @@
|
|||
//#define BYD_CAN //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus
|
||||
//#define BYD_KOSTAL_RS485 //Enable this line to emulate a "BYD 11kWh HVM battery" over Kostal RS485
|
||||
//#define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
||||
//#define BYD_SMA //Enable this line to emulate a SMA compatible "BYD Battery-Box HVS 10.2KW battery" over CAN bus
|
||||
//#define FOXESS_CAN //Enable this line to emulate a "HV2600/ECS4100 battery" over CAN bus
|
||||
//#define PYLON_LV_CAN //Enable this line to emulate a "48V Pylontech battery" over CAN bus
|
||||
//#define PYLON_CAN //Enable this line to emulate a "High Voltage Pylontech battery" over CAN bus
|
||||
//#define SCHNEIDER_CAN //Enable this line to emulate a "Schneider Version 2: SE BMS" over CAN bus
|
||||
//#define SMA_CAN //Enable this line to emulate a "BYD Battery-Box H 8.9kWh, 7 mod" over CAN bus
|
||||
//#define SMA_BYD_H_CAN //Enable this line to emulate a "BYD Battery-Box H 8.9kWh, 7 mod" (SMA compatible) over CAN bus
|
||||
//#define SMA_BYD_HVS_CAN //Enable this line to emulate a "BYD Battery-Box HVS 10.2KW battery" (SMA compatible) over CAN bus
|
||||
//#define SMA_LV_CAN //Enable this line to emulate a "SMA Sunny Island 48V battery" over CAN bus
|
||||
//#define SMA_TRIPOWER_CAN //Enable this line to emulate a "SMA Home Storage battery" over CAN bus
|
||||
//#define SOFAR_CAN //Enable this line to emulate a "Sofar Energy Storage Inverter High Voltage BMS General Protocol (Extended Frame)" over CAN bus
|
||||
//#define SOLAX_CAN //Enable this line to emulate a "SolaX Triple Power LFP" over CAN bus
|
||||
|
||||
/* Select hardware used for Battery-Emulator */
|
||||
#define HW_LILYGO
|
||||
//#define HW_LILYGO
|
||||
//#define HW_STARK
|
||||
//#define HW_3LB
|
||||
//#define HW_DEVKIT
|
||||
|
||||
/* Contactor settings. If you have a battery that does not activate contactors via CAN, configure this section */
|
||||
#define PRECHARGE_TIME_MS 500 //Precharge time in milliseconds. Modify to suit your inverter (See wiki for more info)
|
||||
|
@ -69,34 +72,33 @@
|
|||
|
||||
/* Other options */
|
||||
//#define DEBUG_VIA_USB //Enable this line to have the USB port output serial diagnostic data while program runs (WARNING, raises CPU load, do not use for production)
|
||||
//#define DEBUG_VIA_WEB //Enable this line to log diagnostic data while program runs, which can be viewed via webpage (WARNING, slightly raises CPU load, do not use for production)
|
||||
#if defined(DEBUG_VIA_USB) || defined(DEBUG_VIA_WEB)
|
||||
#define DEBUG_LOG
|
||||
#endif
|
||||
|
||||
//#define DEBUG_CAN_DATA //Enable this line to print incoming/outgoing CAN & CAN-FD messages to USB serial (WARNING, raises CPU load, do not use for production)
|
||||
//#define LOG_CAN_TO_SD //Enable this line to log incoming/outgoing CAN & CAN-FD messages to SD card
|
||||
//#define INTERLOCK_REQUIRED //Nissan LEAF specific setting, if enabled requires both high voltage conenctors to be seated before starting
|
||||
//#define CAN_ADDON //Enable this line to activate an isolated secondary CAN Bus using add-on MCP2515 chip (Needed for some inverters / double battery)
|
||||
#define CRYSTAL_FREQUENCY_MHZ 8 //CAN_ADDON option, what is your MCP2515 add-on boards crystal frequency?
|
||||
//#define CANFD_ADDON //Enable this line to activate an isolated secondary CAN-FD bus using add-on MCP2518FD chip / Native CANFD on Stark board
|
||||
#ifdef CANFD_ADDON // CANFD_ADDON additional options if enabled
|
||||
#define CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ \
|
||||
ACAN2517FDSettings:: \
|
||||
OSC_40MHz //CANFD_ADDON option, what is your MCP2518 add-on boards crystal frequency? (Default OSC_40MHz)
|
||||
#endif // CANFD_ADDON
|
||||
ACAN2517FDSettings::OSC_40MHz //CANFD_ADDON option, what is your MCP2518 add-on boards crystal frequency?
|
||||
//#define USE_CANFD_INTERFACE_AS_CLASSIC_CAN // Enable this line if you intend to use the CANFD as normal CAN
|
||||
//#define SERIAL_LINK_RECEIVER //Enable this line to receive battery data over RS485 pins from another Lilygo (This LilyGo interfaces with inverter)
|
||||
//#define SERIAL_LINK_TRANSMITTER //Enable this line to send battery data over RS485 pins to another Lilygo (This LilyGo interfaces with battery)
|
||||
#define WIFI
|
||||
//#define WIFICONFIG //Enable this line to set a static IP address / gateway /subnet mask for the device. see USER_SETTINGS.cpp for the settings
|
||||
#define WEBSERVER //Enable this line to enable WiFi, and to run the webserver. See USER_SETTINGS.cpp for the Wifi settings.
|
||||
#define WEBSERVER_AUTH_REQUIRED \
|
||||
false //Set this line to true to activate webserver authentication (this line must not be commented). Refer to USER_SETTINGS.cpp for setting the credentials.
|
||||
#define WIFIAP //Disable this line to permanently disable WIFI AP mode (make sure to hardcode ssid and password of you home wifi network). When enabled WIFI AP can still be disabled by a setting in the future.
|
||||
#define WIFIAP //When enabled, the emulator will broadcast its own access point Wifi. Can be used at the same time as a normal Wifi connection to a router.
|
||||
#define MDNSRESPONDER //Enable this line to enable MDNS, allows battery monitor te be found by .local address. Requires WEBSERVER to be enabled.
|
||||
#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot (overrides Wifi/battery settings set below)
|
||||
#define LOAD_SAVED_SETTINGS_ON_BOOT // Enable this line to read settings stored via the webserver on boot (overrides Wifi credentials set here)
|
||||
//#define FUNCTION_TIME_MEASUREMENT // Enable this to record execution times and present them in the web UI (WARNING, raises CPU load, do not use for production)
|
||||
//#define EQUIPMENT_STOP_BUTTON // Enable this to allow an equipment stop button connected to the Battery-Emulator to disengage the battery
|
||||
|
||||
/* MQTT options */
|
||||
// #define MQTT // Enable this line to enable MQTT
|
||||
#define MQTT_SERVER "192.168.xxx.yyy"
|
||||
#define MQTT_PORT 1883
|
||||
#define MQTT_MANUAL_TOPIC_OBJECT_NAME // Enable this to use custom MQTT topic, object ID prefix, and device name. \
|
||||
// WARNING: If this is not defined, the previous default naming format \
|
||||
// 'battery-emulator_esp32-XXXXXX' (based on hardware ID) will be used. \
|
||||
|
@ -108,9 +110,6 @@
|
|||
/* Home Assistant options */
|
||||
#define HA_AUTODISCOVERY // Enable this line to send Home Assistant autodiscovery messages. If not enabled manual configuration of Home Assitant is required
|
||||
|
||||
/* Event options*/
|
||||
#define DUMMY_EVENT_ENABLED false //Enable this line to have a dummy event that gets logged to test the interface
|
||||
|
||||
/* Select charger used (Optional) */
|
||||
//#define CHEVYVOLT_CHARGER //Enable this line to control a Chevrolet Volt charger connected to battery - for example, when generator charging or using an inverter without a charging function.
|
||||
//#define NISSANLEAF_CHARGER //Enable this line to control a Nissan LEAF PDM connected to battery - for example, when generator charging
|
||||
|
@ -139,8 +138,8 @@
|
|||
// 3000 = 300.0V, Target discharge voltage (Value can be tuned on the fly via webserver). Not used unless BATTERY_USE_VOLTAGE_LIMITS = true
|
||||
#define BATTERY_MAX_DISCHARGE_VOLTAGE 3000
|
||||
|
||||
/* Do not change any code below this line unless you are sure what you are doing */
|
||||
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
||||
/* Do not change any code below this line */
|
||||
/* Only change battery specific settings above and in "USER_SETTINGS.cpp" */
|
||||
typedef enum { CAN_NATIVE = 0, CANFD_NATIVE = 1, CAN_ADDON_MCP2515 = 2, CANFD_ADDON_MCP2518 = 3 } CAN_Interface;
|
||||
typedef struct {
|
||||
CAN_Interface battery;
|
||||
|
@ -171,9 +170,7 @@ extern volatile STOP_BUTTON_BEHAVIOR equipment_stop_behavior;
|
|||
|
||||
#ifdef WIFICONFIG
|
||||
extern IPAddress local_IP;
|
||||
// Set your Gateway IP address
|
||||
extern IPAddress gateway;
|
||||
// Set your Subnet IP address
|
||||
extern IPAddress subnet;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#ifdef BMW_SBOX
|
||||
#include "BMW-SBOX.h"
|
||||
void receive_can_shunt(CAN_frame rx_frame);
|
||||
void send_can_shunt();
|
||||
void map_can_frame_to_variable_shunt(CAN_frame rx_frame);
|
||||
void transmit_can_shunt();
|
||||
void setup_can_shunt();
|
||||
#endif
|
||||
|
||||
|
@ -17,6 +17,10 @@ void setup_can_shunt();
|
|||
#include "BMW-IX-BATTERY.h"
|
||||
#endif
|
||||
|
||||
#ifdef BOLT_AMPERA_BATTERY
|
||||
#include "BOLT-AMPERA-BATTERY.h"
|
||||
#endif
|
||||
|
||||
#ifdef BYD_ATTO_3_BATTERY
|
||||
#include "BYD-ATTO-3-BATTERY.h"
|
||||
#endif
|
||||
|
@ -30,6 +34,10 @@ void setup_can_shunt();
|
|||
#include "CHADEMO-SHUNTS.h"
|
||||
#endif
|
||||
|
||||
#ifdef STELLANTIS_ECMP_BATTERY
|
||||
#include "ECMP-BATTERY.h"
|
||||
#endif
|
||||
|
||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||
#endif
|
||||
|
@ -111,14 +119,14 @@ void setup_can_shunt();
|
|||
#include "SERIAL-LINK-RECEIVER-FROM-BATTERY.h"
|
||||
#endif
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame);
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame);
|
||||
void update_values_battery();
|
||||
void send_can_battery();
|
||||
void transmit_can_battery();
|
||||
void setup_battery(void);
|
||||
|
||||
#ifdef DOUBLE_BATTERY
|
||||
void update_values_battery2();
|
||||
void receive_can_battery2(CAN_frame rx_frame);
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@ static unsigned long previousMillis10000 = 0; // will store last time a 10000ms
|
|||
|
||||
enum BatterySize { BATTERY_60AH, BATTERY_94AH, BATTERY_120AH };
|
||||
static BatterySize detectedBattery = BATTERY_60AH;
|
||||
static BatterySize detectedBattery2 = BATTERY_60AH; // For double battery setups
|
||||
|
||||
enum CmdState { SOH, CELL_VOLTAGE_MINMAX, SOC, CELL_VOLTAGE_CELLNO, CELL_VOLTAGE_CELLNO_LAST };
|
||||
|
||||
|
@ -269,7 +270,6 @@ static uint8_t battery_status_diagnostics_HV = 0; // 0 all OK, 1 HV protection
|
|||
static uint8_t battery_status_diagnosis_powertrain_maximum_multiplexer = 0;
|
||||
static uint8_t battery_status_diagnosis_powertrain_immediate_multiplexer = 0;
|
||||
static uint8_t battery_ID2 = 0;
|
||||
static uint8_t battery_cellvoltage_mux = 0;
|
||||
static uint8_t battery_soh = 99;
|
||||
|
||||
static uint32_t battery2_serial_number = 0;
|
||||
|
@ -337,7 +337,6 @@ static uint8_t battery2_status_diagnostics_HV = 0; // 0 all OK, 1 HV protection
|
|||
static uint8_t battery2_status_diagnosis_powertrain_maximum_multiplexer = 0;
|
||||
static uint8_t battery2_status_diagnosis_powertrain_immediate_multiplexer = 0;
|
||||
static uint8_t battery2_ID2 = 0;
|
||||
static uint8_t battery2_cellvoltage_mux = 0;
|
||||
static uint8_t battery2_soh = 99;
|
||||
|
||||
static uint8_t message_data[50];
|
||||
|
@ -392,12 +391,12 @@ void update_values_battery2() { //This function maps all the values fetched via
|
|||
|
||||
if (battery2_info_available) {
|
||||
// Start checking safeties. First up, cellvoltages!
|
||||
if (detectedBattery == BATTERY_60AH) {
|
||||
if (detectedBattery2 == BATTERY_60AH) {
|
||||
datalayer.battery2.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_60AH;
|
||||
datalayer.battery2.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_60AH;
|
||||
datalayer.battery2.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_60AH;
|
||||
datalayer.battery2.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_60AH;
|
||||
} else if (detectedBattery == BATTERY_94AH) {
|
||||
} else if (detectedBattery2 == BATTERY_94AH) {
|
||||
datalayer.battery2.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_94AH;
|
||||
datalayer.battery2.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_94AH;
|
||||
datalayer.battery2.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_94AH;
|
||||
|
@ -425,9 +424,15 @@ void update_values_battery2() { //This function maps all the values fetched via
|
|||
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the battery datalayer
|
||||
if (datalayer.system.settings.equipment_stop_active == true) {
|
||||
digitalWrite(WUP_PIN, LOW); // Turn off WUP_PIN
|
||||
digitalWrite(WUP_PIN1, LOW); // Turn off WUP_PIN1
|
||||
#if defined(WUP_PIN2) && defined(DOUBLE_BATTERY)
|
||||
digitalWrite(WUP_PIN2, LOW); // Turn off WUP_PIN2
|
||||
#endif // defined(WUP_PIN2) && defined (DOUBLE_BATTERY)
|
||||
} else {
|
||||
digitalWrite(WUP_PIN, HIGH); // Wake up the battery
|
||||
digitalWrite(WUP_PIN1, HIGH); // Wake up the battery
|
||||
#if defined(WUP_PIN2) && defined(DOUBLE_BATTERY)
|
||||
digitalWrite(WUP_PIN2, HIGH); // Wake up the battery2
|
||||
#endif // defined(WUP_PIN2) && defined (DOUBLE_BATTERY)
|
||||
}
|
||||
|
||||
if (!battery_awake) {
|
||||
|
@ -502,7 +507,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer_extended.bmwi3.ST_cold_shutoff_valve = battery_status_cold_shutoff_valve;
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x112: //BMS [10ms] Status Of High-Voltage Battery - 2
|
||||
battery_awake = true;
|
||||
|
@ -632,7 +637,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
case 0x607: //BMS - responses to message requests on 0x615
|
||||
if ((cmdState == CELL_VOLTAGE_CELLNO || cmdState == CELL_VOLTAGE_CELLNO_LAST) && (rx_frame.data.u8[0] == 0xF4)) {
|
||||
if (rx_frame.DLC == 6) {
|
||||
transmit_can(&BMW_6F4_CELL_CONTINUE, can_config.battery); // tell battery to send the cellvoltage
|
||||
transmit_can_frame(&BMW_6F4_CELL_CONTINUE, can_config.battery); // tell battery to send the cellvoltage
|
||||
}
|
||||
if (rx_frame.DLC == 8) { // We have the full value, map it
|
||||
datalayer.battery.status.cell_voltages_mV[current_cell_polled - 1] =
|
||||
|
@ -645,7 +650,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
while (count < rx_frame.DLC && next_data < 49) {
|
||||
message_data[next_data++] = rx_frame.data.u8[count++];
|
||||
}
|
||||
transmit_can(&BMW_6F1_CONTINUE, can_config.battery); // tell battery to send additional messages
|
||||
transmit_can_frame(&BMW_6F1_CONTINUE, can_config.battery); // tell battery to send additional messages
|
||||
|
||||
} else if (rx_frame.DLC > 3 && next_data > 0 && rx_frame.data.u8[0] == 0xf1 &&
|
||||
((rx_frame.data.u8[1] & 0xF0) == 0x20)) {
|
||||
|
@ -681,7 +686,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void receive_can_battery2(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x112: //BMS [10ms] Status Of High-Voltage Battery - 2
|
||||
battery2_awake = true;
|
||||
|
@ -776,18 +781,6 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
case 0x41C: //BMS [1s] Operating Mode Status Of Hybrid - 2
|
||||
battery2_status_cooling_HV = (rx_frame.data.u8[1] & 0x03);
|
||||
break;
|
||||
case 0x426: // TODO: Figure out how to trigger sending of this. Does the SME require some CAN command?
|
||||
battery2_cellvoltage_mux = rx_frame.data.u8[0];
|
||||
if (battery2_cellvoltage_mux == 0) {
|
||||
datalayer.battery2.status.cell_voltages_mV[0] = ((rx_frame.data.u8[1] * 10) + 1800);
|
||||
datalayer.battery2.status.cell_voltages_mV[1] = ((rx_frame.data.u8[2] * 10) + 1800);
|
||||
datalayer.battery2.status.cell_voltages_mV[2] = ((rx_frame.data.u8[3] * 10) + 1800);
|
||||
datalayer.battery2.status.cell_voltages_mV[3] = ((rx_frame.data.u8[4] * 10) + 1800);
|
||||
datalayer.battery2.status.cell_voltages_mV[4] = ((rx_frame.data.u8[5] * 10) + 1800);
|
||||
datalayer.battery2.status.cell_voltages_mV[5] = ((rx_frame.data.u8[6] * 10) + 1800);
|
||||
datalayer.battery2.status.cell_voltages_mV[6] = ((rx_frame.data.u8[7] * 10) + 1800);
|
||||
}
|
||||
break;
|
||||
case 0x430: //BMS [1s] - Charging status of high-voltage battery - 2
|
||||
battery2_prediction_voltage_shortterm_charge = (rx_frame.data.u8[1] << 8 | rx_frame.data.u8[0]);
|
||||
battery2_prediction_voltage_shortterm_discharge = (rx_frame.data.u8[3] << 8 | rx_frame.data.u8[2]);
|
||||
|
@ -801,6 +794,13 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
battery2_prediction_duration_charging_minutes = (rx_frame.data.u8[3] << 8 | rx_frame.data.u8[2]);
|
||||
battery2_prediction_time_end_of_charging_minutes = rx_frame.data.u8[4];
|
||||
battery2_energy_content_maximum_kWh = (((rx_frame.data.u8[6] & 0x0F) << 8 | rx_frame.data.u8[5])) / 50;
|
||||
if (battery2_energy_content_maximum_kWh > 33) {
|
||||
detectedBattery2 = BATTERY_120AH;
|
||||
} else if (battery2_energy_content_maximum_kWh > 20) {
|
||||
detectedBattery2 = BATTERY_94AH;
|
||||
} else {
|
||||
detectedBattery2 = BATTERY_60AH;
|
||||
}
|
||||
break;
|
||||
case 0x432: //BMS [200ms] SOC% info
|
||||
battery2_request_operating_mode = (rx_frame.data.u8[0] & 0x03);
|
||||
|
@ -815,12 +815,23 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
battery2_ID2 = rx_frame.data.u8[0];
|
||||
break;
|
||||
case 0x607: //BMS - responses to message requests on 0x615
|
||||
if ((cmdState == CELL_VOLTAGE_CELLNO || cmdState == CELL_VOLTAGE_CELLNO_LAST) && (rx_frame.data.u8[0] == 0xF4)) {
|
||||
if (rx_frame.DLC == 6) {
|
||||
transmit_can_frame(&BMW_6F4_CELL_CONTINUE,
|
||||
can_config.battery_double); // tell battery to send the cellvoltage
|
||||
}
|
||||
if (rx_frame.DLC == 8) { // We have the full value, map it
|
||||
datalayer.battery2.status.cell_voltages_mV[current_cell_polled - 1] =
|
||||
(rx_frame.data.u8[6] << 8 | rx_frame.data.u8[7]);
|
||||
}
|
||||
}
|
||||
|
||||
if (rx_frame.DLC > 6 && next_data == 0 && rx_frame.data.u8[0] == 0xf1) {
|
||||
uint8_t count2 = 6;
|
||||
while (count2 < rx_frame.DLC && next_data < 49) {
|
||||
message_data[next_data++] = rx_frame.data.u8[count2++];
|
||||
}
|
||||
transmit_can(&BMW_6F1_CONTINUE, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_6F1_CONTINUE, can_config.battery_double);
|
||||
|
||||
} else if (rx_frame.DLC > 3 && next_data > 0 && rx_frame.data.u8[0] == 0xf1 &&
|
||||
((rx_frame.data.u8[1] & 0xF0) == 0x20)) {
|
||||
|
@ -856,7 +867,7 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
if (battery_awake) {
|
||||
|
@ -887,12 +898,12 @@ void send_can_battery() {
|
|||
if (datalayer.battery.status.bms_status == FAULT) {
|
||||
} //If battery is not in Fault mode, allow contactor to close by sending 10B
|
||||
else {
|
||||
transmit_can(&BMW_10B, can_config.battery);
|
||||
transmit_can_frame(&BMW_10B, can_config.battery);
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_BATTERY //If second battery is allowed to join in, also send 10B
|
||||
if (datalayer.system.status.battery2_allows_contactor_closing == true) {
|
||||
transmit_can(&BMW_10B, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_10B, can_config.battery_double);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -905,9 +916,9 @@ void send_can_battery() {
|
|||
|
||||
alive_counter_100ms = increment_alive_counter(alive_counter_100ms);
|
||||
|
||||
transmit_can(&BMW_12F, can_config.battery);
|
||||
transmit_can_frame(&BMW_12F, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_12F, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_12F, can_config.battery_double);
|
||||
#endif
|
||||
}
|
||||
// Send 200ms CAN Message
|
||||
|
@ -919,9 +930,9 @@ void send_can_battery() {
|
|||
|
||||
alive_counter_200ms = increment_alive_counter(alive_counter_200ms);
|
||||
|
||||
transmit_can(&BMW_19B, can_config.battery);
|
||||
transmit_can_frame(&BMW_19B, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_19B, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_19B, can_config.battery_double);
|
||||
#endif
|
||||
}
|
||||
// Send 500ms CAN Message
|
||||
|
@ -933,20 +944,20 @@ void send_can_battery() {
|
|||
|
||||
alive_counter_500ms = increment_alive_counter(alive_counter_500ms);
|
||||
|
||||
transmit_can(&BMW_30B, can_config.battery);
|
||||
transmit_can_frame(&BMW_30B, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_30B, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_30B, can_config.battery_double);
|
||||
#endif
|
||||
}
|
||||
// Send 640ms CAN Message
|
||||
if (currentMillis - previousMillis640 >= INTERVAL_640_MS) {
|
||||
previousMillis640 = currentMillis;
|
||||
|
||||
transmit_can(&BMW_512, can_config.battery); // Keep BMS alive
|
||||
transmit_can(&BMW_5F8, can_config.battery);
|
||||
transmit_can_frame(&BMW_512, can_config.battery); // Keep BMS alive
|
||||
transmit_can_frame(&BMW_5F8, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_512, can_config.battery_double);
|
||||
transmit_can(&BMW_5F8, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_512, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_5F8, can_config.battery_double);
|
||||
#endif
|
||||
}
|
||||
// Send 1000ms CAN Message
|
||||
|
@ -973,39 +984,39 @@ void send_can_battery() {
|
|||
|
||||
alive_counter_1000ms = increment_alive_counter(alive_counter_1000ms);
|
||||
|
||||
transmit_can(&BMW_3E8, can_config.battery); //Order comes from CAN logs
|
||||
transmit_can(&BMW_328, can_config.battery);
|
||||
transmit_can(&BMW_3F9, can_config.battery);
|
||||
transmit_can(&BMW_2E2, can_config.battery);
|
||||
transmit_can(&BMW_41D, can_config.battery);
|
||||
transmit_can(&BMW_3D0, can_config.battery);
|
||||
transmit_can(&BMW_3CA, can_config.battery);
|
||||
transmit_can(&BMW_3A7, can_config.battery);
|
||||
transmit_can(&BMW_2CA, can_config.battery);
|
||||
transmit_can(&BMW_3FB, can_config.battery);
|
||||
transmit_can(&BMW_418, can_config.battery);
|
||||
transmit_can(&BMW_1D0, can_config.battery);
|
||||
transmit_can(&BMW_3EC, can_config.battery);
|
||||
transmit_can(&BMW_192, can_config.battery);
|
||||
transmit_can(&BMW_13E, can_config.battery);
|
||||
transmit_can(&BMW_433, can_config.battery);
|
||||
transmit_can_frame(&BMW_3E8, can_config.battery); //Order comes from CAN logs
|
||||
transmit_can_frame(&BMW_328, can_config.battery);
|
||||
transmit_can_frame(&BMW_3F9, can_config.battery);
|
||||
transmit_can_frame(&BMW_2E2, can_config.battery);
|
||||
transmit_can_frame(&BMW_41D, can_config.battery);
|
||||
transmit_can_frame(&BMW_3D0, can_config.battery);
|
||||
transmit_can_frame(&BMW_3CA, can_config.battery);
|
||||
transmit_can_frame(&BMW_3A7, can_config.battery);
|
||||
transmit_can_frame(&BMW_2CA, can_config.battery);
|
||||
transmit_can_frame(&BMW_3FB, can_config.battery);
|
||||
transmit_can_frame(&BMW_418, can_config.battery);
|
||||
transmit_can_frame(&BMW_1D0, can_config.battery);
|
||||
transmit_can_frame(&BMW_3EC, can_config.battery);
|
||||
transmit_can_frame(&BMW_192, can_config.battery);
|
||||
transmit_can_frame(&BMW_13E, can_config.battery);
|
||||
transmit_can_frame(&BMW_433, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_3E8, can_config.battery_double);
|
||||
transmit_can(&BMW_328, can_config.battery_double);
|
||||
transmit_can(&BMW_3F9, can_config.battery_double);
|
||||
transmit_can(&BMW_2E2, can_config.battery_double);
|
||||
transmit_can(&BMW_41D, can_config.battery_double);
|
||||
transmit_can(&BMW_3D0, can_config.battery_double);
|
||||
transmit_can(&BMW_3CA, can_config.battery_double);
|
||||
transmit_can(&BMW_3A7, can_config.battery_double);
|
||||
transmit_can(&BMW_2CA, can_config.battery_double);
|
||||
transmit_can(&BMW_3FB, can_config.battery_double);
|
||||
transmit_can(&BMW_418, can_config.battery_double);
|
||||
transmit_can(&BMW_1D0, can_config.battery_double);
|
||||
transmit_can(&BMW_3EC, can_config.battery_double);
|
||||
transmit_can(&BMW_192, can_config.battery_double);
|
||||
transmit_can(&BMW_13E, can_config.battery_double);
|
||||
transmit_can(&BMW_433, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3E8, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_328, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3F9, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_2E2, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_41D, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3D0, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3CA, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3A7, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_2CA, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3FB, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_418, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_1D0, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3EC, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_192, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_13E, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_433, can_config.battery_double);
|
||||
#endif
|
||||
|
||||
BMW_433.data.u8[1] = 0x01; // First 433 message byte1 we send is unique, once we sent initial value send this
|
||||
|
@ -1014,23 +1025,23 @@ void send_can_battery() {
|
|||
next_data = 0;
|
||||
switch (cmdState) {
|
||||
case SOC:
|
||||
transmit_can(&BMW_6F1_CELL, can_config.battery);
|
||||
transmit_can_frame(&BMW_6F1_CELL, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_6F1_CELL, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_6F1_CELL, can_config.battery_double);
|
||||
#endif
|
||||
cmdState = CELL_VOLTAGE_MINMAX;
|
||||
break;
|
||||
case CELL_VOLTAGE_MINMAX:
|
||||
transmit_can(&BMW_6F1_SOH, can_config.battery);
|
||||
transmit_can_frame(&BMW_6F1_SOH, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_6F1_SOH, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_6F1_SOH, can_config.battery_double);
|
||||
#endif
|
||||
cmdState = SOH;
|
||||
break;
|
||||
case SOH:
|
||||
transmit_can(&BMW_6F1_CELL_VOLTAGE_AVG, can_config.battery);
|
||||
transmit_can_frame(&BMW_6F1_CELL_VOLTAGE_AVG, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_6F1_CELL_VOLTAGE_AVG, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_6F1_CELL_VOLTAGE_AVG, can_config.battery_double);
|
||||
#endif
|
||||
cmdState = CELL_VOLTAGE_CELLNO;
|
||||
current_cell_polled = 0;
|
||||
|
@ -1045,16 +1056,16 @@ void send_can_battery() {
|
|||
cmdState = CELL_VOLTAGE_CELLNO;
|
||||
|
||||
BMW_6F4_CELL_VOLTAGE_CELLNO.data.u8[6] = current_cell_polled;
|
||||
transmit_can(&BMW_6F4_CELL_VOLTAGE_CELLNO, can_config.battery);
|
||||
transmit_can_frame(&BMW_6F4_CELL_VOLTAGE_CELLNO, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_6F4_CELL_VOLTAGE_CELLNO, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_6F4_CELL_VOLTAGE_CELLNO, can_config.battery_double);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case CELL_VOLTAGE_CELLNO_LAST:
|
||||
transmit_can(&BMW_6F1_SOC, can_config.battery);
|
||||
transmit_can_frame(&BMW_6F1_SOC, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_6F1_SOC, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_6F1_SOC, can_config.battery_double);
|
||||
#endif
|
||||
cmdState = SOC;
|
||||
break;
|
||||
|
@ -1067,25 +1078,25 @@ void send_can_battery() {
|
|||
BMW_3FC.data.u8[1] = ((BMW_3FC.data.u8[1] & 0xF0) + alive_counter_5000ms);
|
||||
BMW_3C5.data.u8[0] = ((BMW_3C5.data.u8[0] & 0xF0) + alive_counter_5000ms);
|
||||
|
||||
transmit_can(&BMW_3FC, can_config.battery); //Order comes from CAN logs
|
||||
transmit_can(&BMW_3C5, can_config.battery);
|
||||
transmit_can(&BMW_3A0, can_config.battery);
|
||||
transmit_can(&BMW_592_0, can_config.battery);
|
||||
transmit_can(&BMW_592_1, can_config.battery);
|
||||
transmit_can_frame(&BMW_3FC, can_config.battery); //Order comes from CAN logs
|
||||
transmit_can_frame(&BMW_3C5, can_config.battery);
|
||||
transmit_can_frame(&BMW_3A0, can_config.battery);
|
||||
transmit_can_frame(&BMW_592_0, can_config.battery);
|
||||
transmit_can_frame(&BMW_592_1, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_3FC, can_config.battery_double);
|
||||
transmit_can(&BMW_3C5, can_config.battery_double);
|
||||
transmit_can(&BMW_3A0, can_config.battery_double);
|
||||
transmit_can(&BMW_592_0, can_config.battery_double);
|
||||
transmit_can(&BMW_592_1, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3FC, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3C5, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3A0, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_592_0, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_592_1, can_config.battery_double);
|
||||
#endif
|
||||
|
||||
alive_counter_5000ms = increment_alive_counter(alive_counter_5000ms);
|
||||
|
||||
if (BMW_380_counter < 3) {
|
||||
transmit_can(&BMW_380, can_config.battery); // This message stops after 3 times on startup
|
||||
transmit_can_frame(&BMW_380, can_config.battery); // This message stops after 3 times on startup
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_380, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_380, can_config.battery_double);
|
||||
#endif
|
||||
BMW_380_counter++;
|
||||
}
|
||||
|
@ -1094,13 +1105,13 @@ void send_can_battery() {
|
|||
if (currentMillis - previousMillis10000 >= INTERVAL_10_S) {
|
||||
previousMillis10000 = currentMillis;
|
||||
|
||||
transmit_can(&BMW_3E5, can_config.battery); //Order comes from CAN logs
|
||||
transmit_can(&BMW_3E4, can_config.battery);
|
||||
transmit_can(&BMW_37B, can_config.battery);
|
||||
transmit_can_frame(&BMW_3E5, can_config.battery); //Order comes from CAN logs
|
||||
transmit_can_frame(&BMW_3E4, can_config.battery);
|
||||
transmit_can_frame(&BMW_37B, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&BMW_3E5, can_config.battery_double);
|
||||
transmit_can(&BMW_3E4, can_config.battery_double);
|
||||
transmit_can(&BMW_37B, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3E5, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_3E4, can_config.battery_double);
|
||||
transmit_can_frame(&BMW_37B, can_config.battery_double);
|
||||
#endif
|
||||
|
||||
BMW_3E5.data.u8[0] = 0xFD; // First 3E5 message byte0 we send is unique, once we sent initial value send this
|
||||
|
@ -1134,8 +1145,12 @@ void setup_battery(void) { // Performs one time setup at startup
|
|||
datalayer.battery2.status.voltage_dV =
|
||||
0; //Init voltage to 0 to allow contactor check to operate without fear of default values colliding
|
||||
#endif
|
||||
pinMode(WUP_PIN, OUTPUT);
|
||||
digitalWrite(WUP_PIN, HIGH); // Wake up the battery
|
||||
pinMode(WUP_PIN1, OUTPUT);
|
||||
digitalWrite(WUP_PIN1, HIGH); // Wake up the battery
|
||||
#if defined(DOUBLE_BATTERY) && defined(WUP_PIN2)
|
||||
pinMode(WUP_PIN2, OUTPUT);
|
||||
digitalWrite(WUP_PIN2, HIGH); // Wake up the battery
|
||||
#endif // defined(WUP_PIN2) && defined (DOUBLE_BATTERY)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
#define WUP_PIN 25
|
||||
#define MAX_CELL_VOLTAGE_60AH 4110 // Battery is put into emergency stop if one cell goes over this value
|
||||
#define MIN_CELL_VOLTAGE_60AH 2700 // Battery is put into emergency stop if one cell goes below this value
|
||||
#define MAX_CELL_VOLTAGE_94AH 4140 // Battery is put into emergency stop if one cell goes over this value
|
||||
|
@ -20,6 +19,6 @@
|
|||
#define MAX_PACK_VOLTAGE_120AH 4030 // Charge stops if pack voltage exceeds this value
|
||||
#define MIN_PACK_VOLTAGE_120AH 2680 // Discharge stops if pack voltage exceeds this value
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -516,7 +516,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||
}
|
||||
}
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
battery_awake = true;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x112:
|
||||
|
@ -540,7 +540,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
|
||||
//Frame has continued data - so request it
|
||||
transmit_can(&BMWiX_6F4_CONTINUE_DATA, can_config.battery);
|
||||
transmit_can_frame(&BMWiX_6F4_CONTINUE_DATA, can_config.battery);
|
||||
}
|
||||
|
||||
if (rx_frame.DLC = 64 && rx_frame.data.u8[0] == 0xF4 &&
|
||||
|
@ -670,11 +670,11 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
|
||||
if ((rx_frame.data.u8[6] << 8 | rx_frame.data.u8[7]) == 10000 ||
|
||||
(rx_frame.data.u8[8] << 8 | rx_frame.data.u8[9]) == 10000) { //Qualifier Invalid Mode - Request Reboot
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Cell MinMax Qualifier Invalid - Requesting BMS Reset");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell MinMax Qualifier Invalid - Requesting BMS Reset");
|
||||
#endif
|
||||
//set_event(EVENT_BATTERY_VALUE_UNAVAILABLE, (millis())); //Eventually need new Info level event type
|
||||
transmit_can(&BMWiX_6F4_REQUEST_HARD_RESET, can_config.battery);
|
||||
transmit_can_frame(&BMWiX_6F4_REQUEST_HARD_RESET, can_config.battery);
|
||||
} else { //Only ingest values if they are not the 10V Error state
|
||||
min_cell_voltage = (rx_frame.data.u8[6] << 8 | rx_frame.data.u8[7]);
|
||||
max_cell_voltage = (rx_frame.data.u8[8] << 8 | rx_frame.data.u8[9]);
|
||||
|
@ -724,7 +724,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
//if (battery_awake) { //We can always send CAN as the iX BMS will wake up on vehicle comms
|
||||
|
@ -734,10 +734,10 @@ void send_can_battery() {
|
|||
|
||||
//Loop through and send a different UDS request each cycle
|
||||
uds_req_id_counter = increment_uds_req_id_counter(uds_req_id_counter);
|
||||
transmit_can(UDS_REQUESTS100MS[uds_req_id_counter], can_config.battery);
|
||||
transmit_can_frame(UDS_REQUESTS100MS[uds_req_id_counter], can_config.battery);
|
||||
|
||||
//Send SME Keep alive values 100ms
|
||||
transmit_can(&BMWiX_510, can_config.battery);
|
||||
transmit_can_frame(&BMWiX_510, can_config.battery);
|
||||
}
|
||||
// Send 200ms CAN Message
|
||||
if (currentMillis - previousMillis200 >= INTERVAL_200_MS) {
|
||||
|
@ -745,16 +745,16 @@ void send_can_battery() {
|
|||
|
||||
//Send SME Keep alive values 200ms
|
||||
BMWiX_0C0.data.u8[0] = increment_0C0_counter(BMWiX_0C0.data.u8[0]); //Keep Alive 1
|
||||
transmit_can(&BMWiX_0C0, can_config.battery);
|
||||
transmit_can_frame(&BMWiX_0C0, can_config.battery);
|
||||
}
|
||||
// Send 1000ms CAN Message
|
||||
if (currentMillis - previousMillis1000 >= INTERVAL_1_S) {
|
||||
previousMillis1000 = currentMillis;
|
||||
|
||||
//Send SME Keep alive values 1000ms
|
||||
//Don't believe this is needed: transmit_can(&BMWiX_06D, can_config.battery);
|
||||
//Don't believe this is needed: transmit_can(&BMWiX_2F1, can_config.battery);
|
||||
//Don't believe this is needed: transmit_can(&BMWiX_439, can_config.battery);
|
||||
//Don't believe this is needed: transmit_can_frame(&BMWiX_06D, can_config.battery);
|
||||
//Don't believe this is needed: transmit_can_frame(&BMWiX_2F1, can_config.battery);
|
||||
//Don't believe this is needed: transmit_can_frame(&BMWiX_439, can_config.battery);
|
||||
}
|
||||
// Send 5000ms CAN Message
|
||||
if (currentMillis - previousMillis5000 >= INTERVAL_5_S) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
//#define WUP_PIN 25 //Not used
|
||||
#define MAX_PACK_VOLTAGE_DV 4650 //4650 = 465.0V
|
||||
#define MIN_PACK_VOLTAGE_DV 3000
|
||||
#define MAX_CELL_DEVIATION_MV 250
|
||||
|
@ -18,6 +17,6 @@
|
|||
#define STALE_PERIOD_CONFIG \
|
||||
300000; //Number of milliseconds before critical values are classed as stale/stuck 300000 = 300 seconds
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,13 +21,14 @@ uint32_t avg_sum;
|
|||
|
||||
uint8_t k; //avg array pointer
|
||||
|
||||
uint8_t CAN100_cnt=0;
|
||||
uint8_t CAN100_cnt = 0;
|
||||
|
||||
CAN_frame SBOX_100 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 4,
|
||||
.ID = 0x100,
|
||||
.data = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00}}; // Byte 0: relay control, Byte 1: counter 0-E, Byte 4: CRC
|
||||
.data = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}; // Byte 0: relay control, Byte 1: counter 0-E, Byte 4: CRC
|
||||
|
||||
CAN_frame SBOX_300 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
|
@ -35,7 +36,6 @@ CAN_frame SBOX_300 = {.FD = false,
|
|||
.ID = 0x300,
|
||||
.data = {0xFF, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}}; // Static frame
|
||||
|
||||
|
||||
uint8_t reverse_bits(uint8_t byte) {
|
||||
uint8_t reversed = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
@ -45,7 +45,6 @@ uint8_t reverse_bits(uint8_t byte) {
|
|||
return reversed;
|
||||
}
|
||||
|
||||
|
||||
/** CRC8, both inverted, poly 0x31 **/
|
||||
uint8_t calculateCRC(CAN_frame CAN) {
|
||||
uint8_t crc = 0;
|
||||
|
@ -61,58 +60,54 @@ uint8_t calculateCRC(CAN_frame CAN) {
|
|||
crc &= 0xFF;
|
||||
}
|
||||
}
|
||||
crc=reverse_bits(crc);
|
||||
crc = reverse_bits(crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
void receive_can_shunt(CAN_frame rx_frame) {
|
||||
void map_can_frame_to_variable_shunt(CAN_frame rx_frame) {
|
||||
unsigned long currentTime = millis();
|
||||
if(rx_frame.ID ==0x200)
|
||||
{
|
||||
ShuntLastSeen=currentTime;
|
||||
datalayer.shunt.measured_amperage_mA=((rx_frame.data.u8[2]<<24)| (rx_frame.data.u8[1]<<16)| (rx_frame.data.u8[0]<<8))/256;
|
||||
if (rx_frame.ID == 0x200) {
|
||||
ShuntLastSeen = currentTime;
|
||||
datalayer.shunt.measured_amperage_mA =
|
||||
((rx_frame.data.u8[2] << 24) | (rx_frame.data.u8[1] << 16) | (rx_frame.data.u8[0] << 8)) / 256;
|
||||
datalayer.shunt.measured_amperage_dA = datalayer.shunt.measured_amperage_mA / 100;
|
||||
|
||||
/** Calculate 1S avg current **/
|
||||
if(LastAvgTime+100<currentTime)
|
||||
{
|
||||
LastAvgTime=currentTime;
|
||||
if(k>9) {
|
||||
k=0;
|
||||
if (LastAvgTime + 100 < currentTime) {
|
||||
LastAvgTime = currentTime;
|
||||
if (k > 9) {
|
||||
k = 0;
|
||||
}
|
||||
avg_mA_array[k]=datalayer.shunt.measured_amperage_mA;
|
||||
avg_mA_array[k] = datalayer.shunt.measured_amperage_mA;
|
||||
k++;
|
||||
avg_sum=0;
|
||||
for (uint8_t i = 0; i < 10; i++)
|
||||
avg_sum = 0;
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
avg_sum = avg_sum + avg_mA_array[i];
|
||||
}
|
||||
datalayer.shunt.measured_avg1S_amperage_mA = avg_sum / 10;
|
||||
}
|
||||
} else if (rx_frame.ID == 0x210) //SBOX input (battery side) voltage
|
||||
{
|
||||
avg_sum=avg_sum+avg_mA_array[i];
|
||||
}
|
||||
datalayer.shunt.measured_avg1S_amperage_mA=avg_sum/10;
|
||||
}
|
||||
}
|
||||
else if(rx_frame.ID ==0x210) //SBOX input (battery side) voltage
|
||||
ShuntLastSeen = currentTime;
|
||||
datalayer.shunt.measured_voltage_mV =
|
||||
((rx_frame.data.u8[2] << 16) | (rx_frame.data.u8[1] << 8) | (rx_frame.data.u8[0]));
|
||||
} else if (rx_frame.ID == 0x220) //SBOX output voltage
|
||||
{
|
||||
ShuntLastSeen=currentTime;
|
||||
datalayer.shunt.measured_voltage_mV=((rx_frame.data.u8[2]<<16)| (rx_frame.data.u8[1]<<8)| (rx_frame.data.u8[0]));
|
||||
}
|
||||
else if(rx_frame.ID ==0x220) //SBOX output voltage
|
||||
{
|
||||
ShuntLastSeen=currentTime;
|
||||
datalayer.shunt.measured_outvoltage_mV=((rx_frame.data.u8[2]<<16)| (rx_frame.data.u8[1]<<8)| (rx_frame.data.u8[0]));
|
||||
datalayer.shunt.available=true;
|
||||
ShuntLastSeen = currentTime;
|
||||
datalayer.shunt.measured_outvoltage_mV =
|
||||
((rx_frame.data.u8[2] << 16) | (rx_frame.data.u8[1] << 8) | (rx_frame.data.u8[0]));
|
||||
datalayer.shunt.available = true;
|
||||
}
|
||||
}
|
||||
|
||||
void send_can_shunt() {
|
||||
void transmit_can_shunt() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
/** Shunt can frames seen? **/
|
||||
if(ShuntLastSeen+1000<currentTime)
|
||||
{
|
||||
datalayer.shunt.available=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
datalayer.shunt.available=true;
|
||||
if (ShuntLastSeen + 1000 < currentTime) {
|
||||
datalayer.shunt.available = false;
|
||||
} else {
|
||||
datalayer.shunt.available = true;
|
||||
}
|
||||
// Send 20ms CAN Message
|
||||
if (currentTime - LastMsgTime >= INTERVAL_20_MS) {
|
||||
|
@ -127,7 +122,7 @@ void send_can_shunt() {
|
|||
//handle contactor control SHUTDOWN_REQUESTED
|
||||
if (timeSpentInFaultedMode > MAX_ALLOWED_FAULT_TICKS) {
|
||||
contactorStatus = SHUTDOWN_REQUESTED;
|
||||
SBOX_100.data.u8[0]=0x55; // All open
|
||||
SBOX_100.data.u8[0] = 0x55; // All open
|
||||
}
|
||||
|
||||
if (contactorStatus == SHUTDOWN_REQUESTED) {
|
||||
|
@ -138,24 +133,27 @@ void send_can_shunt() {
|
|||
// After that, check if we are OK to start turning on the contactors
|
||||
if (contactorStatus == DISCONNECTED) {
|
||||
datalayer.shunt.contactors_engaged = false;
|
||||
SBOX_100.data.u8[0]=0x55; // All open
|
||||
SBOX_100.data.u8[0] = 0x55; // All open
|
||||
|
||||
if (datalayer.system.status.battery_allows_contactor_closing &&
|
||||
datalayer.system.status.inverter_allows_contactor_closing && !datalayer.system.settings.equipment_stop_active && ( datalayer.shunt.measured_voltage_mV > MINIMUM_INPUT_VOLTAGE*1000)) {
|
||||
datalayer.system.status.inverter_allows_contactor_closing &&
|
||||
!datalayer.system.settings.equipment_stop_active &&
|
||||
(datalayer.shunt.measured_voltage_mV > MINIMUM_INPUT_VOLTAGE * 1000)) {
|
||||
contactorStatus = 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) {
|
||||
if (!datalayer.system.status.inverter_allows_contactor_closing ||
|
||||
datalayer.system.settings.equipment_stop_active) {
|
||||
contactorStatus = DISCONNECTED;
|
||||
}
|
||||
}
|
||||
// Handle actual state machine. This first turns on Precharge, then Negative, then Positive, and finally turns OFF precharge
|
||||
switch (contactorStatus) {
|
||||
case PRECHARGE:
|
||||
SBOX_100.data.u8[0]=0x86; // Precharge relay only
|
||||
SBOX_100.data.u8[0] = 0x86; // Precharge relay only
|
||||
prechargeStartTime = currentTime;
|
||||
contactorStatus = NEGATIVE;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
|
@ -164,7 +162,7 @@ void send_can_shunt() {
|
|||
break;
|
||||
case NEGATIVE:
|
||||
if (currentTime - prechargeStartTime >= CONTACTOR_CONTROL_T1) {
|
||||
SBOX_100.data.u8[0]=0xA6; // Precharge + Negative
|
||||
SBOX_100.data.u8[0] = 0xA6; // Precharge + Negative
|
||||
negativeStartTime = currentTime;
|
||||
contactorStatus = POSITIVE;
|
||||
datalayer.shunt.precharging = true;
|
||||
|
@ -174,8 +172,10 @@ void send_can_shunt() {
|
|||
}
|
||||
break;
|
||||
case POSITIVE:
|
||||
if (currentTime - negativeStartTime >= CONTACTOR_CONTROL_T2 && (datalayer.shunt.measured_voltage_mV * MAX_PRECHARGE_RESISTOR_VOLTAGE_PERCENT < datalayer.shunt.measured_outvoltage_mV)) {
|
||||
SBOX_100.data.u8[0]=0xAA; // Precharge + Negative + Positive
|
||||
if (currentTime - negativeStartTime >= CONTACTOR_CONTROL_T2 &&
|
||||
(datalayer.shunt.measured_voltage_mV * MAX_PRECHARGE_RESISTOR_VOLTAGE_PERCENT <
|
||||
datalayer.shunt.measured_outvoltage_mV)) {
|
||||
SBOX_100.data.u8[0] = 0xAA; // Precharge + Negative + Positive
|
||||
positiveStartTime = currentTime;
|
||||
contactorStatus = PRECHARGE_OFF;
|
||||
datalayer.shunt.precharging = false;
|
||||
|
@ -186,7 +186,7 @@ void send_can_shunt() {
|
|||
break;
|
||||
case PRECHARGE_OFF:
|
||||
if (currentTime - positiveStartTime >= CONTACTOR_CONTROL_T3) {
|
||||
SBOX_100.data.u8[0]=0x6A; // Negative + Positive
|
||||
SBOX_100.data.u8[0] = 0x6A; // Negative + Positive
|
||||
contactorStatus = COMPLETED;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("S-BOX Precharge relay released");
|
||||
|
@ -195,19 +195,19 @@ void send_can_shunt() {
|
|||
}
|
||||
break;
|
||||
case COMPLETED:
|
||||
SBOX_100.data.u8[0]=0x6A; // Negative + Positive
|
||||
SBOX_100.data.u8[0] = 0x6A; // Negative + Positive
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CAN100_cnt++;
|
||||
if (CAN100_cnt>0x0E) {
|
||||
CAN100_cnt=0;
|
||||
if (CAN100_cnt > 0x0E) {
|
||||
CAN100_cnt = 0;
|
||||
}
|
||||
SBOX_100.data.u8[1]=CAN100_cnt<<4|0x01;
|
||||
SBOX_100.data.u8[3]=0x00;
|
||||
SBOX_100.data.u8[3]=calculateCRC(SBOX_100);
|
||||
transmit_can(&SBOX_100, can_config.shunt);
|
||||
transmit_can(&SBOX_300, can_config.shunt);
|
||||
SBOX_100.data.u8[1] = CAN100_cnt << 4 | 0x01;
|
||||
SBOX_100.data.u8[3] = 0x00;
|
||||
SBOX_100.data.u8[3] = calculateCRC(SBOX_100);
|
||||
transmit_can_frame(&SBOX_100, can_config.shunt);
|
||||
transmit_can_frame(&SBOX_300, can_config.shunt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
789
Software/src/battery/BOLT-AMPERA-BATTERY.cpp
Normal file
789
Software/src/battery/BOLT-AMPERA-BATTERY.cpp
Normal file
|
@ -0,0 +1,789 @@
|
|||
#include "../include.h"
|
||||
#ifdef BOLT_AMPERA_BATTERY
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "../datalayer/datalayer_extended.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "BOLT-AMPERA-BATTERY.h"
|
||||
|
||||
/*
|
||||
TODOs left for this implementation
|
||||
- The battery has 3 CAN ports. One of them is responsible for the 7E4 polls, the other for the 7E7 polls
|
||||
- Current implementation only seems to get the 7E7 polls working.
|
||||
- Could on of the CAN channels be GMLAN?
|
||||
|
||||
- The values missing for a working implementation is:
|
||||
- SOC% missing! This is absolutely mandatory to fix before starting to use this!
|
||||
- Capacity (kWh) (can be estimated)
|
||||
- Charge max power (can be estimated)
|
||||
- Discharge max power (can be estimated)
|
||||
- SOH% (low prio))
|
||||
*/
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis20ms = 0; // will store last time a 20ms CAN Message was send
|
||||
static unsigned long previousMillis100ms = 0; // will store last time a 100ms CAN Message was send
|
||||
static unsigned long previousMillis120ms = 0; // will store last time a 120ms CAN Message was send
|
||||
|
||||
CAN_frame BOLT_778 = {.FD = false, // Unsure of what this message is, added only as example
|
||||
.ext_ID = false,
|
||||
.DLC = 7,
|
||||
.ID = 0x778,
|
||||
.data = {0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame BOLT_POLL_7E4 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x7E4,
|
||||
.data = {0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame BOLT_ACK_7E4 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x7E4,
|
||||
.data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame BOLT_POLL_7E7 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x7E7,
|
||||
.data = {0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame BOLT_ACK_7E7 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x7E7,
|
||||
.data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
// 7E4 Battery , reply 000007EC
|
||||
// 7E7 Battery (Cell voltages), reply 000007EF
|
||||
|
||||
static uint16_t battery_cell_voltages[96]; //array with all the cellvoltages
|
||||
static uint16_t battery_capacity_my17_18 = 0;
|
||||
static uint16_t battery_capacity_my19plus = 0;
|
||||
static uint16_t battery_SOC_display = 0;
|
||||
static uint16_t battery_SOC_raw_highprec = 0;
|
||||
static uint16_t battery_max_temperature = 0;
|
||||
static uint16_t battery_min_temperature = 0;
|
||||
static uint16_t battery_min_cell_voltage = 0;
|
||||
static uint16_t battery_max_cell_voltage = 0;
|
||||
static uint16_t battery_internal_resistance = 0;
|
||||
static uint16_t battery_lowest_cell = 0;
|
||||
static uint16_t battery_highest_cell = 0;
|
||||
static uint16_t battery_voltage_polled = 0;
|
||||
static uint16_t battery_voltage_periodic = 0;
|
||||
static uint16_t battery_vehicle_isolation = 0;
|
||||
static uint16_t battery_isolation_kohm = 0;
|
||||
static uint16_t battery_HV_locked = 0;
|
||||
static uint16_t battery_crash_event = 0;
|
||||
static uint16_t battery_HVIL = 0;
|
||||
static uint16_t battery_HVIL_status = 0;
|
||||
static uint16_t battery_5V_ref = 0;
|
||||
static int16_t battery_current_7E4 = 0;
|
||||
static int16_t battery_module_temp_1 = 0;
|
||||
static int16_t battery_module_temp_2 = 0;
|
||||
static int16_t battery_module_temp_3 = 0;
|
||||
static int16_t battery_module_temp_4 = 0;
|
||||
static int16_t battery_module_temp_5 = 0;
|
||||
static int16_t battery_module_temp_6 = 0;
|
||||
static uint16_t battery_cell_average_voltage = 0;
|
||||
static uint16_t battery_cell_average_voltage_2 = 0;
|
||||
static uint16_t battery_terminal_voltage = 0;
|
||||
static uint16_t battery_ignition_power_mode = 0;
|
||||
static int16_t battery_current_7E7 = 0;
|
||||
static int16_t temperature_1 = 0;
|
||||
static int16_t temperature_2 = 0;
|
||||
static int16_t temperature_3 = 0;
|
||||
static int16_t temperature_4 = 0;
|
||||
static int16_t temperature_5 = 0;
|
||||
static int16_t temperature_6 = 0;
|
||||
static int16_t temperature_highest = 0;
|
||||
static int16_t temperature_lowest = 0;
|
||||
static uint8_t mux = 0;
|
||||
static uint8_t poll_index_7E4 = 0;
|
||||
static uint16_t currentpoll_7E4 = POLL_7E4_CAPACITY_EST_GEN1;
|
||||
static uint16_t reply_poll_7E4 = 0;
|
||||
static uint8_t poll_index_7E7 = 0;
|
||||
static uint16_t currentpoll_7E7 = POLL_7E7_CURRENT;
|
||||
static uint16_t reply_poll_7E7 = 0;
|
||||
|
||||
const uint16_t poll_commands_7E4[19] = {POLL_7E4_CAPACITY_EST_GEN1,
|
||||
POLL_7E4_CAPACITY_EST_GEN2,
|
||||
POLL_7E4_SOC_DISPLAY,
|
||||
POLL_7E4_SOC_RAW_HIGHPREC,
|
||||
POLL_7E4_MAX_TEMPERATURE,
|
||||
POLL_7E4_MIN_TEMPERATURE,
|
||||
POLL_7E4_MIN_CELL_V,
|
||||
POLL_7E4_MAX_CELL_V,
|
||||
POLL_7E4_INTERNAL_RES,
|
||||
POLL_7E4_LOWEST_CELL_NUMBER,
|
||||
POLL_7E4_HIGHEST_CELL_NUMBER,
|
||||
POLL_7E4_VOLTAGE,
|
||||
POLL_7E4_VEHICLE_ISOLATION,
|
||||
POLL_7E4_ISOLATION_TEST_KOHM,
|
||||
POLL_7E4_HV_LOCKED_OUT,
|
||||
POLL_7E4_CRASH_EVENT,
|
||||
POLL_7E4_HVIL,
|
||||
POLL_7E4_HVIL_STATUS,
|
||||
POLL_7E4_CURRENT};
|
||||
|
||||
const uint16_t poll_commands_7E7[108] = {POLL_7E7_CURRENT, POLL_7E7_5V_REF,
|
||||
POLL_7E7_MODULE_TEMP_1, POLL_7E7_MODULE_TEMP_2,
|
||||
POLL_7E7_MODULE_TEMP_3, POLL_7E7_MODULE_TEMP_4,
|
||||
POLL_7E7_MODULE_TEMP_5, POLL_7E7_MODULE_TEMP_6,
|
||||
POLL_7E7_CELL_AVG_VOLTAGE, POLL_7E7_CELL_AVG_VOLTAGE_2,
|
||||
POLL_7E7_TERMINAL_VOLTAGE, POLL_7E7_IGNITION_POWER_MODE,
|
||||
POLL_7E7_CELL_01, POLL_7E7_CELL_02,
|
||||
POLL_7E7_CELL_03, POLL_7E7_CELL_04,
|
||||
POLL_7E7_CELL_05, POLL_7E7_CELL_06,
|
||||
POLL_7E7_CELL_07, POLL_7E7_CELL_08,
|
||||
POLL_7E7_CELL_09, POLL_7E7_CELL_10,
|
||||
POLL_7E7_CELL_11, POLL_7E7_CELL_12,
|
||||
POLL_7E7_CELL_13, POLL_7E7_CELL_14,
|
||||
POLL_7E7_CELL_15, POLL_7E7_CELL_16,
|
||||
POLL_7E7_CELL_17, POLL_7E7_CELL_18,
|
||||
POLL_7E7_CELL_19, POLL_7E7_CELL_20,
|
||||
POLL_7E7_CELL_21, POLL_7E7_CELL_22,
|
||||
POLL_7E7_CELL_23, POLL_7E7_CELL_24,
|
||||
POLL_7E7_CELL_25, POLL_7E7_CELL_26,
|
||||
POLL_7E7_CELL_27, POLL_7E7_CELL_28,
|
||||
POLL_7E7_CELL_29, POLL_7E7_CELL_30,
|
||||
POLL_7E7_CELL_31, POLL_7E7_CELL_32,
|
||||
POLL_7E7_CELL_33, POLL_7E7_CELL_34,
|
||||
POLL_7E7_CELL_35, POLL_7E7_CELL_36,
|
||||
POLL_7E7_CELL_37, POLL_7E7_CELL_38,
|
||||
POLL_7E7_CELL_39, POLL_7E7_CELL_40,
|
||||
POLL_7E7_CELL_41, POLL_7E7_CELL_42,
|
||||
POLL_7E7_CELL_43, POLL_7E7_CELL_44,
|
||||
POLL_7E7_CELL_45, POLL_7E7_CELL_46,
|
||||
POLL_7E7_CELL_47, POLL_7E7_CELL_48,
|
||||
POLL_7E7_CELL_49, POLL_7E7_CELL_50,
|
||||
POLL_7E7_CELL_51, POLL_7E7_CELL_52,
|
||||
POLL_7E7_CELL_53, POLL_7E7_CELL_54,
|
||||
POLL_7E7_CELL_55, POLL_7E7_CELL_56,
|
||||
POLL_7E7_CELL_57, POLL_7E7_CELL_58,
|
||||
POLL_7E7_CELL_59, POLL_7E7_CELL_60,
|
||||
POLL_7E7_CELL_61, POLL_7E7_CELL_62,
|
||||
POLL_7E7_CELL_63, POLL_7E7_CELL_64,
|
||||
POLL_7E7_CELL_65, POLL_7E7_CELL_66,
|
||||
POLL_7E7_CELL_67, POLL_7E7_CELL_68,
|
||||
POLL_7E7_CELL_69, POLL_7E7_CELL_70,
|
||||
POLL_7E7_CELL_71, POLL_7E7_CELL_72,
|
||||
POLL_7E7_CELL_73, POLL_7E7_CELL_74,
|
||||
POLL_7E7_CELL_75, POLL_7E7_CELL_76,
|
||||
POLL_7E7_CELL_77, POLL_7E7_CELL_78,
|
||||
POLL_7E7_CELL_79, POLL_7E7_CELL_80,
|
||||
POLL_7E7_CELL_81, POLL_7E7_CELL_82,
|
||||
POLL_7E7_CELL_83, POLL_7E7_CELL_84,
|
||||
POLL_7E7_CELL_85, POLL_7E7_CELL_86,
|
||||
POLL_7E7_CELL_87, POLL_7E7_CELL_88,
|
||||
POLL_7E7_CELL_89, POLL_7E7_CELL_90,
|
||||
POLL_7E7_CELL_91, POLL_7E7_CELL_92,
|
||||
POLL_7E7_CELL_93, POLL_7E7_CELL_94,
|
||||
POLL_7E7_CELL_95, POLL_7E7_CELL_96};
|
||||
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the battery datalayer
|
||||
|
||||
datalayer.battery.status.real_soc = battery_SOC_display;
|
||||
|
||||
//datalayer.battery.status.voltage_dV = battery_voltage * 0.52;
|
||||
datalayer.battery.status.voltage_dV = (battery_voltage_periodic / 8) * 10;
|
||||
|
||||
datalayer.battery.status.current_dA = battery_current_7E7;
|
||||
|
||||
datalayer.battery.info.total_capacity_Wh;
|
||||
|
||||
datalayer.battery.status.remaining_capacity_Wh;
|
||||
|
||||
datalayer.battery.status.soh_pptt;
|
||||
|
||||
datalayer.battery.status.max_discharge_power_W;
|
||||
|
||||
datalayer.battery.status.max_charge_power_W;
|
||||
|
||||
// Store temperatures in an array
|
||||
int16_t temperatures[] = {temperature_1, temperature_2, temperature_3, temperature_4, temperature_5, temperature_6};
|
||||
|
||||
// Initialize highest and lowest to the first element
|
||||
temperature_highest = temperatures[0];
|
||||
temperature_lowest = temperatures[0];
|
||||
|
||||
// Iterate through the array to find the highest and lowest values
|
||||
for (uint8_t i = 1; i < 6; ++i) {
|
||||
if (temperatures[i] > temperature_highest) {
|
||||
temperature_highest = temperatures[i];
|
||||
}
|
||||
if (temperatures[i] < temperature_lowest) {
|
||||
temperature_lowest = temperatures[i];
|
||||
}
|
||||
}
|
||||
|
||||
datalayer.battery.status.temperature_min_dC = temperature_lowest * 10;
|
||||
|
||||
datalayer.battery.status.temperature_max_dC = temperature_highest * 10;
|
||||
|
||||
//Map all cell voltages to the global array
|
||||
memcpy(datalayer.battery.status.cell_voltages_mV, battery_cell_voltages, 96 * sizeof(uint16_t));
|
||||
|
||||
// Update webserver datalayer
|
||||
datalayer_extended.boltampera.battery_5V_ref = battery_5V_ref;
|
||||
datalayer_extended.boltampera.battery_module_temp_1 = battery_module_temp_1;
|
||||
datalayer_extended.boltampera.battery_module_temp_2 = battery_module_temp_2;
|
||||
datalayer_extended.boltampera.battery_module_temp_3 = battery_module_temp_3;
|
||||
datalayer_extended.boltampera.battery_module_temp_4 = battery_module_temp_4;
|
||||
datalayer_extended.boltampera.battery_module_temp_5 = battery_module_temp_5;
|
||||
datalayer_extended.boltampera.battery_module_temp_6 = battery_module_temp_6;
|
||||
datalayer_extended.boltampera.battery_cell_average_voltage = battery_cell_average_voltage;
|
||||
datalayer_extended.boltampera.battery_cell_average_voltage_2 = battery_cell_average_voltage_2;
|
||||
datalayer_extended.boltampera.battery_terminal_voltage = battery_terminal_voltage;
|
||||
datalayer_extended.boltampera.battery_ignition_power_mode = battery_ignition_power_mode;
|
||||
datalayer_extended.boltampera.battery_current_7E7 = battery_current_7E7;
|
||||
datalayer_extended.boltampera.battery_capacity_my17_18 = battery_capacity_my17_18;
|
||||
datalayer_extended.boltampera.battery_capacity_my19plus = battery_capacity_my19plus;
|
||||
datalayer_extended.boltampera.battery_SOC_display = battery_SOC_display;
|
||||
datalayer_extended.boltampera.battery_SOC_raw_highprec = battery_SOC_raw_highprec;
|
||||
datalayer_extended.boltampera.battery_max_temperature = battery_max_temperature;
|
||||
datalayer_extended.boltampera.battery_min_temperature = battery_min_temperature;
|
||||
datalayer_extended.boltampera.battery_min_cell_voltage = battery_min_cell_voltage;
|
||||
datalayer_extended.boltampera.battery_max_cell_voltage = battery_max_cell_voltage;
|
||||
datalayer_extended.boltampera.battery_lowest_cell = battery_lowest_cell;
|
||||
datalayer_extended.boltampera.battery_highest_cell = battery_highest_cell;
|
||||
datalayer_extended.boltampera.battery_internal_resistance = battery_internal_resistance;
|
||||
datalayer_extended.boltampera.battery_voltage_polled = battery_voltage_polled;
|
||||
datalayer_extended.boltampera.battery_vehicle_isolation = battery_vehicle_isolation;
|
||||
datalayer_extended.boltampera.battery_isolation_kohm = battery_isolation_kohm;
|
||||
datalayer_extended.boltampera.battery_HV_locked = battery_HV_locked;
|
||||
datalayer_extended.boltampera.battery_crash_event = battery_crash_event;
|
||||
datalayer_extended.boltampera.battery_HVIL = battery_HVIL;
|
||||
datalayer_extended.boltampera.battery_HVIL_status = battery_HVIL_status;
|
||||
datalayer_extended.boltampera.battery_current_7E4 = battery_current_7E4;
|
||||
}
|
||||
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x200:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7
|
||||
break;
|
||||
case 0x202:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7
|
||||
break;
|
||||
case 0x204:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7
|
||||
break;
|
||||
case 0x206:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7
|
||||
break;
|
||||
case 0x208:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7
|
||||
break;
|
||||
case 0x20C:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x216:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x2C7:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
battery_voltage_periodic = (rx_frame.data.u8[3] << 4) | (rx_frame.data.u8[4] >> 4);
|
||||
break;
|
||||
case 0x260:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x270:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x272:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x274:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x302:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
temperature_1 = ((rx_frame.data.u8[1] / 2) - 40); //Module 1 Temperature
|
||||
temperature_2 = ((rx_frame.data.u8[2] / 2) - 40); //Module 2 Temperature
|
||||
temperature_3 = ((rx_frame.data.u8[3] / 2) - 40); //Module 3 Temperature
|
||||
temperature_4 = ((rx_frame.data.u8[4] / 2) - 40); //Module 4 Temperature
|
||||
temperature_5 = ((rx_frame.data.u8[5] / 2) - 40); //Module 5 Temperature
|
||||
temperature_6 = ((rx_frame.data.u8[6] / 2) - 40); //Module 6 Temperature
|
||||
break;
|
||||
case 0x3E3:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x460:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x5EF:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
break;
|
||||
case 0x7EC: //When polling 7E4 BMS replies with 7EC ??
|
||||
|
||||
if (rx_frame.data.u8[0] == 0x10) { //"PID Header"
|
||||
transmit_can_frame(&BOLT_ACK_7E4, can_config.battery);
|
||||
}
|
||||
|
||||
//Frame 2 & 3 contains reply
|
||||
reply_poll_7E4 = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
|
||||
switch (reply_poll_7E4) {
|
||||
case POLL_7E4_CAPACITY_EST_GEN1:
|
||||
battery_capacity_my17_18 = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]);
|
||||
break;
|
||||
case POLL_7E4_CAPACITY_EST_GEN2:
|
||||
battery_capacity_my19plus = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]);
|
||||
break;
|
||||
case POLL_7E4_SOC_DISPLAY:
|
||||
battery_SOC_display = ((rx_frame.data.u8[4] * 100) / 255);
|
||||
break;
|
||||
case POLL_7E4_SOC_RAW_HIGHPREC:
|
||||
battery_SOC_raw_highprec = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 100) / 65535);
|
||||
break;
|
||||
case POLL_7E4_MAX_TEMPERATURE:
|
||||
battery_max_temperature = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E4_MIN_TEMPERATURE:
|
||||
battery_min_temperature = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E4_MIN_CELL_V:
|
||||
battery_min_cell_voltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 1666;
|
||||
break;
|
||||
case POLL_7E4_MAX_CELL_V:
|
||||
battery_max_cell_voltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 1666;
|
||||
break;
|
||||
case POLL_7E4_INTERNAL_RES:
|
||||
battery_internal_resistance = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 2;
|
||||
break;
|
||||
case POLL_7E4_LOWEST_CELL_NUMBER:
|
||||
battery_lowest_cell = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E4_HIGHEST_CELL_NUMBER:
|
||||
battery_highest_cell = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E4_VOLTAGE:
|
||||
battery_voltage_polled = (((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 0.52);
|
||||
break;
|
||||
case POLL_7E4_VEHICLE_ISOLATION:
|
||||
battery_vehicle_isolation = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]);
|
||||
break;
|
||||
case POLL_7E4_ISOLATION_TEST_KOHM:
|
||||
battery_isolation_kohm = (rx_frame.data.u8[4] * 25);
|
||||
break;
|
||||
case POLL_7E4_HV_LOCKED_OUT:
|
||||
battery_HV_locked = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E4_CRASH_EVENT:
|
||||
battery_crash_event = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E4_HVIL:
|
||||
battery_HVIL = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E4_HVIL_STATUS:
|
||||
battery_HVIL_status = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E4_CURRENT:
|
||||
battery_current_7E4 = (((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / (-6.675));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 0x7EF: //When polling 7E7 BMS replies with 7EF
|
||||
|
||||
if (rx_frame.data.u8[0] == 0x10) { //"PID Header"
|
||||
transmit_can_frame(&BOLT_ACK_7E7, can_config.battery);
|
||||
}
|
||||
|
||||
//Frame 2 & 3 contains reply
|
||||
reply_poll_7E7 = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
|
||||
switch (reply_poll_7E7) {
|
||||
case POLL_7E7_CURRENT:
|
||||
battery_current_7E7 = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
break;
|
||||
case POLL_7E7_5V_REF:
|
||||
battery_5V_ref = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5) / 65535);
|
||||
break;
|
||||
case POLL_7E7_MODULE_TEMP_1:
|
||||
battery_module_temp_1 = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E7_MODULE_TEMP_2:
|
||||
battery_module_temp_2 = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E7_MODULE_TEMP_3:
|
||||
battery_module_temp_3 = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E7_MODULE_TEMP_4:
|
||||
battery_module_temp_4 = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E7_MODULE_TEMP_5:
|
||||
battery_module_temp_5 = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E7_MODULE_TEMP_6:
|
||||
battery_module_temp_6 = (rx_frame.data.u8[4] - 40);
|
||||
break;
|
||||
case POLL_7E7_CELL_AVG_VOLTAGE:
|
||||
battery_cell_average_voltage = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_AVG_VOLTAGE_2:
|
||||
battery_cell_average_voltage_2 = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 8000) * 1000);
|
||||
break;
|
||||
case POLL_7E7_TERMINAL_VOLTAGE:
|
||||
battery_terminal_voltage = rx_frame.data.u8[4] * 2;
|
||||
break;
|
||||
case POLL_7E7_IGNITION_POWER_MODE:
|
||||
battery_ignition_power_mode = rx_frame.data.u8[4];
|
||||
break;
|
||||
case POLL_7E7_CELL_01:
|
||||
battery_cell_voltages[0] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_02:
|
||||
battery_cell_voltages[1] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_03:
|
||||
battery_cell_voltages[2] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_04:
|
||||
battery_cell_voltages[3] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_05:
|
||||
battery_cell_voltages[4] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_06:
|
||||
battery_cell_voltages[5] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_07:
|
||||
battery_cell_voltages[6] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_08:
|
||||
battery_cell_voltages[7] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_09:
|
||||
battery_cell_voltages[8] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_10:
|
||||
battery_cell_voltages[9] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_11:
|
||||
battery_cell_voltages[10] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_12:
|
||||
battery_cell_voltages[11] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_13:
|
||||
battery_cell_voltages[12] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_14:
|
||||
battery_cell_voltages[13] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_15:
|
||||
battery_cell_voltages[14] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_16:
|
||||
battery_cell_voltages[15] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_17:
|
||||
battery_cell_voltages[16] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_18:
|
||||
battery_cell_voltages[17] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_19:
|
||||
battery_cell_voltages[18] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_20:
|
||||
battery_cell_voltages[19] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_21:
|
||||
battery_cell_voltages[20] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_22:
|
||||
battery_cell_voltages[21] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_23:
|
||||
battery_cell_voltages[22] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_24:
|
||||
battery_cell_voltages[23] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_25:
|
||||
battery_cell_voltages[24] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_26:
|
||||
battery_cell_voltages[25] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_27:
|
||||
battery_cell_voltages[26] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_28:
|
||||
battery_cell_voltages[27] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_29:
|
||||
battery_cell_voltages[28] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_30:
|
||||
battery_cell_voltages[29] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_31:
|
||||
battery_cell_voltages[30] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_32:
|
||||
battery_cell_voltages[31] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_33:
|
||||
battery_cell_voltages[32] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_34:
|
||||
battery_cell_voltages[33] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_35:
|
||||
battery_cell_voltages[34] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_36:
|
||||
battery_cell_voltages[35] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_37:
|
||||
battery_cell_voltages[36] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_38:
|
||||
battery_cell_voltages[37] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_39:
|
||||
battery_cell_voltages[38] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_40:
|
||||
battery_cell_voltages[39] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_41:
|
||||
battery_cell_voltages[40] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_42:
|
||||
battery_cell_voltages[41] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_43:
|
||||
battery_cell_voltages[42] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_44:
|
||||
battery_cell_voltages[43] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_45:
|
||||
battery_cell_voltages[44] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_46:
|
||||
battery_cell_voltages[45] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_47:
|
||||
battery_cell_voltages[46] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_48:
|
||||
battery_cell_voltages[47] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_49:
|
||||
battery_cell_voltages[48] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_50:
|
||||
battery_cell_voltages[49] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_51:
|
||||
battery_cell_voltages[50] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_52:
|
||||
battery_cell_voltages[51] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_53:
|
||||
battery_cell_voltages[52] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_54:
|
||||
battery_cell_voltages[53] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_55:
|
||||
battery_cell_voltages[54] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_56:
|
||||
battery_cell_voltages[55] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_57:
|
||||
battery_cell_voltages[56] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_58:
|
||||
battery_cell_voltages[57] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_59:
|
||||
battery_cell_voltages[58] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_60:
|
||||
battery_cell_voltages[59] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_61:
|
||||
battery_cell_voltages[60] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_62:
|
||||
battery_cell_voltages[61] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_63:
|
||||
battery_cell_voltages[62] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_64:
|
||||
battery_cell_voltages[63] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_65:
|
||||
battery_cell_voltages[64] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_66:
|
||||
battery_cell_voltages[65] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_67:
|
||||
battery_cell_voltages[66] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_68:
|
||||
battery_cell_voltages[67] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_69:
|
||||
battery_cell_voltages[68] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_70:
|
||||
battery_cell_voltages[69] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_71:
|
||||
battery_cell_voltages[70] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_72:
|
||||
battery_cell_voltages[71] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_73:
|
||||
battery_cell_voltages[72] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_74:
|
||||
battery_cell_voltages[73] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_75:
|
||||
battery_cell_voltages[74] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_76:
|
||||
battery_cell_voltages[75] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_77:
|
||||
battery_cell_voltages[76] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_78:
|
||||
battery_cell_voltages[77] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_79:
|
||||
battery_cell_voltages[78] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_80:
|
||||
battery_cell_voltages[79] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_81:
|
||||
battery_cell_voltages[80] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_82:
|
||||
battery_cell_voltages[81] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_83:
|
||||
battery_cell_voltages[82] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_84:
|
||||
battery_cell_voltages[83] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_85:
|
||||
battery_cell_voltages[84] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_86:
|
||||
battery_cell_voltages[85] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_87:
|
||||
battery_cell_voltages[86] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_88:
|
||||
battery_cell_voltages[87] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_89:
|
||||
battery_cell_voltages[88] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_90:
|
||||
battery_cell_voltages[89] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_91:
|
||||
battery_cell_voltages[90] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_92:
|
||||
battery_cell_voltages[91] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_93:
|
||||
battery_cell_voltages[92] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_94:
|
||||
battery_cell_voltages[93] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_95:
|
||||
battery_cell_voltages[94] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
case POLL_7E7_CELL_96:
|
||||
battery_cell_voltages[95] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
//Send 20ms message
|
||||
if (currentMillis - previousMillis20ms >= INTERVAL_20_MS) {
|
||||
// Check if sending of CAN messages has been delayed too much.
|
||||
if ((currentMillis - previousMillis20ms >= INTERVAL_20_MS_DELAYED) && (currentMillis > BOOTUP_TIME)) {
|
||||
set_event(EVENT_CAN_OVERRUN, (currentMillis - previousMillis20ms));
|
||||
} else {
|
||||
clear_event(EVENT_CAN_OVERRUN);
|
||||
}
|
||||
previousMillis20ms = currentMillis;
|
||||
transmit_can_frame(&BOLT_778, can_config.battery);
|
||||
}
|
||||
|
||||
//Send 100ms message
|
||||
if (currentMillis - previousMillis100ms >= INTERVAL_100_MS) {
|
||||
previousMillis100ms = currentMillis;
|
||||
|
||||
// Update current poll from the 7E7 array
|
||||
currentpoll_7E7 = poll_commands_7E7[poll_index_7E7];
|
||||
poll_index_7E7 = (poll_index_7E7 + 1) % 108;
|
||||
|
||||
BOLT_POLL_7E7.data.u8[2] = (uint8_t)((currentpoll_7E7 & 0xFF00) >> 8);
|
||||
BOLT_POLL_7E7.data.u8[3] = (uint8_t)(currentpoll_7E7 & 0x00FF);
|
||||
|
||||
transmit_can_frame(&BOLT_POLL_7E7, can_config.battery);
|
||||
}
|
||||
|
||||
//Send 120ms message
|
||||
if (currentMillis - previousMillis120ms >= 120) {
|
||||
previousMillis120ms = currentMillis;
|
||||
|
||||
// Update current poll from the 7E4 array
|
||||
currentpoll_7E4 = poll_commands_7E4[poll_index_7E4];
|
||||
poll_index_7E4 = (poll_index_7E4 + 1) % 19;
|
||||
|
||||
BOLT_POLL_7E4.data.u8[2] = (uint8_t)((currentpoll_7E4 & 0xFF00) >> 8);
|
||||
BOLT_POLL_7E4.data.u8[3] = (uint8_t)(currentpoll_7E4 & 0x00FF);
|
||||
|
||||
transmit_can_frame(&BOLT_POLL_7E4, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
strncpy(datalayer.system.info.battery_protocol, "Chevrolet Bolt EV/Opel Ampera-e", 63);
|
||||
datalayer.system.info.battery_protocol[63] = '\0';
|
||||
datalayer.battery.info.number_of_cells = 96;
|
||||
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
||||
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
|
||||
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.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||
}
|
||||
|
||||
#endif
|
146
Software/src/battery/BOLT-AMPERA-BATTERY.h
Normal file
146
Software/src/battery/BOLT-AMPERA-BATTERY.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
#ifndef BOLT_AMPERA_BATTERY_H
|
||||
#define BOLT_AMPERA_BATTERY_H
|
||||
#include <Arduino.h>
|
||||
#include "../include.h"
|
||||
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
#define MAX_PACK_VOLTAGE_DV 4150 //5000 = 500.0V
|
||||
#define MIN_PACK_VOLTAGE_DV 2500
|
||||
#define MAX_CELL_DEVIATION_MV 500
|
||||
#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
|
||||
|
||||
#define POLL_7E4_CAPACITY_EST_GEN1 0x41A3
|
||||
#define POLL_7E4_CAPACITY_EST_GEN2 0x45F9
|
||||
#define POLL_7E4_SOC_DISPLAY 0x8334
|
||||
#define POLL_7E4_SOC_RAW_HIGHPREC 0x43AF
|
||||
#define POLL_7E4_MAX_TEMPERATURE 0x4349
|
||||
#define POLL_7E4_MIN_TEMPERATURE 0x434A
|
||||
#define POLL_7E4_MIN_CELL_V 0x4329
|
||||
#define POLL_7E4_MAX_CELL_V 0x432B
|
||||
#define POLL_7E4_INTERNAL_RES 0x40E9
|
||||
#define POLL_7E4_LOWEST_CELL_NUMBER 0x433B
|
||||
#define POLL_7E4_HIGHEST_CELL_NUMBER 0x433C
|
||||
#define POLL_7E4_VOLTAGE 0x432D
|
||||
#define POLL_7E4_VEHICLE_ISOLATION 0x41EC
|
||||
#define POLL_7E4_ISOLATION_TEST_KOHM 0x43A6
|
||||
#define POLL_7E4_HV_LOCKED_OUT 0x44F8
|
||||
#define POLL_7E4_CRASH_EVENT 0x4522
|
||||
#define POLL_7E4_HVIL 0x4310
|
||||
#define POLL_7E4_HVIL_STATUS 0x4311
|
||||
#define POLL_7E4_CURRENT 0x4356
|
||||
|
||||
#define POLL_7E7_CURRENT 0x40D4
|
||||
#define POLL_7E7_5V_REF 0x40D3
|
||||
#define POLL_7E7_MODULE_TEMP_1 0x40D7
|
||||
#define POLL_7E7_MODULE_TEMP_2 0x40D9
|
||||
#define POLL_7E7_MODULE_TEMP_3 0x40DB
|
||||
#define POLL_7E7_MODULE_TEMP_4 0x40DD
|
||||
#define POLL_7E7_MODULE_TEMP_5 0x40DF
|
||||
#define POLL_7E7_MODULE_TEMP_6 0x40E1
|
||||
#define POLL_7E7_CELL_AVG_VOLTAGE 0xC218
|
||||
#define POLL_7E7_CELL_AVG_VOLTAGE_2 0x44B9
|
||||
#define POLL_7E7_TERMINAL_VOLTAGE 0x82A3
|
||||
#define POLL_7E7_IGNITION_POWER_MODE 0x8002
|
||||
#define POLL_7E7_CELL_01 0x4181
|
||||
#define POLL_7E7_CELL_02 0x4182
|
||||
#define POLL_7E7_CELL_03 0x4183
|
||||
#define POLL_7E7_CELL_04 0x4184
|
||||
#define POLL_7E7_CELL_05 0x4185
|
||||
#define POLL_7E7_CELL_06 0x4186
|
||||
#define POLL_7E7_CELL_07 0x4187
|
||||
#define POLL_7E7_CELL_08 0x4188
|
||||
#define POLL_7E7_CELL_09 0x4189
|
||||
#define POLL_7E7_CELL_10 0x418A
|
||||
#define POLL_7E7_CELL_11 0x418B
|
||||
#define POLL_7E7_CELL_12 0x418C
|
||||
#define POLL_7E7_CELL_13 0x418D
|
||||
#define POLL_7E7_CELL_14 0x418E
|
||||
#define POLL_7E7_CELL_15 0x418F
|
||||
#define POLL_7E7_CELL_16 0x4190
|
||||
#define POLL_7E7_CELL_17 0x4191
|
||||
#define POLL_7E7_CELL_18 0x4192
|
||||
#define POLL_7E7_CELL_19 0x4193
|
||||
#define POLL_7E7_CELL_20 0x4194
|
||||
#define POLL_7E7_CELL_21 0x4195
|
||||
#define POLL_7E7_CELL_22 0x4196
|
||||
#define POLL_7E7_CELL_23 0x4197
|
||||
#define POLL_7E7_CELL_24 0x4198
|
||||
#define POLL_7E7_CELL_25 0x4199
|
||||
#define POLL_7E7_CELL_26 0x419A
|
||||
#define POLL_7E7_CELL_27 0x419B
|
||||
#define POLL_7E7_CELL_28 0x419C
|
||||
#define POLL_7E7_CELL_29 0x419D
|
||||
#define POLL_7E7_CELL_30 0x419E
|
||||
#define POLL_7E7_CELL_31 0x419F
|
||||
#define POLL_7E7_CELL_32 0x4200
|
||||
#define POLL_7E7_CELL_33 0x4201
|
||||
#define POLL_7E7_CELL_34 0x4202
|
||||
#define POLL_7E7_CELL_35 0x4203
|
||||
#define POLL_7E7_CELL_36 0x4204
|
||||
#define POLL_7E7_CELL_37 0x4205
|
||||
#define POLL_7E7_CELL_38 0x4206
|
||||
#define POLL_7E7_CELL_39 0x4207
|
||||
#define POLL_7E7_CELL_40 0x4208
|
||||
#define POLL_7E7_CELL_41 0x4209
|
||||
#define POLL_7E7_CELL_42 0x420A
|
||||
#define POLL_7E7_CELL_43 0x420B
|
||||
#define POLL_7E7_CELL_44 0x420C
|
||||
#define POLL_7E7_CELL_45 0x420D
|
||||
#define POLL_7E7_CELL_46 0x420E
|
||||
#define POLL_7E7_CELL_47 0x420F
|
||||
#define POLL_7E7_CELL_48 0x4210
|
||||
#define POLL_7E7_CELL_49 0x4211
|
||||
#define POLL_7E7_CELL_50 0x4212
|
||||
#define POLL_7E7_CELL_51 0x4213
|
||||
#define POLL_7E7_CELL_52 0x4214
|
||||
#define POLL_7E7_CELL_53 0x4215
|
||||
#define POLL_7E7_CELL_54 0x4216
|
||||
#define POLL_7E7_CELL_55 0x4217
|
||||
#define POLL_7E7_CELL_56 0x4218
|
||||
#define POLL_7E7_CELL_57 0x4219
|
||||
#define POLL_7E7_CELL_58 0x421A
|
||||
#define POLL_7E7_CELL_59 0x421B
|
||||
#define POLL_7E7_CELL_60 0x421C
|
||||
#define POLL_7E7_CELL_61 0x421D
|
||||
#define POLL_7E7_CELL_62 0x421E
|
||||
#define POLL_7E7_CELL_63 0x421F
|
||||
#define POLL_7E7_CELL_64 0x4220
|
||||
#define POLL_7E7_CELL_65 0x4221
|
||||
#define POLL_7E7_CELL_66 0x4222
|
||||
#define POLL_7E7_CELL_67 0x4223
|
||||
#define POLL_7E7_CELL_68 0x4224
|
||||
#define POLL_7E7_CELL_69 0x4225
|
||||
#define POLL_7E7_CELL_70 0x4226
|
||||
#define POLL_7E7_CELL_71 0x4227
|
||||
#define POLL_7E7_CELL_72 0x4228
|
||||
#define POLL_7E7_CELL_73 0x4229
|
||||
#define POLL_7E7_CELL_74 0x422A
|
||||
#define POLL_7E7_CELL_75 0x422B
|
||||
#define POLL_7E7_CELL_76 0x422C
|
||||
#define POLL_7E7_CELL_77 0x422D
|
||||
#define POLL_7E7_CELL_78 0x422E
|
||||
#define POLL_7E7_CELL_79 0x422F
|
||||
#define POLL_7E7_CELL_80 0x4230
|
||||
#define POLL_7E7_CELL_81 0x4231
|
||||
#define POLL_7E7_CELL_82 0x4232
|
||||
#define POLL_7E7_CELL_83 0x4233
|
||||
#define POLL_7E7_CELL_84 0x4234
|
||||
#define POLL_7E7_CELL_85 0x4235
|
||||
#define POLL_7E7_CELL_86 0x4236
|
||||
#define POLL_7E7_CELL_87 0x4237
|
||||
#define POLL_7E7_CELL_88 0x4238
|
||||
#define POLL_7E7_CELL_89 0x4239
|
||||
#define POLL_7E7_CELL_90 0x423A
|
||||
#define POLL_7E7_CELL_91 0x423B
|
||||
#define POLL_7E7_CELL_92 0x423C
|
||||
#define POLL_7E7_CELL_93 0x423D
|
||||
#define POLL_7E7_CELL_94 0x423E
|
||||
#define POLL_7E7_CELL_95 0x423F
|
||||
#define POLL_7E7_CELL_96 0x4240
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
|
@ -162,7 +162,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer_extended.bydAtto3.voltage_polled = BMS_voltage;
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) { //Log values taken with 422V from battery
|
||||
case 0x244: //00,00,00,04,41,0F,20,8B - Static, values never changes between logs
|
||||
break;
|
||||
|
@ -292,7 +292,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
//Send 50ms message
|
||||
if (currentMillis - previousMillis50 >= INTERVAL_50_MS) {
|
||||
|
@ -334,9 +334,9 @@ void send_can_battery() {
|
|||
ATTO_3_12D.data.u8[6] = (0x0F | (frame6_counter << 4));
|
||||
ATTO_3_12D.data.u8[7] = (0x09 | (frame7_counter << 4));
|
||||
|
||||
transmit_can(&ATTO_3_12D, can_config.battery);
|
||||
transmit_can_frame(&ATTO_3_12D, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&ATTO_3_12D, can_config.battery_double);
|
||||
transmit_can_frame(&ATTO_3_12D, can_config.battery_double);
|
||||
#endif //DOUBLE_BATTERY
|
||||
}
|
||||
// Send 100ms CAN Message
|
||||
|
@ -355,9 +355,9 @@ void send_can_battery() {
|
|||
ATTO_3_441.data.u8[7] = 0xF5;
|
||||
}
|
||||
|
||||
transmit_can(&ATTO_3_441, can_config.battery);
|
||||
transmit_can_frame(&ATTO_3_441, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&ATTO_3_441, can_config.battery_double);
|
||||
transmit_can_frame(&ATTO_3_441, can_config.battery_double);
|
||||
#endif //DOUBLE_BATTERY
|
||||
}
|
||||
// Send 500ms CAN Message
|
||||
|
@ -402,9 +402,9 @@ void send_can_battery() {
|
|||
break;
|
||||
}
|
||||
|
||||
transmit_can(&ATTO_3_7E7_POLL, can_config.battery);
|
||||
transmit_can_frame(&ATTO_3_7E7_POLL, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&ATTO_3_7E7_POLL, can_config.battery_double);
|
||||
transmit_can_frame(&ATTO_3_7E7_POLL, can_config.battery_double);
|
||||
#endif //DOUBLE_BATTERY
|
||||
}
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ void update_values_battery2() { //This function maps all the values fetched via
|
|||
datalayer.battery2.status.temperature_max_dC = battery2_calc_max_temperature * 10;
|
||||
}
|
||||
|
||||
void receive_can_battery2(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) { //Log values taken with 422V from battery2
|
||||
case 0x244: //00,00,00,04,41,0F,20,8B - Static, values never changes between logs
|
||||
break;
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2800 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -213,7 +213,7 @@ void update_values_battery() {
|
|||
//TODO, shall we react on this?
|
||||
}
|
||||
}
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
|
||||
switch (rx_frame.ID) {
|
||||
case 0x1A4: //PDO1_TX - 200ms
|
||||
|
@ -316,7 +316,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 1s CAN Message
|
||||
if (currentMillis - previousMillis1s >= INTERVAL_1_S) {
|
||||
|
@ -324,10 +324,10 @@ void send_can_battery() {
|
|||
previousMillis1s = currentMillis;
|
||||
|
||||
/*
|
||||
transmit_can(&CELLPOWER_18FF50E9, can_config.battery);
|
||||
transmit_can(&CELLPOWER_18FF50E8, can_config.battery);
|
||||
transmit_can(&CELLPOWER_18FF50E7, can_config.battery);
|
||||
transmit_can(&CELLPOWER_18FF50E5, can_config.battery);
|
||||
transmit_can_frame(&CELLPOWER_18FF50E9, can_config.battery);
|
||||
transmit_can_frame(&CELLPOWER_18FF50E8, can_config.battery);
|
||||
transmit_can_frame(&CELLPOWER_18FF50E7, can_config.battery);
|
||||
transmit_can_frame(&CELLPOWER_18FF50E5, can_config.battery);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
#define NATIVECAN_250KBPS
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -197,13 +197,13 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
x102_chg_session.ChargingCurrentRequest = newChargingCurrentRequest;
|
||||
x102_chg_session.TargetBatteryVoltage = newTargetBatteryVoltage;
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
//Note on p131
|
||||
uint8_t chargingrate = 0;
|
||||
if (x100_chg_lim.ConstantOfChargingRateIndication > 0) {
|
||||
chargingrate = x102_chg_session.StateOfCharge / x100_chg_lim.ConstantOfChargingRateIndication * 100;
|
||||
Serial.print("Charge Rate (kW): ");
|
||||
Serial.println(chargingrate);
|
||||
logging.print("Charge Rate (kW): ");
|
||||
logging.println(chargingrate);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -217,40 +217,40 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
*/
|
||||
if ((CHADEMO_Status == CHADEMO_INIT && vehicle_permission) ||
|
||||
(x102_chg_session.s.status.StatusVehicleChargingEnabled && !vehicle_permission)) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Inconsistent charge/discharge state.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inconsistent charge/discharge state.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_FAULT;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryOverVoltage) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Vehicle indicates fault, battery over voltage.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery over voltage.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryUnderVoltage) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Vehicle indicates fault, battery under voltage.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery under voltage.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryCurrentDeviation) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Vehicle indicates fault, battery current deviation. Possible EVSE issue?");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery current deviation. Possible EVSE issue?");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryVoltageDeviation) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Vehicle indicates fault, battery voltage deviation. Possible EVSE issue?");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery voltage deviation. Possible EVSE issue?");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
|
@ -264,8 +264,8 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
|
||||
//FIXME condition nesting or more stanzas needed here for clear determination of cessation reason
|
||||
if (CHADEMO_Status == CHADEMO_POWERFLOW && EVSE_mode == CHADEMO_CHARGE && !vehicle_permission) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("State of charge ceiling reached or charging interrupted, stop charging");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("State of charge ceiling reached or charging interrupted, stop charging");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
|
@ -273,8 +273,8 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
|
||||
if (vehicle_permission && CHADEMO_Status == CHADEMO_NEGOTIATE) {
|
||||
CHADEMO_Status = CHADEMO_EV_ALLOWED;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("STATE shift to CHADEMO_EV_ALLOWED in process_vehicle_charging_session()");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("STATE shift to CHADEMO_EV_ALLOWED in process_vehicle_charging_session()");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -284,22 +284,22 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
// consider relocating
|
||||
if (vehicle_permission && CHADEMO_Status == CHADEMO_EVSE_PREPARE && priorTargetBatteryVoltage == 0 &&
|
||||
newTargetBatteryVoltage > 0 && x102_chg_session.s.status.StatusVehicleChargingEnabled) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("STATE SHIFT to EVSE_START reached in process_vehicle_charging_session()");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("STATE SHIFT to EVSE_START reached in process_vehicle_charging_session()");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_EVSE_START;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vehicle_permission && evse_permission && CHADEMO_Status == CHADEMO_POWERFLOW) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("updating vehicle request in process_vehicle_charging_session()");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("updating vehicle request in process_vehicle_charging_session()");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("UNHANDLED STATE IN process_vehicle_charging_session()");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("UNHANDLED STATE IN process_vehicle_charging_session()");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -312,20 +312,20 @@ inline void process_vehicle_charging_limits(CAN_frame rx_frame) {
|
|||
x200_discharge_limits.MinimumBatteryDischargeLevel = rx_frame.data.u8[6];
|
||||
x200_discharge_limits.MaxRemainingCapacityForCharging = rx_frame.data.u8[7];
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
/* unsigned long currentMillis = millis();
|
||||
if (currentMillis - previousMillis5000 >= INTERVAL_5_S) {
|
||||
previousMillis5000 = currentMillis;
|
||||
Serial.println("x200 Max remaining capacity for charging/discharging:");
|
||||
logging.println("x200 Max remaining capacity for charging/discharging:");
|
||||
// initially this is set to 0, which is represented as 0xFF
|
||||
Serial.println(0xFF - x200_discharge_limits.MaxRemainingCapacityForCharging);
|
||||
logging.println(0xFF - x200_discharge_limits.MaxRemainingCapacityForCharging);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (get_measured_voltage() <= x200_discharge_limits.MinimumDischargeVoltage && CHADEMO_Status > CHADEMO_NEGOTIATE) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("x200 minimum discharge voltage met or exceeded, stopping.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("x200 minimum discharge voltage met or exceeded, stopping.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
@ -341,13 +341,13 @@ inline void process_vehicle_discharge_estimate(CAN_frame rx_frame) {
|
|||
x201_discharge_estimate.ApproxDischargeCompletionTime = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]);
|
||||
x201_discharge_estimate.AvailableVehicleEnergy = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[3]);
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
if (currentMillis - previousMillis5000 >= INTERVAL_5_S) {
|
||||
previousMillis5000 = currentMillis;
|
||||
Serial.print("x201 availabile vehicle energy, completion time: ");
|
||||
Serial.println(x201_discharge_estimate.AvailableVehicleEnergy);
|
||||
Serial.print("x201 approx vehicle completion time: ");
|
||||
Serial.println(x201_discharge_estimate.ApproxDischargeCompletionTime);
|
||||
logging.print("x201 availabile vehicle energy, completion time: ");
|
||||
logging.println(x201_discharge_estimate.AvailableVehicleEnergy);
|
||||
logging.print("x201 approx vehicle completion time: ");
|
||||
logging.println(x201_discharge_estimate.ApproxDischargeCompletionTime);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -367,19 +367,19 @@ inline void process_vehicle_vendor_ID(CAN_frame rx_frame) {
|
|||
((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]); //Actually more bytes, but not needed for our purpose
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
#ifdef CH_CAN_DEBUG
|
||||
Serial.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.ID, HEX);
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.DLC);
|
||||
Serial.print(" ");
|
||||
logging.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
logging.print(" ");
|
||||
logging.print(rx_frame.ID, HEX);
|
||||
logging.print(" ");
|
||||
logging.print(rx_frame.DLC);
|
||||
logging.print(" ");
|
||||
for (int i = 0; i < rx_frame.DLC; ++i) {
|
||||
Serial.print(rx_frame.data.u8[i], HEX);
|
||||
Serial.print(" ");
|
||||
logging.print(rx_frame.data.u8[i], HEX);
|
||||
logging.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
#endif
|
||||
|
||||
// CHADEMO coexists with a CAN-based shunt. Only process CHADEMO-specific IDs
|
||||
|
@ -657,7 +657,7 @@ void update_evse_discharge_capabilities(CAN_frame& f) {
|
|||
CHADEMO_208.data.u8[7] = highByte(x208_evse_dischg_cap.lower_threshold_voltage);
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
|
@ -693,8 +693,8 @@ void send_can_battery() {
|
|||
* that is the limiting factor. Therefore, we
|
||||
* can generally send as is without tweaks here.
|
||||
*/
|
||||
transmit_can(&CHADEMO_108, can_config.battery);
|
||||
transmit_can(&CHADEMO_109, can_config.battery);
|
||||
transmit_can_frame(&CHADEMO_108, can_config.battery);
|
||||
transmit_can_frame(&CHADEMO_109, can_config.battery);
|
||||
|
||||
/* TODO for dynamic control: can send x118 with byte 6 bit 0 set to 0 for 1s (before flipping back to 1) as a way of giving vehicle a chance to update 101.1 and 101.2
|
||||
* within 6 seconds of x118 toggle.
|
||||
|
@ -703,9 +703,9 @@ void send_can_battery() {
|
|||
*/
|
||||
|
||||
if (EVSE_mode == CHADEMO_DISCHARGE || EVSE_mode == CHADEMO_BIDIRECTIONAL) {
|
||||
transmit_can(&CHADEMO_208, can_config.battery);
|
||||
transmit_can_frame(&CHADEMO_208, can_config.battery);
|
||||
if (x201_received) {
|
||||
transmit_can(&CHADEMO_209, can_config.battery);
|
||||
transmit_can_frame(&CHADEMO_209, can_config.battery);
|
||||
x209_sent = true;
|
||||
}
|
||||
}
|
||||
|
@ -713,11 +713,11 @@ void send_can_battery() {
|
|||
// TODO need an update_evse_dynamic_control(..) function above before we send 118
|
||||
// 110.0.0
|
||||
if (x102_chg_session.ControlProtocolNumberEV >= 0x03) { //Only send the following on Chademo 2.0 vehicles?
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
//FIXME REMOVE
|
||||
Serial.println("REMOVE: proto 2.0");
|
||||
logging.println("REMOVE: proto 2.0");
|
||||
#endif
|
||||
transmit_can(&CHADEMO_118, can_config.battery);
|
||||
transmit_can_frame(&CHADEMO_118, can_config.battery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -753,15 +753,15 @@ void handle_chademo_sequence() {
|
|||
/* ------------------- State override conditions checks ------------------- */
|
||||
/* ------------------------------------------------------------------------------ */
|
||||
if (CHADEMO_Status >= CHADEMO_EV_ALLOWED && x102_chg_session.s.status.StatusVehicleShifterPosition) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Vehicle is not parked, abort.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle is not parked, abort.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
||||
if (CHADEMO_Status >= CHADEMO_EV_ALLOWED && !vehicle_permission) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Vehicle charge/discharge permission ended, stop.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle charge/discharge permission ended, stop.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
@ -775,24 +775,24 @@ void handle_chademo_sequence() {
|
|||
plug_inserted = digitalRead(CHADEMO_PIN_7);
|
||||
|
||||
if (!plug_inserted) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
// Serial.println("CHADEMO plug is not inserted.");
|
||||
// logging.println("CHADEMO plug is not inserted.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
CHADEMO_Status = CHADEMO_CONNECTED;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CHADEMO plug is inserted. Provide EVSE power to vehicle to trigger initialization.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CHADEMO plug is inserted. Provide EVSE power to vehicle to trigger initialization.");
|
||||
#endif
|
||||
|
||||
break;
|
||||
case CHADEMO_CONNECTED:
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
//Serial.println("CHADEMO_CONNECTED State");
|
||||
//logging.println("CHADEMO_CONNECTED State");
|
||||
#endif
|
||||
/* plug_inserted is .. essentially a volatile of sorts, so verify */
|
||||
if (plug_inserted) {
|
||||
|
@ -810,8 +810,8 @@ void handle_chademo_sequence() {
|
|||
* with timers to have higher confidence of certain conditions hitting
|
||||
* a steady state
|
||||
*/
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CHADEMO plug is not inserted, cannot connect d2 relay to begin initialization.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CHADEMO plug is not inserted, cannot connect d2 relay to begin initialization.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_IDLE;
|
||||
}
|
||||
|
@ -819,10 +819,10 @@ void handle_chademo_sequence() {
|
|||
case CHADEMO_INIT:
|
||||
/* Transient state while awaiting CAN from Vehicle.
|
||||
* Used for triggers/error handling elsewhere;
|
||||
* State change to CHADEMO_NEGOTIATE occurs in receive_can_battery(..)
|
||||
* State change to CHADEMO_NEGOTIATE occurs in handle_incoming_can_frame_battery(..)
|
||||
*/
|
||||
#ifdef DEBUG_VIA_USB
|
||||
// Serial.println("Awaiting initial vehicle CAN to trigger negotiation");
|
||||
#ifdef DEBUG_LOG
|
||||
// logging.println("Awaiting initial vehicle CAN to trigger negotiation");
|
||||
#endif
|
||||
evse_init();
|
||||
break;
|
||||
|
@ -830,16 +830,16 @@ void handle_chademo_sequence() {
|
|||
/* Vehicle and EVSE dance */
|
||||
//TODO if pin 4 / j goes high,
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
// Serial.println("CHADEMO_NEGOTIATE State");
|
||||
// logging.println("CHADEMO_NEGOTIATE State");
|
||||
#endif
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
break;
|
||||
case CHADEMO_EV_ALLOWED:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_EV_ALLOWED State");
|
||||
logging.println("CHADEMO_EV_ALLOWED State");
|
||||
#endif
|
||||
// If we are in this state, vehicle_permission was already set to true...but re-verify
|
||||
// that pin 4 (j) reads high
|
||||
|
@ -855,9 +855,9 @@ void handle_chademo_sequence() {
|
|||
}
|
||||
break;
|
||||
case CHADEMO_EVSE_PREPARE:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_EVSE_PREPARE State");
|
||||
logging.println("CHADEMO_EVSE_PREPARE State");
|
||||
#endif
|
||||
/* TODO voltage check of output < 20v
|
||||
* insulation test hypothetically happens here before triggering PIN 10 high
|
||||
|
@ -878,7 +878,7 @@ void handle_chademo_sequence() {
|
|||
digitalWrite(CHADEMO_PIN_10, HIGH);
|
||||
evse_permission = true;
|
||||
} else {
|
||||
Serial.println("Insulation check measures > 20v ");
|
||||
logging.println("Insulation check measures > 20v ");
|
||||
}
|
||||
|
||||
// likely unnecessary but just to be sure. consider removal
|
||||
|
@ -891,9 +891,9 @@ void handle_chademo_sequence() {
|
|||
//state changes to CHADEMO_EVSE_START only upon receipt of charging session request
|
||||
break;
|
||||
case CHADEMO_EVSE_START:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_EVSE_START State");
|
||||
logging.println("CHADEMO_EVSE_START State");
|
||||
#endif
|
||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
|
@ -901,8 +901,8 @@ void handle_chademo_sequence() {
|
|||
|
||||
CHADEMO_Status = CHADEMO_EVSE_CONTACTORS_ENABLED;
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Initiating contactors");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Initiating contactors");
|
||||
#endif
|
||||
|
||||
/* break rather than fall through because contactors are not instantaneous;
|
||||
|
@ -911,17 +911,17 @@ void handle_chademo_sequence() {
|
|||
|
||||
break;
|
||||
case CHADEMO_EVSE_CONTACTORS_ENABLED:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_EVSE_CONTACTORS State");
|
||||
logging.println("CHADEMO_EVSE_CONTACTORS State");
|
||||
#endif
|
||||
|
||||
/* check whether contactors ready, because externally dependent upon inverter allow during discharge */
|
||||
if (contactors_ready) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Contactors ready");
|
||||
Serial.print("Voltage: ");
|
||||
Serial.println(get_measured_voltage());
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Contactors ready");
|
||||
logging.print("Voltage: ");
|
||||
logging.println(get_measured_voltage());
|
||||
#endif
|
||||
/* transition to POWERFLOW state if discharge compatible on both sides */
|
||||
if (x109_evse_state.discharge_compatible && x102_chg_session.s.status.StatusVehicleDischargeCompatible &&
|
||||
|
@ -941,9 +941,9 @@ void handle_chademo_sequence() {
|
|||
/* break or fall through ? TODO */
|
||||
break;
|
||||
case CHADEMO_POWERFLOW:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_POWERFLOW State");
|
||||
logging.println("CHADEMO_POWERFLOW State");
|
||||
#endif
|
||||
/* POWERFLOW for charging, discharging, and bidirectional */
|
||||
/* Interpretation */
|
||||
|
@ -961,8 +961,8 @@ void handle_chademo_sequence() {
|
|||
}
|
||||
|
||||
if (get_measured_voltage() <= x200_discharge_limits.MinimumDischargeVoltage) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("x200 minimum discharge voltage met or exceeded, stopping.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("x200 minimum discharge voltage met or exceeded, stopping.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
@ -972,9 +972,9 @@ void handle_chademo_sequence() {
|
|||
x109_evse_state.s.status.EVSE_status = 1;
|
||||
break;
|
||||
case CHADEMO_STOP:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_STOP State");
|
||||
logging.println("CHADEMO_STOP State");
|
||||
#endif
|
||||
/* back to CHADEMO_IDLE after teardown */
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
|
@ -1000,16 +1000,16 @@ void handle_chademo_sequence() {
|
|||
|
||||
break;
|
||||
case CHADEMO_FAULT:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
Serial.println("CHADEMO_FAULT State");
|
||||
logging.println("CHADEMO_FAULT State");
|
||||
#endif
|
||||
/* Once faulted, never departs CHADEMO_FAULT state unless device is power cycled as a safety measure */
|
||||
x109_evse_state.s.status.EVSE_error = 1;
|
||||
x109_evse_state.s.status.ChgDischError = 1;
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CHADEMO fault encountered, tearing down to make safe");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CHADEMO fault encountered, tearing down to make safe");
|
||||
#endif
|
||||
digitalWrite(CHADEMO_PIN_10, LOW);
|
||||
digitalWrite(CHADEMO_PIN_2, LOW);
|
||||
|
@ -1020,8 +1020,8 @@ void handle_chademo_sequence() {
|
|||
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("UNHANDLED CHADEMO_STATE, setting FAULT");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("UNHANDLED CHADEMO_STATE, setting FAULT");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_FAULT;
|
||||
break;
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
#define ISA_SHUNT
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -91,17 +91,17 @@ void ISA_handleFrame(CAN_frame* frame) {
|
|||
|
||||
case 0x510:
|
||||
case 0x511:
|
||||
Serial.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
Serial.print(" ");
|
||||
Serial.print(frame->ID, HEX);
|
||||
Serial.print(" ");
|
||||
Serial.print(frame->DLC);
|
||||
Serial.print(" ");
|
||||
logging.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
logging.print(" ");
|
||||
logging.print(frame->ID, HEX);
|
||||
logging.print(" ");
|
||||
logging.print(frame->DLC);
|
||||
logging.print(" ");
|
||||
for (int i = 0; i < frame->DLC; ++i) {
|
||||
Serial.print(frame->data.u8[i], HEX);
|
||||
Serial.print(" ");
|
||||
logging.print(frame->data.u8[i], HEX);
|
||||
logging.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
break;
|
||||
|
||||
case 0x521:
|
||||
|
@ -245,8 +245,8 @@ void ISA_initialize() {
|
|||
ISA_STOP();
|
||||
delay(500);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Serial.print("ISA Initialization ");
|
||||
Serial.println(i);
|
||||
logging.print("ISA Initialization ");
|
||||
logging.println(i);
|
||||
|
||||
outframe.data.u8[0] = (0x20 + i);
|
||||
outframe.data.u8[1] = 0x02;
|
||||
|
@ -257,7 +257,7 @@ void ISA_initialize() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ void ISA_initialize() {
|
|||
}
|
||||
|
||||
void ISA_STOP() {
|
||||
Serial.println("ISA STOP");
|
||||
logging.println("ISA STOP");
|
||||
|
||||
outframe.data.u8[0] = 0x34;
|
||||
outframe.data.u8[1] = 0x00;
|
||||
|
@ -282,11 +282,11 @@ void ISA_STOP() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
|
||||
void ISA_sendSTORE() {
|
||||
Serial.println("ISA send STORE");
|
||||
logging.println("ISA send STORE");
|
||||
|
||||
outframe.data.u8[0] = 0x32;
|
||||
outframe.data.u8[1] = 0x00;
|
||||
|
@ -297,11 +297,11 @@ void ISA_sendSTORE() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
|
||||
void ISA_START() {
|
||||
Serial.println("ISA START");
|
||||
logging.println("ISA START");
|
||||
|
||||
outframe.data.u8[0] = 0x34;
|
||||
outframe.data.u8[1] = 0x01;
|
||||
|
@ -312,12 +312,12 @@ void ISA_START() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
|
||||
void ISA_RESTART() {
|
||||
//Has the effect of zeroing AH and KWH
|
||||
Serial.println("ISA RESTART");
|
||||
logging.println("ISA RESTART");
|
||||
|
||||
outframe.data.u8[0] = 0x3F;
|
||||
outframe.data.u8[1] = 0x00;
|
||||
|
@ -328,7 +328,7 @@ void ISA_RESTART() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
|
||||
void ISA_deFAULT() {
|
||||
|
@ -336,7 +336,7 @@ void ISA_deFAULT() {
|
|||
ISA_STOP();
|
||||
delay(500);
|
||||
|
||||
Serial.println("ISA RESTART to default");
|
||||
logging.println("ISA RESTART to default");
|
||||
|
||||
outframe.data.u8[0] = 0x3D;
|
||||
outframe.data.u8[1] = 0x00;
|
||||
|
@ -347,7 +347,7 @@ void ISA_deFAULT() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
delay(500);
|
||||
|
||||
ISA_START();
|
||||
|
@ -358,7 +358,7 @@ void ISA_initCurrent() {
|
|||
ISA_STOP();
|
||||
delay(500);
|
||||
|
||||
Serial.println("ISA Initialization Current");
|
||||
logging.println("ISA Initialization Current");
|
||||
|
||||
outframe.data.u8[0] = 0x21;
|
||||
outframe.data.u8[1] = 0x02;
|
||||
|
@ -369,7 +369,7 @@ void ISA_initCurrent() {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
delay(500);
|
||||
|
||||
ISA_sendSTORE();
|
||||
|
@ -382,8 +382,8 @@ void ISA_initCurrent() {
|
|||
}
|
||||
|
||||
void ISA_getCONFIG(uint8_t i) {
|
||||
Serial.print("ISA Get Config ");
|
||||
Serial.println(i);
|
||||
logging.print("ISA Get Config ");
|
||||
logging.println(i);
|
||||
|
||||
outframe.data.u8[0] = (0x60 + i);
|
||||
outframe.data.u8[1] = 0x00;
|
||||
|
@ -394,12 +394,12 @@ void ISA_getCONFIG(uint8_t i) {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
|
||||
void ISA_getCAN_ID(uint8_t i) {
|
||||
Serial.print("ISA Get CAN ID ");
|
||||
Serial.println(i);
|
||||
logging.print("ISA Get CAN ID ");
|
||||
logging.println(i);
|
||||
|
||||
outframe.data.u8[0] = (0x50 + i);
|
||||
if (i == 8)
|
||||
|
@ -414,12 +414,12 @@ void ISA_getCAN_ID(uint8_t i) {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
|
||||
void ISA_getINFO(uint8_t i) {
|
||||
Serial.print("ISA Get INFO ");
|
||||
Serial.println(i, HEX);
|
||||
logging.print("ISA Get INFO ");
|
||||
logging.println(i, HEX);
|
||||
|
||||
outframe.data.u8[0] = (0x70 + i);
|
||||
outframe.data.u8[1] = 0x00;
|
||||
|
@ -430,6 +430,6 @@ void ISA_getINFO(uint8_t i) {
|
|||
outframe.data.u8[6] = 0x00;
|
||||
outframe.data.u8[7] = 0x00;
|
||||
|
||||
transmit_can(&outframe, can_config.battery);
|
||||
transmit_can_frame(&outframe, can_config.battery);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,6 @@ void ISA_getCONFIG(uint8_t i);
|
|||
void ISA_getCAN_ID(uint8_t i);
|
||||
void ISA_getINFO(uint8_t i);
|
||||
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
308
Software/src/battery/ECMP-BATTERY.cpp
Normal file
308
Software/src/battery/ECMP-BATTERY.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
#include "../include.h"
|
||||
#ifdef STELLANTIS_ECMP_BATTERY
|
||||
#include <algorithm> // For std::min and std::max
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "ECMP-BATTERY.h"
|
||||
|
||||
/* TODO:
|
||||
This integration is still ongoing. Here is what still needs to be done in order to use this battery type
|
||||
- Find SOC%
|
||||
- Find battery voltage
|
||||
- Find current value
|
||||
- Find/estimate charge/discharge limits
|
||||
- Find temperature
|
||||
- Figure out contactor closing
|
||||
- Which CAN messages need to be sent towards the battery?
|
||||
*/
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis1000 = 0; // will store last time a 1s CAN Message was sent
|
||||
|
||||
//Actual content messages
|
||||
CAN_frame ECMP_XXX = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 8,
|
||||
.ID = 0x301,
|
||||
.data = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
static uint16_t battery_voltage = 37000;
|
||||
static uint16_t battery_soc = 0;
|
||||
static uint16_t cellvoltages[108];
|
||||
|
||||
void update_values_battery() {
|
||||
|
||||
datalayer.battery.status.real_soc = battery_soc * 100;
|
||||
|
||||
datalayer.battery.status.soh_pptt;
|
||||
|
||||
datalayer.battery.status.voltage_dV = (battery_voltage / 10);
|
||||
|
||||
datalayer.battery.status.current_dA;
|
||||
|
||||
datalayer.battery.status.active_power_W = //Power in watts, Negative = charging batt
|
||||
((datalayer.battery.status.voltage_dV * datalayer.battery.status.current_dA) / 100);
|
||||
|
||||
datalayer.battery.status.max_charge_power_W;
|
||||
|
||||
datalayer.battery.status.max_discharge_power_W;
|
||||
|
||||
datalayer.battery.status.temperature_min_dC;
|
||||
|
||||
datalayer.battery.status.temperature_max_dC;
|
||||
|
||||
// Initialize min and max, lets find which cells are min and max!
|
||||
uint16_t min_cell_mv_value = std::numeric_limits<uint16_t>::max();
|
||||
uint16_t max_cell_mv_value = 0;
|
||||
// Loop to find the min and max while ignoring zero values
|
||||
for (uint8_t i = 0; i < datalayer.battery.info.number_of_cells; ++i) {
|
||||
uint16_t voltage_mV = datalayer.battery.status.cell_voltages_mV[i];
|
||||
if (voltage_mV != 0) { // Skip unread values (0)
|
||||
min_cell_mv_value = std::min(min_cell_mv_value, voltage_mV);
|
||||
max_cell_mv_value = std::max(max_cell_mv_value, voltage_mV);
|
||||
}
|
||||
}
|
||||
// If all array values are 0, reset min/max to 3700
|
||||
if (min_cell_mv_value == std::numeric_limits<uint16_t>::max()) {
|
||||
min_cell_mv_value = 3700;
|
||||
max_cell_mv_value = 3700;
|
||||
}
|
||||
|
||||
datalayer.battery.status.cell_min_voltage_mV = min_cell_mv_value;
|
||||
datalayer.battery.status.cell_max_voltage_mV = max_cell_mv_value;
|
||||
}
|
||||
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x125:
|
||||
break;
|
||||
case 0x127:
|
||||
break;
|
||||
case 0x129:
|
||||
break;
|
||||
case 0x31B:
|
||||
break;
|
||||
case 0x358:
|
||||
break;
|
||||
case 0x359:
|
||||
break;
|
||||
case 0x361:
|
||||
battery_voltage = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
break;
|
||||
case 0x362:
|
||||
break;
|
||||
case 0x454:
|
||||
break;
|
||||
case 0x494:
|
||||
break;
|
||||
case 0x594:
|
||||
break;
|
||||
case 0x6D0:
|
||||
battery_soc = (100 - rx_frame.data.u8[0]);
|
||||
break;
|
||||
case 0x6D1:
|
||||
break;
|
||||
case 0x6D2:
|
||||
break;
|
||||
case 0x6D3:
|
||||
cellvoltages[0] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[1] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[2] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[3] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6D4:
|
||||
cellvoltages[4] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[5] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[6] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[7] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6E0:
|
||||
break;
|
||||
case 0x6E1:
|
||||
cellvoltages[8] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[9] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[10] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[11] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6E2:
|
||||
cellvoltages[12] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[13] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[14] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[15] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6E3:
|
||||
break;
|
||||
case 0x6E4:
|
||||
break;
|
||||
case 0x6E5:
|
||||
break;
|
||||
case 0x6E6:
|
||||
break;
|
||||
case 0x6E7:
|
||||
cellvoltages[16] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[17] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[18] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[19] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6E8:
|
||||
cellvoltages[20] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[21] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[22] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[23] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6E9:
|
||||
cellvoltages[24] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[25] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[26] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[27] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6EB:
|
||||
cellvoltages[28] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[29] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[30] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[31] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6EC:
|
||||
//Not available on e-C4
|
||||
break;
|
||||
case 0x6ED:
|
||||
cellvoltages[32] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[33] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[34] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[35] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6EE:
|
||||
cellvoltages[36] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[37] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[38] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[39] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6EF:
|
||||
cellvoltages[40] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[41] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[42] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[43] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F0:
|
||||
cellvoltages[44] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[45] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[46] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[47] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F1:
|
||||
cellvoltages[48] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[49] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[50] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[51] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F2:
|
||||
cellvoltages[52] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[53] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[54] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[55] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F3:
|
||||
cellvoltages[56] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[57] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[58] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[59] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F4:
|
||||
cellvoltages[60] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[61] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[62] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[63] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F5:
|
||||
cellvoltages[64] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[65] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[66] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[67] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F6:
|
||||
cellvoltages[68] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[69] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[70] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[71] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F7:
|
||||
cellvoltages[72] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[73] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[74] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[75] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F8:
|
||||
cellvoltages[76] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[77] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[78] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[79] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6F9:
|
||||
cellvoltages[80] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[81] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[82] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[83] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6FA:
|
||||
cellvoltages[84] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[85] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[86] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[87] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6FB:
|
||||
cellvoltages[88] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[89] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[90] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[91] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6FC:
|
||||
cellvoltages[92] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[93] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[94] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[95] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6FD:
|
||||
cellvoltages[96] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[97] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[98] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[99] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6FE:
|
||||
cellvoltages[100] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[101] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[102] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[103] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
break;
|
||||
case 0x6FF:
|
||||
cellvoltages[104] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1];
|
||||
cellvoltages[105] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3];
|
||||
cellvoltages[106] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
cellvoltages[107] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7];
|
||||
memcpy(datalayer.battery.status.cell_voltages_mV, cellvoltages, 108 * sizeof(uint16_t));
|
||||
break;
|
||||
case 0x794:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 1s CAN Message
|
||||
if (currentMillis - previousMillis1000 >= INTERVAL_1_S) {
|
||||
previousMillis1000 = currentMillis;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("ECMP battery selected");
|
||||
#endif
|
||||
datalayer.battery.info.number_of_cells = 108;
|
||||
datalayer.battery.info.max_design_voltage_dV = 4546; // 454.6V, charging over this is not possible
|
||||
datalayer.battery.info.min_design_voltage_dV = 3210; // 321.0V, under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
12
Software/src/battery/ECMP-BATTERY.h
Normal file
12
Software/src/battery/ECMP-BATTERY.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef STELLANTIS_ECMP_BATTERY_H
|
||||
#define STELLANTIS_ECMP_BATTERY_H
|
||||
#include <Arduino.h>
|
||||
#include "../include.h"
|
||||
|
||||
#define BATTERY_SELECTED
|
||||
#define MAX_CELL_DEVIATION_MV 250
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
|
@ -103,33 +103,33 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
|
||||
if (!BMU_Detected) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BMU not detected, check wiring!");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BMU not detected, check wiring!");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Battery Values");
|
||||
Serial.print("BMU SOC: ");
|
||||
Serial.print(BMU_SOC);
|
||||
Serial.print(" BMU Current: ");
|
||||
Serial.print(BMU_Current);
|
||||
Serial.print(" BMU Battery Voltage: ");
|
||||
Serial.print(BMU_PackVoltage);
|
||||
Serial.print(" BMU_Power: ");
|
||||
Serial.print(BMU_Power);
|
||||
Serial.print(" Cell max voltage: ");
|
||||
Serial.print(max_volt_cel);
|
||||
Serial.print(" Cell min voltage: ");
|
||||
Serial.print(min_volt_cel);
|
||||
Serial.print(" Cell max temp: ");
|
||||
Serial.print(max_temp_cel);
|
||||
Serial.print(" Cell min temp: ");
|
||||
Serial.println(min_temp_cel);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Battery Values");
|
||||
logging.print("BMU SOC: ");
|
||||
logging.print(BMU_SOC);
|
||||
logging.print(" BMU Current: ");
|
||||
logging.print(BMU_Current);
|
||||
logging.print(" BMU Battery Voltage: ");
|
||||
logging.print(BMU_PackVoltage);
|
||||
logging.print(" BMU_Power: ");
|
||||
logging.print(BMU_Power);
|
||||
logging.print(" Cell max voltage: ");
|
||||
logging.print(max_volt_cel);
|
||||
logging.print(" Cell min voltage: ");
|
||||
logging.print(min_volt_cel);
|
||||
logging.print(" Cell max temp: ");
|
||||
logging.print(max_temp_cel);
|
||||
logging.print(" Cell min temp: ");
|
||||
logging.println(min_temp_cel);
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x374: //BMU message, 10ms - SOC
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -207,7 +207,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2750 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,9 +57,9 @@ CAN_frame ipace_keep_alive = {.FD = false,
|
|||
.data = {0x9E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};*/
|
||||
|
||||
void print_units(char* header, int value, char* units) {
|
||||
Serial.print(header);
|
||||
Serial.print(value);
|
||||
Serial.print(units);
|
||||
logging.print(header);
|
||||
logging.print(value);
|
||||
logging.print(units);
|
||||
}
|
||||
|
||||
void update_values_battery() {
|
||||
|
@ -104,10 +104,10 @@ void update_values_battery() {
|
|||
}
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Values going to inverter");
|
||||
print_units("SOH%: ", (datalayer.battery.status.soh_pptt * 0.01), "% ");
|
||||
print_units(", SOC%: ", (datalayer.battery.status.reported_soc * 0.01), "% ");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Values going to inverter");
|
||||
print_units("SOH: ", (datalayer.battery.status.soh_pptt * 0.01), "pct ");
|
||||
print_units(", SOC: ", (datalayer.battery.status.reported_soc * 0.01), "pct ");
|
||||
print_units(", Voltage: ", (datalayer.battery.status.voltage_dV * 0.1), "V ");
|
||||
print_units(", Max discharge power: ", datalayer.battery.status.max_discharge_power_W, "W ");
|
||||
print_units(", Max charge power: ", datalayer.battery.status.max_charge_power_W, "W ");
|
||||
|
@ -115,11 +115,11 @@ void update_values_battery() {
|
|||
print_units(", Min temp: ", (datalayer.battery.status.temperature_min_dC * 0.1), "°C ");
|
||||
print_units(", Max cell voltage: ", datalayer.battery.status.cell_max_voltage_mV, "mV ");
|
||||
print_units(", Min cell voltage: ", datalayer.battery.status.cell_min_voltage_mV, "mV ");
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
|
||||
// Do not log noisy startup messages - there are many !
|
||||
if (rx_frame.ID == 0 && rx_frame.DLC == 8 && rx_frame.data.u8[0] == 0 && rx_frame.data.u8[1] == 0 &&
|
||||
|
@ -229,26 +229,26 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
|
||||
// All CAN messages recieved will be logged via serial
|
||||
Serial.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.ID, HEX);
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.DLC);
|
||||
Serial.print(" ");
|
||||
logging.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
logging.print(" ");
|
||||
logging.print(rx_frame.ID, HEX);
|
||||
logging.print(" ");
|
||||
logging.print(rx_frame.DLC);
|
||||
logging.print(" ");
|
||||
for (int i = 0; i < rx_frame.DLC; ++i) {
|
||||
Serial.print(rx_frame.data.u8[i], HEX);
|
||||
Serial.print(" ");
|
||||
logging.print(rx_frame.data.u8[i], HEX);
|
||||
logging.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
/* Send keep-alive every 200ms */
|
||||
if (currentMillis - previousMillisKeepAlive >= INTERVAL_200_MS) {
|
||||
previousMillisKeepAlive = currentMillis;
|
||||
transmit_can(&ipace_keep_alive, can_config.battery);
|
||||
transmit_can_frame(&ipace_keep_alive, can_config.battery);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -690,67 +690,67 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
|
||||
/* Safeties verified. Perform USB serial printout if configured to do so */
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println(); //sepatator
|
||||
Serial.println("Values from battery: ");
|
||||
Serial.print("SOC BMS: ");
|
||||
Serial.print((uint16_t)SOC_BMS / 10.0, 1);
|
||||
Serial.print("% | SOC Display: ");
|
||||
Serial.print((uint16_t)SOC_Display / 10.0, 1);
|
||||
Serial.print("% | SOH ");
|
||||
Serial.print((uint16_t)batterySOH / 10.0, 1);
|
||||
Serial.println("%");
|
||||
Serial.print((int16_t)batteryAmps / 10.0, 1);
|
||||
Serial.print(" Amps | ");
|
||||
Serial.print((uint16_t)batteryVoltage / 10.0, 1);
|
||||
Serial.print(" Volts | ");
|
||||
Serial.print((int16_t)datalayer.battery.status.active_power_W);
|
||||
Serial.println(" Watts");
|
||||
Serial.print("Allowed Charge ");
|
||||
Serial.print((uint16_t)allowedChargePower * 10);
|
||||
Serial.print(" W | Allowed Discharge ");
|
||||
Serial.print((uint16_t)allowedDischargePower * 10);
|
||||
Serial.println(" W");
|
||||
Serial.print("MaxCellVolt ");
|
||||
Serial.print(CellVoltMax_mV);
|
||||
Serial.print(" mV No ");
|
||||
Serial.print(CellVmaxNo);
|
||||
Serial.print(" | MinCellVolt ");
|
||||
Serial.print(CellVoltMin_mV);
|
||||
Serial.print(" mV No ");
|
||||
Serial.println(CellVminNo);
|
||||
Serial.print("TempHi ");
|
||||
Serial.print((int16_t)temperatureMax);
|
||||
Serial.print("°C TempLo ");
|
||||
Serial.print((int16_t)temperatureMin);
|
||||
Serial.print("°C WaterInlet ");
|
||||
Serial.print((int8_t)temperature_water_inlet);
|
||||
Serial.print("°C PowerRelay ");
|
||||
Serial.print((int8_t)powerRelayTemperature * 2);
|
||||
Serial.println("°C");
|
||||
Serial.print("Aux12volt: ");
|
||||
Serial.print((int16_t)leadAcidBatteryVoltage / 10.0, 1);
|
||||
Serial.println("V | ");
|
||||
Serial.print("BmsManagementMode ");
|
||||
Serial.print((uint8_t)batteryManagementMode, BIN);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println(); //sepatator
|
||||
logging.println("Values from battery: ");
|
||||
logging.print("SOC BMS: ");
|
||||
logging.print((uint16_t)SOC_BMS / 10.0, 1);
|
||||
logging.print("pct | SOC Display: ");
|
||||
logging.print((uint16_t)SOC_Display / 10.0, 1);
|
||||
logging.print("pct | SOH ");
|
||||
logging.print((uint16_t)batterySOH / 10.0, 1);
|
||||
logging.println("pct");
|
||||
logging.print((int16_t)batteryAmps / 10.0, 1);
|
||||
logging.print(" Amps | ");
|
||||
logging.print((uint16_t)batteryVoltage / 10.0, 1);
|
||||
logging.print(" Volts | ");
|
||||
logging.print((int16_t)datalayer.battery.status.active_power_W);
|
||||
logging.println(" Watts");
|
||||
logging.print("Allowed Charge ");
|
||||
logging.print((uint16_t)allowedChargePower * 10);
|
||||
logging.print(" W | Allowed Discharge ");
|
||||
logging.print((uint16_t)allowedDischargePower * 10);
|
||||
logging.println(" W");
|
||||
logging.print("MaxCellVolt ");
|
||||
logging.print(CellVoltMax_mV);
|
||||
logging.print(" mV No ");
|
||||
logging.print(CellVmaxNo);
|
||||
logging.print(" | MinCellVolt ");
|
||||
logging.print(CellVoltMin_mV);
|
||||
logging.print(" mV No ");
|
||||
logging.println(CellVminNo);
|
||||
logging.print("TempHi ");
|
||||
logging.print((int16_t)temperatureMax);
|
||||
logging.print("°C TempLo ");
|
||||
logging.print((int16_t)temperatureMin);
|
||||
logging.print("°C WaterInlet ");
|
||||
logging.print((int8_t)temperature_water_inlet);
|
||||
logging.print("°C PowerRelay ");
|
||||
logging.print((int8_t)powerRelayTemperature * 2);
|
||||
logging.println("°C");
|
||||
logging.print("Aux12volt: ");
|
||||
logging.print((int16_t)leadAcidBatteryVoltage / 10.0, 1);
|
||||
logging.println("V | ");
|
||||
logging.print("BmsManagementMode ");
|
||||
logging.print((uint8_t)batteryManagementMode, BIN);
|
||||
if (bitRead((uint8_t)BMS_ign, 2) == 1) {
|
||||
Serial.print(" | BmsIgnition ON");
|
||||
logging.print(" | BmsIgnition ON");
|
||||
} else {
|
||||
Serial.print(" | BmsIgnition OFF");
|
||||
logging.print(" | BmsIgnition OFF");
|
||||
}
|
||||
|
||||
if (bitRead((uint8_t)batteryRelay, 0) == 1) {
|
||||
Serial.print(" | PowerRelay ON");
|
||||
logging.print(" | PowerRelay ON");
|
||||
} else {
|
||||
Serial.print(" | PowerRelay OFF");
|
||||
logging.print(" | PowerRelay OFF");
|
||||
}
|
||||
Serial.print(" | Inverter ");
|
||||
Serial.print(inverterVoltage);
|
||||
Serial.println(" Volts");
|
||||
logging.print(" | Inverter ");
|
||||
logging.print(inverterVoltage);
|
||||
logging.println(" Volts");
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
startedUp = true;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x055:
|
||||
|
@ -808,10 +808,10 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
// print_canfd_frame(frame);
|
||||
switch (rx_frame.data.u8[0]) {
|
||||
case 0x10: //"PID Header"
|
||||
// Serial.println ("Send ack");
|
||||
// logging.println ("Send ack");
|
||||
poll_data_pid = rx_frame.data.u8[4];
|
||||
// if (rx_frame.data.u8[4] == poll_data_pid) {
|
||||
transmit_can(&EGMP_7E4_ack, can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
transmit_can_frame(&EGMP_7E4_ack, can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
// }
|
||||
break;
|
||||
case 0x21: //First frame in PID group
|
||||
|
@ -982,7 +982,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
if (startedUp) {
|
||||
//Send Contactor closing message loop
|
||||
|
@ -993,7 +993,7 @@ void send_can_battery() {
|
|||
if (currentMillis - startMillis >= messageDelays[messageIndex]) {
|
||||
|
||||
// Transmit the current message
|
||||
transmit_can(messages[messageIndex], can_config.battery);
|
||||
transmit_can_frame(messages[messageIndex], can_config.battery);
|
||||
|
||||
// Move to the next message
|
||||
messageIndex++;
|
||||
|
@ -1019,7 +1019,7 @@ void send_can_battery() {
|
|||
EGMP_7E4.data.u8[3] = KIA_7E4_COUNTER;
|
||||
|
||||
if (ok_start_polling_battery) {
|
||||
transmit_can(&EGMP_7E4, can_config.battery);
|
||||
transmit_can_frame(&EGMP_7E4, can_config.battery);
|
||||
}
|
||||
|
||||
KIA_7E4_COUNTER++;
|
||||
|
|
|
@ -18,6 +18,6 @@ extern ACAN2517FD canfd;
|
|||
#define RAMPDOWNPOWERALLOWED 10000 // What power we ramp down from towards top balancing
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -142,63 +142,63 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
|
||||
/* Safeties verified. Perform USB serial printout if configured to do so */
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println(); //sepatator
|
||||
Serial.println("Values from battery: ");
|
||||
Serial.print("SOC BMS: ");
|
||||
Serial.print((uint16_t)SOC_BMS / 10.0, 1);
|
||||
Serial.print("% | SOC Display: ");
|
||||
Serial.print((uint16_t)SOC_Display / 10.0, 1);
|
||||
Serial.print("% | SOH ");
|
||||
Serial.print((uint16_t)batterySOH / 10.0, 1);
|
||||
Serial.println("%");
|
||||
Serial.print((int16_t)batteryAmps / 10.0, 1);
|
||||
Serial.print(" Amps | ");
|
||||
Serial.print((uint16_t)batteryVoltage / 10.0, 1);
|
||||
Serial.print(" Volts | ");
|
||||
Serial.print((int16_t)datalayer.battery.status.active_power_W);
|
||||
Serial.println(" Watts");
|
||||
Serial.print("Allowed Charge ");
|
||||
Serial.print((uint16_t)allowedChargePower * 10);
|
||||
Serial.print(" W | Allowed Discharge ");
|
||||
Serial.print((uint16_t)allowedDischargePower * 10);
|
||||
Serial.println(" W");
|
||||
Serial.print("MaxCellVolt ");
|
||||
Serial.print(CellVoltMax_mV);
|
||||
Serial.print(" mV No ");
|
||||
Serial.print(CellVmaxNo);
|
||||
Serial.print(" | MinCellVolt ");
|
||||
Serial.print(CellVoltMin_mV);
|
||||
Serial.print(" mV No ");
|
||||
Serial.println(CellVminNo);
|
||||
Serial.print("TempHi ");
|
||||
Serial.print((int16_t)temperatureMax);
|
||||
Serial.print("°C TempLo ");
|
||||
Serial.print((int16_t)temperatureMin);
|
||||
Serial.print("°C WaterInlet ");
|
||||
Serial.print((int8_t)temperature_water_inlet);
|
||||
Serial.print("°C PowerRelay ");
|
||||
Serial.print((int8_t)powerRelayTemperature * 2);
|
||||
Serial.println("°C");
|
||||
Serial.print("Aux12volt: ");
|
||||
Serial.print((int16_t)leadAcidBatteryVoltage / 10.0, 1);
|
||||
Serial.println("V | ");
|
||||
Serial.print("BmsManagementMode ");
|
||||
Serial.print((uint8_t)batteryManagementMode, BIN);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println(); //sepatator
|
||||
logging.println("Values from battery: ");
|
||||
logging.print("SOC BMS: ");
|
||||
logging.print((uint16_t)SOC_BMS / 10.0, 1);
|
||||
logging.print("pct | SOC Display: ");
|
||||
logging.print((uint16_t)SOC_Display / 10.0, 1);
|
||||
logging.print("pct | SOH ");
|
||||
logging.print((uint16_t)batterySOH / 10.0, 1);
|
||||
logging.println("pct");
|
||||
logging.print((int16_t)batteryAmps / 10.0, 1);
|
||||
logging.print(" Amps | ");
|
||||
logging.print((uint16_t)batteryVoltage / 10.0, 1);
|
||||
logging.print(" Volts | ");
|
||||
logging.print((int16_t)datalayer.battery.status.active_power_W);
|
||||
logging.println(" Watts");
|
||||
logging.print("Allowed Charge ");
|
||||
logging.print((uint16_t)allowedChargePower * 10);
|
||||
logging.print(" W | Allowed Discharge ");
|
||||
logging.print((uint16_t)allowedDischargePower * 10);
|
||||
logging.println(" W");
|
||||
logging.print("MaxCellVolt ");
|
||||
logging.print(CellVoltMax_mV);
|
||||
logging.print(" mV No ");
|
||||
logging.print(CellVmaxNo);
|
||||
logging.print(" | MinCellVolt ");
|
||||
logging.print(CellVoltMin_mV);
|
||||
logging.print(" mV No ");
|
||||
logging.println(CellVminNo);
|
||||
logging.print("TempHi ");
|
||||
logging.print((int16_t)temperatureMax);
|
||||
logging.print("°C TempLo ");
|
||||
logging.print((int16_t)temperatureMin);
|
||||
logging.print("°C WaterInlet ");
|
||||
logging.print((int8_t)temperature_water_inlet);
|
||||
logging.print("°C PowerRelay ");
|
||||
logging.print((int8_t)powerRelayTemperature * 2);
|
||||
logging.println("°C");
|
||||
logging.print("Aux12volt: ");
|
||||
logging.print((int16_t)leadAcidBatteryVoltage / 10.0, 1);
|
||||
logging.println("V | ");
|
||||
logging.print("BmsManagementMode ");
|
||||
logging.print((uint8_t)batteryManagementMode, BIN);
|
||||
if (bitRead((uint8_t)BMS_ign, 2) == 1) {
|
||||
Serial.print(" | BmsIgnition ON");
|
||||
logging.print(" | BmsIgnition ON");
|
||||
} else {
|
||||
Serial.print(" | BmsIgnition OFF");
|
||||
logging.print(" | BmsIgnition OFF");
|
||||
}
|
||||
|
||||
if (bitRead((uint8_t)batteryRelay, 0) == 1) {
|
||||
Serial.print(" | PowerRelay ON");
|
||||
logging.print(" | PowerRelay ON");
|
||||
} else {
|
||||
Serial.print(" | PowerRelay OFF");
|
||||
logging.print(" | PowerRelay OFF");
|
||||
}
|
||||
Serial.print(" | Inverter ");
|
||||
Serial.print(inverterVoltage);
|
||||
Serial.println(" Volts");
|
||||
logging.print(" | Inverter ");
|
||||
logging.print(inverterVoltage);
|
||||
logging.println(" Volts");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ void update_number_of_cells() {
|
|||
}
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x4DE:
|
||||
startedUp = true;
|
||||
|
@ -268,17 +268,17 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
poll_data_pid++;
|
||||
if (poll_data_pid == 1) {
|
||||
transmit_can(&KIA64_7E4_id1, can_config.battery);
|
||||
transmit_can_frame(&KIA64_7E4_id1, can_config.battery);
|
||||
} else if (poll_data_pid == 2) {
|
||||
transmit_can(&KIA64_7E4_id2, can_config.battery);
|
||||
transmit_can_frame(&KIA64_7E4_id2, can_config.battery);
|
||||
} else if (poll_data_pid == 3) {
|
||||
transmit_can(&KIA64_7E4_id3, can_config.battery);
|
||||
transmit_can_frame(&KIA64_7E4_id3, can_config.battery);
|
||||
} else if (poll_data_pid == 4) {
|
||||
transmit_can(&KIA64_7E4_id4, can_config.battery);
|
||||
transmit_can_frame(&KIA64_7E4_id4, can_config.battery);
|
||||
} else if (poll_data_pid == 5) {
|
||||
transmit_can(&KIA64_7E4_id5, can_config.battery);
|
||||
transmit_can_frame(&KIA64_7E4_id5, can_config.battery);
|
||||
} else if (poll_data_pid == 6) {
|
||||
transmit_can(&KIA64_7E4_id6, can_config.battery);
|
||||
transmit_can_frame(&KIA64_7E4_id6, can_config.battery);
|
||||
} else if (poll_data_pid == 7) {
|
||||
} else if (poll_data_pid == 8) {
|
||||
} else if (poll_data_pid == 9) {
|
||||
|
@ -289,7 +289,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
switch (rx_frame.data.u8[0]) {
|
||||
case 0x10: //"PID Header"
|
||||
if (rx_frame.data.u8[4] == poll_data_pid) {
|
||||
transmit_can(&KIA64_7E4_ack, can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
transmit_can_frame(&KIA64_7E4_ack,
|
||||
can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
}
|
||||
break;
|
||||
case 0x21: //First frame in PID group
|
||||
|
@ -460,7 +461,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
if (!startedUp) {
|
||||
|
@ -471,9 +472,9 @@ void send_can_battery() {
|
|||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
previousMillis100 = currentMillis;
|
||||
|
||||
transmit_can(&KIA64_553, can_config.battery);
|
||||
transmit_can(&KIA64_57F, can_config.battery);
|
||||
transmit_can(&KIA64_2A1, can_config.battery);
|
||||
transmit_can_frame(&KIA64_553, can_config.battery);
|
||||
transmit_can_frame(&KIA64_57F, can_config.battery);
|
||||
transmit_can_frame(&KIA64_2A1, can_config.battery);
|
||||
}
|
||||
// Send 10ms CAN Message
|
||||
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
||||
|
@ -525,11 +526,11 @@ void send_can_battery() {
|
|||
break;
|
||||
}
|
||||
|
||||
transmit_can(&KIA_HYUNDAI_200, can_config.battery);
|
||||
transmit_can_frame(&KIA_HYUNDAI_200, can_config.battery);
|
||||
|
||||
transmit_can(&KIA_HYUNDAI_523, can_config.battery);
|
||||
transmit_can_frame(&KIA_HYUNDAI_523, can_config.battery);
|
||||
|
||||
transmit_can(&KIA_HYUNDAI_524, can_config.battery);
|
||||
transmit_can_frame(&KIA_HYUNDAI_524, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
|
||||
void setup_battery(void);
|
||||
void update_number_of_cells();
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -86,7 +86,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x5F1:
|
||||
|
@ -108,7 +108,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
switch (rx_frame.data.u8[0]) {
|
||||
case 0x10: //"PID Header"
|
||||
if (rx_frame.data.u8[3] == poll_data_pid) {
|
||||
transmit_can(&KIA_7E4_ack, can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
transmit_can_frame(&KIA_7E4_ack, can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
}
|
||||
break;
|
||||
case 0x21: //First frame in PID group
|
||||
|
@ -230,7 +230,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// Send 1000ms CAN Message
|
||||
|
@ -243,15 +243,15 @@ void send_can_battery() {
|
|||
}
|
||||
poll_data_pid++;
|
||||
if (poll_data_pid == 1) {
|
||||
transmit_can(&KIA_7E4_id1, can_config.battery);
|
||||
transmit_can_frame(&KIA_7E4_id1, can_config.battery);
|
||||
} else if (poll_data_pid == 2) {
|
||||
transmit_can(&KIA_7E4_id2, can_config.battery);
|
||||
transmit_can_frame(&KIA_7E4_id2, can_config.battery);
|
||||
} else if (poll_data_pid == 3) {
|
||||
transmit_can(&KIA_7E4_id3, can_config.battery);
|
||||
transmit_can_frame(&KIA_7E4_id3, can_config.battery);
|
||||
} else if (poll_data_pid == 4) {
|
||||
|
||||
} else if (poll_data_pid == 5) {
|
||||
transmit_can(&KIA_7E4_id5, can_config.battery);
|
||||
transmit_can_frame(&KIA_7E4_id5, can_config.battery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -618,7 +618,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer_extended.meb.rt_battery_unathorized = realtime_warning_battery_unathorized;
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
last_can_msg_timestamp = millis();
|
||||
if (first_can_msg == 0)
|
||||
first_can_msg = last_can_msg_timestamp;
|
||||
|
@ -994,7 +994,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
case 0x1C42007B: // Reply from battery
|
||||
if (rx_frame.data.u8[0] == 0x10) { //PID header
|
||||
transmit_can(&MEB_ACK_FRAME, can_config.battery);
|
||||
transmit_can_frame(&MEB_ACK_FRAME, can_config.battery);
|
||||
}
|
||||
if (rx_frame.DLC == 8) {
|
||||
pid_reply = (rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3];
|
||||
|
@ -1453,7 +1453,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 10ms CAN Message
|
||||
if (currentMillis > last_can_msg_timestamp + 500) {
|
||||
|
@ -1474,7 +1474,7 @@ void send_can_battery() {
|
|||
|
||||
counter_10ms = (counter_10ms + 1) % 16; //Goes from 0-1-2-3...15-0-1-2-3..
|
||||
|
||||
transmit_can(&MEB_0FC, can_config.battery); // Required for contactor closing
|
||||
transmit_can_frame(&MEB_0FC, can_config.battery); // Required for contactor closing
|
||||
}
|
||||
// Send 20ms CAN Message
|
||||
if (currentMillis - previousMillis20ms >= INTERVAL_20_MS) {
|
||||
|
@ -1485,7 +1485,7 @@ void send_can_battery() {
|
|||
|
||||
counter_20ms = (counter_20ms + 1) % 16; //Goes from 0-1-2-3...15-0-1-2-3..
|
||||
|
||||
transmit_can(&MEB_0FD, can_config.battery); // Required for contactor closing
|
||||
transmit_can_frame(&MEB_0FD, can_config.battery); // Required for contactor closing
|
||||
}
|
||||
// Send 40ms CAN Message
|
||||
if (currentMillis - previousMillis40ms >= INTERVAL_40_MS) {
|
||||
|
@ -1502,7 +1502,7 @@ void send_can_battery() {
|
|||
}
|
||||
toggle = !toggle; // Flip the toggle each time the code block is executed
|
||||
|
||||
transmit_can(&MEB_040, can_config.battery); // Airbag message - Needed for contactor closing
|
||||
transmit_can_frame(&MEB_040, can_config.battery); // Airbag message - Needed for contactor closing
|
||||
}
|
||||
// Send 50ms CAN Message
|
||||
if (currentMillis - previousMillis50ms >= INTERVAL_50_MS) {
|
||||
|
@ -1518,7 +1518,7 @@ void send_can_battery() {
|
|||
MEB_0C0.data.u8[0] = vw_crc_calc(MEB_0C0.data.u8, MEB_0C0.DLC, MEB_0C0.ID);
|
||||
counter_50ms = (counter_50ms + 1) % 16; //Goes from 0-1-2-3...15-0-1-2-3..
|
||||
|
||||
transmit_can(&MEB_0C0, can_config.battery); // Needed for contactor closing
|
||||
transmit_can_frame(&MEB_0C0, can_config.battery); // Needed for contactor closing
|
||||
}
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100ms >= INTERVAL_100_MS) {
|
||||
|
@ -1560,11 +1560,11 @@ void send_can_battery() {
|
|||
MEB_14C.data.u8[0] = vw_crc_calc(MEB_14C.data.u8, MEB_14C.DLC, MEB_14C.ID);
|
||||
|
||||
counter_100ms = (counter_100ms + 1) % 16; //Goes from 0-1-2-3...15-0-1-2-3..
|
||||
transmit_can(&MEB_503, can_config.battery);
|
||||
transmit_can(&MEB_272, can_config.battery);
|
||||
transmit_can(&MEB_3C0, can_config.battery);
|
||||
transmit_can(&MEB_3BE, can_config.battery);
|
||||
transmit_can(&MEB_14C, can_config.battery);
|
||||
transmit_can_frame(&MEB_503, can_config.battery);
|
||||
transmit_can_frame(&MEB_272, can_config.battery);
|
||||
transmit_can_frame(&MEB_3C0, can_config.battery);
|
||||
transmit_can_frame(&MEB_3BE, can_config.battery);
|
||||
transmit_can_frame(&MEB_14C, can_config.battery);
|
||||
}
|
||||
//Send 200ms message
|
||||
if (currentMillis - previousMillis200ms >= INTERVAL_200_MS) {
|
||||
|
@ -1574,11 +1574,11 @@ void send_can_battery() {
|
|||
|
||||
//TODO: MEB_1B0000B9 & MEB_1B000010 & MEB_1B000046 has CAN sleep commands, static OK?
|
||||
|
||||
transmit_can(&MEB_5E1, can_config.battery);
|
||||
transmit_can(&MEB_153, can_config.battery);
|
||||
transmit_can(&MEB_1B0000B9, can_config.battery);
|
||||
transmit_can(&MEB_1B000010, can_config.battery);
|
||||
transmit_can(&MEB_1B000046, can_config.battery);
|
||||
transmit_can_frame(&MEB_5E1, can_config.battery);
|
||||
transmit_can_frame(&MEB_153, can_config.battery);
|
||||
transmit_can_frame(&MEB_1B0000B9, can_config.battery);
|
||||
transmit_can_frame(&MEB_1B000010, can_config.battery);
|
||||
transmit_can_frame(&MEB_1B000046, can_config.battery);
|
||||
|
||||
switch (poll_pid) {
|
||||
case PID_SOC:
|
||||
|
@ -2076,7 +2076,7 @@ void send_can_battery() {
|
|||
break;
|
||||
}
|
||||
if (first_can_msg > 0 && currentMillis > first_can_msg + 2000) {
|
||||
transmit_can(&MEB_POLLING_FRAME, can_config.battery);
|
||||
transmit_can_frame(&MEB_POLLING_FRAME, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2084,11 +2084,11 @@ void send_can_battery() {
|
|||
if (currentMillis - previousMillis500ms >= INTERVAL_500_MS) {
|
||||
previousMillis500ms = currentMillis;
|
||||
|
||||
transmit_can(&MEB_16A954B4, can_config.battery); //eTM, Cooling valves and pumps for BMS
|
||||
transmit_can(&MEB_569, can_config.battery); // Battery heating requests
|
||||
transmit_can(&MEB_1A55552B, can_config.battery); //Climate, heatpump and priorities
|
||||
transmit_can(&MEB_1A555548, can_config.battery); //ORU, OTA update message for reserving battery
|
||||
transmit_can(&MEB_16A954FB, can_config.battery); //Climate, request to BMS for starting preconditioning
|
||||
transmit_can_frame(&MEB_16A954B4, can_config.battery); //eTM, Cooling valves and pumps for BMS
|
||||
transmit_can_frame(&MEB_569, can_config.battery); // Battery heating requests
|
||||
transmit_can_frame(&MEB_1A55552B, can_config.battery); //Climate, heatpump and priorities
|
||||
transmit_can_frame(&MEB_1A555548, can_config.battery); //ORU, OTA update message for reserving battery
|
||||
transmit_can_frame(&MEB_16A954FB, can_config.battery); //Climate, request to BMS for starting preconditioning
|
||||
}
|
||||
|
||||
//Send 1s CANFD message
|
||||
|
@ -2110,11 +2110,11 @@ void send_can_battery() {
|
|||
seconds = (seconds + 1) % 60;
|
||||
|
||||
counter_1000ms = (counter_1000ms + 1) % 16; //Goes from 0-1-2-3...15-0-1-2-3..
|
||||
transmit_can(&MEB_6B2, can_config.battery); // Diagnostics - Needed for contactor closing
|
||||
transmit_can(&MEB_641, can_config.battery); // Motor - OBD
|
||||
transmit_can(&MEB_5F5, can_config.battery); // Loading profile
|
||||
transmit_can(&MEB_585, can_config.battery); // Systeminfo
|
||||
transmit_can(&MEB_1A5555A6, can_config.battery); // Temperature QBit
|
||||
transmit_can_frame(&MEB_6B2, can_config.battery); // Diagnostics - Needed for contactor closing
|
||||
transmit_can_frame(&MEB_641, can_config.battery); // Motor - OBD
|
||||
transmit_can_frame(&MEB_5F5, can_config.battery); // Loading profile
|
||||
transmit_can_frame(&MEB_585, can_config.battery); // Systeminfo
|
||||
transmit_can_frame(&MEB_1A5555A6, can_config.battery); // Temperature QBit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,6 @@
|
|||
#define PID_CELLVOLTAGE_CELL_108 0x1EAB
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,13 +42,9 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer.battery.status.temperature_min_dC;
|
||||
|
||||
datalayer.battery.status.temperature_max_dC;
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x171: //Following messages were detected on a MG5 battery BMS
|
||||
|
@ -112,7 +108,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
//Send 10ms message
|
||||
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
||||
|
@ -124,13 +120,13 @@ void send_can_battery() {
|
|||
}
|
||||
previousMillis10 = currentMillis;
|
||||
|
||||
transmit_can(&MG_5_100, can_config.battery);
|
||||
transmit_can_frame(&MG_5_100, can_config.battery);
|
||||
}
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
previousMillis100 = currentMillis;
|
||||
|
||||
//transmit_can(&MG_5_100, can_config.battery);
|
||||
//transmit_can_frame(&MG_5_100, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -502,7 +502,7 @@ void update_values_battery2() { // Handle the values coming in from battery #2
|
|||
}
|
||||
}
|
||||
}
|
||||
void receive_can_battery2(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x1DB:
|
||||
if (is_message_corrupt(rx_frame)) {
|
||||
|
@ -612,7 +612,7 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
//First check which group data we are getting
|
||||
if (rx_frame.data.u8[0] == 0x10) { //First message of a group
|
||||
battery2_group_7bb = rx_frame.data.u8[3];
|
||||
transmit_can(&LEAF_NEXT_LINE_REQUEST, can_config.battery_double);
|
||||
transmit_can_frame(&LEAF_NEXT_LINE_REQUEST, can_config.battery_double);
|
||||
}
|
||||
|
||||
if (battery2_group_7bb == 1) //High precision SOC, Current, voltages etc.
|
||||
|
@ -740,7 +740,7 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
}
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x1DB:
|
||||
if (is_message_corrupt(rx_frame)) {
|
||||
|
@ -870,7 +870,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
if (rx_frame.data.u8[0] == 0x10) { //First message of a group
|
||||
group_7bb = rx_frame.data.u8[3];
|
||||
|
||||
transmit_can(&LEAF_NEXT_LINE_REQUEST, can_config.battery); //Request the next frame for the group
|
||||
transmit_can_frame(&LEAF_NEXT_LINE_REQUEST, can_config.battery); //Request the next frame for the group
|
||||
}
|
||||
|
||||
if (group_7bb == 1) //High precision SOC, Current, voltages etc.
|
||||
|
@ -1056,7 +1056,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
if (battery_can_alive) {
|
||||
|
||||
unsigned long currentMillis = millis();
|
||||
|
@ -1089,9 +1089,9 @@ void send_can_battery() {
|
|||
LEAF_1D4.data.u8[7] = 0xDE;
|
||||
break;
|
||||
}
|
||||
transmit_can(&LEAF_1D4, can_config.battery);
|
||||
transmit_can_frame(&LEAF_1D4, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&LEAF_1D4, can_config.battery_double);
|
||||
transmit_can_frame(&LEAF_1D4, can_config.battery_double);
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
switch (mprun10r) {
|
||||
|
@ -1185,9 +1185,9 @@ void send_can_battery() {
|
|||
|
||||
//Only send this message when NISSANLEAF_CHARGER is not defined (otherwise it will collide!)
|
||||
#ifndef NISSANLEAF_CHARGER
|
||||
transmit_can(&LEAF_1F2, can_config.battery);
|
||||
transmit_can_frame(&LEAF_1F2, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&LEAF_1F2, can_config.battery_double);
|
||||
transmit_can_frame(&LEAF_1F2, can_config.battery_double);
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif
|
||||
|
||||
|
@ -1212,9 +1212,9 @@ void send_can_battery() {
|
|||
}
|
||||
|
||||
// VCM message, containing info if battery should sleep or stay awake
|
||||
transmit_can(&LEAF_50B, can_config.battery); // HCM_WakeUpSleepCommand == 11b == WakeUp, and CANMASK = 1
|
||||
transmit_can_frame(&LEAF_50B, can_config.battery); // HCM_WakeUpSleepCommand == 11b == WakeUp, and CANMASK = 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&LEAF_50B, can_config.battery_double);
|
||||
transmit_can_frame(&LEAF_50B, can_config.battery_double);
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
LEAF_50C.data.u8[3] = mprun100;
|
||||
|
@ -1236,9 +1236,9 @@ void send_can_battery() {
|
|||
LEAF_50C.data.u8[5] = 0x9A;
|
||||
break;
|
||||
}
|
||||
transmit_can(&LEAF_50C, can_config.battery);
|
||||
transmit_can_frame(&LEAF_50C, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&LEAF_50C, can_config.battery_double);
|
||||
transmit_can_frame(&LEAF_50C, can_config.battery_double);
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
mprun100 = (mprun100 + 1) % 4; // mprun100 cycles between 0-1-2-3-0-1...
|
||||
|
@ -1255,9 +1255,9 @@ void send_can_battery() {
|
|||
PIDindex = (PIDindex + 1) % 6; // 6 = amount of elements in the PIDgroups[]
|
||||
LEAF_GROUP_REQUEST.data.u8[2] = PIDgroups[PIDindex];
|
||||
|
||||
transmit_can(&LEAF_GROUP_REQUEST, can_config.battery);
|
||||
transmit_can_frame(&LEAF_GROUP_REQUEST, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&LEAF_GROUP_REQUEST, can_config.battery_double);
|
||||
transmit_can_frame(&LEAF_GROUP_REQUEST, can_config.battery_double);
|
||||
#endif // DOUBLE_BATTERY
|
||||
}
|
||||
|
||||
|
@ -1320,19 +1320,19 @@ void clearSOH(void) {
|
|||
break;
|
||||
case 1: // Set CAN_PROCESS_FLAG to 0xC0
|
||||
LEAF_CLEAR_SOH.data = {0x02, 0x10, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
// BMS should reply 02 50 C0 FF FF FF FF FF
|
||||
stateMachineClearSOH = 2;
|
||||
break;
|
||||
case 2: // Set something ?
|
||||
LEAF_CLEAR_SOH.data = {0x02, 0x3E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
// BMS should reply 7E FF FF FF FF FF FF
|
||||
stateMachineClearSOH = 3;
|
||||
break;
|
||||
case 3: // Request challenge to solve
|
||||
LEAF_CLEAR_SOH.data = {0x02, 0x27, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
// BMS should reply with (challenge) 06 67 65 (02 DD 86 43) FF
|
||||
stateMachineClearSOH = 4;
|
||||
break;
|
||||
|
@ -1340,34 +1340,34 @@ void clearSOH(void) {
|
|||
decodeChallengeData(incomingChallenge, solvedChallenge);
|
||||
LEAF_CLEAR_SOH.data = {
|
||||
0x10, 0x0A, 0x27, 0x66, solvedChallenge[0], solvedChallenge[1], solvedChallenge[2], solvedChallenge[3]};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
// BMS should reply 7BB 8 30 01 00 FF FF FF FF FF // Proceed with more data (PID ACK)
|
||||
stateMachineClearSOH = 5;
|
||||
break;
|
||||
case 5: // Reply with even more decoded challenge data
|
||||
LEAF_CLEAR_SOH.data = {
|
||||
0x21, solvedChallenge[4], solvedChallenge[5], solvedChallenge[6], solvedChallenge[7], 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
// BMS should reply 02 67 66 FF FF FF FF FF // Thank you for the data
|
||||
stateMachineClearSOH = 6;
|
||||
break;
|
||||
case 6: // Check if solved data was OK
|
||||
LEAF_CLEAR_SOH.data = {0x03, 0x31, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
//7BB 8 03 71 03 01 FF FF FF FF // If all is well, BMS replies with 03 71 03 01.
|
||||
//Incase you sent wrong challenge, you get 03 7f 31 12
|
||||
stateMachineClearSOH = 7;
|
||||
break;
|
||||
case 7: // Reset SOH% request
|
||||
LEAF_CLEAR_SOH.data = {0x03, 0x31, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
//7BB 8 03 71 03 02 FF FF FF FF // 03 71 03 02 means that BMS accepted command.
|
||||
//7BB 03 7f 31 12 means your challenge was wrong, so command ignored
|
||||
stateMachineClearSOH = 8;
|
||||
break;
|
||||
case 8: // Please proceed with resetting SOH
|
||||
LEAF_CLEAR_SOH.data = {0x02, 0x10, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
transmit_can_frame(&LEAF_CLEAR_SOH, can_config.battery);
|
||||
// 7BB 8 02 50 81 FF FF FF FF FF // SOH reset OK
|
||||
stateMachineClearSOH = 255;
|
||||
break;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
uint16_t Temp_fromRAW_to_F(uint16_t temperature);
|
||||
bool is_message_corrupt(CAN_frame rx_frame);
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
void clearSOH(void);
|
||||
//Cryptographic functions
|
||||
void decodeChallengeData(unsigned int SeedInput, unsigned char* Crypt_Output_Buffer);
|
||||
|
|
|
@ -80,7 +80,7 @@ void update_values_battery() {
|
|||
datalayer.battery.info.min_design_voltage_dV = discharge_cutoff_voltage;
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x7310:
|
||||
|
@ -156,17 +156,17 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 1s CAN Message
|
||||
if (currentMillis - previousMillis1000 >= INTERVAL_1_S) {
|
||||
|
||||
previousMillis1000 = currentMillis;
|
||||
|
||||
transmit_can(&PYLON_3010, can_config.battery); // Heartbeat
|
||||
transmit_can(&PYLON_4200, can_config.battery); // Ensemble OR System equipment info, depends on frame0
|
||||
transmit_can(&PYLON_8200, can_config.battery); // Control device quit sleep status
|
||||
transmit_can(&PYLON_8210, can_config.battery); // Charge command
|
||||
transmit_can_frame(&PYLON_3010, can_config.battery); // Heartbeat
|
||||
transmit_can_frame(&PYLON_4200, can_config.battery); // Ensemble OR System equipment info, depends on frame0
|
||||
transmit_can_frame(&PYLON_8200, can_config.battery); // Control device quit sleep status
|
||||
transmit_can_frame(&PYLON_8210, can_config.battery); // Charge command
|
||||
|
||||
if (ensemble_info_ack) {
|
||||
PYLON_4200.data.u8[0] = 0x00; //Request system equipment info
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
#define MAX_CELL_DEVIATION_MV 500
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -180,7 +180,7 @@ void update_values_battery() {
|
|||
datalayer.battery.info.min_design_voltage_dV = DischargeVoltageLimit * 10;
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x080: // 15ms
|
||||
|
@ -301,14 +301,14 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 50ms CAN Message
|
||||
if (currentMillis - previousMillis50ms >= INTERVAL_50_MS) {
|
||||
|
||||
previousMillis50ms = currentMillis;
|
||||
|
||||
transmit_can(&RANGE_ROVER_18B, can_config.battery);
|
||||
transmit_can_frame(&RANGE_ROVER_18B, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
#define MAX_CELL_DEVIATION_MV 500 //TODO: Configure
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -103,41 +103,41 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
|
||||
datalayer.battery.status.cell_max_voltage_mV = LB_Cell_Max_Voltage;
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Values going to inverter:");
|
||||
Serial.print("SOH%: ");
|
||||
Serial.print(datalayer.battery.status.soh_pptt);
|
||||
Serial.print(", SOC% scaled: ");
|
||||
Serial.print(datalayer.battery.status.reported_soc);
|
||||
Serial.print(", Voltage: ");
|
||||
Serial.print(datalayer.battery.status.voltage_dV);
|
||||
Serial.print(", Max discharge power: ");
|
||||
Serial.print(datalayer.battery.status.max_discharge_power_W);
|
||||
Serial.print(", Max charge power: ");
|
||||
Serial.print(datalayer.battery.status.max_charge_power_W);
|
||||
Serial.print(", Max temp: ");
|
||||
Serial.print(datalayer.battery.status.temperature_max_dC);
|
||||
Serial.print(", Min temp: ");
|
||||
Serial.print(datalayer.battery.status.temperature_min_dC);
|
||||
Serial.print(", BMS Status (3=OK): ");
|
||||
Serial.print(datalayer.battery.status.bms_status);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Values going to inverter:");
|
||||
logging.print("SOH: ");
|
||||
logging.print(datalayer.battery.status.soh_pptt);
|
||||
logging.print(", SOC scaled: ");
|
||||
logging.print(datalayer.battery.status.reported_soc);
|
||||
logging.print(", Voltage: ");
|
||||
logging.print(datalayer.battery.status.voltage_dV);
|
||||
logging.print(", Max discharge power: ");
|
||||
logging.print(datalayer.battery.status.max_discharge_power_W);
|
||||
logging.print(", Max charge power: ");
|
||||
logging.print(datalayer.battery.status.max_charge_power_W);
|
||||
logging.print(", Max temp: ");
|
||||
logging.print(datalayer.battery.status.temperature_max_dC);
|
||||
logging.print(", Min temp: ");
|
||||
logging.print(datalayer.battery.status.temperature_min_dC);
|
||||
logging.print(", BMS Status (3=OK): ");
|
||||
logging.print(datalayer.battery.status.bms_status);
|
||||
|
||||
Serial.println("Battery values: ");
|
||||
Serial.print("Real SOC: ");
|
||||
Serial.print(LB_SOC);
|
||||
Serial.print(", Current: ");
|
||||
Serial.print(LB_Current);
|
||||
Serial.print(", kWh remain: ");
|
||||
Serial.print(LB_kWh_Remaining);
|
||||
Serial.print(", max mV: ");
|
||||
Serial.print(LB_Cell_Max_Voltage);
|
||||
Serial.print(", min mV: ");
|
||||
Serial.print(LB_Cell_Min_Voltage);
|
||||
logging.println("Battery values: ");
|
||||
logging.print("Real SOC: ");
|
||||
logging.print(LB_SOC);
|
||||
logging.print(", Current: ");
|
||||
logging.print(LB_Current);
|
||||
logging.print(", kWh remain: ");
|
||||
logging.print(LB_kWh_Remaining);
|
||||
logging.print(", max mV: ");
|
||||
logging.print(LB_Cell_Max_Voltage);
|
||||
logging.print(", min mV: ");
|
||||
logging.print(LB_Cell_Min_Voltage);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
|
||||
switch (rx_frame.ID) {
|
||||
case 0x155: //BMS1
|
||||
|
@ -210,12 +210,12 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message (for 2.4s, then pause 10s)
|
||||
if ((currentMillis - previousMillis100) >= (INTERVAL_100_MS + GVL_pause)) {
|
||||
previousMillis100 = currentMillis;
|
||||
transmit_can(&KANGOO_423, can_config.battery);
|
||||
transmit_can_frame(&KANGOO_423, can_config.battery);
|
||||
GVI_Pollcounter++;
|
||||
GVL_pause = 0;
|
||||
if (GVI_Pollcounter >= 24) {
|
||||
|
@ -227,9 +227,9 @@ void send_can_battery() {
|
|||
if (currentMillis - previousMillis1000 >= INTERVAL_1_S) {
|
||||
previousMillis1000 = currentMillis;
|
||||
if (GVB_79B_Continue)
|
||||
transmit_can(&KANGOO_79B_Continue, can_config.battery);
|
||||
transmit_can_frame(&KANGOO_79B_Continue, can_config.battery);
|
||||
} else {
|
||||
transmit_can(&KANGOO_79B, can_config.battery);
|
||||
transmit_can_frame(&KANGOO_79B, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
#define MAX_CHARGE_POWER_W 5000 // Battery can be charged with this amount of power
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,7 +65,7 @@ void update_values_battery() {
|
|||
max_value(cell_temperatures_dC, sizeof(cell_temperatures_dC) / sizeof(*cell_temperatures_dC));
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x155:
|
||||
|
@ -127,7 +127,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
// we do not need to send anything to the battery for now
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
|
||||
datalayer.battery.status.max_discharge_power_W = LB_Discharge_allowed_W;
|
||||
|
||||
datalayer.battery.status.max_charge_power_W = LB_Charging_Power_W;
|
||||
datalayer.battery.status.max_charge_power_W = LB_Regen_allowed_W;
|
||||
|
||||
int16_t temperatures[] = {cell_1_temperature_polled, cell_2_temperature_polled, cell_3_temperature_polled,
|
||||
cell_4_temperature_polled, cell_5_temperature_polled, cell_6_temperature_polled,
|
||||
|
@ -135,7 +135,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer.battery.status.voltage_dV = static_cast<uint32_t>((calculated_total_pack_voltage_mV / 100)); // mV to dV
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x155: //10ms - Charging power, current and SOC
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -195,7 +195,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
switch (frame0) {
|
||||
case 0x10: //PID HEADER, datarow 0
|
||||
requested_poll = rx_frame.data.u8[3];
|
||||
transmit_can(&ZOE_ACK_79B, can_config.battery);
|
||||
transmit_can_frame(&ZOE_ACK_79B, can_config.battery);
|
||||
|
||||
if (requested_poll == GROUP1_CELLVOLTAGES_1_POLL) {
|
||||
cellvoltages[0] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
|
||||
|
@ -486,7 +486,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
|
@ -495,7 +495,7 @@ void send_can_battery() {
|
|||
set_event(EVENT_CAN_OVERRUN, (currentMillis - previousMillis100));
|
||||
}
|
||||
previousMillis100 = currentMillis;
|
||||
transmit_can(&ZOE_423, can_config.battery);
|
||||
transmit_can_frame(&ZOE_423, can_config.battery);
|
||||
|
||||
if ((counter_423 / 5) % 2 == 0) { // Alternate every 5 messages between these two
|
||||
ZOE_423.data.u8[4] = 0xB2;
|
||||
|
@ -534,7 +534,7 @@ void send_can_battery() {
|
|||
|
||||
ZOE_POLL_79B.data.u8[2] = current_poll;
|
||||
|
||||
transmit_can(&ZOE_POLL_79B, can_config.battery);
|
||||
transmit_can_frame(&ZOE_POLL_79B, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -216,13 +216,9 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer_extended.zoePH2.battery_pack_time = battery_pack_time;
|
||||
datalayer_extended.zoePH2.battery_soc_min = battery_soc_min;
|
||||
datalayer_extended.zoePH2.battery_soc_max = battery_soc_max;
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x18DAF1DB: // LBC Reply from active polling
|
||||
|
@ -362,7 +358,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 200ms CAN Message
|
||||
if (currentMillis - previousMillis200 >= INTERVAL_200_MS) {
|
||||
|
@ -379,8 +375,8 @@ void send_can_battery() {
|
|||
ZOE_POLL_18DADBF1.data.u8[2] = (uint8_t)((currentpoll & 0xFF00) >> 8);
|
||||
ZOE_POLL_18DADBF1.data.u8[3] = (uint8_t)(currentpoll & 0x00FF);
|
||||
|
||||
transmit_can(&ZOE_POLL_18DADBF1, can_config.battery);
|
||||
transmit_can(&ZOE_373, can_config.battery);
|
||||
transmit_can_frame(&ZOE_POLL_18DADBF1, can_config.battery);
|
||||
transmit_can_frame(&ZOE_373, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#define POLL_SOC 0x9001
|
||||
#define POLL_USABLE_SOC 0x9002
|
||||
|
|
|
@ -158,21 +158,21 @@ void update_values_battery() {
|
|||
datalayer.battery.status.cell_min_voltage_mV = minimum_cell_voltage;
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
|
||||
/*
|
||||
// All CAN messages recieved will be logged via serial
|
||||
Serial.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.ID, HEX);
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.DLC);
|
||||
Serial.print(" ");
|
||||
logging.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
logging.print(" ");
|
||||
logging.print(rx_frame.ID, HEX);
|
||||
logging.print(" ");
|
||||
logging.print(rx_frame.DLC);
|
||||
logging.print(" ");
|
||||
for (int i = 0; i < rx_frame.DLC; ++i) {
|
||||
Serial.print(rx_frame.data.u8[i], HEX);
|
||||
Serial.print(" ");
|
||||
logging.print(rx_frame.data.u8[i], HEX);
|
||||
logging.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
*/
|
||||
switch (rx_frame.ID) {
|
||||
case 0xF5: // This is the only message is sent from BMS
|
||||
|
@ -550,7 +550,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 10s CAN Message
|
||||
if (currentMillis - previousMillis10s >= INTERVAL_10_S) {
|
||||
|
@ -563,8 +563,8 @@ void send_can_battery() {
|
|||
}
|
||||
|
||||
if (!setup_completed) {
|
||||
transmit_can(&RJXZS_10, can_config.battery); // Communication connected flag
|
||||
transmit_can(&RJXZS_1C, can_config.battery); // CAN OK
|
||||
transmit_can_frame(&RJXZS_10, can_config.battery); // Communication connected flag
|
||||
transmit_can_frame(&RJXZS_1C, can_config.battery); // CAN OK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,6 @@
|
|||
#define NATIVECAN_250KBPS
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,7 +116,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x1FF:
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -171,7 +171,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
switch (rx_frame.data.u8[0]) {
|
||||
case 0x10: //"PID Header"
|
||||
if (rx_frame.data.u8[4] == poll_data_pid) {
|
||||
transmit_can(&SANTAFE_7E4_ack, can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
transmit_can_frame(&SANTAFE_7E4_ack,
|
||||
can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||
}
|
||||
break;
|
||||
case 0x21: //First frame in PID group
|
||||
|
@ -332,7 +333,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
//Send 10ms message
|
||||
|
@ -351,13 +352,13 @@ void send_can_battery() {
|
|||
|
||||
SANTAFE_200.data.u8[7] = checksum_200;
|
||||
|
||||
transmit_can(&SANTAFE_200, can_config.battery);
|
||||
transmit_can(&SANTAFE_2A1, can_config.battery);
|
||||
transmit_can(&SANTAFE_2F0, can_config.battery);
|
||||
transmit_can_frame(&SANTAFE_200, can_config.battery);
|
||||
transmit_can_frame(&SANTAFE_2A1, can_config.battery);
|
||||
transmit_can_frame(&SANTAFE_2F0, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&SANTAFE_200, can_config.battery_double);
|
||||
transmit_can(&SANTAFE_2A1, can_config.battery_double);
|
||||
transmit_can(&SANTAFE_2F0, can_config.battery_double);
|
||||
transmit_can_frame(&SANTAFE_200, can_config.battery_double);
|
||||
transmit_can_frame(&SANTAFE_2A1, can_config.battery_double);
|
||||
transmit_can_frame(&SANTAFE_2F0, can_config.battery_double);
|
||||
#endif //DOUBLE_BATTERY
|
||||
|
||||
counter_200++;
|
||||
|
@ -370,9 +371,9 @@ void send_can_battery() {
|
|||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
previousMillis100 = currentMillis;
|
||||
|
||||
transmit_can(&SANTAFE_523, can_config.battery);
|
||||
transmit_can_frame(&SANTAFE_523, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&SANTAFE_523, can_config.battery_double);
|
||||
transmit_can_frame(&SANTAFE_523, can_config.battery_double);
|
||||
#endif //DOUBLE_BATTERY
|
||||
}
|
||||
|
||||
|
@ -383,9 +384,9 @@ void send_can_battery() {
|
|||
// PID data is polled after last message sent from battery:
|
||||
poll_data_pid = (poll_data_pid % 5) + 1;
|
||||
SANTAFE_7E4_poll.data.u8[3] = (uint8_t)poll_data_pid;
|
||||
transmit_can(&SANTAFE_7E4_poll, can_config.battery);
|
||||
transmit_can_frame(&SANTAFE_7E4_poll, can_config.battery);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
transmit_can(&SANTAFE_7E4_poll, can_config.battery_double);
|
||||
transmit_can_frame(&SANTAFE_7E4_poll, can_config.battery_double);
|
||||
#endif //DOUBLE_BATTERY
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +426,7 @@ void update_values_battery2() { //This function maps all the values fetched via
|
|||
}
|
||||
}
|
||||
|
||||
void receive_can_battery2(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||
switch (rx_frame.ID) {
|
||||
case 0x1FF:
|
||||
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -480,7 +481,7 @@ void receive_can_battery2(CAN_frame rx_frame) {
|
|||
switch (rx_frame.data.u8[0]) {
|
||||
case 0x10: //"PID Header"
|
||||
if (rx_frame.data.u8[4] == poll_data_pid) {
|
||||
transmit_can(&SANTAFE_7E4_ack,
|
||||
transmit_can_frame(&SANTAFE_7E4_ack,
|
||||
can_config.battery_double); //Send ack to BMS if the same frame is sent as polled
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
|
||||
uint8_t CalculateCRC8(CAN_frame rx_frame);
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,8 +94,8 @@ void manageSerialLinkReceiver() {
|
|||
bool readError = dataLinkReceive.checkReadError(true); // check for error & clear error flag
|
||||
|
||||
if (readError) {
|
||||
Serial.print(currentTime);
|
||||
Serial.println(" - ERROR: SerialDataLink - Read Error");
|
||||
logging.print(currentTime);
|
||||
logging.println(" - ERROR: SerialDataLink - Read Error");
|
||||
lasterror = true;
|
||||
errors++;
|
||||
}
|
||||
|
@ -112,8 +112,8 @@ void manageSerialLinkReceiver() {
|
|||
//bms_status = ACTIVE; // just testing
|
||||
if (lasterror) {
|
||||
lasterror = false;
|
||||
Serial.print(currentTime);
|
||||
Serial.println(" - RECOVERY: SerialDataLink - Read GOOD");
|
||||
logging.print(currentTime);
|
||||
logging.println(" - RECOVERY: SerialDataLink - Read GOOD");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,34 +134,34 @@ void manageSerialLinkReceiver() {
|
|||
// report Lost data & Max charge / Discharge reductions
|
||||
if (minutesLost != last_minutesLost) {
|
||||
last_minutesLost = minutesLost;
|
||||
Serial.print(currentTime);
|
||||
logging.print(currentTime);
|
||||
if (batteryFault) {
|
||||
Serial.print("Battery Fault (minutes) : ");
|
||||
logging.print("Battery Fault (minutes) : ");
|
||||
} else {
|
||||
Serial.print(" - Minutes without data : ");
|
||||
logging.print(" - Minutes without data : ");
|
||||
}
|
||||
Serial.print(minutesLost);
|
||||
Serial.print(", max Charge = ");
|
||||
Serial.print(datalayer.battery.status.max_charge_power_W);
|
||||
Serial.print(", max Discharge = ");
|
||||
Serial.println(datalayer.battery.status.max_discharge_power_W);
|
||||
logging.print(minutesLost);
|
||||
logging.print(", max Charge = ");
|
||||
logging.print(datalayer.battery.status.max_charge_power_W);
|
||||
logging.print(", max Discharge = ");
|
||||
logging.println(datalayer.battery.status.max_discharge_power_W);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentTime - reportTime > 59999) {
|
||||
reportTime = currentTime;
|
||||
Serial.print(currentTime);
|
||||
Serial.print(" SerialDataLink-Receiver - NewData :");
|
||||
Serial.print(reads);
|
||||
Serial.print(" Errors : ");
|
||||
Serial.println(errors);
|
||||
logging.print(currentTime);
|
||||
logging.print(" SerialDataLink-Receiver - NewData :");
|
||||
logging.print(reads);
|
||||
logging.print(" Errors : ");
|
||||
logging.println(errors);
|
||||
reads = 0;
|
||||
errors = 0;
|
||||
|
||||
// --- printUsefullData();
|
||||
//Serial.print("SOC = ");
|
||||
//Serial.println(SOC);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
//logging.print("SOC = ");
|
||||
//logging.println(SOC);
|
||||
#ifdef DEBUG_LOG
|
||||
update_values_serial_link();
|
||||
#endif
|
||||
}
|
||||
|
@ -179,43 +179,43 @@ void manageSerialLinkReceiver() {
|
|||
}
|
||||
|
||||
void update_values_serial_link() {
|
||||
Serial.println("Values from battery: ");
|
||||
Serial.print("SOC: ");
|
||||
Serial.print(datalayer.battery.status.real_soc);
|
||||
Serial.print(" SOH: ");
|
||||
Serial.print(datalayer.battery.status.soh_pptt);
|
||||
Serial.print(" Voltage: ");
|
||||
Serial.print(datalayer.battery.status.voltage_dV);
|
||||
Serial.print(" Current: ");
|
||||
Serial.print(datalayer.battery.status.current_dA);
|
||||
Serial.print(" Capacity: ");
|
||||
Serial.print(datalayer.battery.info.total_capacity_Wh);
|
||||
Serial.print(" Remain cap: ");
|
||||
Serial.print(datalayer.battery.status.remaining_capacity_Wh);
|
||||
Serial.print(" Max discharge W: ");
|
||||
Serial.print(datalayer.battery.status.max_discharge_power_W);
|
||||
Serial.print(" Max charge W: ");
|
||||
Serial.print(datalayer.battery.status.max_charge_power_W);
|
||||
Serial.print(" BMS status: ");
|
||||
Serial.print(datalayer.battery.status.bms_status);
|
||||
Serial.print(" Power: ");
|
||||
Serial.print(datalayer.battery.status.active_power_W);
|
||||
Serial.print(" Temp min: ");
|
||||
Serial.print(datalayer.battery.status.temperature_min_dC);
|
||||
Serial.print(" Temp max: ");
|
||||
Serial.print(datalayer.battery.status.temperature_max_dC);
|
||||
Serial.print(" Cell max: ");
|
||||
Serial.print(datalayer.battery.status.cell_max_voltage_mV);
|
||||
Serial.print(" Cell min: ");
|
||||
Serial.print(datalayer.battery.status.cell_min_voltage_mV);
|
||||
Serial.print(" LFP : ");
|
||||
Serial.print(datalayer.battery.info.chemistry);
|
||||
Serial.print(" Battery Allows Contactor Closing: ");
|
||||
Serial.print(datalayer.system.status.battery_allows_contactor_closing);
|
||||
Serial.print(" Inverter Allows Contactor Closing: ");
|
||||
Serial.print(datalayer.system.status.inverter_allows_contactor_closing);
|
||||
logging.println("Values from battery: ");
|
||||
logging.print("SOC: ");
|
||||
logging.print(datalayer.battery.status.real_soc);
|
||||
logging.print(" SOH: ");
|
||||
logging.print(datalayer.battery.status.soh_pptt);
|
||||
logging.print(" Voltage: ");
|
||||
logging.print(datalayer.battery.status.voltage_dV);
|
||||
logging.print(" Current: ");
|
||||
logging.print(datalayer.battery.status.current_dA);
|
||||
logging.print(" Capacity: ");
|
||||
logging.print(datalayer.battery.info.total_capacity_Wh);
|
||||
logging.print(" Remain cap: ");
|
||||
logging.print(datalayer.battery.status.remaining_capacity_Wh);
|
||||
logging.print(" Max discharge W: ");
|
||||
logging.print(datalayer.battery.status.max_discharge_power_W);
|
||||
logging.print(" Max charge W: ");
|
||||
logging.print(datalayer.battery.status.max_charge_power_W);
|
||||
logging.print(" BMS status: ");
|
||||
logging.print(datalayer.battery.status.bms_status);
|
||||
logging.print(" Power: ");
|
||||
logging.print(datalayer.battery.status.active_power_W);
|
||||
logging.print(" Temp min: ");
|
||||
logging.print(datalayer.battery.status.temperature_min_dC);
|
||||
logging.print(" Temp max: ");
|
||||
logging.print(datalayer.battery.status.temperature_max_dC);
|
||||
logging.print(" Cell max: ");
|
||||
logging.print(datalayer.battery.status.cell_max_voltage_mV);
|
||||
logging.print(" Cell min: ");
|
||||
logging.print(datalayer.battery.status.cell_min_voltage_mV);
|
||||
logging.print(" LFP : ");
|
||||
logging.print(datalayer.battery.info.chemistry);
|
||||
logging.print(" Battery Allows Contactor Closing: ");
|
||||
logging.print(datalayer.system.status.battery_allows_contactor_closing);
|
||||
logging.print(" Inverter Allows Contactor Closing: ");
|
||||
logging.print(datalayer.system.status.inverter_allows_contactor_closing);
|
||||
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
}
|
||||
|
||||
void setup_battery(void) {
|
||||
|
@ -224,7 +224,7 @@ void setup_battery(void) {
|
|||
}
|
||||
// Needed to make the compiler happy
|
||||
void update_values_battery() {}
|
||||
void send_can_battery() {}
|
||||
void receive_can_battery(CAN_frame rx_frame) {}
|
||||
void transmit_can_battery() {}
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,7 @@ void printDebugIfActive(uint8_t symbol, const char* message);
|
|||
void print_int_with_units(char* header, int value, char* units);
|
||||
void print_SOC(char* header, int SOC);
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
#ifdef DOUBLE_BATTERY
|
||||
void printFaultCodesIfActive_battery2();
|
||||
#endif //DOUBLE_BATTERY
|
||||
|
|
|
@ -15,9 +15,9 @@ CAN_frame TEST = {.FD = false,
|
|||
.data = {0x10, 0x64, 0x00, 0xB0, 0x00, 0x1E, 0x00, 0x8F}};
|
||||
|
||||
void print_units(char* header, int value, char* units) {
|
||||
Serial.print(header);
|
||||
Serial.print(value);
|
||||
Serial.print(units);
|
||||
logging.print(header);
|
||||
logging.print(value);
|
||||
logging.print(units);
|
||||
}
|
||||
|
||||
void update_values_battery() { /* This function puts fake values onto the parameters sent towards the inverter */
|
||||
|
@ -54,10 +54,10 @@ void update_values_battery() { /* This function puts fake values onto the parame
|
|||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("FAKE Values going to inverter");
|
||||
print_units("SOH%: ", (datalayer.battery.status.soh_pptt * 0.01), "% ");
|
||||
print_units(", SOC%: ", (datalayer.battery.status.reported_soc * 0.01), "% ");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("FAKE Values going to inverter");
|
||||
print_units("SOH: ", (datalayer.battery.status.soh_pptt * 0.01), "pct ");
|
||||
print_units(", SOC: ", (datalayer.battery.status.reported_soc * 0.01), "pct ");
|
||||
print_units(", Voltage: ", (datalayer.battery.status.voltage_dV * 0.1), "V ");
|
||||
print_units(", Max discharge power: ", datalayer.battery.status.max_discharge_power_W, "W ");
|
||||
print_units(", Max charge power: ", datalayer.battery.status.max_charge_power_W, "W ");
|
||||
|
@ -65,7 +65,7 @@ void update_values_battery() { /* This function puts fake values onto the parame
|
|||
print_units(", Min temp: ", (datalayer.battery.status.temperature_min_dC * 0.1), "°C ");
|
||||
print_units(", Max cell voltage: ", datalayer.battery.status.cell_max_voltage_mV, "mV ");
|
||||
print_units(", Min cell voltage: ", datalayer.battery.status.cell_min_voltage_mV, "mV ");
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -107,10 +107,10 @@ void update_values_battery2() { // Handle the values coming in from battery #2
|
|||
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("FAKE Values battery 2 going to inverter");
|
||||
print_units("SOH 2 %: ", (datalayer.battery2.status.soh_pptt * 0.01), "% ");
|
||||
print_units(", SOC 2 %: ", (datalayer.battery2.status.reported_soc * 0.01), "% ");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("FAKE Values battery 2 going to inverter");
|
||||
print_units("SOH 2: ", (datalayer.battery2.status.soh_pptt * 0.01), "pct ");
|
||||
print_units(", SOC 2: ", (datalayer.battery2.status.reported_soc * 0.01), "pct ");
|
||||
print_units(", Voltage 2: ", (datalayer.battery2.status.voltage_dV * 0.1), "V ");
|
||||
print_units(", Max discharge power 2: ", datalayer.battery2.status.max_discharge_power_W, "W ");
|
||||
print_units(", Max charge power 2: ", datalayer.battery2.status.max_charge_power_W, "W ");
|
||||
|
@ -118,25 +118,25 @@ void update_values_battery2() { // Handle the values coming in from battery #2
|
|||
print_units(", Min temp 2: ", (datalayer.battery2.status.temperature_min_dC * 0.1), "°C ");
|
||||
print_units(", Max cell voltage 2: ", datalayer.battery2.status.cell_max_voltage_mV, "mV ");
|
||||
print_units(", Min cell voltage 2: ", datalayer.battery2.status.cell_min_voltage_mV, "mV ");
|
||||
Serial.println("");
|
||||
logging.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery2(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
}
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
}
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
previousMillis100 = currentMillis;
|
||||
// Put fake messages here incase you want to test sending CAN
|
||||
//transmit_can(&TEST, can_config.battery);
|
||||
//transmit_can_frame(&TEST, can_config.battery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
#define MAX_CELL_DEVIATION_MV 9999
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,53 +94,53 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
datalayer.battery.status.cell_voltages_mV[i] = cell_voltages[i];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.print("BMS reported SOC%: ");
|
||||
Serial.println(SOC_BMS);
|
||||
Serial.print("Calculated SOC%: ");
|
||||
Serial.println(SOC_CALC);
|
||||
Serial.print("Rescaled SOC%: ");
|
||||
Serial.println(datalayer.battery.status.reported_soc / 100);
|
||||
Serial.print("Battery current: ");
|
||||
Serial.println(BATT_I);
|
||||
Serial.print("Battery voltage: ");
|
||||
Serial.println(BATT_U);
|
||||
Serial.print("Battery maximum voltage limit: ");
|
||||
Serial.println(MAX_U);
|
||||
Serial.print("Battery minimum voltage limit: ");
|
||||
Serial.println(MIN_U);
|
||||
Serial.print("Remaining Energy: ");
|
||||
Serial.println(remaining_capacity);
|
||||
Serial.print("Discharge limit: ");
|
||||
Serial.println(HvBattPwrLimDchaSoft);
|
||||
Serial.print("Battery Error Indication: ");
|
||||
Serial.println(BATT_ERR_INDICATION);
|
||||
Serial.print("Maximum battery temperature: ");
|
||||
Serial.println(BATT_T_MAX / 10);
|
||||
Serial.print("Minimum battery temperature: ");
|
||||
Serial.println(BATT_T_MIN / 10);
|
||||
Serial.print("Average battery temperature: ");
|
||||
Serial.println(BATT_T_AVG / 10);
|
||||
Serial.print("BMS Highest cell voltage: ");
|
||||
Serial.println(CELL_U_MAX * 10);
|
||||
Serial.print("BMS Lowest cell voltage: ");
|
||||
Serial.println(CELL_U_MIN * 10);
|
||||
Serial.print("BMS Highest cell nr: ");
|
||||
Serial.println(CELL_ID_U_MAX);
|
||||
Serial.print("Highest cell voltage: ");
|
||||
Serial.println(min_max_voltage[1]);
|
||||
Serial.print("Lowest cell voltage: ");
|
||||
Serial.println(min_max_voltage[0]);
|
||||
Serial.print("Cell voltage,");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("BMS reported SOC: ");
|
||||
logging.println(SOC_BMS);
|
||||
logging.print("Calculated SOC: ");
|
||||
logging.println(SOC_CALC);
|
||||
logging.print("Rescaled SOC: ");
|
||||
logging.println(datalayer.battery.status.reported_soc / 100);
|
||||
logging.print("Battery current: ");
|
||||
logging.println(BATT_I);
|
||||
logging.print("Battery voltage: ");
|
||||
logging.println(BATT_U);
|
||||
logging.print("Battery maximum voltage limit: ");
|
||||
logging.println(MAX_U);
|
||||
logging.print("Battery minimum voltage limit: ");
|
||||
logging.println(MIN_U);
|
||||
logging.print("Remaining Energy: ");
|
||||
logging.println(remaining_capacity);
|
||||
logging.print("Discharge limit: ");
|
||||
logging.println(HvBattPwrLimDchaSoft);
|
||||
logging.print("Battery Error Indication: ");
|
||||
logging.println(BATT_ERR_INDICATION);
|
||||
logging.print("Maximum battery temperature: ");
|
||||
logging.println(BATT_T_MAX / 10);
|
||||
logging.print("Minimum battery temperature: ");
|
||||
logging.println(BATT_T_MIN / 10);
|
||||
logging.print("Average battery temperature: ");
|
||||
logging.println(BATT_T_AVG / 10);
|
||||
logging.print("BMS Highest cell voltage: ");
|
||||
logging.println(CELL_U_MAX * 10);
|
||||
logging.print("BMS Lowest cell voltage: ");
|
||||
logging.println(CELL_U_MIN * 10);
|
||||
logging.print("BMS Highest cell nr: ");
|
||||
logging.println(CELL_ID_U_MAX);
|
||||
logging.print("Highest cell voltage: ");
|
||||
logging.println(min_max_voltage[1]);
|
||||
logging.print("Lowest cell voltage: ");
|
||||
logging.println(min_max_voltage[0]);
|
||||
logging.print("Cell voltage,");
|
||||
while (cnt < 108) {
|
||||
Serial.print(cell_voltages[cnt++]);
|
||||
Serial.print(",");
|
||||
logging.print(cell_voltages[cnt++]);
|
||||
logging.print(",");
|
||||
}
|
||||
Serial.println(";");
|
||||
logging.println(";");
|
||||
#endif
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
switch (rx_frame.ID) {
|
||||
case 0x3A:
|
||||
|
@ -148,8 +148,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
BATT_I = (0 - ((((rx_frame.data.u8[6] & 0x7F) * 256.0 + rx_frame.data.u8[7]) * 0.1) - 1638));
|
||||
else {
|
||||
BATT_I = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BATT_I not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_I not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -157,22 +157,22 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
MAX_U = (((rx_frame.data.u8[2] & 0x07) * 256.0 + rx_frame.data.u8[3]) * 0.25);
|
||||
else {
|
||||
//MAX_U = 0;
|
||||
//Serial.println("MAX_U not valid"); // Value toggles between true/false from BMS
|
||||
//logging.println("MAX_U not valid"); // Value toggles between true/false from BMS
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[4] & 0x08) == 0x08)
|
||||
MIN_U = (((rx_frame.data.u8[4] & 0x07) * 256.0 + rx_frame.data.u8[5]) * 0.25);
|
||||
else {
|
||||
//MIN_U = 0;
|
||||
//Serial.println("MIN_U not valid"); // Value toggles between true/false from BMS
|
||||
//logging.println("MIN_U not valid"); // Value toggles between true/false from BMS
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[0] & 0x08) == 0x08)
|
||||
BATT_U = (((rx_frame.data.u8[0] & 0x07) * 256.0 + rx_frame.data.u8[1]) * 0.25);
|
||||
else {
|
||||
BATT_U = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BATT_U not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_U not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -189,8 +189,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
BATT_ERR_INDICATION = ((rx_frame.data.u8[0] & 0x40) >> 6);
|
||||
else {
|
||||
BATT_ERR_INDICATION = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BATT_ERR_INDICATION not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_ERR_INDICATION not valid");
|
||||
#endif
|
||||
}
|
||||
if ((rx_frame.data.u8[0] & 0x20) == 0x20) {
|
||||
|
@ -201,8 +201,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
BATT_T_MAX = 0;
|
||||
BATT_T_MIN = 0;
|
||||
BATT_T_AVG = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BATT_T not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_T not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -211,8 +211,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
HvBattPwrLimDchaSoft = (((rx_frame.data.u8[6] & 0x03) * 256 + rx_frame.data.u8[6]) >> 2);
|
||||
} else {
|
||||
HvBattPwrLimDchaSoft = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("HvBattPwrLimDchaSoft not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("HvBattPwrLimDchaSoft not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -221,8 +221,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
SOC_BMS = ((rx_frame.data.u8[6] & 0x03) * 256 + rx_frame.data.u8[7]);
|
||||
} else {
|
||||
SOC_BMS = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("SOC_BMS not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("SOC_BMS not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -230,8 +230,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
CELL_U_MAX = ((rx_frame.data.u8[2] & 0x01) * 256 + rx_frame.data.u8[3]);
|
||||
else {
|
||||
CELL_U_MAX = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CELL_U_MAX not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CELL_U_MAX not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -239,8 +239,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
CELL_U_MIN = ((rx_frame.data.u8[0] & 0x01) * 256.0 + rx_frame.data.u8[1]);
|
||||
else {
|
||||
CELL_U_MIN = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CELL_U_MIN not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CELL_U_MIN not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -248,8 +248,8 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
CELL_ID_U_MAX = ((rx_frame.data.u8[4] & 0x01) * 256.0 + rx_frame.data.u8[5]);
|
||||
else {
|
||||
CELL_ID_U_MAX = 0;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CELL_ID_U_MAX not valid");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CELL_ID_U_MAX not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -263,7 +263,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
{
|
||||
cell_voltages[battery_request_idx++] = ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[6]);
|
||||
cell_voltages[battery_request_idx] = (rx_frame.data.u8[7] << 8);
|
||||
transmit_can(&VOLVO_FlowControl, can_config.battery); // Send flow control
|
||||
transmit_can_frame(&VOLVO_FlowControl, can_config.battery); // Send flow control
|
||||
rxConsecutiveFrames = 1;
|
||||
} else if ((rx_frame.data.u8[0] == 0x21) && (rxConsecutiveFrames == 1)) {
|
||||
cell_voltages[battery_request_idx++] = cell_voltages[battery_request_idx] | rx_frame.data.u8[1];
|
||||
|
@ -273,7 +273,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
if (batteryModuleNumber <= 0x2A) // Run until last pack is read
|
||||
{
|
||||
VOLVO_CELL_U_Req.data.u8[3] = batteryModuleNumber++;
|
||||
transmit_can(&VOLVO_CELL_U_Req, can_config.battery); //Send cell voltage read request for next module
|
||||
transmit_can_frame(&VOLVO_CELL_U_Req, can_config.battery); //Send cell voltage read request for next module
|
||||
} else {
|
||||
min_max_voltage[0] = 9999;
|
||||
min_max_voltage[1] = 0;
|
||||
|
@ -284,7 +284,7 @@ void receive_can_battery(CAN_frame rx_frame) {
|
|||
min_max_voltage[1] = cell_voltages[cellcounter];
|
||||
}
|
||||
|
||||
transmit_can(&VOLVO_SOH_Req, can_config.battery); //Send SOH read request
|
||||
transmit_can_frame(&VOLVO_SOH_Req, can_config.battery); //Send SOH read request
|
||||
}
|
||||
rxConsecutiveFrames = 0;
|
||||
}
|
||||
|
@ -299,10 +299,10 @@ void readCellVoltages() {
|
|||
batteryModuleNumber = 0x10;
|
||||
rxConsecutiveFrames = 0;
|
||||
VOLVO_CELL_U_Req.data.u8[3] = batteryModuleNumber++;
|
||||
transmit_can(&VOLVO_CELL_U_Req, can_config.battery); //Send cell voltage read request for first module
|
||||
transmit_can_frame(&VOLVO_CELL_U_Req, can_config.battery); //Send cell voltage read request for first module
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
void transmit_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
|
@ -314,8 +314,8 @@ void send_can_battery() {
|
|||
}
|
||||
previousMillis100 = currentMillis;
|
||||
|
||||
transmit_can(&VOLVO_536, can_config.battery); //Send 0x536 Network managing frame to keep BMS alive
|
||||
transmit_can(&VOLVO_372, can_config.battery); //Send 0x372 ECMAmbientTempCalculated
|
||||
transmit_can_frame(&VOLVO_536, can_config.battery); //Send 0x536 Network managing frame to keep BMS alive
|
||||
transmit_can_frame(&VOLVO_372, can_config.battery); //Send 0x372 ECMAmbientTempCalculated
|
||||
|
||||
if (datalayer.battery.status.bms_status == ACTIVE) {
|
||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "NISSAN-LEAF-CHARGER.h"
|
||||
#endif
|
||||
|
||||
void receive_can_charger(CAN_frame rx_frame);
|
||||
void send_can_charger();
|
||||
void map_can_frame_to_variable_charger(CAN_frame rx_frame);
|
||||
void transmit_can_charger();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -56,7 +56,7 @@ static CAN_frame charger_set_targets = {
|
|||
.data = {0x40, 0x00, 0x00, 0x00}}; // data[0] is a static value, meaning unknown
|
||||
|
||||
/* We are mostly sending out not receiving */
|
||||
void receive_can_charger(CAN_frame rx_frame) {
|
||||
void map_can_frame_to_variable_charger(CAN_frame rx_frame) {
|
||||
uint16_t charger_stat_HVcur_temp = 0;
|
||||
uint16_t charger_stat_HVvol_temp = 0;
|
||||
uint16_t charger_stat_LVcur_temp = 0;
|
||||
|
@ -101,14 +101,11 @@ void receive_can_charger(CAN_frame rx_frame) {
|
|||
case 0x308:
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.printf("CAN Rcv unknown frame MsgID=%x\n", rx_frame.MsgID);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void send_can_charger() {
|
||||
void transmit_can_charger() {
|
||||
unsigned long currentMillis = millis();
|
||||
uint16_t Vol_temp = 0;
|
||||
|
||||
|
@ -137,7 +134,7 @@ void send_can_charger() {
|
|||
|
||||
charger_keepalive_frame.data.u8[0] = charger_mode;
|
||||
|
||||
transmit_can(&charger_keepalive_frame, can_config.charger);
|
||||
transmit_can_frame(&charger_keepalive_frame, can_config.charger);
|
||||
}
|
||||
|
||||
/* Send current targets every 200ms */
|
||||
|
@ -174,18 +171,18 @@ void send_can_charger() {
|
|||
/* LSB of the voltage command. Then MSB LSB is divided by 2 */
|
||||
charger_set_targets.data.u8[3] = lowByte(Vol_temp);
|
||||
|
||||
transmit_can(&charger_set_targets, can_config.charger);
|
||||
transmit_can_frame(&charger_set_targets, can_config.charger);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
/* Serial echo every 5s of charger stats */
|
||||
if (currentMillis - previousMillis5000ms >= INTERVAL_5_S) {
|
||||
previousMillis5000ms = currentMillis;
|
||||
Serial.printf("Charger AC in IAC=%fA VAC=%fV\n", charger_stat_ACcur, charger_stat_ACvol);
|
||||
Serial.printf("Charger HV out IDC=%fA VDC=%fV\n", charger_stat_HVcur, charger_stat_HVvol);
|
||||
Serial.printf("Charger LV out IDC=%fA VDC=%fV\n", charger_stat_LVcur, charger_stat_LVvol);
|
||||
Serial.printf("Charger mode=%s\n", (charger_mode > MODE_DISABLED) ? "Enabled" : "Disabled");
|
||||
Serial.printf("Charger HVset=%uV,%uA finishCurrent=%uA\n", setpoint_HV_VDC, setpoint_HV_IDC, setpoint_HV_IDC_END);
|
||||
logging.printf("Charger AC in IAC=%fA VAC=%fV\n", charger_stat_ACcur, charger_stat_ACvol);
|
||||
logging.printf("Charger HV out IDC=%fA VDC=%fV\n", charger_stat_HVcur, charger_stat_HVvol);
|
||||
logging.printf("Charger LV out IDC=%fA VDC=%fV\n", charger_stat_LVcur, charger_stat_LVvol);
|
||||
logging.printf("Charger mode=%s\n", (charger_mode > MODE_DISABLED) ? "Enabled" : "Disabled");
|
||||
logging.printf("Charger HVset=%uV,%uA finishCurrent=%uA\n", setpoint_HV_VDC, setpoint_HV_IDC, setpoint_HV_IDC_END);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ static uint8_t calculate_checksum_nibble(CAN_frame* frame) {
|
|||
return sum;
|
||||
}
|
||||
|
||||
void receive_can_charger(CAN_frame rx_frame) {
|
||||
void map_can_frame_to_variable_charger(CAN_frame rx_frame) {
|
||||
|
||||
switch (rx_frame.ID) {
|
||||
case 0x679: // This message fires once when charging cable is plugged in
|
||||
|
@ -166,7 +166,7 @@ void receive_can_charger(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_charger() {
|
||||
void transmit_can_charger() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
/* Send keepalive with mode every 10ms */
|
||||
|
@ -182,13 +182,13 @@ void send_can_charger() {
|
|||
#ifndef NISSAN_LEAF_BATTERY
|
||||
|
||||
// VCM message, containing info if battery should sleep or stay awake
|
||||
transmit_can(&LEAF_50B, can_config.charger); // HCM_WakeUpSleepCommand == 11b == WakeUp, and CANMASK = 1
|
||||
transmit_can_frame(&LEAF_50B, can_config.charger); // HCM_WakeUpSleepCommand == 11b == WakeUp, and CANMASK = 1
|
||||
|
||||
LEAF_1DB.data.u8[7] = calculate_CRC_Nissan(&LEAF_1DB);
|
||||
transmit_can(&LEAF_1DB, can_config.charger);
|
||||
transmit_can_frame(&LEAF_1DB, can_config.charger);
|
||||
|
||||
LEAF_1DC.data.u8[7] = calculate_CRC_Nissan(&LEAF_1DC);
|
||||
transmit_can(&LEAF_1DC, can_config.charger);
|
||||
transmit_can_frame(&LEAF_1DC, can_config.charger);
|
||||
#endif
|
||||
|
||||
OBCpowerSetpoint = ((charger_setpoint_HV_IDC * 4) + 0x64);
|
||||
|
@ -233,7 +233,8 @@ void send_can_charger() {
|
|||
LEAF_1F2.data.u8[6] = mprun10;
|
||||
LEAF_1F2.data.u8[7] = calculate_checksum_nibble(&LEAF_1F2);
|
||||
|
||||
transmit_can(&LEAF_1F2,
|
||||
transmit_can_frame(
|
||||
&LEAF_1F2,
|
||||
can_config.charger); // Sending of 1F2 message is halted in LEAF-BATTERY function incase used here
|
||||
}
|
||||
|
||||
|
@ -252,11 +253,11 @@ void send_can_charger() {
|
|||
LEAF_55B.data.u8[6] = ((0x1 << 4) | (mprun100));
|
||||
|
||||
LEAF_55B.data.u8[7] = calculate_CRC_Nissan(&LEAF_55B);
|
||||
transmit_can(&LEAF_55B, can_config.charger);
|
||||
transmit_can_frame(&LEAF_55B, can_config.charger);
|
||||
|
||||
transmit_can(&LEAF_59E, can_config.charger);
|
||||
transmit_can_frame(&LEAF_59E, can_config.charger);
|
||||
|
||||
transmit_can(&LEAF_5BC, can_config.charger);
|
||||
transmit_can_frame(&LEAF_5BC, can_config.charger);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "comm_can.h"
|
||||
#include "../../include.h"
|
||||
#include "src/devboard/sdcard/sdcard.h"
|
||||
|
||||
// Parameters
|
||||
|
||||
|
@ -9,11 +10,13 @@ volatile bool send_ok = 0;
|
|||
|
||||
#ifdef CAN_ADDON
|
||||
static const uint32_t QUARTZ_FREQUENCY = CRYSTAL_FREQUENCY_MHZ * 1000000UL; //MHZ configured in USER_SETTINGS.h
|
||||
ACAN2515 can(MCP2515_CS, SPI, MCP2515_INT);
|
||||
SPIClass SPI2515;
|
||||
ACAN2515 can(MCP2515_CS, SPI2515, MCP2515_INT);
|
||||
static ACAN2515_Buffer16 gBuffer;
|
||||
#endif //CAN_ADDON
|
||||
#ifdef CANFD_ADDON
|
||||
ACAN2517FD canfd(MCP2517_CS, SPI, MCP2517_INT);
|
||||
SPIClass SPI2517;
|
||||
ACAN2517FD canfd(MCP2517_CS, SPI2517, MCP2517_INT);
|
||||
#endif //CANFD_ADDON
|
||||
|
||||
// Initialization functions
|
||||
|
@ -35,78 +38,100 @@ void init_CAN() {
|
|||
ESP32Can.CANInit();
|
||||
|
||||
#ifdef CAN_ADDON
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Dual CAN Bus (ESP32+MCP2515) selected");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Dual CAN Bus (ESP32+MCP2515) selected");
|
||||
#endif // DEBUG_LOG
|
||||
gBuffer.initWithSize(25);
|
||||
SPI.begin(MCP2515_SCK, MCP2515_MISO, MCP2515_MOSI);
|
||||
ACAN2515Settings settings(QUARTZ_FREQUENCY, 500UL * 1000UL); // CAN bit rate 500 kb/s
|
||||
settings.mRequestedMode = ACAN2515Settings::NormalMode;
|
||||
const uint16_t errorCodeMCP = can.begin(settings, [] { can.isr(); });
|
||||
if (errorCodeMCP == 0) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Can ok");
|
||||
#endif // DEBUG_VIA_USB
|
||||
SPI2515.begin(MCP2515_SCK, MCP2515_MISO, MCP2515_MOSI);
|
||||
ACAN2515Settings settings2515(QUARTZ_FREQUENCY, 500UL * 1000UL); // CAN bit rate 500 kb/s
|
||||
settings2515.mRequestedMode = ACAN2515Settings::NormalMode;
|
||||
const uint16_t errorCode2515 = can.begin(settings2515, [] { can.isr(); });
|
||||
if (errorCode2515 == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Can ok");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.print("Error Can: 0x");
|
||||
Serial.println(errorCodeMCP, HEX);
|
||||
#endif // DEBUG_VIA_USB
|
||||
set_event(EVENT_CANMCP_INIT_FAILURE, (uint8_t)errorCodeMCP);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Error Can: 0x");
|
||||
logging.println(errorCode2515, HEX);
|
||||
#endif // DEBUG_LOG
|
||||
set_event(EVENT_CANMCP2515_INIT_FAILURE, (uint8_t)errorCode2515);
|
||||
}
|
||||
#endif // CAN_ADDON
|
||||
|
||||
#ifdef CANFD_ADDON
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CAN FD add-on (ESP32+MCP2517) selected");
|
||||
#endif // DEBUG_VIA_USB
|
||||
SPI.begin(MCP2517_SCK, MCP2517_SDO, MCP2517_SDI);
|
||||
ACAN2517FDSettings settings(CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ, 500 * 1000,
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN FD add-on (ESP32+MCP2517) selected");
|
||||
#endif // DEBUG_LOG
|
||||
SPI2517.begin(MCP2517_SCK, MCP2517_SDO, MCP2517_SDI);
|
||||
ACAN2517FDSettings settings2517(CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ, 500 * 1000,
|
||||
DataBitRateFactor::x4); // Arbitration bit rate: 500 kbit/s, data bit rate: 2 Mbit/s
|
||||
#ifdef USE_CANFD_INTERFACE_AS_CLASSIC_CAN
|
||||
settings.mRequestedMode = ACAN2517FDSettings::Normal20B; // ListenOnly / Normal20B / NormalFD
|
||||
settings2517.mRequestedMode = ACAN2517FDSettings::Normal20B; // ListenOnly / Normal20B / NormalFD
|
||||
#else // not USE_CANFD_INTERFACE_AS_CLASSIC_CAN
|
||||
settings.mRequestedMode = ACAN2517FDSettings::NormalFD; // ListenOnly / Normal20B / NormalFD
|
||||
settings2517.mRequestedMode = ACAN2517FDSettings::NormalFD; // ListenOnly / Normal20B / NormalFD
|
||||
#endif // USE_CANFD_INTERFACE_AS_CLASSIC_CAN
|
||||
const uint32_t errorCode = canfd.begin(settings, [] { canfd.isr(); });
|
||||
const uint32_t errorCode2517 = canfd.begin(settings2517, [] { canfd.isr(); });
|
||||
canfd.poll();
|
||||
if (errorCode == 0) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.print("Bit Rate prescaler: ");
|
||||
Serial.println(settings.mBitRatePrescaler);
|
||||
Serial.print("Arbitration Phase segment 1: ");
|
||||
Serial.println(settings.mArbitrationPhaseSegment1);
|
||||
Serial.print("Arbitration Phase segment 2: ");
|
||||
Serial.println(settings.mArbitrationPhaseSegment2);
|
||||
Serial.print("Arbitration SJW:");
|
||||
Serial.println(settings.mArbitrationSJW);
|
||||
Serial.print("Actual Arbitration Bit Rate: ");
|
||||
Serial.print(settings.actualArbitrationBitRate());
|
||||
Serial.println(" bit/s");
|
||||
Serial.print("Exact Arbitration Bit Rate ? ");
|
||||
Serial.println(settings.exactArbitrationBitRate() ? "yes" : "no");
|
||||
Serial.print("Arbitration Sample point: ");
|
||||
Serial.print(settings.arbitrationSamplePointFromBitStart());
|
||||
Serial.println("%");
|
||||
#endif // DEBUG_VIA_USB
|
||||
if (errorCode2517 == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Bit Rate prescaler: ");
|
||||
logging.println(settings2517.mBitRatePrescaler);
|
||||
logging.print("Arbitration Phase segment 1: ");
|
||||
logging.print(settings2517.mArbitrationPhaseSegment1);
|
||||
logging.print(" segment 2: ");
|
||||
logging.print(settings2517.mArbitrationPhaseSegment2);
|
||||
logging.print(" SJW: ");
|
||||
logging.println(settings2517.mArbitrationSJW);
|
||||
logging.print("Actual Arbitration Bit Rate: ");
|
||||
logging.print(settings2517.actualArbitrationBitRate());
|
||||
logging.print(" bit/s");
|
||||
logging.print(" (Exact:");
|
||||
logging.println(settings2517.exactArbitrationBitRate() ? "yes)" : "no)");
|
||||
logging.print("Arbitration Sample point: ");
|
||||
logging.print(settings2517.arbitrationSamplePointFromBitStart());
|
||||
logging.println("pct");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.print("CAN-FD Configuration error 0x");
|
||||
Serial.println(errorCode, HEX);
|
||||
#endif // DEBUG_VIA_USB
|
||||
set_event(EVENT_CANFD_INIT_FAILURE, (uint8_t)errorCode);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("CAN-FD Configuration error 0x");
|
||||
logging.println(errorCode2517, HEX);
|
||||
#endif // DEBUG_LOG
|
||||
set_event(EVENT_CANMCP2517FD_INIT_FAILURE, (uint8_t)errorCode2517);
|
||||
}
|
||||
#endif // CANFD_ADDON
|
||||
}
|
||||
|
||||
// Transmit functions
|
||||
void transmit_can() {
|
||||
if (!allowed_to_send_CAN) {
|
||||
return;
|
||||
}
|
||||
transmit_can_battery();
|
||||
|
||||
void transmit_can(CAN_frame* tx_frame, int interface) {
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
transmit_can_inverter();
|
||||
#endif // CAN_INVERTER_SELECTED
|
||||
|
||||
#ifdef CHARGER_SELECTED
|
||||
transmit_can_charger();
|
||||
#endif // CHARGER_SELECTED
|
||||
|
||||
#ifdef CAN_SHUNT_SELECTED
|
||||
transmit_can_shunt();
|
||||
#endif // CAN_SHUNT_SELECTED
|
||||
}
|
||||
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface) {
|
||||
if (!allowed_to_send_CAN) {
|
||||
return;
|
||||
}
|
||||
print_can_frame(*tx_frame, frameDirection(MSG_TX));
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
add_can_frame_to_buffer(*tx_frame, frameDirection(MSG_TX));
|
||||
#endif
|
||||
|
||||
switch (interface) {
|
||||
case CAN_NATIVE:
|
||||
CAN_frame_t frame;
|
||||
|
@ -153,6 +178,8 @@ void transmit_can(CAN_frame* tx_frame, int interface) {
|
|||
send_ok = canfd.tryToSend(MCP2518Frame);
|
||||
if (!send_ok) {
|
||||
set_event(EVENT_CANFD_BUFFER_FULL, interface);
|
||||
} else {
|
||||
clear_event(EVENT_CANFD_BUFFER_FULL);
|
||||
}
|
||||
#else // Interface not compiled, and settings try to use it
|
||||
set_event(EVENT_INTERFACE_MISSING, interface);
|
||||
|
@ -164,58 +191,18 @@ void transmit_can(CAN_frame* tx_frame, int interface) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can() {
|
||||
if (!allowed_to_send_CAN) {
|
||||
return;
|
||||
}
|
||||
send_can_battery();
|
||||
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
send_can_inverter();
|
||||
#endif // CAN_INVERTER_SELECTED
|
||||
|
||||
#ifdef CHARGER_SELECTED
|
||||
send_can_charger();
|
||||
#endif // CHARGER_SELECTED
|
||||
#ifdef CAN_SHUNT_SELECTED
|
||||
send_can_shunt();
|
||||
#endif // CAN_SHUNT_SELECTED
|
||||
}
|
||||
|
||||
// Receive functions
|
||||
|
||||
void receive_can(CAN_frame* rx_frame, int interface) {
|
||||
print_can_frame(*rx_frame, frameDirection(MSG_RX));
|
||||
|
||||
if (interface == can_config.battery) {
|
||||
receive_can_battery(*rx_frame);
|
||||
#ifdef CHADEMO_BATTERY
|
||||
ISA_handleFrame(rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.inverter) {
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
receive_can_inverter(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.battery_double) {
|
||||
#ifdef DOUBLE_BATTERY
|
||||
receive_can_battery2(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.charger) {
|
||||
#ifdef CHARGER_SELECTED
|
||||
receive_can_charger(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.shunt) {
|
||||
#ifdef CAN_SHUNT_SELECTED
|
||||
receive_can_shunt(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
void receive_can() {
|
||||
receive_frame_can_native(); // Receive CAN messages from native CAN port
|
||||
#ifdef CAN_ADDON
|
||||
receive_frame_can_addon(); // Receive CAN messages on add-on MCP2515 chip
|
||||
#endif // CAN_ADDON
|
||||
#ifdef CANFD_ADDON
|
||||
receive_frame_canfd_addon(); // Receive CAN-FD messages.
|
||||
#endif // CANFD_ADDON
|
||||
}
|
||||
|
||||
void receive_can_native() { // This section checks if we have a complete CAN message incoming on native CAN port
|
||||
void receive_frame_can_native() { // This section checks if we have a complete CAN message incoming on native CAN port
|
||||
CAN_frame_t rx_frame_native;
|
||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame_native, 0) == pdTRUE) {
|
||||
CAN_frame rx_frame;
|
||||
|
@ -230,47 +217,46 @@ void receive_can_native() { // This section checks if we have a complete CAN me
|
|||
rx_frame.data.u8[i] = rx_frame_native.data.u8[i];
|
||||
}
|
||||
//message incoming, pass it on to the handler
|
||||
receive_can(&rx_frame, CAN_NATIVE);
|
||||
map_can_frame_to_variable(&rx_frame, CAN_NATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CAN_ADDON
|
||||
void receive_can_addon() { // This section checks if we have a complete CAN message incoming on add-on CAN port
|
||||
void receive_frame_can_addon() { // This section checks if we have a complete CAN message incoming on add-on CAN port
|
||||
CAN_frame rx_frame; // Struct with our CAN format
|
||||
CANMessage MCP2515Frame; // Struct with ACAN2515 library format, needed to use the MCP2515 library
|
||||
CANMessage MCP2515frame; // Struct with ACAN2515 library format, needed to use the MCP2515 library
|
||||
|
||||
if (can.available()) {
|
||||
can.receive(MCP2515Frame);
|
||||
can.receive(MCP2515frame);
|
||||
|
||||
rx_frame.ID = MCP2515Frame.id;
|
||||
rx_frame.ext_ID = MCP2515Frame.ext ? CAN_frame_ext : CAN_frame_std;
|
||||
rx_frame.DLC = MCP2515Frame.len;
|
||||
for (uint8_t i = 0; i < MCP2515Frame.len && i < 8; i++) {
|
||||
rx_frame.data.u8[i] = MCP2515Frame.data[i];
|
||||
rx_frame.ID = MCP2515frame.id;
|
||||
rx_frame.ext_ID = MCP2515frame.ext ? CAN_frame_ext : CAN_frame_std;
|
||||
rx_frame.DLC = MCP2515frame.len;
|
||||
for (uint8_t i = 0; i < MCP2515frame.len && i < 8; i++) {
|
||||
rx_frame.data.u8[i] = MCP2515frame.data[i];
|
||||
}
|
||||
|
||||
//message incoming, pass it on to the handler
|
||||
receive_can(&rx_frame, CAN_ADDON_MCP2515);
|
||||
map_can_frame_to_variable(&rx_frame, CAN_ADDON_MCP2515);
|
||||
}
|
||||
}
|
||||
#endif // CAN_ADDON
|
||||
|
||||
#ifdef CANFD_ADDON
|
||||
// Functions
|
||||
void receive_canfd_addon() { // This section checks if we have a complete CAN-FD message incoming
|
||||
CANFDMessage frame;
|
||||
void receive_frame_canfd_addon() { // This section checks if we have a complete CAN-FD message incoming
|
||||
CANFDMessage MCP2518frame;
|
||||
int count = 0;
|
||||
while (canfd.available() && count++ < 16) {
|
||||
canfd.receive(frame);
|
||||
canfd.receive(MCP2518frame);
|
||||
|
||||
CAN_frame rx_frame;
|
||||
rx_frame.ID = frame.id;
|
||||
rx_frame.ext_ID = frame.ext;
|
||||
rx_frame.DLC = frame.len;
|
||||
memcpy(rx_frame.data.u8, frame.data, MIN(rx_frame.DLC, 64));
|
||||
rx_frame.ID = MCP2518frame.id;
|
||||
rx_frame.ext_ID = MCP2518frame.ext;
|
||||
rx_frame.DLC = MCP2518frame.len;
|
||||
memcpy(rx_frame.data.u8, MCP2518frame.data, MIN(rx_frame.DLC, 64));
|
||||
//message incoming, pass it on to the handler
|
||||
receive_can(&rx_frame, CANFD_ADDON_MCP2518);
|
||||
receive_can(&rx_frame, CANFD_NATIVE);
|
||||
map_can_frame_to_variable(&rx_frame, CANFD_ADDON_MCP2518);
|
||||
map_can_frame_to_variable(&rx_frame, CANFD_NATIVE);
|
||||
}
|
||||
}
|
||||
#endif // CANFD_ADDON
|
||||
|
@ -330,3 +316,38 @@ void print_can_frame(CAN_frame frame, frameDirection msgDir) {
|
|||
datalayer.system.info.logged_can_messages_offset = offset; // Update offset in buffer
|
||||
}
|
||||
}
|
||||
|
||||
void map_can_frame_to_variable(CAN_frame* rx_frame, int interface) {
|
||||
print_can_frame(*rx_frame, frameDirection(MSG_RX));
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
add_can_frame_to_buffer(*rx_frame, frameDirection(MSG_RX));
|
||||
#endif
|
||||
|
||||
if (interface == can_config.battery) {
|
||||
handle_incoming_can_frame_battery(*rx_frame);
|
||||
#ifdef CHADEMO_BATTERY
|
||||
ISA_handleFrame(rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.inverter) {
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
map_can_frame_to_variable_inverter(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.battery_double) {
|
||||
#ifdef DOUBLE_BATTERY
|
||||
handle_incoming_can_frame_battery2(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.charger) {
|
||||
#ifdef CHARGER_SELECTED
|
||||
map_can_frame_to_variable_charger(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.shunt) {
|
||||
#ifdef CAN_SHUNT_SELECTED
|
||||
map_can_frame_to_variable_shunt(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include "../../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
||||
#endif //CANFD_ADDON
|
||||
|
||||
enum frameDirection { MSG_RX, MSG_TX }; //RX = 0, TX = 1
|
||||
|
||||
/**
|
||||
* @brief Initialization function for CAN.
|
||||
*
|
||||
|
@ -34,7 +32,7 @@ void init_CAN();
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
void transmit_can();
|
||||
void transmit_can_frame();
|
||||
|
||||
/**
|
||||
* @brief Send CAN messages to all components
|
||||
|
@ -43,7 +41,7 @@ void transmit_can();
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
void send_can();
|
||||
void transmit_can();
|
||||
|
||||
/**
|
||||
* @brief Receive CAN messages from all interfaces
|
||||
|
@ -61,7 +59,7 @@ void receive_can();
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
void receive_can_native();
|
||||
void receive_frame_can_native();
|
||||
|
||||
/**
|
||||
* @brief Receive CAN messages from CAN addon chip
|
||||
|
@ -70,7 +68,7 @@ void receive_can_native();
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
void receive_can_addon();
|
||||
void receive_frame_can_addon();
|
||||
|
||||
/**
|
||||
* @brief Receive CAN messages from CANFD addon chip
|
||||
|
@ -79,7 +77,7 @@ void receive_can_addon();
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
void receive_canfd_addon();
|
||||
void receive_frame_canfd_addon();
|
||||
|
||||
/**
|
||||
* @brief print CAN frames via USB
|
||||
|
@ -90,4 +88,14 @@ void receive_canfd_addon();
|
|||
*/
|
||||
void print_can_frame(CAN_frame frame, frameDirection msgDir);
|
||||
|
||||
/**
|
||||
* @brief Map CAN frame from specified interface to variable
|
||||
*
|
||||
* @param[in] CAN_frame* rx_frame
|
||||
* @param[in] int interface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void map_can_frame_to_variable(CAN_frame* rx_frame, int interface);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,9 +90,9 @@ void init_contactors() {
|
|||
|
||||
// Main functions
|
||||
void handle_contactors() {
|
||||
#ifdef BYD_SMA
|
||||
#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);
|
||||
#endif // BYD_SMA
|
||||
#endif
|
||||
|
||||
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
||||
handle_contactors_battery2();
|
||||
|
|
|
@ -147,7 +147,7 @@ typedef struct {
|
|||
/** True if the contactor controlled by battery-emulator is closed */
|
||||
bool contactors_engaged = false;
|
||||
/** True if shunt communication ok **/
|
||||
bool available=false;
|
||||
bool available = false;
|
||||
} DATALAYER_SHUNT_TYPE;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -3,6 +3,42 @@
|
|||
|
||||
#include "../include.h"
|
||||
|
||||
typedef struct {
|
||||
/** uint16_t */
|
||||
/** PID polling parameters */
|
||||
uint16_t battery_5V_ref = 0;
|
||||
int16_t battery_module_temp_1 = 0;
|
||||
int16_t battery_module_temp_2 = 0;
|
||||
int16_t battery_module_temp_3 = 0;
|
||||
int16_t battery_module_temp_4 = 0;
|
||||
int16_t battery_module_temp_5 = 0;
|
||||
int16_t battery_module_temp_6 = 0;
|
||||
uint16_t battery_cell_average_voltage = 0;
|
||||
uint16_t battery_cell_average_voltage_2 = 0;
|
||||
uint16_t battery_terminal_voltage = 0;
|
||||
uint16_t battery_ignition_power_mode = 0;
|
||||
int16_t battery_current_7E7 = 0;
|
||||
uint16_t battery_capacity_my17_18 = 0;
|
||||
uint16_t battery_capacity_my19plus = 0;
|
||||
uint16_t battery_SOC_display = 0;
|
||||
uint16_t battery_SOC_raw_highprec = 0;
|
||||
uint16_t battery_max_temperature = 0;
|
||||
uint16_t battery_min_temperature = 0;
|
||||
uint16_t battery_max_cell_voltage = 0;
|
||||
uint16_t battery_min_cell_voltage = 0;
|
||||
uint16_t battery_lowest_cell = 0;
|
||||
uint16_t battery_highest_cell = 0;
|
||||
uint16_t battery_internal_resistance = 0;
|
||||
uint16_t battery_voltage_polled = 0;
|
||||
uint16_t battery_vehicle_isolation = 0;
|
||||
uint16_t battery_isolation_kohm = 0;
|
||||
uint16_t battery_HV_locked = 0;
|
||||
uint16_t battery_crash_event = 0;
|
||||
uint16_t battery_HVIL = 0;
|
||||
uint16_t battery_HVIL_status = 0;
|
||||
int16_t battery_current_7E4 = 0;
|
||||
} DATALAYER_INFO_BOLTAMPERA;
|
||||
|
||||
typedef struct {
|
||||
/** uint16_t */
|
||||
/** Terminal 30 - 12V SME Supply Voltage */
|
||||
|
@ -179,7 +215,12 @@ typedef struct {
|
|||
uint8_t packCtrsClosingAllowed = 0;
|
||||
/** uint8_t */
|
||||
/** Pyro test in progress */
|
||||
uint8_t pyroTestInProgress = 0;
|
||||
bool pyroTestInProgress = false;
|
||||
bool battery_packCtrsOpenNowRequested = false;
|
||||
bool battery_packCtrsOpenRequested = false;
|
||||
uint8_t battery_packCtrsRequestStatus = 0;
|
||||
bool battery_packCtrsResetRequestRequired = false;
|
||||
bool battery_dcLinkAllowedToEnergize = false;
|
||||
uint8_t battery_beginning_of_life = 0;
|
||||
uint8_t battery_battTempPct = 0;
|
||||
uint16_t battery_dcdcLvBusVolt = 0;
|
||||
|
@ -195,10 +236,20 @@ typedef struct {
|
|||
uint16_t battery_energy_to_charge_complete_m1 = 0;
|
||||
uint16_t battery_energy_buffer = 0;
|
||||
uint16_t battery_energy_buffer_m1 = 0;
|
||||
uint16_t battery_full_charge_complete = 0;
|
||||
uint8_t battery_fully_charged = 0;
|
||||
uint16_t battery_expected_energy_remaining = 0;
|
||||
uint16_t battery_expected_energy_remaining_m1 = 0;
|
||||
bool battery_full_charge_complete = false;
|
||||
bool battery_fully_charged = false;
|
||||
uint16_t battery_total_discharge = 0;
|
||||
uint16_t battery_total_charge = 0;
|
||||
uint16_t battery_BrickVoltageMax = 0;
|
||||
uint16_t battery_BrickVoltageMin = 0;
|
||||
uint8_t battery_BrickVoltageMaxNum = 0;
|
||||
uint8_t battery_BrickVoltageMinNum = 0;
|
||||
uint8_t battery_BrickTempMaxNum = 0;
|
||||
uint8_t battery_BrickTempMinNum = 0;
|
||||
uint8_t battery_BrickModelTMax = 0;
|
||||
uint8_t battery_BrickModelTMin = 0;
|
||||
uint16_t battery_packConfigMultiplexer = 0;
|
||||
uint16_t battery_moduleType = 0;
|
||||
uint16_t battery_reservedConfig = 0;
|
||||
|
@ -212,6 +263,123 @@ typedef struct {
|
|||
uint32_t battery_soc_max = 0;
|
||||
uint32_t battery_soc_ave = 0;
|
||||
uint32_t battery_soc_ui = 0;
|
||||
uint8_t battery_BMS_contactorState = 0;
|
||||
uint8_t battery_BMS_state = 0;
|
||||
uint8_t battery_BMS_hvState = 0;
|
||||
uint16_t battery_BMS_isolationResistance = 0;
|
||||
uint8_t battery_BMS_uiChargeStatus = 0;
|
||||
bool battery_BMS_diLimpRequest = false;
|
||||
uint16_t battery_BMS_chgPowerAvailable = 0;
|
||||
bool battery_BMS_pcsPwmEnabled = false;
|
||||
uint8_t battery_PCS_dcdcPrechargeStatus = 0;
|
||||
uint8_t battery_PCS_dcdc12VSupportStatus = 0;
|
||||
uint8_t battery_PCS_dcdcHvBusDischargeStatus = 0;
|
||||
uint8_t battery_PCS_dcdcMainState = 0;
|
||||
uint8_t battery_PCS_dcdcSubState = 0;
|
||||
bool battery_PCS_dcdcFaulted = false;
|
||||
bool battery_PCS_dcdcOutputIsLimited = false;
|
||||
uint16_t battery_PCS_dcdcMaxOutputCurrentAllowed = 0;
|
||||
uint8_t battery_PCS_dcdcPrechargeRtyCnt = 0;
|
||||
uint8_t battery_PCS_dcdc12VSupportRtyCnt = 0;
|
||||
uint8_t battery_PCS_dcdcDischargeRtyCnt = 0;
|
||||
uint8_t battery_PCS_dcdcPwmEnableLine = 0;
|
||||
uint8_t battery_PCS_dcdcSupportingFixedLvTarget = 0;
|
||||
uint8_t battery_PCS_dcdcPrechargeRestartCnt = 0;
|
||||
uint8_t battery_PCS_dcdcInitialPrechargeSubState = 0;
|
||||
uint16_t BMS_maxRegenPower = 0;
|
||||
uint16_t BMS_maxDischargePower = 0;
|
||||
uint16_t BMS_maxStationaryHeatPower = 0;
|
||||
uint16_t BMS_hvacPowerBudget = 0;
|
||||
uint8_t BMS_notEnoughPowerForHeatPump = 0;
|
||||
uint8_t BMS_powerLimitState = 0;
|
||||
uint8_t BMS_inverterTQF = 0;
|
||||
uint16_t BMS_powerDissipation = 0;
|
||||
uint8_t BMS_flowRequest = 0;
|
||||
uint16_t BMS_inletActiveCoolTargetT = 0;
|
||||
uint16_t BMS_inletPassiveTargetT = 0;
|
||||
uint16_t BMS_inletActiveHeatTargetT = 0;
|
||||
uint16_t BMS_packTMin = 0;
|
||||
uint16_t BMS_packTMax = 0;
|
||||
bool BMS_pcsNoFlowRequest = false;
|
||||
bool BMS_noFlowRequest = false;
|
||||
uint16_t PCS_dcdcTemp = 0;
|
||||
uint16_t PCS_ambientTemp = 0;
|
||||
uint16_t PCS_dcdcMaxLvOutputCurrent = 0;
|
||||
uint16_t PCS_dcdcCurrentLimit = 0;
|
||||
uint16_t PCS_dcdcLvOutputCurrentTempLimit = 0;
|
||||
uint16_t PCS_dcdcUnifiedCommand = 0;
|
||||
uint16_t PCS_dcdcCLAControllerOutput = 0;
|
||||
uint16_t PCS_dcdcTankVoltage = 0;
|
||||
uint16_t PCS_dcdcTankVoltageTarget = 0;
|
||||
uint16_t PCS_dcdcClaCurrentFreq = 0;
|
||||
uint16_t PCS_dcdcTCommMeasured = 0;
|
||||
uint16_t PCS_dcdcShortTimeUs = 0;
|
||||
uint16_t PCS_dcdcHalfPeriodUs = 0;
|
||||
uint16_t PCS_dcdcIntervalMaxFrequency = 0;
|
||||
uint16_t PCS_dcdcIntervalMaxHvBusVolt = 0;
|
||||
uint16_t PCS_dcdcIntervalMaxLvBusVolt = 0;
|
||||
uint16_t PCS_dcdcIntervalMaxLvOutputCurr = 0;
|
||||
uint16_t PCS_dcdcIntervalMinFrequency = 0;
|
||||
uint16_t PCS_dcdcIntervalMinHvBusVolt = 0;
|
||||
uint16_t PCS_dcdcIntervalMinLvBusVolt = 0;
|
||||
uint16_t PCS_dcdcIntervalMinLvOutputCurr = 0;
|
||||
uint32_t PCS_dcdc12vSupportLifetimekWh = 0;
|
||||
bool HVP_gpioPassivePyroDepl = false;
|
||||
bool HVP_gpioPyroIsoEn = false;
|
||||
bool HVP_gpioCpFaultIn = false;
|
||||
bool HVP_gpioPackContPowerEn = false;
|
||||
bool HVP_gpioHvCablesOk = false;
|
||||
bool HVP_gpioHvpSelfEnable = false;
|
||||
bool HVP_gpioLed = false;
|
||||
bool HVP_gpioCrashSignal = false;
|
||||
bool HVP_gpioShuntDataReady = false;
|
||||
bool HVP_gpioFcContPosAux = false;
|
||||
bool HVP_gpioFcContNegAux = false;
|
||||
bool HVP_gpioBmsEout = false;
|
||||
bool HVP_gpioCpFaultOut = false;
|
||||
bool HVP_gpioPyroPor = false;
|
||||
bool HVP_gpioShuntEn = false;
|
||||
bool HVP_gpioHvpVerEn = false;
|
||||
bool HVP_gpioPackCoontPosFlywheel = false;
|
||||
bool HVP_gpioCpLatchEnable = false;
|
||||
bool HVP_gpioPcsEnable = false;
|
||||
bool HVP_gpioPcsDcdcPwmEnable = false;
|
||||
bool HVP_gpioPcsChargePwmEnable = false;
|
||||
bool HVP_gpioFcContPowerEnable = false;
|
||||
bool HVP_gpioHvilEnable = false;
|
||||
bool HVP_gpioSecDrdy = false;
|
||||
uint16_t HVP_hvp1v5Ref = 0;
|
||||
uint16_t HVP_shuntCurrentDebug = 0;
|
||||
bool HVP_packCurrentMia = false;
|
||||
bool HVP_auxCurrentMia = false;
|
||||
bool HVP_currentSenseMia = false;
|
||||
bool HVP_shuntRefVoltageMismatch = false;
|
||||
bool HVP_shuntThermistorMia = false;
|
||||
uint8_t HVP_shuntHwMia = 0;
|
||||
uint16_t HVP_dcLinkVoltage = 0;
|
||||
uint16_t HVP_packVoltage = 0;
|
||||
uint16_t HVP_fcLinkVoltage = 0;
|
||||
uint16_t HVP_packContVoltage = 0;
|
||||
uint16_t HVP_packNegativeV = 0;
|
||||
uint16_t HVP_packPositiveV = 0;
|
||||
uint16_t HVP_pyroAnalog = 0;
|
||||
uint16_t HVP_dcLinkNegativeV = 0;
|
||||
uint16_t HVP_dcLinkPositiveV = 0;
|
||||
uint16_t HVP_fcLinkNegativeV = 0;
|
||||
uint16_t HVP_fcContCoilCurrent = 0;
|
||||
uint16_t HVP_fcContVoltage = 0;
|
||||
uint16_t HVP_hvilInVoltage = 0;
|
||||
uint16_t HVP_hvilOutVoltage = 0;
|
||||
uint16_t HVP_fcLinkPositiveV = 0;
|
||||
uint16_t HVP_packContCoilCurrent = 0;
|
||||
uint16_t HVP_battery12V = 0;
|
||||
uint16_t HVP_shuntRefVoltageDbg = 0;
|
||||
uint16_t HVP_shuntAuxCurrentDbg = 0;
|
||||
uint16_t HVP_shuntBarTempDbg = 0;
|
||||
uint16_t HVP_shuntAsicTempDbg = 0;
|
||||
uint8_t HVP_shuntAuxCurrentStatus = 0;
|
||||
uint8_t HVP_shuntBarTempStatus = 0;
|
||||
uint8_t HVP_shuntAsicTempStatus = 0;
|
||||
} DATALAYER_INFO_TESLA;
|
||||
|
||||
typedef struct {
|
||||
|
@ -403,6 +571,7 @@ typedef struct {
|
|||
|
||||
class DataLayerExtended {
|
||||
public:
|
||||
DATALAYER_INFO_BOLTAMPERA boltampera;
|
||||
DATALAYER_INFO_BMWIX bmwix;
|
||||
DATALAYER_INFO_BMWI3 bmwi3;
|
||||
DATALAYER_INFO_BYDATTO3 bydAtto3;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "hw_stark.h"
|
||||
#elif defined(HW_3LB)
|
||||
#include "hw_3LB.h"
|
||||
#elif defined(HW_DEVKIT)
|
||||
#include "hw_devkit.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,6 +72,14 @@
|
|||
// Equipment stop pin
|
||||
#define EQUIPMENT_STOP_PIN 35
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
#define HW_CONFIGURED
|
||||
|
@ -98,9 +106,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#ifdef CONTACTOR_CONTROL
|
||||
#if defined(CONTACTOR_CONTROL) && defined(WUP_PIN1)
|
||||
#error GPIO PIN 25 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL
|
||||
#endif
|
||||
#if defined(CONTACTOR_CONTROL) && defined(WUP_PIN2)
|
||||
#error GPIO PIN 32 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
93
Software/src/devboard/hal/hw_devkit.h
Normal file
93
Software/src/devboard/hal/hw_devkit.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
#ifndef __HW_DEVKIT_H__
|
||||
#define __HW_DEVKIT_H__
|
||||
|
||||
/*
|
||||
ESP32 DevKit V1 development board with 30 pins.
|
||||
For more information, see: https://lastminuteengineers.com/esp32-pinout-reference/.
|
||||
|
||||
The pin layout below supports the following:
|
||||
- 1x RS485
|
||||
- 2x CAN (1x via SN65HVD230 (UART), 1x via MCP2515 (SPI))
|
||||
- 1x CANFD (via MCP2518FD (SPI))
|
||||
*/
|
||||
|
||||
// Board boot-up time
|
||||
#define BOOTUP_TIME 1000 // Time in ms it takes before system is considered fully started up
|
||||
|
||||
// Core assignment
|
||||
#define CORE_FUNCTION_CORE 1
|
||||
#define MODBUS_CORE 0
|
||||
#define WIFI_CORE 0
|
||||
|
||||
// RS485
|
||||
#define RS485_TX_PIN GPIO_NUM_1
|
||||
#define RS485_RX_PIN GPIO_NUM_3
|
||||
|
||||
// CAN settings
|
||||
#define CAN_1_TYPE ESP32CAN
|
||||
//#define CAN_2_TYPE MCP2515
|
||||
//#define CAN_3_TYPE MCP2518FD
|
||||
|
||||
// CAN1 PIN mappings, do not change these unless you are adding on extra hardware to the PCB
|
||||
#define CAN_TX_PIN GPIO_NUM_27
|
||||
#define CAN_RX_PIN GPIO_NUM_26
|
||||
|
||||
// CAN_ADDON defines
|
||||
#define MCP2515_SCK GPIO_NUM_22 // SCK input of MCP2515
|
||||
#define MCP2515_MOSI GPIO_NUM_21 // SDI input of MCP2515
|
||||
#define MCP2515_MISO GPIO_NUM_19 // SDO output of MCP2515
|
||||
#define MCP2515_CS GPIO_NUM_18 // CS input of MCP2515
|
||||
#define MCP2515_INT GPIO_NUM_23 // INT output of MCP2515
|
||||
|
||||
// CANFD_ADDON defines
|
||||
#define MCP2517_SCK GPIO_NUM_33 // SCK input of MCP2517
|
||||
#define MCP2517_SDI GPIO_NUM_32 // SDI input of MCP2517
|
||||
#define MCP2517_SDO GPIO_NUM_35 // SDO output of MCP2517 | Pin 35 is input only, without pullup/down resistors
|
||||
#define MCP2517_CS GPIO_NUM_25 // CS input of MCP2517
|
||||
#define MCP2517_INT GPIO_NUM_34 // INT output of MCP2517 | Pin 34 is input only, without pullup/down resistors
|
||||
|
||||
// Contactor handling
|
||||
#define POSITIVE_CONTACTOR_PIN GPIO_NUM_5
|
||||
#define NEGATIVE_CONTACTOR_PIN GPIO_NUM_16
|
||||
#define PRECHARGE_PIN GPIO_NUM_17
|
||||
|
||||
// SMA CAN contactor pins
|
||||
#define INVERTER_CONTACTOR_ENABLE_PIN GPIO_NUM_14
|
||||
|
||||
// LED
|
||||
#define LED_PIN GPIO_NUM_4
|
||||
#define LED_MAX_BRIGHTNESS 40
|
||||
#define INVERTER_CONTACTOR_ENABLE_LED_PIN GPIO_NUM_2
|
||||
|
||||
// Equipment stop pin
|
||||
#define EQUIPMENT_STOP_PIN GPIO_NUM_12
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
#define HW_CONFIGURED
|
||||
#else
|
||||
#error Multiple HW defined! Please select a single HW
|
||||
#endif // HW_CONFIGURED
|
||||
|
||||
#ifdef CHADEMO_BATTERY
|
||||
#error CHADEMO pins are not defined for this hardware.
|
||||
#endif // CHADEMO_BATTERY
|
||||
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#if defined(WUP_PIN1) && defined(CANFD_ADDON)
|
||||
#error GPIO PIN 25 cannot be used for both BMWi3 Wakeup and a CANFD addon board using these pins. Choose between BMW_I3_BATTERY and CANFD_ADDON
|
||||
#endif // defined(WUP_PIN1) && defined(CANFD_ADDON)
|
||||
#if defined(WUP_PIN2) && defined(CANFD_ADDON)
|
||||
#error GPIO PIN 32 cannot be used for both BMWi3 Wakeup and a CANFD addon board using these pins. Choose between BMW_I3_BATTERY and CANFD_ADDON
|
||||
#endif // defined(WUP_PIN2) && defined(CANFD_ADDON)
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
#endif // __HW_DEVKIT_H__
|
|
@ -68,6 +68,14 @@
|
|||
// Equipment stop pin
|
||||
#define EQUIPMENT_STOP_PIN 35
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
#define HW_CONFIGURED
|
||||
|
@ -75,6 +83,11 @@
|
|||
#error Multiple HW defined! Please select a single HW
|
||||
#endif
|
||||
|
||||
#if defined(CAN_ADDON) && defined(CANFD_ADDON)
|
||||
// Check that user did not try to use dual can and fd-can on same hardware pins
|
||||
#error CAN_ADDON AND CANFD_ADDON CANNOT BE USED SIMULTANEOUSLY
|
||||
#endif
|
||||
|
||||
#ifdef CHADEMO_BATTERY
|
||||
#ifdef CAN_ADDON
|
||||
#error CHADEMO and CAN_ADDON cannot coexist due to overlapping GPIO pin usage
|
||||
|
@ -94,9 +107,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#ifdef CONTACTOR_CONTROL
|
||||
#if defined(CONTACTOR_CONTROL) && defined(WUP_PIN1)
|
||||
#error GPIO PIN 25 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL
|
||||
#endif
|
||||
#if defined(CONTACTOR_CONTROL) && defined(WUP_PIN2)
|
||||
#error GPIO PIN 32 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,11 +61,28 @@ GPIOs on extra header
|
|||
// Equipment stop pin
|
||||
#define EQUIPMENT_STOP_PIN 2
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
#define HW_CONFIGURED
|
||||
#else
|
||||
#error Multiple HW defined! Please select a single HW
|
||||
#endif
|
||||
#endif // HW_CONFIGURED
|
||||
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#if defined(CONTACTOR_CONTROL) && defined(WUP_PIN1)
|
||||
#error GPIO PIN 25 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL
|
||||
#endif
|
||||
#if defined(CONTACTOR_CONTROL) && defined(WUP_PIN2)
|
||||
#error GPIO PIN 32 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL
|
||||
#endif
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
#endif // __HW_STARK_H__
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include "../../../USER_SECRETS.h"
|
||||
#include "../../../USER_SETTINGS.h"
|
||||
#include "../../battery/BATTERIES.h"
|
||||
#include "../../datalayer/datalayer.h"
|
||||
|
@ -194,9 +195,9 @@ static void publish_common_info(void) {
|
|||
#endif // DOUBLE_BATTERY
|
||||
serializeJson(doc, mqtt_msg);
|
||||
if (!mqtt_publish(state_topic.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Common info MQTT msg could not be sent");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Common info MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
doc.clear();
|
||||
#ifdef HA_AUTODISCOVERY
|
||||
|
@ -292,9 +293,9 @@ static void publish_cell_voltages(void) {
|
|||
serializeJson(doc, mqtt_msg, sizeof(mqtt_msg));
|
||||
|
||||
if (!mqtt_publish(state_topic.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Cell voltage MQTT msg could not be sent");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell voltage MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
doc.clear();
|
||||
}
|
||||
|
@ -312,9 +313,9 @@ static void publish_cell_voltages(void) {
|
|||
serializeJson(doc, mqtt_msg, sizeof(mqtt_msg));
|
||||
|
||||
if (!mqtt_publish(state_topic_2.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Cell voltage MQTT msg could not be sent");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell voltage MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
doc.clear();
|
||||
}
|
||||
|
@ -384,9 +385,9 @@ void publish_events() {
|
|||
|
||||
serializeJson(doc, mqtt_msg);
|
||||
if (!mqtt_publish(state_topic.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Common info MQTT msg could not be sent");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Common info MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
set_event_MQTTpublished(event_handle);
|
||||
}
|
||||
|
@ -402,9 +403,9 @@ void publish_events() {
|
|||
/* If we lose the connection, get it back */
|
||||
static bool reconnect() {
|
||||
// attempt one reconnection
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.print("Attempting MQTT connection... ");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Attempting MQTT connection... ");
|
||||
#endif // DEBUG_LOG
|
||||
char clientId[64]; // Adjust the size as needed
|
||||
snprintf(clientId, sizeof(clientId), "BatteryEmulatorClient-%s", WiFi.getHostname());
|
||||
// Attempt to connect
|
||||
|
@ -413,19 +414,19 @@ static bool reconnect() {
|
|||
clear_event(EVENT_MQTT_DISCONNECT);
|
||||
set_event(EVENT_MQTT_CONNECT, 0);
|
||||
reconnectAttempts = 0; // Reset attempts on successful connection
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("connected");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("connected");
|
||||
#endif // DEBUG_LOG
|
||||
clear_event(EVENT_MQTT_CONNECT);
|
||||
} else {
|
||||
if (connected_once)
|
||||
set_event(EVENT_MQTT_DISCONNECT, 0);
|
||||
reconnectAttempts++; // Count failed attempts
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.print("failed, rc=");
|
||||
Serial.print(client.state());
|
||||
Serial.println(" try again in 5 seconds");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("failed, rc=");
|
||||
logging.print(client.state());
|
||||
logging.println(" try again in 5 seconds");
|
||||
#endif // DEBUG_LOG
|
||||
// Wait 5 seconds before retrying
|
||||
}
|
||||
return client.connected();
|
||||
|
@ -449,9 +450,9 @@ void init_mqtt(void) {
|
|||
#endif
|
||||
|
||||
client.setServer(MQTT_SERVER, MQTT_PORT);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("MQTT initialized");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("MQTT initialized");
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
client.setKeepAlive(30); // Increase keepalive to manage network latency better. default is 15
|
||||
|
||||
|
@ -478,8 +479,8 @@ void mqtt_loop(void) {
|
|||
if (reconnect()) {
|
||||
lastReconnectAttempt = 0;
|
||||
} else if (reconnectAttempts >= maxReconnectAttempts) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Too many failed reconnect attempts, restarting client.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Too many failed reconnect attempts, restarting client.");
|
||||
#endif
|
||||
client.disconnect(); // Force close the MQTT client connection
|
||||
reconnectAttempts = 0; // Reset attempts to avoid infinite loop
|
||||
|
|
|
@ -283,12 +283,12 @@ void setBatteryPause(bool pause_battery, bool pause_CAN, bool equipment_stop, bo
|
|||
}
|
||||
|
||||
//immediate check if we can send CAN messages
|
||||
emulator_pause_state_send_CAN_battery();
|
||||
emulator_pause_state_transmit_can_battery();
|
||||
}
|
||||
|
||||
/// @brief handle emulator pause status
|
||||
/// @return true if CAN messages should be sent to battery, false if not
|
||||
void emulator_pause_state_send_CAN_battery() {
|
||||
void emulator_pause_state_transmit_can_battery() {
|
||||
bool previous_allowed_to_send_CAN = allowed_to_send_CAN;
|
||||
|
||||
if (emulator_pause_status == NORMAL) {
|
||||
|
|
|
@ -22,7 +22,7 @@ void update_machineryprotection();
|
|||
|
||||
//battery pause status begin
|
||||
void setBatteryPause(bool pause_battery, bool pause_CAN, bool equipment_stop = false, bool store_settings = true);
|
||||
void emulator_pause_state_send_CAN_battery();
|
||||
void emulator_pause_state_transmit_can_battery();
|
||||
std::string get_emulator_pause_status();
|
||||
//battery pause status end
|
||||
|
||||
|
|
155
Software/src/devboard/sdcard/sdcard.cpp
Normal file
155
Software/src/devboard/sdcard/sdcard.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
#include "sdcard.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
|
||||
#if defined(SD_CS_PIN) && defined(SD_SCLK_PIN) && defined(SD_MOSI_PIN) && \
|
||||
defined(SD_MISO_PIN) // ensure code is only compiled if all SD card pins are defined
|
||||
|
||||
File can_log_file;
|
||||
RingbufHandle_t can_bufferHandle;
|
||||
|
||||
bool can_logging_paused = false;
|
||||
bool can_file_open = false;
|
||||
bool delete_can_file = false;
|
||||
bool sd_card_active = false;
|
||||
|
||||
void delete_can_log() {
|
||||
can_logging_paused = true;
|
||||
delete_can_file = true;
|
||||
}
|
||||
|
||||
void resume_can_writing() {
|
||||
can_logging_paused = false;
|
||||
can_log_file = SD.open(CAN_LOG_FILE, FILE_APPEND);
|
||||
can_file_open = true;
|
||||
}
|
||||
|
||||
void pause_can_writing() {
|
||||
can_logging_paused = true;
|
||||
}
|
||||
|
||||
void add_can_frame_to_buffer(CAN_frame frame, frameDirection msgDir) {
|
||||
|
||||
if (!sd_card_active)
|
||||
return;
|
||||
|
||||
CAN_log_frame log_frame = {frame, msgDir};
|
||||
if (xRingbufferSend(can_bufferHandle, &log_frame, sizeof(log_frame), 0) != pdTRUE) {
|
||||
Serial.println("Failed to send CAN frame to ring buffer!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void write_can_frame_to_sdcard() {
|
||||
|
||||
if (!sd_card_active)
|
||||
return;
|
||||
|
||||
size_t receivedMessageSize;
|
||||
CAN_log_frame* log_frame =
|
||||
(CAN_log_frame*)xRingbufferReceive(can_bufferHandle, &receivedMessageSize, pdMS_TO_TICKS(10));
|
||||
|
||||
if (log_frame != NULL) {
|
||||
|
||||
if (can_logging_paused) {
|
||||
if (can_file_open) {
|
||||
can_log_file.close();
|
||||
can_file_open = false;
|
||||
}
|
||||
if (delete_can_file) {
|
||||
SD.remove(CAN_LOG_FILE);
|
||||
delete_can_file = false;
|
||||
can_logging_paused = false;
|
||||
}
|
||||
vRingbufferReturnItem(can_bufferHandle, (void*)log_frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if (can_file_open == false) {
|
||||
can_log_file = SD.open(CAN_LOG_FILE, FILE_APPEND);
|
||||
can_file_open = true;
|
||||
}
|
||||
|
||||
uint8_t i = 0;
|
||||
can_log_file.print("(");
|
||||
can_log_file.print(millis() / 1000.0);
|
||||
(log_frame->direction == MSG_RX) ? can_log_file.print(") RX0 ") : can_log_file.print(") TX1 ");
|
||||
can_log_file.print(log_frame->frame.ID, HEX);
|
||||
can_log_file.print(" [");
|
||||
can_log_file.print(log_frame->frame.DLC);
|
||||
can_log_file.print("] ");
|
||||
for (i = 0; i < log_frame->frame.DLC; i++) {
|
||||
can_log_file.print(log_frame->frame.data.u8[i] < 16 ? "0" : "");
|
||||
can_log_file.print(log_frame->frame.data.u8[i], HEX);
|
||||
if (i < log_frame->frame.DLC - 1)
|
||||
can_log_file.print(" ");
|
||||
}
|
||||
can_log_file.println("");
|
||||
|
||||
vRingbufferReturnItem(can_bufferHandle, (void*)log_frame);
|
||||
}
|
||||
}
|
||||
|
||||
void init_logging_buffer() {
|
||||
can_bufferHandle = xRingbufferCreate(64 * 1024, RINGBUF_TYPE_BYTEBUF);
|
||||
if (can_bufferHandle == NULL) {
|
||||
Serial.println("Failed to create CAN ring buffer!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void init_sdcard() {
|
||||
|
||||
pinMode(SD_CS_PIN, OUTPUT);
|
||||
digitalWrite(SD_CS_PIN, HIGH);
|
||||
pinMode(SD_SCLK_PIN, OUTPUT);
|
||||
pinMode(SD_MOSI_PIN, OUTPUT);
|
||||
pinMode(SD_MISO_PIN, INPUT);
|
||||
|
||||
SPI.begin(SD_SCLK_PIN, SD_MISO_PIN, SD_MOSI_PIN, SD_CS_PIN);
|
||||
if (!SD.begin(SD_CS_PIN)) {
|
||||
Serial.println("SD Card initialization failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("SD Card initialization successful.");
|
||||
sd_card_active = true;
|
||||
|
||||
print_sdcard_details();
|
||||
}
|
||||
|
||||
void print_sdcard_details() {
|
||||
|
||||
Serial.print("SD Card Type: ");
|
||||
switch (SD.cardType()) {
|
||||
case CARD_MMC:
|
||||
Serial.println("MMC");
|
||||
break;
|
||||
case CARD_SD:
|
||||
Serial.println("SD");
|
||||
break;
|
||||
case CARD_SDHC:
|
||||
Serial.println("SDHC");
|
||||
break;
|
||||
case CARD_UNKNOWN:
|
||||
Serial.println("UNKNOWN");
|
||||
break;
|
||||
case CARD_NONE:
|
||||
Serial.println("No SD Card found");
|
||||
break;
|
||||
}
|
||||
|
||||
if (SD.cardType() != CARD_NONE) {
|
||||
Serial.print("SD Card Size: ");
|
||||
Serial.print(SD.cardSize() / 1024 / 1024);
|
||||
Serial.println(" MB");
|
||||
|
||||
Serial.print("Total space: ");
|
||||
Serial.print(SD.totalBytes() / 1024 / 1024);
|
||||
Serial.println(" MB");
|
||||
|
||||
Serial.print("Used space: ");
|
||||
Serial.print(SD.usedBytes() / 1024 / 1024);
|
||||
Serial.println(" MB");
|
||||
}
|
||||
}
|
||||
#endif // defined(SD_CS_PIN) && defined(SD_SCLK_PIN) && defined(SD_MOSI_PIN) && defined(SD_MISO_PIN)
|
26
Software/src/devboard/sdcard/sdcard.h
Normal file
26
Software/src/devboard/sdcard/sdcard.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef SDCARD_H
|
||||
#define SDCARD_H
|
||||
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
#include "../../communication/can/comm_can.h"
|
||||
#include "../hal/hal.h"
|
||||
|
||||
#if defined(SD_CS_PIN) && defined(SD_SCLK_PIN) && defined(SD_MOSI_PIN) && \
|
||||
defined(SD_MISO_PIN) // ensure code is only compiled if all SD card pins are defined
|
||||
#define CAN_LOG_FILE "/canlog.txt"
|
||||
|
||||
void init_logging_buffer();
|
||||
|
||||
void init_sdcard();
|
||||
void print_sdcard_details();
|
||||
|
||||
void add_can_frame_to_buffer(CAN_frame frame, frameDirection msgDir);
|
||||
void write_can_frame_to_sdcard();
|
||||
|
||||
void pause_can_writing();
|
||||
void resume_can_writing();
|
||||
void delete_can_log();
|
||||
#endif // defined(SD_CS_PIN) && defined(SD_SCLK_PIN) && defined(SD_MOSI_PIN) && defined(SD_MISO_PIN)
|
||||
|
||||
#endif // SDCARD_H
|
|
@ -118,15 +118,15 @@ void init_events(void) {
|
|||
|
||||
// Push changes to eeprom
|
||||
EEPROM.commit();
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("EEPROM wasn't ready");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("EEPROM wasn't ready");
|
||||
#endif
|
||||
} else {
|
||||
events.event_log_head_index = EEPROM.readUShort(EE_EVENT_LOG_HEAD_INDEX_ADDRESS);
|
||||
events.event_log_tail_index = EEPROM.readUShort(EE_EVENT_LOG_TAIL_INDEX_ADDRESS);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("EEPROM was initialized for event logging");
|
||||
Serial.println("head: " + String(events.event_log_head_index) + ", tail: " + String(events.event_log_tail_index));
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("EEPROM was initialized for event logging");
|
||||
logging.println("head: " + String(events.event_log_head_index) + ", tail: " + String(events.event_log_tail_index));
|
||||
#endif
|
||||
print_event_log();
|
||||
}
|
||||
|
@ -140,8 +140,8 @@ void init_events(void) {
|
|||
events.entries[i].MQTTpublished = false; // Not published by default
|
||||
}
|
||||
|
||||
events.entries[EVENT_CANFD_INIT_FAILURE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_CANMCP_INIT_FAILURE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_CANMCP2517FD_INIT_FAILURE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_CANMCP2515_INIT_FAILURE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_CANFD_BUFFER_FULL].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_CAN_OVERRUN].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_CANFD_RX_OVERRUN].level = EVENT_LEVEL_WARNING;
|
||||
|
@ -264,9 +264,9 @@ void set_event_MQTTpublished(EVENTS_ENUM_TYPE event) {
|
|||
|
||||
const char* get_event_message_string(EVENTS_ENUM_TYPE event) {
|
||||
switch (event) {
|
||||
case EVENT_CANFD_INIT_FAILURE:
|
||||
case EVENT_CANMCP2517FD_INIT_FAILURE:
|
||||
return "CAN-FD initialization failed. Check hardware or bitrate settings";
|
||||
case EVENT_CANMCP_INIT_FAILURE:
|
||||
case EVENT_CANMCP2515_INIT_FAILURE:
|
||||
return "CAN-MCP addon initialization failed. Check hardware";
|
||||
case EVENT_CANFD_BUFFER_FULL:
|
||||
return "CAN-FD buffer overflowed. Some CAN messages were not sent. Contact developers.";
|
||||
|
@ -471,6 +471,10 @@ static void set_event(EVENTS_ENUM_TYPE event, uint8_t data, bool latched) {
|
|||
if (events.entries[event].log) {
|
||||
log_event(event, events.entries[event].millisrolloverCount, events.entries[event].timestamp, data);
|
||||
}
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Event: ");
|
||||
logging.println(get_event_message_string(event));
|
||||
#endif
|
||||
}
|
||||
|
||||
// We should set the event, update event info
|
||||
|
@ -484,10 +488,6 @@ static void set_event(EVENTS_ENUM_TYPE event, uint8_t data, bool latched) {
|
|||
events.level = max(events.level, events.entries[event].level);
|
||||
|
||||
update_bms_status();
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println(get_event_message_string(event));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void update_bms_status(void) {
|
||||
|
@ -561,8 +561,8 @@ static void log_event(EVENTS_ENUM_TYPE event, uint8_t millisrolloverCount, uint3
|
|||
// Store the new indices
|
||||
EEPROM.writeUShort(EE_EVENT_LOG_HEAD_INDEX_ADDRESS, events.event_log_head_index);
|
||||
EEPROM.writeUShort(EE_EVENT_LOG_TAIL_INDEX_ADDRESS, events.event_log_tail_index);
|
||||
//Serial.println("Wrote event " + String(event) + " to " + String(entry_address));
|
||||
//Serial.println("head: " + String(events.event_log_head_index) + ", tail: " + String(events.event_log_tail_index));
|
||||
//logging.println("Wrote event " + String(event) + " to " + String(entry_address));
|
||||
//logging.println("head: " + String(events.event_log_head_index) + ", tail: " + String(events.event_log_tail_index));
|
||||
|
||||
// We don't need the exact number, it's just for deciding to store or not
|
||||
events.nof_logged_events += (events.nof_logged_events < 255) ? 1 : 0;
|
||||
|
@ -571,8 +571,8 @@ static void log_event(EVENTS_ENUM_TYPE event, uint8_t millisrolloverCount, uint3
|
|||
static void print_event_log(void) {
|
||||
// If the head actually points to the tail, the log is probably blank
|
||||
if (events.event_log_head_index == events.event_log_tail_index) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("No events in log");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("No events in log");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -588,8 +588,8 @@ static void print_event_log(void) {
|
|||
// The entry is a blank that has been left behind somehow
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Event: " + String(get_event_enum_string(entry.event)) + ", data: " + String(entry.data) +
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Event: " + String(get_event_enum_string(entry.event)) + ", data: " + String(entry.data) +
|
||||
", time: " + String(entry.timestamp));
|
||||
#endif
|
||||
if (index == events.event_log_head_index) {
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
*/
|
||||
|
||||
#define EVENTS_ENUM_TYPE(XX) \
|
||||
XX(EVENT_CANFD_INIT_FAILURE) \
|
||||
XX(EVENT_CANMCP_INIT_FAILURE) \
|
||||
XX(EVENT_CANMCP2517FD_INIT_FAILURE) \
|
||||
XX(EVENT_CANMCP2515_INIT_FAILURE) \
|
||||
XX(EVENT_CANFD_BUFFER_FULL) \
|
||||
XX(EVENT_CAN_OVERRUN) \
|
||||
XX(EVENT_CANFD_RX_OVERRUN) \
|
||||
|
|
|
@ -25,9 +25,9 @@ void run_sequence_on_target(void) {
|
|||
case ETOT_INIT:
|
||||
timer.set_interval(10000);
|
||||
events_test_state = ETOT_FIRST_WAIT;
|
||||
Serial.println("Events test: initialized");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test: initialized");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
break;
|
||||
case ETOT_FIRST_WAIT:
|
||||
if (timer.elapsed()) {
|
||||
|
@ -35,9 +35,9 @@ void run_sequence_on_target(void) {
|
|||
events_test_state = ETOT_INFO;
|
||||
set_event(EVENT_DUMMY_INFO, 123);
|
||||
set_event(EVENT_DUMMY_INFO, 234); // 234 should show, occurrence 1
|
||||
Serial.println("Events test: info event set, data: 234");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test: info event set, data: 234");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_INFO:
|
||||
|
@ -45,9 +45,9 @@ void run_sequence_on_target(void) {
|
|||
timer.set_interval(8000);
|
||||
clear_event(EVENT_DUMMY_INFO);
|
||||
events_test_state = ETOT_INFO_CLEAR;
|
||||
Serial.println("Events test : info event cleared");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : info event cleared");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_INFO_CLEAR:
|
||||
|
@ -56,9 +56,9 @@ void run_sequence_on_target(void) {
|
|||
events_test_state = ETOT_DEBUG;
|
||||
set_event(EVENT_DUMMY_DEBUG, 111);
|
||||
set_event(EVENT_DUMMY_DEBUG, 222); // 222 should show, occurrence 1
|
||||
Serial.println("Events test : debug event set, data: 222");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : debug event set, data: 222");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_DEBUG:
|
||||
|
@ -66,9 +66,9 @@ void run_sequence_on_target(void) {
|
|||
timer.set_interval(8000);
|
||||
clear_event(EVENT_DUMMY_DEBUG);
|
||||
events_test_state = ETOT_DEBUG_CLEAR;
|
||||
Serial.println("Events test : info event cleared");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : info event cleared");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_DEBUG_CLEAR:
|
||||
|
@ -77,9 +77,9 @@ void run_sequence_on_target(void) {
|
|||
events_test_state = ETOT_WARNING;
|
||||
set_event(EVENT_DUMMY_WARNING, 234);
|
||||
set_event(EVENT_DUMMY_WARNING, 121); // 121 should show, occurrence 1
|
||||
Serial.println("Events test : warning event set, data: 121");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : warning event set, data: 121");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_WARNING:
|
||||
|
@ -87,9 +87,9 @@ void run_sequence_on_target(void) {
|
|||
timer.set_interval(8000);
|
||||
clear_event(EVENT_DUMMY_WARNING);
|
||||
events_test_state = ETOT_WARNING_CLEAR;
|
||||
Serial.println("Events test : warning event cleared");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : warning event cleared");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_WARNING_CLEAR:
|
||||
|
@ -98,9 +98,9 @@ void run_sequence_on_target(void) {
|
|||
events_test_state = ETOT_ERROR;
|
||||
set_event(EVENT_DUMMY_ERROR, 221);
|
||||
set_event(EVENT_DUMMY_ERROR, 133); // 133 should show, occurrence 1
|
||||
Serial.println("Events test : error event set, data: 133");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : error event set, data: 133");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_ERROR:
|
||||
|
@ -108,9 +108,9 @@ void run_sequence_on_target(void) {
|
|||
timer.set_interval(8000);
|
||||
clear_event(EVENT_DUMMY_ERROR);
|
||||
events_test_state = ETOT_ERROR_CLEAR;
|
||||
Serial.println("Events test : error event cleared");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : error event cleared");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_ERROR_CLEAR:
|
||||
|
@ -119,9 +119,9 @@ void run_sequence_on_target(void) {
|
|||
events_test_state = ETOT_ERROR_LATCHED;
|
||||
set_event_latched(EVENT_DUMMY_ERROR, 221);
|
||||
set_event_latched(EVENT_DUMMY_ERROR, 133); // 133 should show, occurrence 1
|
||||
Serial.println("Events test : latched error event set, data: 133");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : latched error event set, data: 133");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_ERROR_LATCHED:
|
||||
|
@ -129,9 +129,9 @@ void run_sequence_on_target(void) {
|
|||
timer.set_interval(8000);
|
||||
clear_event(EVENT_DUMMY_ERROR);
|
||||
events_test_state = ETOT_DONE;
|
||||
Serial.println("Events test : latched error event cleared?");
|
||||
Serial.print("datalayer.battery.status.bms_status: ");
|
||||
Serial.println(datalayer.battery.status.bms_status);
|
||||
logging.println("Events test : latched error event cleared?");
|
||||
logging.print("datalayer.battery.status.bms_status: ");
|
||||
logging.println(datalayer.battery.status.bms_status);
|
||||
}
|
||||
break;
|
||||
case ETOT_DONE:
|
||||
|
|
86
Software/src/devboard/utils/logging.cpp
Normal file
86
Software/src/devboard/utils/logging.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#include "logging.h"
|
||||
#include "../../datalayer/datalayer.h"
|
||||
|
||||
size_t Logging::write(const uint8_t* buffer, size_t size) {
|
||||
#ifdef DEBUG_LOG
|
||||
char* message_string = datalayer.system.info.logged_can_messages;
|
||||
int offset = datalayer.system.info.logged_can_messages_offset; // Keeps track of the current position in the buffer
|
||||
size_t message_string_size = sizeof(datalayer.system.info.logged_can_messages);
|
||||
unsigned long currentTime = millis();
|
||||
#ifdef DEBUG_VIA_USB
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (Serial.write(*buffer++))
|
||||
n++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
#endif
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (datalayer.system.info.can_logging_active) {
|
||||
return 0;
|
||||
}
|
||||
if (offset + size + 13 > sizeof(datalayer.system.info.logged_can_messages)) {
|
||||
offset = 0;
|
||||
}
|
||||
if (buffer[0] != '\r' && buffer[0] != '\n' &&
|
||||
(offset == 0 || message_string[offset - 1] == '\r' || message_string[offset - 1] == '\n')) {
|
||||
offset += snprintf(message_string + offset, message_string_size - offset - 1, "%8lu.%03lu ", currentTime / 1000,
|
||||
currentTime % 1000);
|
||||
}
|
||||
memcpy(message_string + offset, buffer, size);
|
||||
datalayer.system.info.logged_can_messages_offset = offset + size; // Update offset in buffer
|
||||
return size;
|
||||
#endif // DEBUG_VIA_WEB
|
||||
#endif // DEBUG_LOG
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Logging::printf(const char* fmt, ...) {
|
||||
#ifdef DEBUG_LOG
|
||||
char* message_string = datalayer.system.info.logged_can_messages;
|
||||
int offset = datalayer.system.info.logged_can_messages_offset; // Keeps track of the current position in the buffer
|
||||
size_t message_string_size = sizeof(datalayer.system.info.logged_can_messages);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
static char buf[128];
|
||||
message_string = buf;
|
||||
offset = 0;
|
||||
message_string_size = sizeof(buf);
|
||||
#endif
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (datalayer.system.info.can_logging_active) {
|
||||
return;
|
||||
}
|
||||
message_string = datalayer.system.info.logged_can_messages;
|
||||
offset = datalayer.system.info.logged_can_messages_offset; // Keeps track of the current position in the buffer
|
||||
message_string_size = sizeof(datalayer.system.info.logged_can_messages);
|
||||
#endif
|
||||
if (offset + 128 > sizeof(datalayer.system.info.logged_can_messages)) {
|
||||
// Not enough space, reset and start from the beginning
|
||||
offset = 0;
|
||||
}
|
||||
unsigned long currentTime = millis();
|
||||
// Add timestamp
|
||||
offset += snprintf(message_string + offset, message_string_size - offset - 1, "%8lu.%03lu ", currentTime / 1000,
|
||||
currentTime % 1000);
|
||||
|
||||
va_list(args);
|
||||
va_start(args, fmt);
|
||||
offset += vsnprintf(message_string + offset, message_string_size - offset - 1, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (datalayer.system.info.can_logging_active) {
|
||||
size_t size = offset;
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (Serial.write(*message_string++))
|
||||
n++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
datalayer.system.info.logged_can_messages_offset = offset; // Update offset in buffer
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
}
|
16
Software/src/devboard/utils/logging.h
Normal file
16
Software/src/devboard/utils/logging.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef __LOGGING_H__
|
||||
#define __LOGGING_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
class Logging : public Print {
|
||||
public:
|
||||
virtual size_t write(const uint8_t* buffer, size_t size);
|
||||
virtual size_t write(uint8_t) { return 0; }
|
||||
void printf(const char* fmt, ...);
|
||||
Logging() {}
|
||||
};
|
||||
|
||||
extern Logging logging;
|
||||
#endif // __LOGGING_H__
|
|
@ -51,6 +51,13 @@ typedef struct {
|
|||
} data;
|
||||
} CAN_frame;
|
||||
|
||||
enum frameDirection { MSG_RX, MSG_TX }; //RX = 0, TX = 1
|
||||
|
||||
typedef struct {
|
||||
CAN_frame frame;
|
||||
frameDirection direction;
|
||||
} CAN_log_frame;
|
||||
|
||||
std::string getBMSStatus(bms_status_enum status);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,44 @@ String advanced_battery_processor(const String& var) {
|
|||
// Start a new block with a specific background color
|
||||
content += "<div style='background-color: #303E47; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
|
||||
|
||||
#ifdef BOLT_AMPERA_BATTERY
|
||||
content += "<h4>5V Reference: " + String(datalayer_extended.boltampera.battery_5V_ref) + "</h4>";
|
||||
content += "<h4>Module 1 temp: " + String(datalayer_extended.boltampera.battery_module_temp_1) + "</h4>";
|
||||
content += "<h4>Module 2 temp: " + String(datalayer_extended.boltampera.battery_module_temp_2) + "</h4>";
|
||||
content += "<h4>Module 3 temp: " + String(datalayer_extended.boltampera.battery_module_temp_3) + "</h4>";
|
||||
content += "<h4>Module 4 temp: " + String(datalayer_extended.boltampera.battery_module_temp_4) + "</h4>";
|
||||
content += "<h4>Module 5 temp: " + String(datalayer_extended.boltampera.battery_module_temp_5) + "</h4>";
|
||||
content += "<h4>Module 6 temp: " + String(datalayer_extended.boltampera.battery_module_temp_6) + "</h4>";
|
||||
content +=
|
||||
"<h4>Cell average voltage: " + String(datalayer_extended.boltampera.battery_cell_average_voltage) + "</h4>";
|
||||
content +=
|
||||
"<h4>Cell average voltage 2: " + String(datalayer_extended.boltampera.battery_cell_average_voltage_2) + "</h4>";
|
||||
content += "<h4>Terminal voltage: " + String(datalayer_extended.boltampera.battery_terminal_voltage) + "</h4>";
|
||||
content +=
|
||||
"<h4>Ignition power mode: " + String(datalayer_extended.boltampera.battery_ignition_power_mode) + "</h4>";
|
||||
content += "<h4>Battery current (7E7): " + String(datalayer_extended.boltampera.battery_current_7E7) + "</h4>";
|
||||
content += "<h4>Capacity MY17-18: " + String(datalayer_extended.boltampera.battery_capacity_my17_18) + "</h4>";
|
||||
content += "<h4>Capacity MY19+: " + String(datalayer_extended.boltampera.battery_capacity_my19plus) + "</h4>";
|
||||
content += "<h4>SOC Display: " + String(datalayer_extended.boltampera.battery_SOC_display) + "</h4>";
|
||||
content += "<h4>SOC Raw highprec: " + String(datalayer_extended.boltampera.battery_SOC_raw_highprec) + "</h4>";
|
||||
content += "<h4>Max temp: " + String(datalayer_extended.boltampera.battery_max_temperature) + "</h4>";
|
||||
content += "<h4>Min temp: " + String(datalayer_extended.boltampera.battery_min_temperature) + "</h4>";
|
||||
content += "<h4>Cell max mV: " + String(datalayer_extended.boltampera.battery_max_cell_voltage) + "</h4>";
|
||||
content += "<h4>Cell min mV: " + String(datalayer_extended.boltampera.battery_min_cell_voltage) + "</h4>";
|
||||
content += "<h4>Lowest cell: " + String(datalayer_extended.boltampera.battery_lowest_cell) + "</h4>";
|
||||
content += "<h4>Highest cell: " + String(datalayer_extended.boltampera.battery_highest_cell) + "</h4>";
|
||||
content +=
|
||||
"<h4>Internal resistance: " + String(datalayer_extended.boltampera.battery_internal_resistance) + "</h4>";
|
||||
content += "<h4>Voltage: " + String(datalayer_extended.boltampera.battery_voltage_polled) + "</h4>";
|
||||
content += "<h4>Isolation Ohm: " + String(datalayer_extended.boltampera.battery_vehicle_isolation) + "</h4>";
|
||||
content += "<h4>Isolation kOhm: " + String(datalayer_extended.boltampera.battery_isolation_kohm) + "</h4>";
|
||||
content += "<h4>HV locked: " + String(datalayer_extended.boltampera.battery_HV_locked) + "</h4>";
|
||||
content += "<h4>Crash event: " + String(datalayer_extended.boltampera.battery_crash_event) + "</h4>";
|
||||
content += "<h4>HVIL: " + String(datalayer_extended.boltampera.battery_HVIL) + "</h4>";
|
||||
content += "<h4>HVIL status: " + String(datalayer_extended.boltampera.battery_HVIL_status) + "</h4>";
|
||||
content += "<h4>Current (7E4): " + String(datalayer_extended.boltampera.battery_current_7E4) + "</h4>";
|
||||
#endif //BOLT_AMPERA_BATTERY
|
||||
|
||||
#ifdef BMW_IX_BATTERY
|
||||
content +=
|
||||
"<h4>Battery Voltage after Contactor: " + String(datalayer_extended.bmwix.battery_voltage_after_contactor) +
|
||||
|
@ -311,6 +349,8 @@ String advanced_battery_processor(const String& var) {
|
|||
static_cast<float>(datalayer_extended.tesla.battery_energy_to_charge_complete_m1) * 0.02;
|
||||
float energy_buffer = static_cast<float>(datalayer_extended.tesla.battery_energy_buffer) * 0.1;
|
||||
float energy_buffer_m1 = static_cast<float>(datalayer_extended.tesla.battery_energy_buffer_m1) * 0.01;
|
||||
float expected_energy_remaining_m1 =
|
||||
static_cast<float>(datalayer_extended.tesla.battery_expected_energy_remaining_m1) * 0.02;
|
||||
float total_discharge = static_cast<float>(datalayer_extended.tesla.battery_total_discharge);
|
||||
float total_charge = static_cast<float>(datalayer_extended.tesla.battery_total_charge);
|
||||
float packMass = static_cast<float>(datalayer_extended.tesla.battery_packMass);
|
||||
|
@ -324,50 +364,85 @@ String advanced_battery_processor(const String& var) {
|
|||
float soc_max = static_cast<float>(datalayer_extended.tesla.battery_soc_max) * 0.1;
|
||||
float soc_min = static_cast<float>(datalayer_extended.tesla.battery_soc_min) * 0.1;
|
||||
float soc_ui = static_cast<float>(datalayer_extended.tesla.battery_soc_ui) * 0.1;
|
||||
|
||||
// Comment what data you would like to dislay, order can be changed.
|
||||
content += "<h4>Battery Beginning of Life: " + String(beginning_of_life) + " kWh</h4>";
|
||||
content += "<h4>BattTempPct: " + String(battTempPct) + " </h4>";
|
||||
content += "<h4>PCS Lv Bus: " + String(dcdcLvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS Hv Bus: " + String(dcdcHvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS Lv Output: " + String(dcdcLvOutputCurrent) + " A</h4>";
|
||||
|
||||
//if using older BMS <2021 and comment 0x352 without MUX
|
||||
//content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " kWh</h4>";
|
||||
//content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining) + " kWh</h4>";
|
||||
//content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining) + " kWh</h4>";
|
||||
//content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete) + " kWh</h4>";
|
||||
//content += "<h4>Energy Buffer: " + String(energy_buffer) + " kWh</h4>";
|
||||
|
||||
//if using newer BMS >2021 and comment 0x352 with MUX
|
||||
content += "<h4>Nominal Full Pack Energy m0: " + String(nominal_full_pack_energy_m0) + " kWh</h4>";
|
||||
content += "<h4>Nominal Energy Remaining m0: " + String(nominal_energy_remaining_m0) + " kWh</h4>";
|
||||
content += "<h4>Ideal Energy Remaining m0: " + String(ideal_energy_remaining_m0) + " kWh</h4>";
|
||||
content += "<h4>Energy to Charge Complete m1: " + String(energy_to_charge_complete_m1) + " kWh</h4>";
|
||||
content += "<h4>Energy Buffer m1: " + String(energy_buffer_m1) + " kWh</h4>";
|
||||
|
||||
content += "<h4>packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "</h4>";
|
||||
content += "<h4>moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "</h4>";
|
||||
content += "<h4>reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "</h4>";
|
||||
content += "<h4>Full Charge Complete: " + String(datalayer_extended.tesla.battery_full_charge_complete) + "</h4>";
|
||||
content += "<h4>Total Discharge: " + String(total_discharge) + " kWh</h4>";
|
||||
content += "<h4>Total Charge: " + String(total_charge) + " kWh</h4>";
|
||||
content += "<h4>Battery Pack Mass: " + String(packMass) + " KG</h4>";
|
||||
content += "<h4>Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V</h4>";
|
||||
content += "<h4>BMS Min Voltage: " + String(bms_min_voltage) + " V</h4>";
|
||||
content += "<h4>BMS Max Voltage: " + String(bms_max_voltage) + " V</h4>";
|
||||
content += "<h4>Max Charge Current: " + String(max_charge_current) + " A</h4>";
|
||||
content += "<h4>Max Discharge Current: " + String(max_discharge_current) + " A</h4>";
|
||||
content += "<h4>Battery SOC Ave: " + String(soc_ave) + " </h4>";
|
||||
content += "<h4>Battery SOC Max: " + String(soc_max) + " </h4>";
|
||||
content += "<h4>Battery SOC Min: " + String(soc_min) + " </h4>";
|
||||
content += "<h4>Battery SOC UI: " + String(soc_ui) + " </h4>";
|
||||
float BrickVoltageMax = static_cast<float>(datalayer_extended.tesla.battery_BrickVoltageMax) * 0.002;
|
||||
float BrickVoltageMin = static_cast<float>(datalayer_extended.tesla.battery_BrickVoltageMin) * 0.002;
|
||||
float BrickModelTMax = static_cast<float>(datalayer_extended.tesla.battery_BrickTempMinNum) * 0.5 - 40;
|
||||
float BrickModelTMin = static_cast<float>(datalayer_extended.tesla.battery_BrickModelTMin) * 0.5 - 40;
|
||||
float isolationResistance = static_cast<float>(datalayer_extended.tesla.battery_BMS_isolationResistance) * 10;
|
||||
float PCS_dcdcMaxOutputCurrentAllowed =
|
||||
static_cast<float>(datalayer_extended.tesla.battery_PCS_dcdcMaxOutputCurrentAllowed) * 0.1;
|
||||
float PCS_dcdcTemp = static_cast<float>(datalayer_extended.tesla.PCS_dcdcTemp) * 0.1 - 40;
|
||||
float PCS_ambientTemp = static_cast<float>(datalayer_extended.tesla.PCS_ambientTemp) * 0.1 - 40;
|
||||
float BMS_maxRegenPower = static_cast<float>(datalayer_extended.tesla.BMS_maxRegenPower) * 0.01;
|
||||
float BMS_maxDischargePower = static_cast<float>(datalayer_extended.tesla.BMS_maxDischargePower) * 0.013;
|
||||
float BMS_maxStationaryHeatPower = static_cast<float>(datalayer_extended.tesla.BMS_maxStationaryHeatPower) * 0.01;
|
||||
float BMS_hvacPowerBudget = static_cast<float>(datalayer_extended.tesla.BMS_hvacPowerBudget) * 0.02;
|
||||
float BMS_powerDissipation = static_cast<float>(datalayer_extended.tesla.BMS_powerDissipation) * 0.02;
|
||||
float BMS_flowRequest = static_cast<float>(datalayer_extended.tesla.BMS_flowRequest) * 0.3;
|
||||
float BMS_inletActiveCoolTargetT =
|
||||
static_cast<float>(datalayer_extended.tesla.BMS_inletActiveCoolTargetT) * 0.25 - 25;
|
||||
float BMS_inletPassiveTargetT = static_cast<float>(datalayer_extended.tesla.BMS_inletPassiveTargetT) * 0.25 - 25;
|
||||
float BMS_inletActiveHeatTargetT =
|
||||
static_cast<float>(datalayer_extended.tesla.BMS_inletActiveHeatTargetT) * 0.25 - 25;
|
||||
float BMS_packTMin = static_cast<float>(datalayer_extended.tesla.BMS_packTMin) * 0.25 - 25;
|
||||
float BMS_packTMax = static_cast<float>(datalayer_extended.tesla.BMS_packTMax) * 0.25 - 25;
|
||||
float PCS_dcdcMaxLvOutputCurrent = static_cast<float>(datalayer_extended.tesla.PCS_dcdcMaxLvOutputCurrent) * 0.1;
|
||||
float PCS_dcdcCurrentLimit = static_cast<float>(datalayer_extended.tesla.PCS_dcdcCurrentLimit) * 0.1;
|
||||
float PCS_dcdcLvOutputCurrentTempLimit =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcLvOutputCurrentTempLimit) * 0.1;
|
||||
float PCS_dcdcUnifiedCommand = static_cast<float>(datalayer_extended.tesla.PCS_dcdcUnifiedCommand) * 0.001;
|
||||
float PCS_dcdcCLAControllerOutput =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcCLAControllerOutput * 0.001);
|
||||
float PCS_dcdcTankVoltage = static_cast<float>(datalayer_extended.tesla.PCS_dcdcTankVoltage);
|
||||
float PCS_dcdcTankVoltageTarget = static_cast<float>(datalayer_extended.tesla.PCS_dcdcTankVoltageTarget);
|
||||
float PCS_dcdcClaCurrentFreq = static_cast<float>(datalayer_extended.tesla.PCS_dcdcClaCurrentFreq) * 0.0976563;
|
||||
float PCS_dcdcTCommMeasured = static_cast<float>(datalayer_extended.tesla.PCS_dcdcTCommMeasured) * 0.00195313;
|
||||
float PCS_dcdcShortTimeUs = static_cast<float>(datalayer_extended.tesla.PCS_dcdcShortTimeUs) * 0.000488281;
|
||||
float PCS_dcdcHalfPeriodUs = static_cast<float>(datalayer_extended.tesla.PCS_dcdcHalfPeriodUs) * 0.000488281;
|
||||
float PCS_dcdcIntervalMaxFrequency = static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMaxFrequency);
|
||||
float PCS_dcdcIntervalMaxHvBusVolt =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMaxHvBusVolt) * 0.1;
|
||||
float PCS_dcdcIntervalMaxLvBusVolt =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMaxLvBusVolt) * 0.1;
|
||||
float PCS_dcdcIntervalMaxLvOutputCurr =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMaxLvOutputCurr);
|
||||
float PCS_dcdcIntervalMinFrequency = static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMinFrequency);
|
||||
float PCS_dcdcIntervalMinHvBusVolt =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMinHvBusVolt) * 0.1;
|
||||
float PCS_dcdcIntervalMinLvBusVolt =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMinLvBusVolt) * 0.1;
|
||||
float PCS_dcdcIntervalMinLvOutputCurr =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdcIntervalMinLvOutputCurr);
|
||||
float PCS_dcdc12vSupportLifetimekWh =
|
||||
static_cast<float>(datalayer_extended.tesla.PCS_dcdc12vSupportLifetimekWh) * 0.01;
|
||||
float HVP_hvp1v5Ref = static_cast<float>(datalayer_extended.tesla.HVP_hvp1v5Ref) * 0.1;
|
||||
float HVP_shuntCurrentDebug = static_cast<float>(datalayer_extended.tesla.HVP_shuntCurrentDebug) * 0.1;
|
||||
float HVP_dcLinkVoltage = static_cast<float>(datalayer_extended.tesla.HVP_dcLinkVoltage) * 0.1;
|
||||
float HVP_packVoltage = static_cast<float>(datalayer_extended.tesla.HVP_packVoltage) * 0.1;
|
||||
float HVP_fcLinkVoltage = static_cast<float>(datalayer_extended.tesla.HVP_fcLinkVoltage) * 0.1;
|
||||
float HVP_packContVoltage = static_cast<float>(datalayer_extended.tesla.HVP_packContVoltage) * 0.1;
|
||||
float HVP_packNegativeV = static_cast<float>(datalayer_extended.tesla.HVP_packNegativeV) * 0.1;
|
||||
float HVP_packPositiveV = static_cast<float>(datalayer_extended.tesla.HVP_packPositiveV) * 0.1;
|
||||
float HVP_pyroAnalog = static_cast<float>(datalayer_extended.tesla.HVP_pyroAnalog) * 0.1;
|
||||
float HVP_dcLinkNegativeV = static_cast<float>(datalayer_extended.tesla.HVP_dcLinkNegativeV) * 0.1;
|
||||
float HVP_dcLinkPositiveV = static_cast<float>(datalayer_extended.tesla.HVP_dcLinkPositiveV) * 0.1;
|
||||
float HVP_fcLinkNegativeV = static_cast<float>(datalayer_extended.tesla.HVP_fcLinkNegativeV) * 0.1;
|
||||
float HVP_fcContCoilCurrent = static_cast<float>(datalayer_extended.tesla.HVP_fcContCoilCurrent) * 0.1;
|
||||
float HVP_fcContVoltage = static_cast<float>(datalayer_extended.tesla.HVP_fcContVoltage) * 0.1;
|
||||
float HVP_hvilInVoltage = static_cast<float>(datalayer_extended.tesla.HVP_hvilInVoltage) * 0.1;
|
||||
float HVP_hvilOutVoltage = static_cast<float>(datalayer_extended.tesla.HVP_hvilOutVoltage) * 0.1;
|
||||
float HVP_fcLinkPositiveV = static_cast<float>(datalayer_extended.tesla.HVP_fcLinkPositiveV) * 0.1;
|
||||
float HVP_packContCoilCurrent = static_cast<float>(datalayer_extended.tesla.HVP_packContCoilCurrent) * 0.1;
|
||||
float HVP_battery12V = static_cast<float>(datalayer_extended.tesla.HVP_battery12V) * 0.1;
|
||||
float HVP_shuntRefVoltageDbg = static_cast<float>(datalayer_extended.tesla.HVP_shuntRefVoltageDbg) * 0.001;
|
||||
float HVP_shuntAuxCurrentDbg = static_cast<float>(datalayer_extended.tesla.HVP_shuntAuxCurrentDbg) * 0.1;
|
||||
float HVP_shuntBarTempDbg = static_cast<float>(datalayer_extended.tesla.HVP_shuntBarTempDbg) * 0.01;
|
||||
float HVP_shuntAsicTempDbg = static_cast<float>(datalayer_extended.tesla.HVP_shuntAsicTempDbg) * 0.01;
|
||||
|
||||
static const char* contactorText[] = {"UNKNOWN(0)", "OPEN", "CLOSING", "BLOCKED", "OPENING",
|
||||
"CLOSED", "UNKNOWN(6)", "WELDED", "POS_CL", "NEG_CL",
|
||||
"UNKNOWN(10)", "UNKNOWN(11)", "UNKNOWN(12)"};
|
||||
content += "<h4>Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "</h4>";
|
||||
static const char* hvilStatusState[] = {"NOT OK",
|
||||
static const char* hvilStatusState[] = {"NOT Ok",
|
||||
"STATUS_OK",
|
||||
"CURRENT_SOURCE_FAULT",
|
||||
"INTERNAL_OPEN_FAULT",
|
||||
|
@ -383,17 +458,292 @@ String advanced_battery_processor(const String& var) {
|
|||
"UNKNOWN(13)",
|
||||
"UNKNOWN(14)",
|
||||
"UNKNOWN(15)"};
|
||||
content += "<h4>HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "</h4>";
|
||||
static const char* contactorState[] = {"SNA", "OPEN", "PRECHARGE", "BLOCKED",
|
||||
"PULLED_IN", "OPENING", "ECONOMIZED", "WELDED",
|
||||
"UNKNOWN(8)", "UNKNOWN(9)", "UNKNOWN(10)", "UNKNOWN(11)"};
|
||||
static const char* BMS_state[] = {"STANDBY", "DRIVE", "SUPPORT", "CHARGE", "FEIM",
|
||||
"CLEAR_FAULT", "FAULT", "WELD", "TEST", "SNA"};
|
||||
static const char* BMS_contactorState[] = {"SNA", "OPEN", "OPENING", "CLOSING", "CLOSED", "WELDED", "BLOCKED"};
|
||||
static const char* BMS_hvState[] = {"DOWN", "COMING_UP", "GOING_DOWN", "UP_FOR_DRIVE",
|
||||
"UP_FOR_CHARGE", "UP_FOR_DC_CHARGE", "UP"};
|
||||
static const char* BMS_uiChargeStatus[] = {"DISCONNECTED", "NO_POWER", "ABOUT_TO_CHARGE",
|
||||
"CHARGING", "CHARGE_COMPLETE", "CHARGE_STOPPED"};
|
||||
static const char* PCS_dcdcStatus[] = {"IDLE", "ACTIVE", "FAULTED"};
|
||||
static const char* PCS_dcdcMainState[] = {"STANDBY", "12V_SUPPORT_ACTIVE", "PRECHARGE_STARTUP",
|
||||
"PRECHARGE_ACTIVE", "DIS_HVBUS_ACTIVE", "SHUTDOWN",
|
||||
"FAULTED"};
|
||||
static const char* PCS_dcdcSubState[] = {"PWR_UP_INIT",
|
||||
"STANDBY",
|
||||
"12V_SUPPORT_ACTIVE",
|
||||
"DIS_HVBUS",
|
||||
"PCHG_FAST_DIS_HVBUS",
|
||||
"PCHG_SLOW_DIS_HVBUS",
|
||||
"PCHG_DWELL_CHARGE",
|
||||
"PCHG_DWELL_WAIT",
|
||||
"PCHG_DI_RECOVERY_WAIT",
|
||||
"PCHG_ACTIVE",
|
||||
"PCHG_FLT_FAST_DIS_HVBUS",
|
||||
"SHUTDOWN",
|
||||
"12V_SUPPORT_FAULTED",
|
||||
"DIS_HVBUS_FAULTED",
|
||||
"PCHG_FAULTED",
|
||||
"CLEAR_FAULTS",
|
||||
"FAULTED",
|
||||
"NUM"};
|
||||
static const char* BMS_powerLimitState[] = {"NOT_CALCULATED_FOR_DRIVE", "CALCULATED_FOR_DRIVE"};
|
||||
static const char* HVP_status[] = {"INVALID", "NOT_AVAILABLE", "STALE", "VALID"};
|
||||
static const char* HVP_contactor[] = {"NOT_ACTIVE", "ACTIVE", "COMPLETED"};
|
||||
static const char* falseTrue[] = {"False", "True"};
|
||||
static const char* noYes[] = {"No", "Yes"};
|
||||
static const char* Fault[] = {"NOT_ACTIVE", "ACTIVE"};
|
||||
//0x20A 522 HVP_contatorState
|
||||
content += "<h4>Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "</h4>";
|
||||
content += "<h4>HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Negative contactor: " + String(contactorState[datalayer_extended.tesla.packContNegativeState]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Positive contactor: " + String(contactorState[datalayer_extended.tesla.packContPositiveState]) + "</h4>";
|
||||
static const char* falseTrue[] = {"False", "True"};
|
||||
content += "<h4>Closing allowed?: " + String(falseTrue[datalayer_extended.tesla.packCtrsClosingAllowed]) + "</h4>";
|
||||
content += "<h4>Pyrotest: " + String(falseTrue[datalayer_extended.tesla.pyroTestInProgress]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Closing allowed?: " + String(noYes[datalayer_extended.tesla.packCtrsClosingAllowed]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>Pyrotest in Progress: " + String(noYes[datalayer_extended.tesla.pyroTestInProgress]) + "</h4>"; //bool
|
||||
content += "<h4>Contactors Open Now Requested: " +
|
||||
String(noYes[datalayer_extended.tesla.battery_packCtrsOpenNowRequested]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>Contactors Open Requested: " + String(noYes[datalayer_extended.tesla.battery_packCtrsOpenRequested]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>Contactors Request Status: " +
|
||||
String(HVP_contactor[datalayer_extended.tesla.battery_packCtrsRequestStatus]) + "</h4>";
|
||||
content += "<h4>Contactors Reset Request Required: " +
|
||||
String(noYes[datalayer_extended.tesla.battery_packCtrsResetRequestRequired]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>DC Link Allowed to Energize: " + String(noYes[datalayer_extended.tesla.battery_dcLinkAllowedToEnergize]) +
|
||||
"</h4>"; //bool
|
||||
// Comment what data you would like to dislay, order can be changed.
|
||||
//0x292 658 BMS_socStates
|
||||
content += "<h4>Battery Beginning of Life: " + String(beginning_of_life) + " KWh</h4>";
|
||||
content += "<h4>BattTempPct: " + String(battTempPct) + " </h4>";
|
||||
content += "<h4>Battery SOC Ave: " + String(soc_ave) + " </h4>";
|
||||
content += "<h4>Battery SOC Max: " + String(soc_max) + " </h4>";
|
||||
content += "<h4>Battery SOC Min: " + String(soc_min) + " </h4>";
|
||||
content += "<h4>Battery SOC UI: " + String(soc_ui) + " </h4>";
|
||||
//0x2B4 PCS_dcdcRailStatus
|
||||
content += "<h4>PCS Lv Bus: " + String(dcdcLvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS Hv Bus: " + String(dcdcHvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS Lv Output: " + String(dcdcLvOutputCurrent) + " A</h4>";
|
||||
//0x2A4 676 PCS_thermalStatus
|
||||
content += "<h4>PCS dcdc Temp: " + String(PCS_dcdcTemp) + " DegC</h4>";
|
||||
content += "<h4>PCS Ambient Temp: " + String(PCS_ambientTemp) + " DegC</h4>";
|
||||
//0x224 548 PCS_dcdcStatus
|
||||
content +=
|
||||
"<h4>Precharge Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcPrechargeStatus]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>12V Support Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdc12VSupportStatus]) +
|
||||
"</h4>";
|
||||
content += "<h4>HV Bus Discharge Status: " +
|
||||
String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcHvBusDischargeStatus]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Main State: " + String(PCS_dcdcMainState[datalayer_extended.tesla.battery_PCS_dcdcMainState]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Sub State: " + String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcSubState]) + "</h4>";
|
||||
content += "<h4>PCS Faulted: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcFaulted]) + "</h4>"; //bool
|
||||
content += "<h4>Output Is Limited: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>Max Output Current Allowed: " + String(PCS_dcdcMaxOutputCurrentAllowed) + " A</h4>";
|
||||
content += "<h4>Precharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRtyCnt]) +
|
||||
"</h4>"; //bool
|
||||
content +=
|
||||
"<h4>12V Support Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdc12VSupportRtyCnt]) +
|
||||
"</h4>"; // bool
|
||||
content += "<h4>Discharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcDischargeRtyCnt]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>PWM Enable Line: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>Supporting Fixed LV Target: " +
|
||||
String(Fault[datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget]) + "</h4>"; //bool
|
||||
content += "<h4>Precharge Restart Cnt: " +
|
||||
String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt]) + "</h4>"; //bool
|
||||
content += "<h4>Initial Precharge Substate: " +
|
||||
String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcInitialPrechargeSubState]) + "</h4>";
|
||||
//0x2C4 708 PCS_logging
|
||||
content += "<h4>PCS_dcdcMaxLvOutputCurrent: " + String(PCS_dcdcMaxLvOutputCurrent) + " A</h4>";
|
||||
content += "<h4>PCS_dcdcCurrentLimit: " + String(PCS_dcdcCurrentLimit) + " A</h4>";
|
||||
content += "<h4>PCS_dcdcLvOutputCurrentTempLimit: " + String(PCS_dcdcLvOutputCurrentTempLimit) + " A</h4>";
|
||||
content += "<h4>PCS_dcdcUnifiedCommand: " + String(PCS_dcdcUnifiedCommand) + "</h4>";
|
||||
content += "<h4>PCS_dcdcCLAControllerOutput: " + String(PCS_dcdcCLAControllerOutput) + "</h4>";
|
||||
content += "<h4>PCS_dcdcTankVoltage: " + String(PCS_dcdcTankVoltage) + " V</h4>";
|
||||
content += "<h4>PCS_dcdcTankVoltageTarget: " + String(PCS_dcdcTankVoltageTarget) + " V</h4>";
|
||||
content += "<h4>PCS_dcdcClaCurrentFreq: " + String(PCS_dcdcClaCurrentFreq) + " kHz</h4>";
|
||||
content += "<h4>PCS_dcdcTCommMeasured: " + String(PCS_dcdcTCommMeasured) + " us</h4>";
|
||||
content += "<h4>PCS_dcdcShortTimeUs: " + String(PCS_dcdcShortTimeUs) + " us</h4>";
|
||||
content += "<h4>PCS_dcdcHalfPeriodUs: " + String(PCS_dcdcHalfPeriodUs) + " us</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMaxFrequency: " + String(PCS_dcdcIntervalMaxFrequency) + " kHz</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMaxHvBusVolt: " + String(PCS_dcdcIntervalMaxHvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMaxLvBusVolt: " + String(PCS_dcdcIntervalMaxLvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMaxLvOutputCurr: " + String(PCS_dcdcIntervalMaxLvOutputCurr) + " A</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMinFrequency: " + String(PCS_dcdcIntervalMinFrequency) + " kHz</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMinHvBusVolt: " + String(PCS_dcdcIntervalMinHvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMinLvBusVolt: " + String(PCS_dcdcIntervalMinLvBusVolt) + " V</h4>";
|
||||
content += "<h4>PCS_dcdcIntervalMinLvOutputCurr: " + String(PCS_dcdcIntervalMinLvOutputCurr) + " A</h4>";
|
||||
content += "<h4>PCS_dcdc12vSupportLifetimekWh: " + String(PCS_dcdc12vSupportLifetimekWh) + " kWh</h4>";
|
||||
//0x3D2 978 BMS_kwhCounter
|
||||
content += "<h4>Total Discharge: " + String(total_discharge) + " KWh</h4>";
|
||||
content += "<h4>Total Charge: " + String(total_charge) + " KWh</h4>";
|
||||
//0x212 530 BMS_status
|
||||
content += "<h4>Isolation Resistance: " + String(isolationResistance) + " kOhms</h4>";
|
||||
content +=
|
||||
"<h4>BMS Contactor State: " + String(BMS_contactorState[datalayer_extended.tesla.battery_BMS_contactorState]) +
|
||||
"</h4>";
|
||||
content += "<h4>BMS State: " + String(BMS_state[datalayer_extended.tesla.battery_BMS_state]) + "</h4>";
|
||||
content += "<h4>BMS HV State: " + String(BMS_hvState[datalayer_extended.tesla.battery_BMS_hvState]) + "</h4>";
|
||||
content += "<h4>BMS UI Charge Status: " + String(BMS_uiChargeStatus[datalayer_extended.tesla.battery_BMS_hvState]) +
|
||||
"</h4>";
|
||||
content += "<h4>BMS PCS PWM Enabled: " + String(Fault[datalayer_extended.tesla.battery_BMS_pcsPwmEnabled]) +
|
||||
"</h4>"; //bool
|
||||
//0x352 850 BMS_energyStatus
|
||||
content += "<h3>Early BMS 0x352:</h3>"; //if using older BMS <2021 and comment 0x352 without MUX
|
||||
content += "<h4>Calculated SOH: " + String(nominal_full_pack_energy * 100 / beginning_of_life) + "</h4>";
|
||||
content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " KWh</h4>";
|
||||
content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining) + " KWh</h4>";
|
||||
content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining) + " KWh</h4>";
|
||||
content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete) + " KWh</h4>";
|
||||
content += "<h4>Energy Buffer: " + String(energy_buffer) + " KWh</h4>";
|
||||
content += "<h4>Full Charge Complete: " + String(noYes[datalayer_extended.tesla.battery_full_charge_complete]) +
|
||||
"</h4>"; //bool
|
||||
//0x352 850 BMS_energyStatus
|
||||
content += "<h3>Late BMS 0x352 with Mux:</h3>"; //if using newer BMS >2021 and comment 0x352 with MUX
|
||||
content += "<h4>Calculated SOH: " + String(nominal_full_pack_energy_m0 * 100 / beginning_of_life) + "</h4>";
|
||||
content += "<h4>Nominal Full Pack Energy: " + String(nominal_full_pack_energy_m0) + " KWh</h4>";
|
||||
content += "<h4>Nominal Energy Remaining: " + String(nominal_energy_remaining_m0) + " KWh</h4>";
|
||||
content += "<h4>Ideal Energy Remaining: " + String(ideal_energy_remaining_m0) + " KWh</h4>";
|
||||
content += "<h4>Energy to Charge Complete: " + String(energy_to_charge_complete_m1) + " KWh</h4>";
|
||||
content += "<h4>Energy Buffer: " + String(energy_buffer_m1) + " KWh</h4>";
|
||||
content += "<h4>Expected Energy Remaining: " + String(expected_energy_remaining_m1) + " KWh</h4>";
|
||||
content += "<h4>Fully Charged: " + String(noYes[datalayer_extended.tesla.battery_fully_charged]) + "</h4>"; //bool
|
||||
//0x392 BMS_packConfig
|
||||
//content += "<h4>packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "</h4>";
|
||||
//content += "<h4>moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "</h4>";
|
||||
//content += "<h4>reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "</h4>";
|
||||
content += "<h4>Battery Pack Mass: " + String(packMass) + " KG</h4>";
|
||||
content += "<h4>Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V</h4>";
|
||||
//0x2D2 722 BMSVAlimits
|
||||
content += "<h4>BMS Min Voltage: " + String(bms_min_voltage) + " V</h4>";
|
||||
content += "<h4>BMS Max Voltage: " + String(bms_max_voltage) + " V</h4>";
|
||||
content += "<h4>Max Charge Current: " + String(max_charge_current) + " A</h4>";
|
||||
content += "<h4>Max Discharge Current: " + String(max_discharge_current) + " A</h4>";
|
||||
//0x332 818 BMS_bmbMinMax
|
||||
content += "<h4>Brick Voltage Max: " + String(BrickVoltageMax) + " V</h4>";
|
||||
content += "<h4>Brick Voltage Min: " + String(BrickVoltageMin) + " V</h4>";
|
||||
content += "<h4>Brick Temp Max Num: " + String(datalayer_extended.tesla.battery_BrickTempMaxNum) + " </h4>";
|
||||
content += "<h4>Brick Temp Min Num: " + String(datalayer_extended.tesla.battery_BrickTempMinNum) + " </h4>";
|
||||
content += "<h4>Brick Model Temp Max: " + String(BrickModelTMax) + " C</h4>";
|
||||
content += "<h4>Brick Model Temp Min: " + String(BrickModelTMin) + " C</h4>";
|
||||
//0x252 594 BMS_powerAvailable
|
||||
content += "<h4>Max Regen Power: " + String(BMS_maxRegenPower) + " KW</h4>";
|
||||
content += "<h4>Max Discharge Power: " + String(BMS_maxDischargePower) + " KW</h4>";
|
||||
content += "<h4>Max Stationary Heat Power: " + String(BMS_maxStationaryHeatPower) + " KWh</h4>";
|
||||
content += "<h4>HVAC Power Budget: " + String(BMS_hvacPowerBudget) + " KW</h4>";
|
||||
content += "<h4>Not Enough Power For Heat Pump: " +
|
||||
String(falseTrue[datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>Power Limit State: " + String(BMS_powerLimitState[datalayer_extended.tesla.BMS_powerLimitState]) + "</h4>";
|
||||
content += "<h4>Inverter TQF: " + String(datalayer_extended.tesla.BMS_inverterTQF) + "</h4>";
|
||||
//0x312 786 BMS_thermalStatus
|
||||
content += "<h4>Power Dissipation: " + String(BMS_powerDissipation) + " kW</h4>";
|
||||
content += "<h4>Flow Request: " + String(BMS_flowRequest) + " LPM</h4>";
|
||||
content += "<h4>Inlet Active Cool Target Temp: " + String(BMS_inletActiveCoolTargetT) + " DegC</h4>";
|
||||
content += "<h4>Inlet Passive Target Temp: " + String(BMS_inletPassiveTargetT) + " DegC</h4>";
|
||||
content += "<h4>Inlet Active Heat Target Temp: " + String(BMS_inletActiveHeatTargetT) + " DegC</h4>";
|
||||
content += "<h4>Pack Temp Min: " + String(BMS_packTMin) + " DegC</h4>";
|
||||
content += "<h4>Pack Temp Max: " + String(BMS_packTMax) + " DegC</h4>";
|
||||
content +=
|
||||
"<h4>PCS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_pcsNoFlowRequest]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>BMS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_noFlowRequest]) + "</h4>"; //bool
|
||||
//0x7AA 1962 HVP_debugMessage
|
||||
content += "<h4>HVP_gpioPassivePyroDepl: " + String(Fault[datalayer_extended.tesla.HVP_gpioPassivePyroDepl]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>HVP_gpioPyroIsoEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroIsoEn]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioCpFaultIn: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultIn]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioPackContPowerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackContPowerEn]) +
|
||||
"</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioHvCablesOk: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvCablesOk]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioHvpSelfEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpSelfEnable]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioLed: " + String(Fault[datalayer_extended.tesla.HVP_gpioLed]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioCrashSignal: " + String(Fault[datalayer_extended.tesla.HVP_gpioCrashSignal]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioShuntDataReady: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntDataReady]) +
|
||||
"</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioFcContPosAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPosAux]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioFcContNegAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContNegAux]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioBmsEout: " + String(Fault[datalayer_extended.tesla.HVP_gpioBmsEout]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioCpFaultOut: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultOut]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioPyroPor: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroPor]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioShuntEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntEn]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioHvpVerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpVerEn]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioPackCoontPosFlywheel: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackCoontPosFlywheel]) +
|
||||
"</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioCpLatchEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpLatchEnable]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioPcsEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsEnable]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioPcsDcdcPwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsDcdcPwmEnable]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>HVP_gpioPcsChargePwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsChargePwmEnable]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>HVP_gpioFcContPowerEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPowerEnable]) +
|
||||
"</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_gpioHvilEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvilEnable]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_gpioSecDrdy: " + String(Fault[datalayer_extended.tesla.HVP_gpioSecDrdy]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_hvp1v5Ref: " + String(HVP_hvp1v5Ref) + " V</h4>";
|
||||
content += "<h4>HVP_shuntCurrentDebug: " + String(HVP_shuntCurrentDebug) + " A</h4>";
|
||||
content +=
|
||||
"<h4>HVP_packCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_packCurrentMia]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_auxCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_auxCurrentMia]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_currentSenseMia: " + String(noYes[datalayer_extended.tesla.HVP_currentSenseMia]) + "</h4>"; //bool
|
||||
content +=
|
||||
"<h4>HVP_shuntRefVoltageMismatch: " + String(noYes[datalayer_extended.tesla.HVP_shuntRefVoltageMismatch]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>HVP_shuntThermistorMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntThermistorMia]) +
|
||||
"</h4>"; //bool
|
||||
content += "<h4>HVP_shuntHwMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntHwMia]) + "</h4>"; //bool
|
||||
content += "<h4>HVP_dcLinkVoltage: " + String(HVP_dcLinkVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_packVoltage: " + String(HVP_packVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_fcLinkVoltage: " + String(HVP_fcLinkVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_packContVoltage: " + String(HVP_packContVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_packNegativeV: " + String(HVP_packNegativeV) + " V</h4>";
|
||||
content += "<h4>HVP_packPositiveV: " + String(HVP_packPositiveV) + " V</h4>";
|
||||
content += "<h4>HVP_pyroAnalog: " + String(HVP_pyroAnalog) + " V</h4>";
|
||||
content += "<h4>HVP_dcLinkNegativeV: " + String(HVP_dcLinkNegativeV) + " V</h4>";
|
||||
content += "<h4>HVP_dcLinkPositiveV: " + String(HVP_dcLinkPositiveV) + " V</h4>";
|
||||
content += "<h4>HVP_fcLinkNegativeV: " + String(HVP_fcLinkNegativeV) + " V</h4>";
|
||||
content += "<h4>HVP_fcContCoilCurrent: " + String(HVP_fcContCoilCurrent) + " A</h4>";
|
||||
content += "<h4>HVP_fcContVoltage: " + String(HVP_fcContVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_hvilInVoltage: " + String(HVP_hvilInVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_hvilOutVoltage: " + String(HVP_hvilOutVoltage) + " V</h4>";
|
||||
content += "<h4>HVP_fcLinkPositiveV: " + String(HVP_fcLinkPositiveV) + " V</h4>";
|
||||
content += "<h4>HVP_packContCoilCurrent: " + String(HVP_packContCoilCurrent) + " A</h4>";
|
||||
content += "<h4>HVP_battery12V: " + String(HVP_battery12V) + " V</h4>";
|
||||
content += "<h4>HVP_shuntRefVoltageDbg: " + String(HVP_shuntRefVoltageDbg) + " V</h4>";
|
||||
content += "<h4>HVP_shuntAuxCurrentDbg: " + String(HVP_shuntAuxCurrentDbg) + " A</h4>";
|
||||
content += "<h4>HVP_shuntBarTempDbg: " + String(HVP_shuntBarTempDbg) + " DegC</h4>";
|
||||
content += "<h4>HVP_shuntAsicTempDbg: " + String(HVP_shuntAsicTempDbg) + " DegC</h4>";
|
||||
content +=
|
||||
"<h4>HVP_shuntAuxCurrentStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAuxCurrentStatus]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>HVP_shuntBarTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntBarTempStatus]) + "</h4>";
|
||||
content += "<h4>HVP_shuntAsicTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAsicTempStatus]) +
|
||||
"</h4>";
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
|
@ -680,9 +1030,10 @@ String advanced_battery_processor(const String& var) {
|
|||
content += "<h4>soc max: " + String(datalayer_extended.zoePH2.battery_soc_max) + "</h4>";
|
||||
#endif //RENAULT_ZOE_GEN2_BATTERY
|
||||
|
||||
#if !defined(TESLA_BATTERY) && !defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && \
|
||||
!defined(BYD_ATTO_3_BATTERY) && !defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && \
|
||||
!defined(MEB_BATTERY) //Only the listed types have extra info
|
||||
#if !defined(BMW_IX_BATTERY) && !defined(BOLT_AMPERA_BATTERY) && !defined(TESLA_BATTERY) && \
|
||||
!defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && !defined(BYD_ATTO_3_BATTERY) && \
|
||||
!defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && \
|
||||
!defined(MEB_BATTERY) // Only the listed types have extra info
|
||||
content += "No extra information available for this battery type";
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
String can_logger_processor(const String& var) {
|
||||
if (var == "X") {
|
||||
if (!datalayer.system.info.can_logging_active) {
|
||||
datalayer.system.info.logged_can_messages_offset = 0;
|
||||
datalayer.system.info.logged_can_messages[0] = '\0';
|
||||
}
|
||||
datalayer.system.info.can_logging_active =
|
||||
true; // Signal to main loop that we should log messages. Disabled by default for performance reasons
|
||||
String content = "";
|
||||
|
@ -19,7 +23,10 @@ String can_logger_processor(const String& var) {
|
|||
"monospace; }";
|
||||
content += "</style>";
|
||||
content += "<button onclick='refreshPage()'>Refresh data</button> ";
|
||||
content += "<button onclick='exportLogs()'>Export to .txt</button> ";
|
||||
content += "<button onclick='exportLog()'>Export to .txt</button> ";
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
content += "<button onclick='deleteLogFile()'>Delete log file</button> ";
|
||||
#endif
|
||||
content += "<button onclick='stopLoggingAndGoToMainPage()'>Back to main page</button>";
|
||||
|
||||
// Start a new block for the CAN messages
|
||||
|
@ -47,9 +54,12 @@ String can_logger_processor(const String& var) {
|
|||
// Add JavaScript for navigation
|
||||
content += "<script>";
|
||||
content += "function refreshPage(){ location.reload(true); }";
|
||||
content += "function exportLogs() { window.location.href = '/export_logs'; }";
|
||||
content += "function exportLog() { window.location.href = '/export_can_log'; }";
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
content += "function deleteLogFile() { window.location.href = '/delete_can_log'; }";
|
||||
#endif
|
||||
content += "function stopLoggingAndGoToMainPage() {";
|
||||
content += " fetch('/stop_logging').then(() => window.location.href = '/');";
|
||||
content += " fetch('/stop_can_logging').then(() => window.location.href = '/');";
|
||||
content += "}";
|
||||
content += "</script>";
|
||||
return content;
|
||||
|
|
36
Software/src/devboard/webserver/debug_logging_html.cpp
Normal file
36
Software/src/devboard/webserver/debug_logging_html.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "debug_logging_html.h"
|
||||
#include <Arduino.h>
|
||||
#include "../../datalayer/datalayer.h"
|
||||
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
String debug_logger_processor(const String& var) {
|
||||
String content = "";
|
||||
// Page format
|
||||
content += "<style>";
|
||||
content += "body { background-color: black; color: white; font-family: Arial, sans-serif; }";
|
||||
content +=
|
||||
"button { background-color: #505E67; color: white; border: none; padding: 10px 20px; margin-bottom: 20px; "
|
||||
"cursor: pointer; border-radius: 10px; }";
|
||||
content += "button:hover { background-color: #3A4A52; }";
|
||||
content +=
|
||||
".can-message { background-color: #404E57; margin-bottom: 5px; padding: 10px; border-radius: 5px; font-family: "
|
||||
"monospace; }";
|
||||
content += "</style>";
|
||||
content += "<button onclick='refreshPage()'>Refresh data</button> ";
|
||||
content += "<button onclick='exportLog()'>Export to .txt</button> ";
|
||||
content += "<button onclick='goToMainPage()'>Back to main page</button>";
|
||||
|
||||
// Start a new block for the debug log messages
|
||||
content += "<PRE style='text-align: left'>";
|
||||
content += String(datalayer.system.info.logged_can_messages);
|
||||
content += "</PRE>";
|
||||
|
||||
// Add JavaScript for navigation
|
||||
content += "<script>";
|
||||
content += "function refreshPage(){ location.reload(true); }";
|
||||
content += "function exportLog() { window.location.href = '/export_log'; }";
|
||||
content += "function goToMainPage() { window.location.href = '/'; }";
|
||||
content += "</script>";
|
||||
return content;
|
||||
}
|
||||
#endif // DEBUG_VIA_WEB
|
16
Software/src/devboard/webserver/debug_logging_html.h
Normal file
16
Software/src/devboard/webserver/debug_logging_html.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef DEBUGLOGGER_H
|
||||
#define DEBUGLOGGER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief Replaces placeholder with content section in web page
|
||||
*
|
||||
* @param[in] var
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String debug_logger_processor(const String& var);
|
||||
|
||||
#endif
|
|
@ -39,8 +39,8 @@ String events_processor(const String& var) {
|
|||
for (const auto& event : order_events) {
|
||||
EVENTS_ENUM_TYPE event_handle = event.event_handle;
|
||||
event_pointer = event.event_pointer;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Event: " + String(get_event_enum_string(event_handle)) +
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Showing Event: " + String(get_event_enum_string(event_handle)) +
|
||||
" count: " + String(event_pointer->occurences) + " seconds: " + String(event_pointer->timestamp) +
|
||||
" data: " + String(event_pointer->data) +
|
||||
" level: " + String(get_event_level_string(event_handle)));
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include "webserver.h"
|
||||
#include <Preferences.h>
|
||||
#include <ctime>
|
||||
#include "../../../USER_SECRETS.h"
|
||||
#include "../../datalayer/datalayer.h"
|
||||
#include "../../datalayer/datalayer_extended.h"
|
||||
#include "../../lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
||||
#include "../sdcard/sdcard.h"
|
||||
#include "../utils/events.h"
|
||||
#include "../utils/led_handler.h"
|
||||
#include "../utils/timer.h"
|
||||
|
@ -17,6 +19,7 @@ unsigned long ota_progress_millis = 0;
|
|||
#include "advanced_battery_html.h"
|
||||
#include "can_logging_html.h"
|
||||
#include "cellmonitor_html.h"
|
||||
#include "debug_logging_html.h"
|
||||
#include "events_html.h"
|
||||
#include "index_html.cpp"
|
||||
#include "settings_html.h"
|
||||
|
@ -63,14 +66,22 @@ void init_webserver() {
|
|||
request->send_P(200, "text/html", index_html, can_logger_processor);
|
||||
});
|
||||
|
||||
// Define the handler to stop logging
|
||||
server.on("/stop_logging", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
// Route for going to debug logging web page
|
||||
server.on("/log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
request->send_P(200, "text/html", index_html, debug_logger_processor);
|
||||
});
|
||||
#endif // DEBUG_VIA_WEB
|
||||
|
||||
// Define the handler to stop can logging
|
||||
server.on("/stop_can_logging", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
datalayer.system.info.can_logging_active = false;
|
||||
request->send_P(200, "text/plain", "Logging stopped");
|
||||
});
|
||||
|
||||
// Define the handler to export logs
|
||||
server.on("/export_logs", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
#ifndef LOG_CAN_TO_SD
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
String logs = String(datalayer.system.info.logged_can_messages);
|
||||
if (logs.length() == 0) {
|
||||
logs = "No logs available.";
|
||||
|
@ -95,6 +106,49 @@ void init_webserver() {
|
|||
response->addHeader("Content-Disposition", String("attachment; filename=\"") + String(filename) + "\"");
|
||||
request->send(response);
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
pause_can_writing();
|
||||
request->send(SD, CAN_LOG_FILE, String(), true);
|
||||
resume_can_writing();
|
||||
});
|
||||
|
||||
// Define the handler to delete can log
|
||||
server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
delete_can_log();
|
||||
request->send_P(200, "text/plain", "Log file deleted");
|
||||
});
|
||||
#endif
|
||||
|
||||
// Define the handler to export debug log
|
||||
server.on("/export_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
String logs = String(datalayer.system.info.logged_can_messages);
|
||||
if (logs.length() == 0) {
|
||||
logs = "No logs available.";
|
||||
}
|
||||
|
||||
// Get the current time
|
||||
time_t now = time(nullptr);
|
||||
struct tm timeinfo;
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
// Ensure time retrieval was successful
|
||||
char filename[32];
|
||||
if (strftime(filename, sizeof(filename), "log_%H-%M-%S.txt", &timeinfo)) {
|
||||
// Valid filename created
|
||||
} else {
|
||||
// Fallback filename if automatic timestamping failed
|
||||
strcpy(filename, "battery_emulator_log.txt");
|
||||
}
|
||||
|
||||
// Use request->send with dynamic headers
|
||||
AsyncWebServerResponse* response = request->beginResponse(200, "text/plain", logs);
|
||||
response->addHeader("Content-Disposition", String("attachment; filename=\"") + String(filename) + "\"");
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// Route for going to cellmonitor web page
|
||||
server.on("/cellmonitor", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
|
@ -509,7 +563,10 @@ String get_firmware_info_processor(const String& var) {
|
|||
#endif // HW_STARK
|
||||
#ifdef HW_3LB
|
||||
doc["hardware"] = "3LB board";
|
||||
#endif // HW_STARK
|
||||
#endif // HW_3LB
|
||||
#ifdef HW_DEVKIT
|
||||
doc["hardware"] = "ESP32 DevKit V1";
|
||||
#endif // HW_DEVKIT
|
||||
|
||||
doc["firmware"] = String(version_number);
|
||||
serializeJson(doc, content);
|
||||
|
@ -535,14 +592,15 @@ String processor(const String& var) {
|
|||
content += "<div style='background-color: #303E47; padding: 10px; margin-bottom: 10px;border-radius: 50px'>";
|
||||
|
||||
// Show version number
|
||||
content += "<h4>Software: " + String(version_number) + "</h4>";
|
||||
content += "<h4>Software: " + String(version_number);
|
||||
// Show hardware used:
|
||||
#ifdef HW_LILYGO
|
||||
content += "<h4>Hardware: LilyGo T-CAN485</h4>";
|
||||
content += " Hardware: LilyGo T-CAN485";
|
||||
#endif // HW_LILYGO
|
||||
#ifdef HW_STARK
|
||||
content += "<h4>Hardware: Stark CMR Module</h4>";
|
||||
content += " Hardware: Stark CMR Module";
|
||||
#endif // HW_STARK
|
||||
content += "</h4>";
|
||||
content += "<h4>Uptime: " + uptime_formatter::getUptime() + "</h4>";
|
||||
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||
// Load information
|
||||
|
@ -566,11 +624,14 @@ String processor(const String& var) {
|
|||
|
||||
wl_status_t status = WiFi.status();
|
||||
// Display ssid of network connected to and, if connected to the WiFi, its own IP
|
||||
content += "<h4>SSID: " + String(ssid.c_str()) + "</h4>";
|
||||
content += "<h4>SSID: " + String(ssid.c_str());
|
||||
if (status == WL_CONNECTED) {
|
||||
// Get and display the signal strength (RSSI) and channel
|
||||
content += " RSSI:" + String(WiFi.RSSI()) + " dBm Ch: " + String(WiFi.channel());
|
||||
}
|
||||
content += "</h4>";
|
||||
if (status == WL_CONNECTED) {
|
||||
content += "<h4>IP: " + WiFi.localIP().toString() + "</h4>";
|
||||
// Get and display the signal strength (RSSI) and channel
|
||||
content += "<h4>Signal strength: " + String(WiFi.RSSI()) + " dBm, at channel " + String(WiFi.channel()) + "</h4>";
|
||||
} else {
|
||||
content += "<h4>Wifi state: " + getConnectResultString(status) + "</h4>";
|
||||
}
|
||||
|
@ -698,13 +759,30 @@ String processor(const String& var) {
|
|||
}
|
||||
content += "<h4>Temperature max: " + String(tempMaxFloat, 1) + " C</h4>";
|
||||
content += "<h4>Temperature min: " + String(tempMinFloat, 1) + " C</h4>";
|
||||
if (datalayer.battery.status.bms_status == ACTIVE) {
|
||||
content += "<h4>System status: OK </h4>";
|
||||
} else if (datalayer.battery.status.bms_status == UPDATING) {
|
||||
content += "<h4>System status: UPDATING </h4>";
|
||||
} else {
|
||||
content += "<h4>System status: FAULT </h4>";
|
||||
|
||||
content += "<h4>System status: ";
|
||||
switch (datalayer.battery.status.bms_status) {
|
||||
case ACTIVE:
|
||||
content += String("OK");
|
||||
break;
|
||||
case UPDATING:
|
||||
content += String("UPDATING");
|
||||
break;
|
||||
case FAULT:
|
||||
content += String("FAULT");
|
||||
break;
|
||||
case INACTIVE:
|
||||
content += String("INACTIVE");
|
||||
break;
|
||||
case STANDBY:
|
||||
content += String("STANDBY");
|
||||
break;
|
||||
default:
|
||||
content += String("??");
|
||||
break;
|
||||
}
|
||||
content += "</h4>";
|
||||
|
||||
if (datalayer.battery.status.current_dA == 0) {
|
||||
content += "<h4>Battery idle</h4>";
|
||||
} else if (datalayer.battery.status.current_dA < 0) {
|
||||
|
@ -983,6 +1061,9 @@ String processor(const String& var) {
|
|||
content += "<button onclick='Settings()'>Change Settings</button> ";
|
||||
content += "<button onclick='Advanced()'>More Battery Info</button> ";
|
||||
content += "<button onclick='CANlog()'>CAN logger</button> ";
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
content += "<button onclick='Log()'>Log</button> ";
|
||||
#endif // DEBUG_VIA_WEB
|
||||
content += "<button onclick='Cellmon()'>Cellmonitor</button> ";
|
||||
content += "<button onclick='Events()'>Events</button> ";
|
||||
content += "<button onclick='askReboot()'>Reboot Emulator</button>";
|
||||
|
@ -1008,6 +1089,7 @@ String processor(const String& var) {
|
|||
content += "function Settings() { window.location.href = '/settings'; }";
|
||||
content += "function Advanced() { window.location.href = '/advanced'; }";
|
||||
content += "function CANlog() { window.location.href = '/canlog'; }";
|
||||
content += "function Log() { window.location.href = '/log'; }";
|
||||
content += "function Events() { window.location.href = '/events'; }";
|
||||
content +=
|
||||
"function askReboot() { if (window.confirm('Are you sure you want to reboot the emulator? NOTE: If "
|
||||
|
@ -1068,9 +1150,9 @@ void onOTAProgress(size_t current, size_t final) {
|
|||
// Log every 1 second
|
||||
if (millis() - ota_progress_millis > 1000) {
|
||||
ota_progress_millis = millis();
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
|
||||
#endif // DEBUG_LOG
|
||||
// Reset the "watchdog"
|
||||
ota_timeout_timer.reset();
|
||||
}
|
||||
|
@ -1087,13 +1169,13 @@ void onOTAEnd(bool success) {
|
|||
// Max Charge/Discharge = 0; CAN = stop; contactors = open
|
||||
setBatteryPause(true, true, true, false);
|
||||
// a reboot will be done by the OTA library. no need to do anything here
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("OTA update finished successfully!");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("OTA update finished successfully!");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("There was an error during OTA update!");
|
||||
#endif // DEBUG_VIA_USB
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("There was an error during OTA update!");
|
||||
#endif // DEBUG_LOG
|
||||
//try to Resume the battery pause and CAN communication
|
||||
setBatteryPause(false, false);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "../../include.h"
|
||||
#include "../../lib/YiannisBourkelis-Uptime-Library/src/uptime_formatter.h"
|
||||
#include "../../lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h"
|
||||
#include "../../lib/mathieucarbou-AsyncTCP/src/AsyncTCP.h"
|
||||
#include "../../lib/me-no-dev-AsyncTCP/src/AsyncTCP.h"
|
||||
#include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h"
|
||||
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
|
|
@ -29,12 +29,8 @@ static bool connected_once = false;
|
|||
void init_WiFi() {
|
||||
|
||||
#ifdef WIFIAP
|
||||
if (AccessPointEnabled) {
|
||||
WiFi.mode(WIFI_AP_STA); // Simultaneous WiFi AP and Router connection
|
||||
init_WiFi_AP();
|
||||
} else {
|
||||
WiFi.mode(WIFI_STA); // Only Router connection
|
||||
}
|
||||
#else
|
||||
WiFi.mode(WIFI_STA); // Only Router connection
|
||||
#endif // WIFIAP
|
||||
|
@ -72,28 +68,28 @@ void wifi_monitor() {
|
|||
// Increase the current check interval if it's not at the maximum
|
||||
if (current_check_interval + STEP_WIFI_CHECK_INTERVAL <= MAX_STEP_WIFI_CHECK_INTERVAL)
|
||||
current_check_interval += STEP_WIFI_CHECK_INTERVAL;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi not connected, attempting to reconnect...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi not connected, attempting to reconnect...");
|
||||
#endif
|
||||
// Try WiFi.reconnect() if it was successfully connected at least once
|
||||
if (hasConnectedBefore) {
|
||||
lastReconnectAttempt = millis(); // Reset reconnection attempt timer
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi reconnect attempt...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi reconnect attempt...");
|
||||
#endif
|
||||
if (WiFi.reconnect()) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi reconnect attempt sucess...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi reconnect attempt sucess...");
|
||||
#endif
|
||||
reconnectAttempts = 0; // Reset the attempt counter on successful reconnect
|
||||
} else {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi reconnect attempt error...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi reconnect attempt error...");
|
||||
#endif
|
||||
reconnectAttempts++;
|
||||
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Failed to reconnect multiple times, forcing a full connection attempt...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Failed to reconnect multiple times, forcing a full connection attempt...");
|
||||
#endif
|
||||
FullReconnectToWiFi();
|
||||
}
|
||||
|
@ -101,8 +97,8 @@ void wifi_monitor() {
|
|||
} else {
|
||||
// If no previous connection, force a full connection attempt
|
||||
if (currentMillis - lastReconnectAttempt > current_full_reconnect_interval) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("No previous OK connection, force a full connection attempt...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("No previous OK connection, force a full connection attempt...");
|
||||
#endif
|
||||
FullReconnectToWiFi();
|
||||
}
|
||||
|
@ -127,13 +123,13 @@ static void FullReconnectToWiFi() {
|
|||
static void connectToWiFi() {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
lastReconnectAttempt = millis(); // Reset the reconnect attempt timer
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Connecting to Wi-Fi...");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Connecting to Wi-Fi...");
|
||||
#endif
|
||||
WiFi.begin(ssid.c_str(), password.c_str(), wifi_channel);
|
||||
} else {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi already connected.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi already connected.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -143,10 +139,11 @@ static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||
clear_event(EVENT_WIFI_DISCONNECT);
|
||||
set_event(EVENT_WIFI_CONNECT, 0);
|
||||
connected_once = true;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi connected.");
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Wi-Fi connected. RSSI: ");
|
||||
logging.print(-WiFi.RSSI());
|
||||
logging.print(" dBm, IP address: ");
|
||||
logging.println(WiFi.localIP().toString());
|
||||
#endif
|
||||
hasConnectedBefore = true; // Mark as successfully connected at least once
|
||||
reconnectAttempts = 0; // Reset the attempt counter
|
||||
|
@ -159,10 +156,10 @@ static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||
static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
//clear disconnects events if we got a IP
|
||||
clear_event(EVENT_WIFI_DISCONNECT);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi Got IP.");
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Wi-Fi Got IP. ");
|
||||
logging.print("IP address: ");
|
||||
logging.println(WiFi.localIP().toString());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -170,8 +167,8 @@ static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||
static void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
if (connected_once)
|
||||
set_event(EVENT_WIFI_DISCONNECT, 0);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Wi-Fi disconnected.");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi disconnected.");
|
||||
#endif
|
||||
//we dont do anything here, the reconnect will be handled by the monitor
|
||||
//too many events received when the connection is lost
|
||||
|
@ -188,8 +185,8 @@ void init_mDNS() {
|
|||
|
||||
// Initialize mDNS .local resolution
|
||||
if (!MDNS.begin(mdnsHost)) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Error setting up MDNS responder!");
|
||||
#endif
|
||||
} else {
|
||||
// Advertise via bonjour the service so we can auto discover these battery emulators on the local network.
|
||||
|
@ -200,16 +197,16 @@ void init_mDNS() {
|
|||
|
||||
#ifdef WIFIAP
|
||||
void init_WiFi_AP() {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Creating Access Point: " + String(ssidAP));
|
||||
Serial.println("With password: " + String(passwordAP));
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Creating Access Point: " + String(ssidAP));
|
||||
logging.println("With password: " + String(passwordAP));
|
||||
#endif
|
||||
WiFi.softAP(ssidAP, passwordAP);
|
||||
IPAddress IP = WiFi.softAPIP();
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Access Point created.");
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(IP);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Access Point created.");
|
||||
logging.print("IP address: ");
|
||||
logging.println(IP);
|
||||
#endif
|
||||
}
|
||||
#endif // WIFIAP
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "devboard/hal/hal.h"
|
||||
#include "devboard/safety/safety.h"
|
||||
#include "devboard/utils/logging.h"
|
||||
#include "devboard/utils/time_meas.h"
|
||||
#include "devboard/utils/types.h"
|
||||
|
||||
|
@ -19,12 +20,7 @@
|
|||
/* - ERROR CHECKS BELOW, DON'T TOUCH - */
|
||||
|
||||
#if !defined(HW_CONFIGURED)
|
||||
#error You must select a HW to run on!
|
||||
#endif
|
||||
|
||||
#if defined(CAN_ADDON) && defined(CANFD_ADDON)
|
||||
// Check that user did not try to use dual can and fd-can on same hardware pins
|
||||
#error CAN_ADDON AND CANFD_ADDON CANNOT BE USED SIMULTANEOUSLY
|
||||
#error You must select a target hardware in the USER_SERTTINGS.h file!
|
||||
#endif
|
||||
|
||||
#ifdef USE_CANFD_INTERFACE_AS_CLASSIC_CAN
|
||||
|
@ -52,4 +48,10 @@
|
|||
#error No battery selected! Choose one from the USER_SETTINGS.h file
|
||||
#endif
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
#if !defined(HW_LILYGO)
|
||||
#error The SD card logging feature is only available on LilyGo hardware
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue