diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 6f0c9d5..a57aabb 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -45,4 +45,12 @@ V1.7 - added soc_estimation.c soc_estimation.h - added MIN/MAX_CELL_VOLTAGE for AMS_HighLevel - cleaned up state_machine code -- changed the format of the CAN message. \ No newline at end of file +- changed the format of the CAN message. + +V1.8 +- removed macros from can.h +- added documentation to PWM_control.h +- the MVBMS only reacts to messages if they are different from the previous message +- powerground calibration now starts at STATE_PRECHARGE +- moved header files from state_machine.c to h +- added status_LED.c, changed the ioc file accordingly \ No newline at end of file diff --git a/Core/Inc/PWM_control.h b/Core/Inc/PWM_control.h index a6356eb..2856930 100644 --- a/Core/Inc/PWM_control.h +++ b/Core/Inc/PWM_control.h @@ -17,6 +17,8 @@ /* 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. 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 diff --git a/Core/Inc/can.h b/Core/Inc/can.h index 73b7fe6..24d5284 100644 --- a/Core/Inc/can.h +++ b/Core/Inc/can.h @@ -16,9 +16,6 @@ #include "state_machine.h" #include -#define CAN_ID_IN 0x501 -#define CAN_ID_OUT 0x502 -#define CAN_STATUS_FREQ 1000 void can_init(CAN_HandleTypeDef* hcan); void can_handle_send_status(); diff --git a/Core/Inc/state_machine.h b/Core/Inc/state_machine.h index 7e9a47c..b8f20ff 100644 --- a/Core/Inc/state_machine.h +++ b/Core/Inc/state_machine.h @@ -11,22 +11,11 @@ #include #include #include "ADBMS_LL_Driver.h" -#include "AMS_HighLevel.h" -#include "errors.h" -#include "PWM_control.h" -#include "TMP1075.h" - -// 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_DURATION 5000 // ms -// Time to wait for discharge -#define DISCHARGE_DURATION 5000 // 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 -// Max time to wait for CAN messages. If we reach it then we emergency shutdown. -#define CAN_TIMEOUT 100000 +#include +#include +#include +#include +#include typedef enum { // states -> 3 bit. valid transitions: (all could transition to error) STATE_INACTIVE, // INACTIVE -> PRECHARGE, CHARGING, ERROR diff --git a/Core/Inc/status_LED.h b/Core/Inc/status_LED.h new file mode 100644 index 0000000..ea9df50 --- /dev/null +++ b/Core/Inc/status_LED.h @@ -0,0 +1,33 @@ +/* + * status_LED.h + * + * Created on: 07.07.2024 + * Author: Hamza + */ + +#ifndef INC_STATUS_LED_H +#define INC_STATUS_LED_H + +#include "stm32f3xx_hal.h" +#include +#include + +typedef enum { + OFF, + RED, + GREEN, + BLUE, + YELLOW, + PINK, + CYAN, + WHITE +} color; + +void status_led_init(TIM_HandleTypeDef* r, TIM_HandleTypeDef* g, TIM_HandleTypeDef* b); +void status_led_update(); + +void status_led_blink_sequence(uint8_t blinks, color color); +void status_led_set_color(color color); +void status_led_set(uint8_t r, uint8_t g, uint8_t b); + +#endif /* "INC_STATUS_LED_H" */ \ No newline at end of file diff --git a/Core/Src/can.c b/Core/Src/can.c index e8d6b2a..3e127f3 100644 --- a/Core/Src/can.c +++ b/Core/Src/can.c @@ -6,13 +6,19 @@ */ #include "can.h" +#include -//#define CAN_ID_IN 0x501 -//#define CAN_ID_OUT 0x502 +#define CAN_ID_IN 0x501 +#define CAN_ID_OUT 0x502 +#define CAN_STATUS_FREQ 100 + +uint8_t last_message[8]; static uint32_t can_delay_manager = 0; void can_init(CAN_HandleTypeDef* hcan) { ftcan_init(hcan); ftcan_add_filter(CAN_ID_IN, 0xFFF); + last_message[0] = -1; + last_message[1] = -1; } /* @@ -66,14 +72,15 @@ void can_handle_send_status() { int16_t lowest_volt = 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] = ((RELAY_BAT_SIDE_VOLTAGE / 1000)); // 8 bit battery voltage - data[4] = ((RELAY_ESC_SIDE_VOLTAGE / 1000)); - //data[5] = (() / 1000); - data[6] = ((CURRENT_MEASUREMENT / 1000)); - data[7] = ((highest_temp) >> 8); + data[3] = (0); // 8 bit state of charge + data[4] = ((RELAY_BAT_SIDE_VOLTAGE / 1000)); // 8 bit battery voltage + data[5] = ((RELAY_ESC_SIDE_VOLTAGE / 1000)); // 8 bit Inverter voltage + data[6] = ((CURRENT_MEASUREMENT / 1000)); // 8 bit Current + data[7] = ((highest_temp) >> 8); // 8 bit highest cell temperature //data[6] = (module.cellVoltages[7] >> 8); //data[7] = (module.cellVoltages[7]); //data[7] = state.error_source; @@ -165,6 +172,10 @@ in MXCUBE under CAN NVIC settings "USB low priority or CAN_RX0 interrupts" has t */ 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); + if (last_message[0] != data[0] || last_message[1] != data[1]){ + last_message[0] = data[0]; + last_message[1] = data[1]; + can_handle_recieve_command(data); + } } } diff --git a/Core/Src/main.c b/Core/Src/main.c index ac8462c..8cd1df1 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -27,6 +27,7 @@ #include "can.h" #include "AMS_HighLevel.h" #include "state_machine.h" +#include #include "TMP1075.h" #include "errors.h" #include "stm32f302xc.h" @@ -134,6 +135,8 @@ int main(void) AMS_Init(&hspi1); can_init(&hcan); PWM_control_init(&htim3, &htim2, &htim15); + status_led_init(&htim4, &htim4, &htim4); + //AMS_Loop(); //int ttrgrtd = 2000 + HAL_GetTick(); //while (ttrgrtd > HAL_GetTick()); @@ -495,7 +498,7 @@ static void MX_TIM4_Init(void) htim4.Instance = TIM4; htim4.Init.Prescaler = 0; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; - htim4.Init.Period = 65535; + htim4.Init.Period = 256; htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&htim4) != HAL_OK) diff --git a/Core/Src/state_machine.c b/Core/Src/state_machine.c index 57d102e..f7d3bc0 100644 --- a/Core/Src/state_machine.c +++ b/Core/Src/state_machine.c @@ -6,15 +6,18 @@ */ #include "state_machine.h" -#include "ADBMS_Abstraction.h" -#include "AMS_HighLevel.h" -#include "PWM_control.h" -#include "TMP1075.h" -#include "errors.h" -#include "main.h" -#include "stm32f302xc.h" -#include "stm32f3xx_hal.h" -#include + +// 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_DURATION 5000 // ms +// Time to wait for discharge +#define DISCHARGE_DURATION 5000 // 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 +// Max time to wait for CAN messages. If we reach it then we emergency shutdown. +#define CAN_TIMEOUT 100000 StateHandle state; int32_t RELAY_BAT_SIDE_VOLTAGE; @@ -155,7 +158,7 @@ void sm_precharge_discharge_manager(){ } void sm_calibrate_powerground(){ - if (powerground_calibration_stage != 4 && state.current_state == STATE_READY){ + if (powerground_calibration_stage != 4 && state.current_state == STATE_PRECHARGE){ switch (powerground_calibration_stage) { case 0: powerground_calibration_timer = HAL_GetTick() + 0; diff --git a/Core/Src/status_LED.c b/Core/Src/status_LED.c new file mode 100644 index 0000000..bbd70eb --- /dev/null +++ b/Core/Src/status_LED.c @@ -0,0 +1,128 @@ +/* + * status_LED.h + * + * Created on: 07.07.2024 + * Author: Hamza + */ + +#include "ADBMS_LL_Driver.h" +#include "state_machine.h" +#include "stm32f3xx_hal.h" +#include +#include + +/* 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. +F_PWM = (F_CLK)/((ARR + 1) * (PSC + 1)) + +Prescaler: +(ARR + 1) * (PSC + 1) = (F_CLK)/(F_PWM) +(PSC + 1) = (F_CLK)/(F_PWM * (ARR + 1)) +625 = (16MHz)/(100Hz * (255 + 1)) + +F_CLK = 16 MHz +*/ + +#define STATUS_LED_ARR 255 +#define BLINK_LENGTH 300 +#define TIME_BETWEEN_BLINKS 200 +#define TIME_BETWEEN_BLINK_SEQS 500 + +TIM_HandleTypeDef* red; +TIM_HandleTypeDef* green; +TIM_HandleTypeDef* blue; +uint8_t blinked; +uint32_t blink_timer; +bool blink_state; + +void status_led_init(TIM_HandleTypeDef* r, TIM_HandleTypeDef* g, TIM_HandleTypeDef* b){ + red = r; + green = g; + blue = b; + + blink_timer = 0; + blink_state = 0; + blinked = 0; + + HAL_TIM_PWM_Start(red, TIM_CHANNEL_1); //TIM4CH1 + HAL_TIM_PWM_Start(green, TIM_CHANNEL_2); //TIM4CH2 + HAL_TIM_PWM_Start(blue, TIM_CHANNEL_3); //TIM4CH3 + + status_led_set(255, 255, 255); +} + +void status_led_update(){ + switch (state.current_state) { + case STATE_INACTIVE: + status_led_blink_sequence(1, GREEN); + break; + case STATE_CHARGING_PRECHARGE: + case STATE_PRECHARGE: + case STATE_DISCHARGE: + status_led_blink_sequence(2, YELLOW); + break; + case STATE_CHARGING: + case STATE_READY: + status_led_blink_sequence(3, PINK); + break; + case STATE_ACTIVE: + status_led_set_color(PINK); + break; + case STATE_ERROR: + status_led_set_color(RED); + break; + } +} + +void status_led_blink_sequence(uint8_t blinks, color color){ + if (blink_timer < HAL_GetTick()) + return; + + if (blink_state){ + if (blinked != blinks){ + blink_timer = HAL_GetTick() + BLINK_LENGTH; + blinks++; + status_led_set_color(GREEN); + } else { + blink_timer = HAL_GetTick() + TIME_BETWEEN_BLINK_SEQS; + blinks = 0; + } + } else { + if (blinked != blinks){ + blink_timer = HAL_GetTick() + TIME_BETWEEN_BLINKS; + status_led_set_color(OFF); + } + } +} + +void status_led_set_color(color color){ + switch (color) { + case RED: + status_led_set(255, 0, 0); + break; + case GREEN: + status_led_set(0, 255, 0); + break; + case BLUE: + status_led_set(0, 0, 255); + break; + case YELLOW: + status_led_set(255, 255, 0); + break; + case PINK: + status_led_set(255, 0, 255); + break; + case CYAN: + status_led_set(0, 255, 255); + break; + case WHITE: + status_led_set(255, 255, 255); + break; + } +} + +void status_led_set(uint8_t r, uint8_t g, uint8_t b){ + __HAL_TIM_SET_COMPARE(red, TIM_CHANNEL_1, r); + __HAL_TIM_SET_COMPARE(green, TIM_CHANNEL_2, g); + __HAL_TIM_SET_COMPARE(blue, TIM_CHANNEL_3, b); +} \ No newline at end of file diff --git a/Makefile b/Makefile index 33ce7dc..4200b74 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [4.3.0-B58] date: [Fri Jul 05 06:59:15 EEST 2024] +# File automatically-generated by tool: [projectgenerator] version: [4.3.0-B58] date: [Tue Jul 09 21:45:50 EEST 2024] ########################################################################################################################## # ------------------------------------------------ diff --git a/mvbms.ioc b/mvbms.ioc index 248d041..4997bfe 100644 --- a/mvbms.ioc +++ b/mvbms.ioc @@ -282,7 +282,9 @@ TIM3.Prescaler=7 TIM4.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 TIM4.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 TIM4.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 -TIM4.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3 +TIM4.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Period,Prescaler +TIM4.Period=256 +TIM4.Prescaler=624 VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick board=custom