1 Commits

Author SHA1 Message Date
c5c4184d6b balancing update 2024-07-08 17:50:17 +02:00
1149 changed files with 11973 additions and 881498 deletions

54
.gitignore vendored
View File

@ -1,45 +1,9 @@
# ---> KiCad /.vscode/
# For PCBs designed using KiCad: https://www.kicad.org/ /build/
# Format documentation: https://kicad.org/help/file-formats/ /Debug
/.cache/
# Temporary files .clangd
*.000 compile_commands.json
*.bak STM32Make.make
*.bck /.metadata/
*.kicad_pcb-bak openocd.cfg
*.kicad_sch-bak
*-backups
*.kicad_prl
*.sch-bak
*~
_autosave-*
*.tmp
*-save.pro
*-save.kicad_pcb
fp-info-cache
# Netlist files (exported from Eeschema)
*.net
# Autorouter files (exported from Pcbnew)
*.dsn
*.ses
# Exported BOM files
*.xml
*.csv
# ---> VisualStudioCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix

4
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "Software/Core/Lib/can-halal"] [submodule "Core/Lib/can-halal"]
path = Software/Core/Lib/can-halal path = Core/Lib/can-halal
url = ssh://git@git.fasttube.de:313/FaSTTUBe/can-halal.git url = ssh://git@git.fasttube.de:313/FaSTTUBe/can-halal.git

25
.mxproject Normal file

File diff suppressed because one or more lines are too long

View File

@ -47,7 +47,7 @@ struct ADBMS6830_Internal_Status {
typedef struct { typedef struct {
int16_t cellVoltages[MAXIMUM_CELL_VOLTAGES]; int16_t cellVoltages[MAXIMUM_CELL_VOLTAGES];
float auxVoltages[MAXIMUM_AUX_VOLTAGES]; int16_t auxVoltages[MAXIMUM_AUX_VOLTAGES];
struct ADBMS6830_Internal_Status status; struct ADBMS6830_Internal_Status status;
uint16 internalDieTemp; uint16 internalDieTemp;

View File

View File

@ -27,8 +27,8 @@ uint8 calculateDataPEC(uint8* data, uint8 datalen);
uint16 updateDataPEC(uint16 currentPEC, uint8 din); uint16 updateDataPEC(uint16 currentPEC, uint8 din);
uint8 checkDataPEC(uint8* data, uint8 datalen); uint8 checkDataPEC(uint8* data, uint8 datalen);
[[gnu::access(read_only, 2, 3)]] uint8 writeCMD(uint16 command, const uint8* args, uint8 arglen); uint8 writeCMD(uint16 command, uint8* args, uint8 arglen);
[[gnu::access(write_only, 2, 3)]] uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen); uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen);
uint8 pollCMD(uint16 command); uint8 pollCMD(uint16 command);
void mcuAdbmsCSLow(); void mcuAdbmsCSLow();

View File

@ -11,10 +11,12 @@
#include "ADBMS_Abstraction.h" #include "ADBMS_Abstraction.h"
#include "ADBMS_CMD_MAKROS.h" #include "ADBMS_CMD_MAKROS.h"
#include "ADBMS_LL_Driver.h" #include "ADBMS_LL_Driver.h"
#include "can.h"
#include "TMP1075.h"
#include "can-halal.h" #include "can-halal.h"
#include "errors.h" #include "errors.h"
#include "stm32f3xx_hal.h" #include "stm32f3xx_hal.h"
#include <stdbool.h> #include <stdint.h>
typedef enum { typedef enum {
AMSDEACTIVE, AMSDEACTIVE,
@ -29,7 +31,11 @@ typedef enum {
extern amsState currentAMSState; extern amsState currentAMSState;
extern Cell_Module module; extern Cell_Module module;
extern uint32_t balancedCells; extern uint32_t balancedCells;
extern bool BalancingActive; extern uint8_t BalancingActive;
extern uint8_t stateofcharge;
extern uint8_t amserrorcode;
extern uint8_t amswarningcode;
extern uint8_t numberofCells; extern uint8_t numberofCells;
extern uint8_t numberofAux; extern uint8_t numberofAux;
@ -44,4 +50,8 @@ uint8_t AMS_Error_Loop();
uint8_t AMS_Charging_Loop(); uint8_t AMS_Charging_Loop();
uint8_t AMS_Discharging_Loop(); uint8_t AMS_Discharging_Loop();
uint8_t writeWarningLog(uint8_t warningCode);
uint8_t writeErrorLog(uint8_t errorCode);
uint8_t integrateCurrent();
#endif /* INC_AMS_HIGHLEVEL_H_ */ #endif /* INC_AMS_HIGHLEVEL_H_ */

View File

@ -1,21 +1,15 @@
/*
* PWM_control.h
*
* Created on: 07.07.2024
* Author: Hamza
*/
#ifndef INC_PWM_CONTROL_H #ifndef INC_PWM_CONTROL_H
#define INC_PWM_CONTROL_H #define INC_PWM_CONTROL_H
#include "stm32f3xx_hal.h" #include "stm32f3xx_hal.h"
#include "ADBMS_LL_Driver.h"
#include "state_machine.h" #include "state_machine.h"
#include <stdint.h>
#include "main.h"
/* The PWM period (1/FPWM) is defined by the following parameters: /* The PWM period (1/FPWM) is defined by the following parameters:
ARR value, the Prescaler value, and the internal clock itself which drives the timer module FCLK. ARR value, the Prescaler value, and the internal clock itself which drives the timer module FCLK.
F_PWM = (F_CLK)/((ARR + 1) * (PSC + 1)) F_PWM = (F_CLK)/((ARR + 1) * (PSC + 1))
(ARR + 1) * (PSC + 1) = (F_CLK)/(F_PWM)
(PSC + 1) = (F_CLK)/(F_PWM * (ARR + 1))
F_CLK = 16 MHz F_CLK = 16 MHz
@ -25,21 +19,14 @@ DUTY CYCLE = 1/20 -> 0%, DUTY CYCLE = 2/20 -> 100%
CCR * DUTY_CYCLE CCR * DUTY_CYCLE
CCR: 1/20 -> 500, 2/20 -> 1000 CCR: 1/20 -> 500, 2/20 -> 1000
*/ */
// UNUSED
#define POWERGROUND_FREQ 50 #define POWERGROUND_FREQ 50
#define POWERGROUND_PRESCALER 7
#define POWERGROUND_ARR 39999
#define POWERGROUND_MIN_DUTY_CYCLE 0.05
#define POWERGROUND_MAX_DUTY_CYCLE 0.1
//#define BATTERY_COOLING_FREQ 20000 //#define BATTERY_COOLING_FREQ 20000
extern uint8_t current_powerground_status; void PWM_control_init(TIM_HandleTypeDef* powerground, TIM_HandleTypeDef* battery_cooling);
extern uint8_t target_powerground_status;
void PWM_control_init(TIM_HandleTypeDef* pg, TIM_HandleTypeDef* bat_cool, TIM_HandleTypeDef* esc_cool);
void PWM_powerground_softcontrol();
void PWM_powerground_control(uint8_t percent); void PWM_powerground_control(uint8_t percent);
void PWM_battery_cooling_control(uint8_t percent); void PWM_battery_cooling_control(uint8_t percent);
void PWM_set_throttle();
#endif /* INC_CHANNEL_CONTROL_H */ #endif /* INC_CHANNEL_CONTROL_H */

View File

@ -1,14 +1,14 @@
#ifndef INC_TMP1075_H_ #ifndef INC_TMP1075_H_
#define INC_TMP1075_H_ #define INC_TMP1075_H_
#include "can.h"
#include "common_defs.h"
#include "stm32f3xx_hal.h" #include "stm32f3xx_hal.h"
#include "TMP1075.h"
#include "can-halal.h" #include "can-halal.h"
#include "errors.h" #include "errors.h"
#include <stdint.h> #include <stdint.h>
#define N_CELLS 13
#define N_TEMP_SENSORS 13
extern uint32_t tmp1075_failed_sensors; extern uint32_t tmp1075_failed_sensors;
extern int16_t tmp1075_temps[N_TEMP_SENSORS]; extern int16_t tmp1075_temps[N_TEMP_SENSORS];

View File

@ -1,26 +1,20 @@
/*
* can.h
*
* Created on: 07.07.2024
* Author: Hamza
*/
#ifndef INC_CAN_H #ifndef INC_CAN_H
#define INC_CAN_H #define INC_CAN_H
#include "stm32f3xx_hal.h" #include "stm32f3xx_hal.h"
#include "ADBMS_Abstraction.h"
#include "main.h" #include "main.h"
#include "can-halal.h" #include "can-halal.h"
#include "AMS_HighLevel.h"
#include "state_machine.h" #include "state_machine.h"
#include <stdint.h>
extern uint32_t can_status_timer, can_log_timer, can_timeout_timer; #define CAN_ID_IN 0x501
#define CAN_ID_OUT 0x502
#define CAN_STATUS_FREQ 1000
void can_init(CAN_HandleTypeDef* hcan); void can_init(CAN_HandleTypeDef* hcan);
void can_handle_send_status(); void can_handle_send_status();
void can_handle_send_log();
void can_handle_dump();
void can_handle_recieve_command(const uint8_t *data); void can_handle_recieve_command(const uint8_t *data);

14
Core/Inc/common_defs.h Normal file
View File

@ -0,0 +1,14 @@
/*
* common_defs.h
*
* Created on: 23 Mar 2022
* Author: Jasper
*/
#ifndef INC_COMMON_DEFS_H_
#define INC_COMMON_DEFS_H_
#define N_CELLS 12
#define N_TEMP_SENSORS 12
#endif /* INC_COMMON_DEFS_H_ */

View File

@ -12,7 +12,7 @@
#define ERROR_TIME_THRESH 150 // ms #define ERROR_TIME_THRESH 150 // ms
typedef enum : uint16_t { typedef enum {
SEK_OVERTEMP = 0x0, SEK_OVERTEMP = 0x0,
SEK_UNDERTEMP = 0x1, SEK_UNDERTEMP = 0x1,
SEK_OVERVOLT = 0x2, SEK_OVERVOLT = 0x2,
@ -27,7 +27,7 @@ typedef enum : uint16_t {
} SlaveErrorKind; } SlaveErrorKind;
typedef struct { typedef struct {
uint16_t error_sources; int error_sources;
SlaveErrorKind data_kind; SlaveErrorKind data_kind;
uint8_t data[4]; uint8_t data[4];
uint32_t errors_since; uint32_t errors_since;
@ -35,7 +35,7 @@ typedef struct {
extern SlaveErrorData error_data; extern SlaveErrorData error_data;
void set_error_source(SlaveErrorKind source); void set_error_source(int source);
void clear_error_source(SlaveErrorKind source); void clear_error_source(int source);
#endif // INC_ERRORS_H #endif // INC_ERRORS_H

View File

@ -59,40 +59,32 @@ void Error_Handler(void);
/* USER CODE END EFP */ /* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/
#define RELAY_EN_Pin GPIO_PIN_0
#define RELAY_EN_GPIO_Port GPIOA
#define _60V_EN_Pin GPIO_PIN_1
#define _60V_EN_GPIO_Port GPIOA
#define PWM_PG_FAN1_Pin GPIO_PIN_2
#define PWM_PG_FAN1_GPIO_Port GPIOA
#define PWM_PG_FAN2_Pin GPIO_PIN_3
#define PWM_PG_FAN2_GPIO_Port GPIOA
#define CSB_Pin GPIO_PIN_4 #define CSB_Pin GPIO_PIN_4
#define CSB_GPIO_Port GPIOA #define CSB_GPIO_Port GPIOA
#define ESC_L_PWM_Pin GPIO_PIN_0 #define STATUS_LED_R_Pin GPIO_PIN_0
#define ESC_L_PWM_GPIO_Port GPIOB
#define ESC_R_PWM_Pin GPIO_PIN_1
#define ESC_R_PWM_GPIO_Port GPIOB
#define BAT_COOLING_PWM_Pin GPIO_PIN_10
#define BAT_COOLING_PWM_GPIO_Port GPIOB
#define BAT_COOLING_ENABLE_Pin GPIO_PIN_11
#define BAT_COOLING_ENABLE_GPIO_Port GPIOB
#define ESC_COOLING_ENABLE_Pin GPIO_PIN_14
#define ESC_COOLING_ENABLE_GPIO_Port GPIOB
#define ESC_COOLING_PWM_Pin GPIO_PIN_15
#define ESC_COOLING_PWM_GPIO_Port GPIOB
#define EEPROM___WC__Pin GPIO_PIN_8
#define EEPROM___WC__GPIO_Port GPIOA
#define EEPROM_SCL_Pin GPIO_PIN_9
#define EEPROM_SCL_GPIO_Port GPIOA
#define EEPROM_SDA_Pin GPIO_PIN_10
#define EEPROM_SDA_GPIO_Port GPIOA
#define TMP_SCL_Pin GPIO_PIN_15
#define TMP_SCL_GPIO_Port GPIOA
#define RELAY_ENABLE_Pin GPIO_PIN_4
#define RELAY_ENABLE_GPIO_Port GPIOB
#define PRECHARGE_ENABLE_Pin GPIO_PIN_5
#define PRECHARGE_ENABLE_GPIO_Port GPIOB
#define STATUS_LED_R_Pin GPIO_PIN_6
#define STATUS_LED_R_GPIO_Port GPIOB #define STATUS_LED_R_GPIO_Port GPIOB
#define STATUS_LED_G_Pin GPIO_PIN_7 #define STATUS_LED_B_Pin GPIO_PIN_1
#define STATUS_LED_G_GPIO_Port GPIOB
#define STATUS_LED_B_Pin GPIO_PIN_8
#define STATUS_LED_B_GPIO_Port GPIOB #define STATUS_LED_B_GPIO_Port GPIOB
#define TMP_SDA_Pin GPIO_PIN_9 #define STATUS_LED_G_Pin GPIO_PIN_2
#define TMP_SDA_GPIO_Port GPIOB #define STATUS_LED_G_GPIO_Port GPIOB
#define PRECHARGE_EN_Pin GPIO_PIN_11
#define PRECHARGE_EN_GPIO_Port GPIOB
#define PWM_Battery_Cooling_Pin GPIO_PIN_15
#define PWM_Battery_Cooling_GPIO_Port GPIOB
#define RELAY_BATT_SIDE_ON_Pin GPIO_PIN_8
#define RELAY_BATT_SIDE_ON_GPIO_Port GPIOA
#define RELAY_ESC_SIDE_ON_Pin GPIO_PIN_9
#define RELAY_ESC_SIDE_ON_GPIO_Port GPIOA
#define CURRENT_SENSOR_ON_Pin GPIO_PIN_10
#define CURRENT_SENSOR_ON_GPIO_Port GPIOA
/* USER CODE BEGIN Private defines */ /* USER CODE BEGIN Private defines */

View File

@ -1,26 +1,30 @@
/*
* state_machine.h
*
* Created on: 07.07.2024
* Author: Hamza
*/
#ifndef INC_STATE_MACHINE_H #ifndef INC_STATE_MACHINE_H
#define INC_STATE_MACHINE_H #define INC_STATE_MACHINE_H
#include "ADBMS_LL_Driver.h"
#include <AMS_HighLevel.h>
#include <can.h>
#include <eeprom.h>
#include <errors.h>
#include <PWM_control.h>
#include <status_LED.h>
#include <TMP1075.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "ADBMS_LL_Driver.h"
#include "AMS_HighLevel.h"
#include "errors.h"
#include "PWM_control.h"
#include "TMP1075.h"
#include <math.h> #include <math.h>
// Minimum vehicle side voltage to exit precharge
#define MIN_VEHICLE_SIDE_VOLTAGE 150000 // mV
// Time to wait after reaching 95% of battery voltage before exiting precharge
// Set this to 1000 in scruti to demonstrate the voltage on the multimeter
#define PRECHARGE_95_DURATION 0 // ms
// Time to wait for discharge
#define DISCHARGE_DURATION 5000 // ms
// Time to wait after there is no more error condition before exiting TS_ERROR
#define NO_ERROR_TIME 1000 // ms
// Time to wait for charger voltage before going to TS_ERROR
#define MAX_CHARGING_CHECK_DURATION 2000 // ms
// Time to wait between closing relays
#define RELAY_CLOSE_WAIT 10 // ms
#warning
typedef enum { // states -> 3 bit. valid transitions: (all could transition to error) typedef enum { // states -> 3 bit. valid transitions: (all could transition to error)
STATE_INACTIVE, // INACTIVE -> PRECHARGE, CHARGING, ERROR STATE_INACTIVE, // INACTIVE -> PRECHARGE, CHARGING, ERROR
STATE_PRECHARGE, // PRECHARGE -> INACTIVE, READY, DISCHARGE, ERROR STATE_PRECHARGE, // PRECHARGE -> INACTIVE, READY, DISCHARGE, ERROR
@ -33,6 +37,7 @@ typedef enum { // states -> 3 bit. valid transitions: (all could t
} State; } State;
typedef struct { typedef struct {
uint16_t bms_timeout : 1; uint16_t bms_timeout : 1;
uint16_t bms_fault : 1; uint16_t bms_fault : 1;
uint16_t temperature_error : 1; uint16_t temperature_error : 1;
@ -41,8 +46,7 @@ typedef struct {
uint16_t voltage_error : 1; uint16_t voltage_error : 1;
uint16_t voltage_missing : 1; uint16_t voltage_missing : 1;
uint16_t state_transition_fail : 1; uint16_t state_transition_fail : 1;
uint16_t eeprom_error : 1;
uint16_t : 7; // padding
} ErrorKind; } ErrorKind;
//typedef enum {} WarningKind; //typedef enum {} WarningKind;
@ -54,27 +58,17 @@ typedef struct {
ErrorKind error_type; // TSErrorKind ErrorKind error_type; // TSErrorKind
} StateHandle; } StateHandle;
typedef enum { RELAY_MAIN, RELAY_PRECHARGE } Relay;
extern StateHandle state; extern StateHandle state;
extern bool programming_mode; static bool relay_closed = 0;
static bool precharge_closed = 0;
extern int16_t RELAY_BAT_SIDE_VOLTAGE;
extern int16_t RELAY_ESC_SIDE_VOLTAGE;
extern int16_t CURRENT_MEASUREMENT;
extern uint8_t powerground_status;
extern int32_t RELAY_BAT_SIDE_VOLTAGE;
extern int32_t RELAY_ESC_SIDE_VOLTAGE;
extern int32_t CURRENT_MEASUREMENT;
void sm_init(); void sm_init();
void sm_update(); void sm_update();
void sm_handle_ams_in(const uint8 *data);
void sm_precharge_discharge_manager();
void sm_powerground_manager();
void sm_calibrate_powerground();
void sm_balancing();
void sm_eeprom_write_status();
void sm_program_powerground();
void sm_check_errors();
void sm_set_error_source();
State sm_update_inactive(); State sm_update_inactive();
State sm_update_precharge(); State sm_update_precharge();
@ -85,14 +79,18 @@ State sm_update_charging_precharge();
State sm_update_charging(); State sm_update_charging();
State sm_update_error(); State sm_update_error();
typedef enum { RELAY_MAIN, RELAY_PRECHARGE } Relay;
void sm_set_relay_positions(State state); void sm_set_relay_positions(State state);
void sm_set_relay(Relay relay, bool closed); void sm_set_relay(Relay relay, bool closed);
void sm_check_charging();
void sm_check_battery_temperature(int8_t* id, int16_t* temp);
void sm_check_battery_temperature(uint8_t* id, uint16_t* temp);
void sm_check_battery_voltage(uint8_t* id, uint16_t* voltage);
int16_t sm_return_cell_temperature(int id); int16_t sm_return_cell_temperature(int id);
int16_t sm_return_cell_voltage(int id); int16_t sm_return_cell_voltage(int id);
void sm_handle_ams_in(const uint8 *data);
void sm_check_errors();
void sm_set_error(ErrorKind error_kind, bool is_errored);
void sm_test_cycle_states(); void sm_test_cycle_states();
#endif /* "INC_STATE_MACHINE_H" */ #endif /* "INC_STATE_MACHINE_H" */

View File

@ -58,7 +58,7 @@
/*#define HAL_RTC_MODULE_ENABLED */ /*#define HAL_RTC_MODULE_ENABLED */
#define HAL_SPI_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED
#define HAL_TIM_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED
/*#define HAL_UART_MODULE_ENABLED */ #define HAL_UART_MODULE_ENABLED
/*#define HAL_USART_MODULE_ENABLED */ /*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_IRDA_MODULE_ENABLED */ /*#define HAL_IRDA_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */ /*#define HAL_SMARTCARD_MODULE_ENABLED */

1
Core/Lib/can-halal Submodule

Submodule Core/Lib/can-halal added at 8cca72d90d

View File

@ -28,7 +28,7 @@ uint8 amsReset() {
amsStopBalancing(); amsStopBalancing();
amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV); amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV);
const uint8 buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8 buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
CHECK_RETURN(writeCMD(CLRFLAG, buffer, 6)); //clear flags, CHECK_RETURN(writeCMD(CLRFLAG, buffer, 6)); //clear flags,
CHECK_RETURN(writeCMD(CLOVUV, buffer, 6)); //OVUV flags CHECK_RETURN(writeCMD(CLOVUV, buffer, 6)); //OVUV flags
@ -131,7 +131,6 @@ uint8 amsAuxAndStatusMeasurement(Cell_Module* module) {
uint8 amsConfigBalancing(uint32 channels, uint8 dutyCycle) { uint8 amsConfigBalancing(uint32 channels, uint8 dutyCycle) {
uint8 buffer_a[PWM_GROUP_A_SIZE] = {}; uint8 buffer_a[PWM_GROUP_A_SIZE] = {};
uint8 buffer_b[PWM_GROUP_B_SIZE] = {}; uint8 buffer_b[PWM_GROUP_B_SIZE] = {};
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT, NULL, 0)); //start continuous cell voltage measurement with redundancy
CHECK_RETURN(readCMD(RDPWMA, buffer_a, PWM_GROUP_A_SIZE)); CHECK_RETURN(readCMD(RDPWMA, buffer_a, PWM_GROUP_A_SIZE));
CHECK_RETURN(readCMD(RDPWMB, buffer_b, PWM_GROUP_B_SIZE)); CHECK_RETURN(readCMD(RDPWMB, buffer_b, PWM_GROUP_B_SIZE));
@ -202,11 +201,13 @@ uint8 amsCheckUnderOverVoltage(Cell_Module* module) {
} }
uint8 amsClearAux() { uint8 amsClearAux() {
return writeCMD(CLRAUX, NULL, 0); uint8 buffer[6];
return writeCMD(CLRAUX, buffer, 0);
} }
uint8 amsClearCells() { uint8 amsClearCells() {
return writeCMD(CLRCELL, NULL, 0); uint8 buffer[6];
return writeCMD(CLRCELL, buffer, 0);
} }
uint8 amsReadCellVoltages(Cell_Module* module) { uint8 amsReadCellVoltages(Cell_Module* module) {

View File

@ -6,6 +6,7 @@
*/ */
#include "ADBMS_LL_Driver.h" #include "ADBMS_LL_Driver.h"
#include <stdbool.h>
#define INITIAL_COMMAND_PEC 0x0010 #define INITIAL_COMMAND_PEC 0x0010
#define INITIAL_DATA_PEC 0x0010 #define INITIAL_DATA_PEC 0x0010
@ -31,7 +32,7 @@ uint8 calculateCommandPEC(uint8_t* data, uint8_t datalen) {
if (datalen >= 3) { if (datalen >= 3) {
for (int i = 0; i < (datalen - 2); i++) { for (int i = 0; i < (datalen - 2); i++) {
for (int n = 0; n < 8; n++) { for (int n = 0; n < 8; n++) {
const uint8 din = data[i] << (n); uint8 din = data[i] << (n);
currentpec = updateCommandPEC(currentpec, din); currentpec = updateCommandPEC(currentpec, din);
} }
} }
@ -53,13 +54,13 @@ uint8 checkCommandPEC(uint8* data, uint8 datalen) {
for (int i = 0; i < (datalen - 2); i++) { for (int i = 0; i < (datalen - 2); i++) {
for (int n = 0; n < 8; n++) { for (int n = 0; n < 8; n++) {
const uint8 din = data[i] << (n); uint8 din = data[i] << (n);
currentpec = updateCommandPEC(currentpec, din); currentpec = updateCommandPEC(currentpec, din);
} }
} }
const uint8 pechigh = (currentpec >> 7) & 0xFF; uint8 pechigh = (currentpec >> 7) & 0xFF;
const uint8 peclow = (currentpec << 1) & 0xFF; uint8 peclow = (currentpec << 1) & 0xFF;
if ((pechigh == data[datalen - 2]) && (peclow == data[datalen - 1])) { if ((pechigh == data[datalen - 2]) && (peclow == data[datalen - 1])) {
return 0; return 0;
@ -70,13 +71,13 @@ uint8 checkCommandPEC(uint8* data, uint8 datalen) {
uint16 updateCommandPEC(uint16 currentPEC, uint8 din) { uint16 updateCommandPEC(uint16 currentPEC, uint8 din) {
din = (din >> 7) & 0x01; din = (din >> 7) & 0x01;
const uint8 in0 = din ^ ((currentPEC >> 14) & 0x01); uint8 in0 = din ^ ((currentPEC >> 14) & 0x01);
const uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01); uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
const uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01); uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01);
const uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01); uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
const uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01); uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01);
const uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01); uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01);
const uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01); uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01);
uint16 newPEC = 0; uint16 newPEC = 0;
@ -103,9 +104,9 @@ uint16 updateCommandPEC(uint16 currentPEC, uint8 din) {
//CRC-10 //CRC-10
//x^10 + x^7 + x^3 + x^2 + x + 1 //x^10 + x^7 + x^3 + x^2 + x + 1
uint16_t pec10_calc(bool rx_cmd, int len, const uint8_t* data) { uint16_t pec10_calc(bool rx_cmd, int len, uint8_t* data) {
uint16_t remainder = 16; /* PEC_SEED; 0000010000 */ uint16_t remainder = 16; /* PEC_SEED; 0000010000 */
const uint16_t polynom = 0x8F; /* x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial uint16_t polynom = 0x8F; /* x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial
100 1000 1111 48F */ 100 1000 1111 48F */
/* Perform modulo-2 division, a byte at a time. */ /* Perform modulo-2 division, a byte at a time. */
@ -149,13 +150,16 @@ crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes);
uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) { uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) {
if (datalen >= 3) { if (datalen >= 3) {
const crc currentpec = pec10_calc(true, datalen - 2, data) & 0x3FF; // mask to 10 bits crc currentpec = pec10_calc(true, datalen - 2, data) & 0x3FF; // mask to 10 bits
// memory layout is [[zeroes], PEC[9:8]], [PEC[7:0]] // memory layout is [[zeroes], PEC[9:8]], [PEC[7:0]]
data[datalen - 2] = (currentpec >> 8) & 0xFF; data[datalen - 2] = (currentpec >> 8) & 0xFF;
data[datalen - 1] = currentpec & 0xFF; data[datalen - 1] = currentpec & 0xFF;
volatile uint8 result = pec10_calc(true, datalen, data);
return 0; return 0;
} else { } else {
return 1; return 1;
@ -167,7 +171,7 @@ uint8 checkDataPEC(uint8* data, uint8 len) {
return 255; return 255;
} }
const crc currentpec = F_CRC_CalculaCheckSum(data, len); crc currentpec = F_CRC_CalculaCheckSum(data, len);
return (currentpec == 0) ? 0 : 1; return (currentpec == 0) ? 0 : 1;
} }
@ -209,10 +213,10 @@ crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes) {
uint16 updateDataPEC(uint16 currentPEC, uint8 din) { uint16 updateDataPEC(uint16 currentPEC, uint8 din) {
din = (din >> 7) & 0x01; din = (din >> 7) & 0x01;
const uint8 in0 = din ^ ((currentPEC >> 9) & 0x01); uint8 in0 = din ^ ((currentPEC >> 9) & 0x01);
const uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01); uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01);
const uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01); uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
const uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01); uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
uint16 newPEC = 0; uint16 newPEC = 0;
@ -229,7 +233,7 @@ uint16 updateDataPEC(uint16 currentPEC, uint8 din) {
return newPEC; return newPEC;
} }
uint8 writeCMD(uint16 command, const uint8 * args, uint8 arglen) { uint8 writeCMD(uint16 command, uint8* args, uint8 arglen) {
uint8 ret; uint8 ret;
if (arglen > 0) { if (arglen > 0) {
uint8 buffer[6 + arglen]; //command + PEC (2 bytes) + data + DPEC (2 bytes) uint8 buffer[6 + arglen]; //command + PEC (2 bytes) + data + DPEC (2 bytes)
@ -263,9 +267,23 @@ uint8 writeCMD(uint16 command, const uint8 * args, uint8 arglen) {
return ret; return ret;
} }
uint8 readCMD(uint16 command, uint8 * buffer, uint8 buflen) { #define ITER_COUNT 50
uint8 txbuffer[6 + buflen]; static uint8_t count = 0;
uint8 rxbuffer[6 + buflen]; static bool isOn = false;
uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen) {
if (count == ITER_COUNT) {
HAL_GPIO_WritePin(STATUS_LED_B_GPIO_Port, STATUS_LED_B_Pin, isOn ? GPIO_PIN_SET : GPIO_PIN_RESET);
count = 0;
isOn = !isOn;
} else {
count++;
}
uint8 txbuffer[6 + buflen] = {};
uint8 rxbuffer[6 + buflen] = {};
txbuffer[0] = (command >> 8) & 0xFF; txbuffer[0] = (command >> 8) & 0xFF;
txbuffer[1] = (command)&0xFF; txbuffer[1] = (command)&0xFF;
@ -318,22 +336,25 @@ void mcuAdbmsCSHigh() {
} }
uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize) { uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize) {
uint8 rxbuf[buffersize]; HAL_StatusTypeDef status;
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize, uint8 rxbuf[buffersize];
ADBMS_SPI_TIMEOUT); status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize,
ADBMS_SPI_TIMEOUT);
__HAL_SPI_CLEAR_OVRFLAG(adbmsspi); __HAL_SPI_CLEAR_OVRFLAG(adbmsspi);
return status; return status;
} }
uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize) { uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize) {
const HAL_StatusTypeDef status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT); HAL_StatusTypeDef status;
status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
return status; return status;
} }
uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer, uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer,
uint8 buffersize) { uint8 buffersize) {
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize, HAL_StatusTypeDef status;
ADBMS_SPI_TIMEOUT); status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize,
ADBMS_SPI_TIMEOUT);
return status; return status;
} }

313
Core/Src/AMS_HighLevel.c Normal file
View File

@ -0,0 +1,313 @@
/*
* AMS_HighLevel.c
*
* Created on: 20.07.2022
* Author: max
*/
#include "AMS_HighLevel.h"
Cell_Module module = {};
uint32_t balancedCells = 0;
uint8_t BalancingActive = 0;
uint8_t stateofcharge = 100;
int64_t currentintegrator = 0;
uint32_t lastticks = 0;
uint32_t currenttick = 0;
uint8_t eepromconfigured = 0;
uint8_t internalbalancingalgo = 1;
uint16_t startbalancingthreshold = 41000;
uint16_t stopbalancingthreshold = 30000;
uint16_t balancingvoltagedelta = 10;
uint16_t amsuv = 0;
uint16_t amsov = 0;
uint8_t amserrorcode = 0;
uint8_t amswarningcode = 0;
uint8_t numberofCells = 14;
uint8_t numberofAux = 0;
uint8_t packetChecksumFails = 0;
#define MAX_PACKET_CHECKSUM_FAILS 5
uint8_t deviceSleeps = 0;
#define MAX_DEVICE_SLEEP 3 //TODO: change to correct value
amsState currentAMSState = AMSDEACTIVE;
amsState lastAMSState = AMSDEACTIVE;
struct pollingTimes {
uint32_t S_ADC_OW_CHECK;
uint32_t TMP1075;
};
struct pollingTimes pollingTimes = {0, 0};
void AMS_Init(SPI_HandleTypeDef* hspi) {
if (eepromconfigured == 1) {
/*amsov = eepromcellovervoltage>>4;
amsuv = (eepromcellundervoltage-1)>>4;
numberofCells = eepromnumofcells;
numberofAux = eepromnumofaux;
initAMS(hspi, eepromnumofcells, eepromnumofaux);*/
amsConfigOverUnderVoltage(amsov, amsuv);
} else {
initAMS(hspi, numberofCells, numberofAux);
amsov = DEFAULT_OV;
amsuv = DEFAULT_UV;
}
pollingTimes = (struct pollingTimes) {HAL_GetTick(), HAL_GetTick()};
currentAMSState = AMSIDLE;
}
void AMS_Loop() {
// On Transition Functions called ones if the State Changed
if (currentAMSState != lastAMSState) {
switch (currentAMSState) {
case AMSIDLE:
break;
case AMSDEACTIVE:
break;
case AMSCHARGING:
break;
case AMSIDLEBALANCING:
break;
case AMSDISCHARGING:
break;
case AMSWARNING:
writeWarningLog(0x01);
break;
case AMSERROR:
writeErrorLog(amserrorcode);
break;
}
lastAMSState = currentAMSState;
}
// Main Loops for different AMS States
switch (currentAMSState) {
case AMSIDLE:
AMS_Idle_Loop();
break;
case AMSDEACTIVE:
break;
case AMSCHARGING:
break;
case AMSIDLEBALANCING:
AMS_Idle_Loop();
break;
case AMSDISCHARGING:
break;
case AMSWARNING:
AMS_Warning_Loop();
break;
case AMSERROR:
break;
}
}
uint8_t AMS_Idle_Loop() {
if (!amsWakeUp()) {
//error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT;
//set_error_source(ERROR_SOURCE_INTERNAL);
}
packetChecksumFails += amsAuxAndStatusMeasurement(&module);
if (module.status.SLEEP) {
deviceSleeps++;
if (deviceSleeps > MAX_DEVICE_SLEEP) {
error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT;
set_error_source(ERROR_SOURCE_INTERNAL);
} else {
amsReset();
}
}
if (module.status.CS_FLT || module.status.SPIFLT || module.status.CMED ||
module.status.SMED || module.status.VDE || module.status.VDEL ||
module.status.OSCCHK || module.status.TMODCHK) {
error_data.data_kind = SEK_INTERNAL_BMS_FAULT;
set_error_source(ERROR_SOURCE_INTERNAL);
}
if (module.status.THSD) {
error_data.data_kind = SEK_INTERNAL_BMS_OVERTEMP;
set_error_source(ERROR_SOURCE_INTERNAL);
}
packetChecksumFails += amsCellMeasurement(&module);
packetChecksumFails += amsCheckUnderOverVoltage(&module);
packetChecksumFails += integrateCurrent();
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
error_data.data_kind = SEK_INTERNAL_BMS_CHECKSUM_FAIL;
set_error_source(ERROR_SOURCE_INTERNAL);
}
tmp1075_measure();
int any_voltage_error = 0;
for (size_t i = 0; i < numberofCells; i++) {
if (module.cellVoltages[i] < 2500) {
any_voltage_error = 1;
error_data.data_kind = SEK_UNDERVOLT;
error_data.data[0] = i;
uint8_t* ptr = &error_data.data[1];
ptr = ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
} else if (module.cellVoltages[i] > 4200) {
any_voltage_error = 1;
error_data.data_kind = SEK_OVERVOLT;
error_data.data[0] = i;
uint8_t* ptr = &error_data.data[1];
ptr = ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
}
}
if (module.internalDieTemp > 28000) { //TODO: change to correct value
error_data.data_kind = SEK_INTERNAL_BMS_OVERTEMP;
uint8_t* ptr = &error_data.data[0];
ptr = ftcan_marshal_unsigned(ptr, module.internalDieTemp, 2);
set_error_source(ERROR_SOURCE_INTERNAL);
} else {
clear_error_source(ERROR_SOURCE_INTERNAL);
}
if (any_voltage_error) {
set_error_source(ERROR_SOURCE_VOLTAGES);
} else {
clear_error_source(ERROR_SOURCE_VOLTAGES);
}
mcuDelay(10);
return 0;
}
uint8_t AMS_Warning_Loop() {
amsWakeUp();
amsConfigOverUnderVoltage(amsov, amsuv);
amsClearAux();
amsCellMeasurement(&module);
amsAuxAndStatusMeasurement(&module);
amsCheckUnderOverVoltage(&module);
if (!(module.overVoltage | module.underVoltage)) {
currentAMSState = AMSIDLE;
// amsClearWarning();
}
amsStopBalancing();
return 0;
}
uint8_t AMS_Error_Loop() { return 0; }
uint8_t AMS_Charging_Loop() { return 0; }
uint8_t AMS_Discharging_Loop() { return 0; }
uint8_t AMS_Balancing_Loop() {
uint8_t balancingdone = 1;
if ((eepromconfigured == 1) && (internalbalancingalgo == 1) &&
(module.internalDieTemp <
28000 /*Thermal Protection 93°C*/)) // If the EEPROM is configured and
// the internal Balancing Algorithm
// should be used
{
uint16_t highestcellvoltage = module.cellVoltages[0];
uint16_t lowestcellvoltage = module.cellVoltages[0];
uint8_t highestcell = 0;
uint8_t lowestcell = 0;
for (uint8_t n = 0; n < numberofCells; n++) {
if (module.cellVoltages[n] > highestcellvoltage) {
highestcellvoltage = module.cellVoltages[n];
highestcell = n;
}
if (module.cellVoltages[n] < lowestcellvoltage) {
lowestcellvoltage = module.cellVoltages[n];
lowestcell = n;
}
}
if (currentAMSState ==
AMSCHARGING) // Balancing is only Active if the BMS is in Charging Mode
{
uint32_t channelstobalance = 0;
if (highestcellvoltage > startbalancingthreshold) {
for (uint8_t n = 0; n < numberofCells; n++) {
if (module.cellVoltages[n] > stopbalancingthreshold) {
uint16_t dv = module.cellVoltages[n] - lowestcellvoltage;
if (dv > (balancingvoltagedelta * 1000)) {
balancingdone = 0;
channelstobalance |= 1 << n;
}
}
}
}
amsConfigBalancing(channelstobalance, 0x0F);
amsStartBalancing(100);
}
else if (currentAMSState == AMSIDLEBALANCING) {
uint32_t channelstobalance = 0;
if (lowestcellvoltage <
stopbalancingthreshold) // If under Voltage of one Cell is reached
{
amsStopBalancing();
balancingdone = 1;
} else // otherwise continue with regular Balancing Algorithm
{
for (uint8_t n = 0; n < numberofCells; n++) {
uint16_t dv = module.cellVoltages[n] - lowestcellvoltage;
if (dv > balancingvoltagedelta) {
balancingdone = 0;
channelstobalance |= 1 << n;
}
}
amsConfigBalancing(channelstobalance, 0x0F);
amsStartBalancing(100);
}
}
} else {
amsStopBalancing();
balancingdone = 1;
}
return balancingdone;
}
uint8_t writeWarningLog(uint8_t warningCode) {
// eepromWriteWarningLog(warningCode);
return 0;
}
uint8_t writeErrorLog(uint8_t errorCode) {
// eepromWriteErrorLog(errorCode);
return 0;
}
uint8_t integrateCurrent() {
lastticks = currenttick;
currenttick = HAL_GetTick();
if (currenttick < lastticks) {
currentintegrator += (module.auxVoltages[0] - module.auxVoltages[2]) *
(currenttick - lastticks);
}
return 0;
}

63
Core/Src/PWM_control.c Normal file
View File

@ -0,0 +1,63 @@
#include "PWM_control.h"
#include "stm32f3xx_hal.h"
#include <stdint.h>
uint8_t battery_cooling_status;
//uint32_t powerground1_CCR, powerground2_CCR, battery_cooling_CCR;
TIM_HandleTypeDef* powerground, *battery_cooling;
/*
Pulse width modulation mode allows for generating a signal with a frequency determined by
the value of the TIMx_ARR register and a duty cycle determined by the value of the TIMx_CCRx register.
*/
void PWM_control_init(TIM_HandleTypeDef* pg, TIM_HandleTypeDef* bat_cool){
powerground_status = 0;
battery_cooling_status = 0;
powerground = pg;
battery_cooling = bat_cool;
HAL_TIM_PWM_Start(pg, TIM_CHANNEL_1); //TIM15CH1
HAL_TIM_PWM_Start(pg, TIM_CHANNEL_2); //TIM15CH2
HAL_TIM_PWM_Start(bat_cool, TIM_CHANNEL_3); //TIM1CH3
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_1, 0);
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_2, 0);
//PWM_powerground_control(0);
//__HAL_TIM_SET_COMPARE(battery_cooling, TIM_CHANNEL_3, 2000);
}
/*
controls the duty cycle of the fans by setting the CCR of the channel percent/100 = x/ARR
DUTYCYCLE = 40000 * X/100
*/
void PWM_powerground_control(uint8_t percent){
if (percent > 100) //something went wrong
return;
powerground_status = percent;
int ccr = 2000 + ((2000) * (percent/100.0));
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_1, ccr);
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_2, ccr);
//TIM15->CCR1 = (TIM15->ARR*POWERGROUND_MAX_DUTY_CYCLE-TIM15->ARR*POWERGROUND_MIN_DUTY_CYCLE) * (percent/100.0) + TIM15->ARR*POWERGROUND_MIN_DUTY_CYCLE;
}
void PWM_set_throttle(){
uint32_t timestamp = HAL_GetTick() + 5000;
while (timestamp > HAL_GetTick()) {}
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_1, 4000);
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_2, 4000);
timestamp = HAL_GetTick() + 2000;
while (timestamp > HAL_GetTick()) {}
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_1, 2000);
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_2, 2000);
timestamp = HAL_GetTick() + 1000;
while (timestamp > HAL_GetTick()) {}
}
void PWM_battery_cooling_control(uint8_t percent){}

View File

@ -1,13 +1,8 @@
#include "TMP1075.h" #include "TMP1075.h"
#include "state_machine.h"
#define MAX_TEMP_DISCHARGING ((int16_t)(59 / 0.0625f)) #define MAX_TEMP ((int16_t)(59 / 0.0625f))
#define MIN_TEMP_DISCHARGING ((int16_t)(-20 / 0.0625f)) #define MAX_FAILED_TEMP 12 //TODO: change value for compliance with the actual number of sensors
#define MAX_TEMP_CHARGING ((int16_t)(45 / 0.0625f)) #warning "change value for compliance with the actual number of sensors"
#define MIN_TEMP_CHARGING ((int16_t)(0 / 0.0625f))
#define MAX_FAILED_TEMP 2 //TODO: change value for compliance with the actual number of sensors
// TODO: "change value for compliance with the actual number of sensors", change temps to float
int16_t tmp1075_temps[N_TEMP_SENSORS] = {0}; int16_t tmp1075_temps[N_TEMP_SENSORS] = {0};
uint32_t tmp1075_failed_sensors = 0; uint32_t tmp1075_failed_sensors = 0;
@ -38,36 +33,19 @@ HAL_StatusTypeDef tmp1075_measure() {
int err = 0; int err = 0;
int temp_error = 0; int temp_error = 0;
for (int i = 0; i < N_TEMP_SENSORS; i++) { for (int i = 0; i < N_TEMP_SENSORS; i++) {
if (tmp1075_sensor_read(i, &tmp1075_temps[i]) != HAL_OK || (tmp1075_temps[i] & 0x000F) != 0) { if (tmp1075_sensor_read(i, &tmp1075_temps[i]) != HAL_OK ||
(tmp1075_temps[i] & 0x000F) != 0) {
tmp1075_failed_sensors |= 1 << i; tmp1075_failed_sensors |= 1 << i;
nfailed_temp_sensors++; nfailed_temp_sensors++;
err = 1; err = 1;
} else { } else {
tmp1075_temps[i] >>= 4; tmp1075_temps[i] >>= 4;
tmp1075_failed_sensors &= ~(1 << i); tmp1075_failed_sensors &= ~(1 << i);
if (state.current_state == STATE_CHARGING || state.current_state == STATE_CHARGING_PRECHARGE){ if (tmp1075_temps[i] >= MAX_TEMP) {
if (tmp1075_temps[i] >= MAX_TEMP_CHARGING) { temp_error = 1;
temp_error = 1; handle_over_maxtemp(i, tmp1075_temps[i]);
handle_over_maxtemp(i, tmp1075_temps[i]);
}
} else {
if (tmp1075_temps[i] >= MAX_TEMP_DISCHARGING) {
temp_error = 1;
handle_over_maxtemp(i, tmp1075_temps[i]);
}
}
if (state.current_state == STATE_CHARGING || state.current_state == STATE_CHARGING_PRECHARGE){
if (tmp1075_temps[i] <= MIN_TEMP_CHARGING) {
temp_error = 1;
handle_over_maxtemp(i, tmp1075_temps[i]);
}
} else {
if (tmp1075_temps[i] <= MIN_TEMP_DISCHARGING) {
temp_error = 1;
handle_over_maxtemp(i, tmp1075_temps[i]);
}
} }
#warning "check for under temp"
} }
} }
if (nfailed_temp_sensors > MAX_FAILED_TEMP) { if (nfailed_temp_sensors > MAX_FAILED_TEMP) {

150
Core/Src/can.c Normal file
View File

@ -0,0 +1,150 @@
/*
* can.c
* Created on: Mai 23, 2024
* Author: Hamza
*/
#include "can.h"
//#define CAN_ID_IN 0x501
//#define CAN_ID_OUT 0x502
int can_delay_manager = 0;
void can_init(CAN_HandleTypeDef* hcan) {
ftcan_init(hcan);
ftcan_add_filter(CAN_ID_IN, 0xFFF);
}
/*
This function sends the status of the mvbms, the battery and of powerground.
once every 1s in states: INACTIVE, PRECHARGE, DISCHARGE, CHARGING, ERROR.
once every 0.5s in states: READY, ACTIVE.
with format of:
CAN Messages:
Error bit
MVBMS state
Powerground Status 0-100%
Errors
Battery state of charge
Pack Voltage
Current
Battery temperature (12 bit)
Min/Max. Cell Temp (ID, Min Temp, ID, Max Temp)(3B),
Min/Max Cell Voltage (ID, Min Voltage, ID, Max Voltage)(3B)
bit 0 (1b): empty
bit 1-3 (3b): state
bit 4-11 (8b): powerground status
bit 12-19 (8b): error
bit 20-27 (8b): state of charge from 0-100%
bit 28-39 (12b): battery voltage
bit 40-51 (12b): current measurement
bit 52-63 (12b): temperature of the cell with highest temperature
bit 0-3 (4b): ID of the sensor with highest temperature
bit 4-7 (4b): ID of the sensor with lowest temperataure
bit 8-19 (12b): temperature of the coldest cell
bit 20-23 (4b): ID of the cell with the lowest voltage
bit 24-35 (12b): lowest cell voltage
bit 36-39 (4b): ID of the cell the the highest voltage
bit 40-51 (12b): highest cell voltage
bit 52-63 (12b): empty
*/
void can_handle_send_status() {
if (can_delay_manager > HAL_GetTick())
return;
else
can_delay_manager = HAL_GetTick() + CAN_STATUS_FREQ;
uint8_t data[8] = {};
int8_t id_highest_temp = -1;
int16_t highest_temp = INT16_MIN;
sm_check_battery_temperature(&id_highest_temp, &highest_temp);
data[0] = ((state.current_state << 4) | (powerground_status >> 4)); // 1 bit emptyy | 3 bit state | 4 bit powerground
data[1] = ((powerground_status << 4) | (state.error_source >> 4)); // 4 bit powerground | 4 bit error
data[2] = ((state.error_source << 4) | (0)); // 4 bit error | 4 bit state of charge
data[3] = ((0) + (RELAY_BAT_SIDE_VOLTAGE >> 12)); // 4 bit state of charge | 4 bit battery voltage
data[4] = ((RELAY_BAT_SIDE_VOLTAGE >> 4));
data[5] = ((CURRENT_MEASUREMENT >> 8));
data[6] = ((CURRENT_MEASUREMENT & 0x00F0) | (highest_temp >> 12));
data[7] = ((highest_temp) >> 4);
ftcan_transmit(CAN_ID_OUT, data, sizeof(data));
int8_t id_lowest_temp = -1;
int16_t lowest_temp = INT16_MIN;
for (int i = 0; i < N_TEMP_SENSORS; i++) {
if (tmp1075_temps[i] < lowest_temp){
id_lowest_temp = i;
lowest_temp = tmp1075_temps[i];
}
}
int8_t id_lowest_volt = -1;
int16_t lowest_volt = INT16_MIN;
int8_t id_highest_volt = -1;
int16_t highest_volt = INT16_MIN;
for (int i = 0; i < module.sumOfCellMeasurements; i++) {
if (sm_return_cell_voltage(i) < lowest_temp){
id_lowest_volt = i;
lowest_volt = sm_return_cell_voltage(i);
}
if (sm_return_cell_voltage(i) > highest_temp){
id_highest_volt = i;
highest_volt = sm_return_cell_voltage(i);
}
}
data[0] = ((id_highest_temp & 0x0F) << 4 | (id_lowest_temp & 0x0F));
data[1] = ((lowest_temp) >> 8);
data[2] = ((lowest_temp & 0x00F0) | (id_lowest_volt & 0x0F));
data[3] = (lowest_volt >> 8);
data[4] = ((lowest_volt & 0x00F0) | (id_highest_volt & 0x0F));
data[5] = ((highest_volt >> 8));
data[6] = ((highest_volt & 0x00F0));
data[7] = 0;
ftcan_transmit(CAN_ID_OUT, data, sizeof(data));
}
/*
can_handle_recieve_command() should only check if the message is valid and then hand it
to the sm_handle_ams_in() which handles the state machine transition.
This function recieves a command from the Autobox with the CAN ID of 0x501.
with format of:
data[0] = target state
0x0 STATE_INACTIVE | disconnect power to the ESC of powerground. Send it to return the mvbms to idle/monitoring mode. If data[1] != 0 -> assume bad CAN message.
0x1 STATE_READY | conneect power to the ESC of powerground and but with no PWM signal. If data[1] != 0 -> assume bad CAN message.
0x2 STATE_ACTIVE | activate powerground at (data[1]) percent. If data[1] > 100 -> assume bad CAN message.
allowed transitions:
STATE_INACTIVE -> STATE_READY
STATE_READY -> STATE_INACTIVE, STATE_ACTIVE
STATE_ACTIVE -> STATE_INACTIVE, STATE_READY
*/
void can_handle_recieve_command(const uint8_t *data){
if (data[0] == 0x00 && data[1] == 0x00){
sm_handle_ams_in(data);
} else if (data[0] == 0x01 && data[1] == 0x00){
sm_handle_ams_in(data);
} else if (data[0] == 0x02 && data[1] <= 100) {
sm_handle_ams_in(data);
}
}
/*
implements the _weak method ftcan_msg_recieved_cb() which throws an interrupt when a CAN message is recieved.
it only checks if the id is and datalen is correct thans hands data over to can_handle_recieve_command().
in MXCUBE under CAN NVIC settings "USB low priority or CAN_RX0 interrupts" has to be on
*/
void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t *data){
if (id == 0x501 && datalen == 2){
can_handle_recieve_command(data);
}
}

13
Core/Src/errors.c Normal file
View File

@ -0,0 +1,13 @@
#include "errors.h"
#include "stm32f3xx_hal.h"
SlaveErrorData error_data;
void set_error_source(int source) {
if (!error_data.error_sources) {
error_data.errors_since = HAL_GetTick();
}
error_data.error_sources |= source;
}
void clear_error_source(int source) { error_data.error_sources &= ~source; }

View File

@ -26,10 +26,7 @@
#include "PWM_control.h" #include "PWM_control.h"
#include "can.h" #include "can.h"
#include "AMS_HighLevel.h" #include "AMS_HighLevel.h"
#include "soc_estimation.h"
#include "state_machine.h" #include "state_machine.h"
#include <status_LED.h>
#include <stdint.h>
#include "TMP1075.h" #include "TMP1075.h"
#include "errors.h" #include "errors.h"
#include "stm32f302xc.h" #include "stm32f302xc.h"
@ -50,26 +47,20 @@
/* Private macro -------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */ /* USER CODE BEGIN PM */
// htim2 CH3,4 BAT_COOLING_PWM,ENABLE
// htim3 CH3,4 ESC_L_PWM,R_PWM
// htim4 CH1,2,3 LED R,G,B
// htim15 CH1,2 ESC_COOLING_ENABLE,PWM
/* USER CODE END PM */ /* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan; CAN_HandleTypeDef hcan;
I2C_HandleTypeDef hi2c1; I2C_HandleTypeDef hi2c1;
I2C_HandleTypeDef hi2c2;
SPI_HandleTypeDef hspi1; SPI_HandleTypeDef hspi1;
TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
TIM_HandleTypeDef htim15; TIM_HandleTypeDef htim15;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */ /* USER CODE BEGIN PV */
/* USER CODE END PV */ /* USER CODE END PV */
@ -81,10 +72,8 @@ static void MX_CAN_Init(void);
static void MX_I2C1_Init(void); static void MX_I2C1_Init(void);
static void MX_SPI1_Init(void); static void MX_SPI1_Init(void);
static void MX_TIM15_Init(void); static void MX_TIM15_Init(void);
static void MX_I2C2_Init(void); static void MX_USART1_UART_Init(void);
static void MX_TIM2_Init(void); static void MX_TIM1_Init(void);
static void MX_TIM3_Init(void);
static void MX_TIM4_Init(void);
/* USER CODE BEGIN PFP */ /* USER CODE BEGIN PFP */
/* USER CODE END PFP */ /* USER CODE END PFP */
@ -127,23 +116,15 @@ int main(void)
MX_I2C1_Init(); MX_I2C1_Init();
MX_SPI1_Init(); MX_SPI1_Init();
MX_TIM15_Init(); MX_TIM15_Init();
MX_I2C2_Init(); MX_USART1_UART_Init();
MX_TIM2_Init(); MX_TIM1_Init();
MX_TIM3_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */ /* USER CODE BEGIN 2 */
sm_init(); sm_init();
tmp1075_init(&hi2c1); tmp1075_init(&hi2c1);
AMS_Init(&hspi1); AMS_Init(&hspi1);
can_init(&hcan); can_init(&hcan);
PWM_control_init(&htim3, &htim2, &htim15); PWM_control_init(&htim15, &htim1);
soc_init(); HAL_Delay(10);
status_led_init(&htim4, &htim4, &htim4);
sm_program_powerground();
eeprom_init(&hi2c2);
AMS_Loop();
uint32_t startup_timer = 500 + HAL_GetTick();
while (startup_timer > HAL_GetTick());
/* USER CODE END 2 */ /* USER CODE END 2 */
/* Infinite loop */ /* Infinite loop */
@ -156,6 +137,7 @@ int main(void)
AMS_Loop(); AMS_Loop();
sm_update(); sm_update();
//sm_test_cycle_states(); //sm_test_cycle_states();
can_handle_send_status();
} }
/* USER CODE END 3 */ /* USER CODE END 3 */
} }
@ -173,9 +155,10 @@ void SystemClock_Config(void)
/** Initializes the RCC Oscillators according to the specified parameters /** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure. * in the RCC_OscInitTypeDef structure.
*/ */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{ {
@ -195,9 +178,11 @@ void SystemClock_Config(void)
{ {
Error_Handler(); Error_Handler();
} }
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_I2C2; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK; |RCC_PERIPHCLK_TIM1;
PeriphClkInit.I2c2ClockSelection = RCC_I2C2CLKSOURCE_SYSCLK; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
PeriphClkInit.Tim1ClockSelection = RCC_TIM1CLK_HCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{ {
Error_Handler(); Error_Handler();
@ -257,7 +242,7 @@ static void MX_I2C1_Init(void)
/* USER CODE END I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1; hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00303D5B; hi2c1.Init.Timing = 0x2000090E;
hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
@ -289,54 +274,6 @@ static void MX_I2C1_Init(void)
} }
/**
* @brief I2C2 Initialization Function
* @param None
* @retval None
*/
static void MX_I2C2_Init(void)
{
/* USER CODE BEGIN I2C2_Init 0 */
/* USER CODE END I2C2_Init 0 */
/* USER CODE BEGIN I2C2_Init 1 */
/* USER CODE END I2C2_Init 1 */
hi2c2.Instance = I2C2;
hi2c2.Init.Timing = 0x00303D5B;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C2_Init 2 */
/* USER CODE END I2C2_Init 2 */
}
/** /**
* @brief SPI1 Initialization Function * @brief SPI1 Initialization Function
* @param None * @param None
@ -378,165 +315,72 @@ static void MX_SPI1_Init(void)
} }
/** /**
* @brief TIM2 Initialization Function * @brief TIM1 Initialization Function
* @param None * @param None
* @retval None * @retval None
*/ */
static void MX_TIM2_Init(void) static void MX_TIM1_Init(void)
{ {
/* USER CODE BEGIN TIM2_Init 0 */ /* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM2_Init 0 */ /* USER CODE END TIM1_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0}; TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM2_Init 1 */ /* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM2_Init 1 */ /* USER CODE END TIM1_Init 1 */
htim2.Instance = TIM2; htim1.Instance = TIM1;
htim2.Init.Prescaler = 0; htim1.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 4294967295; htim1.Init.Period = 65535;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; htim1.Init.RepetitionCounter = 0;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{ {
Error_Handler(); Error_Handler();
} }
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{ {
Error_Handler(); Error_Handler();
} }
sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{ {
Error_Handler(); Error_Handler();
} }
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{ {
Error_Handler(); Error_Handler();
} }
/* USER CODE BEGIN TIM2_Init 2 */ /* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM2_Init 2 */ /* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim2); HAL_TIM_MspPostInit(&htim1);
}
/**
* @brief TIM3 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 7;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 39999;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
/**
* @brief TIM4 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 624;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 255;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
HAL_TIM_MspPostInit(&htim4);
} }
@ -560,9 +404,9 @@ static void MX_TIM15_Init(void)
/* USER CODE END TIM15_Init 1 */ /* USER CODE END TIM15_Init 1 */
htim15.Instance = TIM15; htim15.Instance = TIM15;
htim15.Init.Prescaler = 0; htim15.Init.Prescaler = 7;
htim15.Init.CounterMode = TIM_COUNTERMODE_UP; htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
htim15.Init.Period = 65535; htim15.Init.Period = 39999;
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim15.Init.RepetitionCounter = 0; htim15.Init.RepetitionCounter = 0;
htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
@ -610,6 +454,41 @@ static void MX_TIM15_Init(void)
} }
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 38400;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/** /**
* @brief GPIO Initialization Function * @brief GPIO Initialization Function
* @param None * @param None
@ -628,10 +507,13 @@ static void MX_GPIO_Init(void)
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */ /*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, CSB_Pin|EEPROM___WC__Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, RELAY_EN_Pin|_60V_EN_Pin|CSB_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */ /*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, RELAY_ENABLE_Pin|PRECHARGE_ENABLE_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, STATUS_LED_R_Pin|STATUS_LED_B_Pin|STATUS_LED_G_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PC13 PC14 PC15 */ /*Configure GPIO pins : PC13 PC14 PC15 */
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
@ -639,32 +521,34 @@ static void MX_GPIO_Init(void)
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PA0 PA1 PA2 PA3 */ /*Configure GPIO pins : RELAY_EN_Pin _60V_EN_Pin CSB_Pin */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Pin = RELAY_EN_Pin|_60V_EN_Pin|CSB_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : CSB_Pin EEPROM___WC__Pin */
GPIO_InitStruct.Pin = CSB_Pin|EEPROM___WC__Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB2 PB12 PB13 */ /*Configure GPIO pins : STATUS_LED_R_Pin STATUS_LED_B_Pin STATUS_LED_G_Pin PRECHARGE_EN_Pin */
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_12|GPIO_PIN_13; GPIO_InitStruct.Pin = STATUS_LED_R_Pin|STATUS_LED_B_Pin|STATUS_LED_G_Pin|PRECHARGE_EN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : RELAY_ENABLE_Pin PRECHARGE_ENABLE_Pin */
GPIO_InitStruct.Pin = RELAY_ENABLE_Pin|PRECHARGE_ENABLE_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PB10 PB12 PB13 PB14
PB4 PB5 PB8 */
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : RELAY_BATT_SIDE_ON_Pin RELAY_ESC_SIDE_ON_Pin CURRENT_SENSOR_ON_Pin */
GPIO_InitStruct.Pin = RELAY_BATT_SIDE_ON_Pin|RELAY_ESC_SIDE_ON_Pin|CURRENT_SENSOR_ON_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */
} }

325
Core/Src/state_machine.c Normal file
View File

@ -0,0 +1,325 @@
#include "state_machine.h"
#include "AMS_HighLevel.h"
#include "TMP1075.h"
#include "errors.h"
#include "stm32f3xx_hal.h"
#include <stdint.h>
#include <stdio.h>
StateHandle state;
int16_t RELAY_BAT_SIDE_VOLTAGE;
int16_t RELAY_ESC_SIDE_VOLTAGE;
int16_t CURRENT_MEASUREMENT;
uint8_t powerground_status;
uint32_t timestamp;
void sm_init(){
state.current_state = STATE_INACTIVE;
state.target_state = STATE_INACTIVE;
state.error_source = 0;
}
void sm_update(){
sm_check_errors();
RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[0] * 12.42; // the calculation says the factor is 11.989. 12.42 yields the better result
RELAY_ESC_SIDE_VOLTAGE = module.auxVoltages[1] * 12.42;
CURRENT_MEASUREMENT = (module.auxVoltages[2] - 2496) * 300;
switch (state.current_state) {
case STATE_INACTIVE:
state.current_state = sm_update_inactive(); // monitor only
break;
case STATE_PRECHARGE:
state.current_state = sm_update_precharge(); // set PRECHARGE and turn on cooling at 50% or such
break;
case STATE_READY:
state.current_state = sm_update_ready(); // keep cooling at 50%, get ready to turn on powerground
break;
case STATE_ACTIVE:
state.current_state = sm_update_active(); // set PRECHARGE and turn on cooling at 50% or such
break;
case STATE_DISCHARGE:
state.current_state = sm_update_discharge(); // open the main relay, keep PRECHARGE closed
break;
case STATE_CHARGING_PRECHARGE:
state.current_state = sm_update_charging_precharge();
break;
case STATE_CHARGING:
state.current_state = sm_update_charging(); // monitor and turn on cooling if needed.
break;
case STATE_ERROR:
state.current_state = sm_update_error(); // enter the correct ERROR state
break;
}
sm_set_relay_positions(state.current_state);
state.target_state = state.current_state;
}
State sm_update_inactive(){
switch (state.target_state) {
case STATE_PRECHARGE:
return STATE_PRECHARGE;
case STATE_CHARGING_PRECHARGE:
return STATE_CHARGING_PRECHARGE;
default:
return STATE_INACTIVE;
}
}
State sm_update_precharge(){
switch (state.target_state) {
case STATE_INACTIVE: // if CAN Signal 0000 0000 then immidiete shutdown
return STATE_DISCHARGE;
case STATE_PRECHARGE:
if (RELAY_BAT_SIDE_VOLTAGE-RELAY_ESC_SIDE_VOLTAGE < 100){
PWM_set_throttle();
return STATE_READY;
}
break;
case STATE_DISCHARGE:
return STATE_DISCHARGE;
default:
return STATE_PRECHARGE;
}
}
State sm_update_ready(){
switch (state.target_state) {
case STATE_ACTIVE: // if CAN Signal 1100 0000 then turn on powerground
return STATE_ACTIVE;
case STATE_DISCHARGE: // if CAN Signal 0000 0000 then shutdown
return STATE_DISCHARGE;
default:
return STATE_READY;
}
}
State sm_update_active(){
switch (state.target_state) {
case STATE_READY: // if CAN Signal 1000 0000 then turn oof powerground but stay ready
return STATE_READY;
case STATE_DISCHARGE: // if CAN Signal 0000 0000 then shutdown
return STATE_DISCHARGE;
default:
return STATE_ACTIVE;
}
}
State sm_update_discharge(){
switch (state.target_state) {
case STATE_DISCHARGE:
if (RELAY_ESC_SIDE_VOLTAGE < 5000)
return STATE_INACTIVE;
case STATE_PRECHARGE: // if CAN Signal 1000 0000 then get ready
return STATE_PRECHARGE;
default:
return STATE_DISCHARGE;
}
}
State sm_update_charging_precharge(){
switch (state.target_state) {
case STATE_CHARGING:
return STATE_CHARGING;
case STATE_DISCHARGE:
return STATE_DISCHARGE;
default:
return STATE_CHARGING_PRECHARGE;
}
}
State sm_update_charging(){
switch (state.target_state) {
case STATE_DISCHARGE:
return STATE_DISCHARGE;
default:
return STATE_CHARGING;
}
}
State sm_update_error(){
switch (state.target_state) {
case STATE_DISCHARGE:
return STATE_DISCHARGE;
default:
return STATE_ERROR;
}
}
void sm_set_relay_positions(State current_state){
switch (state.current_state) {
case STATE_INACTIVE:
sm_set_relay(RELAY_MAIN, 0);
sm_set_relay(RELAY_PRECHARGE, 0);
break;
case STATE_PRECHARGE:
sm_set_relay(RELAY_MAIN, 0);
sm_set_relay(RELAY_PRECHARGE, 1);
break;
case STATE_READY:
sm_set_relay(RELAY_MAIN, 1);
sm_set_relay(RELAY_PRECHARGE, 0);
break;
case STATE_ACTIVE:
sm_set_relay(RELAY_MAIN, 1);
sm_set_relay(RELAY_PRECHARGE, 0);
break;
case STATE_DISCHARGE:
sm_set_relay(RELAY_MAIN, 0);
sm_set_relay(RELAY_PRECHARGE, 0);
break;
case STATE_CHARGING_PRECHARGE:
sm_set_relay(RELAY_MAIN, 0);
sm_set_relay(RELAY_PRECHARGE, 1);
break;
case STATE_CHARGING:
sm_set_relay(RELAY_MAIN, 1);
sm_set_relay(RELAY_PRECHARGE, 0);
break;
case STATE_ERROR:
sm_set_relay(RELAY_MAIN, 0);
sm_set_relay(RELAY_PRECHARGE, 0);
break;
}
}
void sm_set_relay(Relay relay, bool closed){
GPIO_PinState state = closed ? GPIO_PIN_SET : GPIO_PIN_RESET;
switch (relay) {
case RELAY_MAIN:
HAL_GPIO_WritePin(RELAY_EN_GPIO_Port, RELAY_EN_Pin, state);
relay_closed = closed;
break;
case RELAY_PRECHARGE:
HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, state);
precharge_closed = closed;
break;
}
}
void sm_check_charging(){
if (RELAY_BAT_SIDE_VOLTAGE < RELAY_ESC_SIDE_VOLTAGE && timestamp == 0)
timestamp = HAL_GetTick() + 5000;
if (timestamp < HAL_GetTick())
state.target_state = STATE_CHARGING_PRECHARGE;
}
/* returns the ID and temperature of the hottest cell */
void sm_check_battery_temperature(int8_t *id, int16_t *temp){
for (int i = 0; i < N_TEMP_SENSORS; i++) {
if (tmp1075_temps[i] > *temp){
*id = i;
*temp = tmp1075_temps[i];
}
}
}
int16_t sm_return_cell_temperature(int id){
return tmp1075_temps[id];
}
int16_t sm_return_cell_voltage(int id){
return module.cellVoltages[id];
}
void sm_handle_ams_in(const uint8_t *data){
switch (data[0]) {
case 0x00:
if (state.current_state != STATE_INACTIVE){
state.target_state = STATE_DISCHARGE;
}
break;
case 0x01:
if (state.target_state == STATE_INACTIVE || state.target_state == STATE_DISCHARGE){
state.target_state = STATE_PRECHARGE;
} else if (state.target_state == STATE_ACTIVE){
state.target_state = STATE_READY;
}
break;
case 0x02:
if (state.current_state == STATE_READY || state.current_state == STATE_ACTIVE){
PWM_powerground_control(data[1]);
state.target_state = STATE_ACTIVE; // READY -> ACTIVE
}
break;
}
}
void sm_set_error(ErrorKind error_kind, bool is_errored){}
#warning TODO: add error checking for everything here
void sm_check_errors(){
switch (error_data.data_kind) {
case SEK_OVERTEMP:
case SEK_UNDERTEMP:
case SEK_TOO_FEW_TEMPS:
state.error_type.temperature_error = 1;
case SEK_OVERVOLT:
case SEK_UNDERVOLT:
case SEK_OPENWIRE:
case SEK_EEPROM_ERR:
case SEK_INTERNAL_BMS_TIMEOUT:
state.error_type.bms_timeout = 1;
case SEK_INTERNAL_BMS_CHECKSUM_FAIL:
case SEK_INTERNAL_BMS_OVERTEMP:
case SEK_INTERNAL_BMS_FAULT:
state.error_type.bms_fault = 1;
break;
}
if (1){
state.error_type.current_error = 1;
}
if (1){
state.error_type.current_sensor_missing = 1;
}
if (RELAY_BAT_SIDE_VOLTAGE < 30000){
state.error_type.voltage_error = 1;
}
if (1){
state.error_type.voltage_missing = 1;
}
}
void sm_test_cycle_states(){
RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[0];
RELAY_ESC_SIDE_VOLTAGE = module.auxVoltages[1];
CURRENT_MEASUREMENT = module.auxVoltages[2];
sm_set_relay_positions(state.current_state);
if (timestamp > HAL_GetTick())
return;
switch (state.current_state) {
case STATE_INACTIVE:
state.current_state = STATE_PRECHARGE;
timestamp = HAL_GetTick() + 30000;
PWM_powerground_control(0);
break;
case STATE_PRECHARGE:
state.current_state = STATE_READY;
timestamp = HAL_GetTick() + 10000;
break;
case STATE_READY:
state.current_state = STATE_ACTIVE;
timestamp = HAL_GetTick() + 10000;
break;
case STATE_ACTIVE:
state.current_state = STATE_DISCHARGE;
timestamp = HAL_GetTick() + 10000;
PWM_powerground_control(1);
break;
case STATE_DISCHARGE:
state.current_state = STATE_INACTIVE;
timestamp = HAL_GetTick() + 10000;
break;
}
state.target_state = state.current_state;
}

View File

@ -59,7 +59,7 @@
/* USER CODE END 0 */ /* USER CODE END 0 */
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/** /**
* Initializes the Global MSP. * Initializes the Global MSP.
*/ */
void HAL_MspInit(void) void HAL_MspInit(void)
@ -173,19 +173,19 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
PA15 ------> I2C1_SCL PA15 ------> I2C1_SCL
PB9 ------> I2C1_SDA PB9 ------> I2C1_SDA
*/ */
GPIO_InitStruct.Pin = TMP_SCL_Pin; GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(TMP_SCL_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = TMP_SDA_Pin; GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(TMP_SDA_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */ /* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE(); __HAL_RCC_I2C1_CLK_ENABLE();
@ -193,30 +193,6 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
/* USER CODE END I2C1_MspInit 1 */ /* USER CODE END I2C1_MspInit 1 */
} }
else if(hi2c->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspInit 0 */
/* USER CODE END I2C2_MspInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**I2C2 GPIO Configuration
PA9 ------> I2C2_SCL
PA10 ------> I2C2_SDA
*/
GPIO_InitStruct.Pin = EEPROM_SCL_Pin|EEPROM_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C2_CLK_ENABLE();
/* USER CODE BEGIN I2C2_MspInit 1 */
/* USER CODE END I2C2_MspInit 1 */
}
} }
@ -240,34 +216,14 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
PA15 ------> I2C1_SCL PA15 ------> I2C1_SCL
PB9 ------> I2C1_SDA PB9 ------> I2C1_SDA
*/ */
HAL_GPIO_DeInit(TMP_SCL_GPIO_Port, TMP_SCL_Pin); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15);
HAL_GPIO_DeInit(TMP_SDA_GPIO_Port, TMP_SDA_Pin); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
/* USER CODE BEGIN I2C1_MspDeInit 1 */ /* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */ /* USER CODE END I2C1_MspDeInit 1 */
} }
else if(hi2c->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspDeInit 0 */
/* USER CODE END I2C2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C2_CLK_DISABLE();
/**I2C2 GPIO Configuration
PA9 ------> I2C2_SCL
PA10 ------> I2C2_SDA
*/
HAL_GPIO_DeInit(EEPROM_SCL_GPIO_Port, EEPROM_SCL_Pin);
HAL_GPIO_DeInit(EEPROM_SDA_GPIO_Port, EEPROM_SDA_Pin);
/* USER CODE BEGIN I2C2_MspDeInit 1 */
/* USER CODE END I2C2_MspDeInit 1 */
}
} }
@ -346,38 +302,16 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
*/ */
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm) void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
{ {
if(htim_pwm->Instance==TIM2) if(htim_pwm->Instance==TIM1)
{ {
/* USER CODE BEGIN TIM2_MspInit 0 */ /* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */ /* USER CODE END TIM1_MspInit 0 */
/* Peripheral clock enable */ /* Peripheral clock enable */
__HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_TIM1_CLK_ENABLE();
/* USER CODE BEGIN TIM2_MspInit 1 */ /* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */ /* USER CODE END TIM1_MspInit 1 */
}
else if(htim_pwm->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
else if(htim_pwm->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
/* USER CODE END TIM4_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM4_CLK_ENABLE();
/* USER CODE BEGIN TIM4_MspInit 1 */
/* USER CODE END TIM4_MspInit 1 */
} }
else if(htim_pwm->Instance==TIM15) else if(htim_pwm->Instance==TIM15)
{ {
@ -396,71 +330,25 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{ {
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM2) if(htim->Instance==TIM1)
{ {
/* USER CODE BEGIN TIM2_MspPostInit 0 */ /* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM2_MspPostInit 0 */ /* USER CODE END TIM1_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM2 GPIO Configuration /**TIM1 GPIO Configuration
PB10 ------> TIM2_CH3 PB15 ------> TIM1_CH3N
PB11 ------> TIM2_CH4
*/ */
GPIO_InitStruct.Pin = BAT_COOLING_PWM_Pin|BAT_COOLING_ENABLE_Pin; GPIO_InitStruct.Pin = PWM_Battery_Cooling_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; GPIO_InitStruct.Alternate = GPIO_AF4_TIM1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(PWM_Battery_Cooling_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN TIM2_MspPostInit 1 */ /* USER CODE BEGIN TIM1_MspPostInit 1 */
/* USER CODE END TIM2_MspPostInit 1 */ /* USER CODE END TIM1_MspPostInit 1 */
}
else if(htim->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspPostInit 0 */
/* USER CODE END TIM3_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM3 GPIO Configuration
PB0 ------> TIM3_CH3
PB1 ------> TIM3_CH4
*/
GPIO_InitStruct.Pin = ESC_L_PWM_Pin|ESC_R_PWM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_MspPostInit 1 */
/* USER CODE END TIM3_MspPostInit 1 */
}
else if(htim->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspPostInit 0 */
/* USER CODE END TIM4_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM4 GPIO Configuration
PB6 ------> TIM4_CH1
PB7 ------> TIM4_CH2
PB8 ------> TIM4_CH3
*/
GPIO_InitStruct.Pin = STATUS_LED_R_Pin|STATUS_LED_G_Pin|STATUS_LED_B_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM4_MspPostInit 1 */
/* USER CODE END TIM4_MspPostInit 1 */
} }
else if(htim->Instance==TIM15) else if(htim->Instance==TIM15)
{ {
@ -468,17 +356,17 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
/* USER CODE END TIM15_MspPostInit 0 */ /* USER CODE END TIM15_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM15 GPIO Configuration /**TIM15 GPIO Configuration
PB14 ------> TIM15_CH1 PA2 ------> TIM15_CH1
PB15 ------> TIM15_CH2 PA3 ------> TIM15_CH2
*/ */
GPIO_InitStruct.Pin = ESC_COOLING_ENABLE_Pin|ESC_COOLING_PWM_Pin; GPIO_InitStruct.Pin = PWM_PG_FAN1_Pin|PWM_PG_FAN2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM15; GPIO_InitStruct.Alternate = GPIO_AF9_TIM15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM15_MspPostInit 1 */ /* USER CODE BEGIN TIM15_MspPostInit 1 */
@ -494,38 +382,16 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
*/ */
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm) void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
{ {
if(htim_pwm->Instance==TIM2) if(htim_pwm->Instance==TIM1)
{ {
/* USER CODE BEGIN TIM2_MspDeInit 0 */ /* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */ /* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */ /* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE(); __HAL_RCC_TIM1_CLK_DISABLE();
/* USER CODE BEGIN TIM2_MspDeInit 1 */ /* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */ /* USER CODE END TIM1_MspDeInit 1 */
}
else if(htim_pwm->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(htim_pwm->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */
/* USER CODE END TIM4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM4_CLK_DISABLE();
/* USER CODE BEGIN TIM4_MspDeInit 1 */
/* USER CODE END TIM4_MspDeInit 1 */
} }
else if(htim_pwm->Instance==TIM15) else if(htim_pwm->Instance==TIM15)
{ {
@ -541,6 +407,71 @@ void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
} }
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
/* USER CODE END 1 */ /* USER CODE END 1 */

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Some files were not shown because too many files have changed in this diff Show More