diff --git a/Core/Inc/imd_monitoring.h b/Core/Inc/imd_monitoring.h new file mode 100644 index 0000000..553c744 --- /dev/null +++ b/Core/Inc/imd_monitoring.h @@ -0,0 +1,36 @@ +#ifndef INC_IMD_MONITORING_H +#define INC_IMD_MONITORING_H + +#include + +#include "stm32f3xx_hal.h" + +typedef enum { + IMD_STATE_UNKNOWN, + IMD_STATE_SHORTCIRCUIT_SUPPLY, + IMD_STATE_SHORTCIRCUIT_GND, + IMD_STATE_NORMAL, + IMD_STATE_UNDERVOLTAGE, + IMD_STATE_SST, + IMD_STATE_DEV_ERROR, + IMD_STATE_GND_FAULT, +} IMDState; + +typedef struct { + int ok; + + IMDState state; + uint32_t r_iso; + + uint32_t freq; + uint32_t duty_cycle; + uint32_t last_high; +} IMDData; + +extern IMDData imd_data; + +void imd_init(TIM_HandleTypeDef *htim); + +void imd_update(void); + +#endif // INC_IMD_MONITORING_H diff --git a/Core/Inc/main.h b/Core/Inc/main.h index 7cf7526..8c1333c 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -61,6 +61,8 @@ void Error_Handler(void); #define HV_MISMATCH_ERR_GPIO_Port GPIOA #define RELAY_MISMATCH_ERR_Pin GPIO_PIN_1 #define RELAY_MISMATCH_ERR_GPIO_Port GPIOA +#define IMD_M_Pin GPIO_PIN_2 +#define IMD_M_GPIO_Port GPIOA #define IMD_OK_Pin GPIO_PIN_3 #define IMD_OK_GPIO_Port GPIOA #define RELAY_CONNECTION_ERR_Pin GPIO_PIN_4 diff --git a/Core/Inc/stm32f3xx_it.h b/Core/Inc/stm32f3xx_it.h index ba25618..658788a 100644 --- a/Core/Inc/stm32f3xx_it.h +++ b/Core/Inc/stm32f3xx_it.h @@ -56,6 +56,7 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void USB_LP_CAN_RX0_IRQHandler(void); +void TIM1_BRK_TIM15_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/Core/Src/can.c b/Core/Src/can.c index 2ae20c7..30c62ab 100644 --- a/Core/Src/can.c +++ b/Core/Src/can.c @@ -1,5 +1,6 @@ #include "can.h" +#include "imd_monitoring.h" #include "main.h" #include "shunt_monitoring.h" #include "slave_monitoring.h" @@ -21,11 +22,17 @@ void can_init(CAN_HandleTypeDef *handle) { } HAL_StatusTypeDef can_send_status() { - uint8_t data[6]; + uint8_t data[8]; data[0] = ts_state.current_state | (sdc_closed << 7); data[1] = roundf(current_soc); ftcan_marshal_unsigned(&data[2], min_voltage, 2); ftcan_marshal_signed(&data[4], max_temp, 2); + data[6] = imd_data.state | (imd_data.ok << 7); + if (imd_data.r_iso < 0xFFF) { + data[7] = imd_data.r_iso >> 4; + } else { + data[7] = 0xFF; + } return ftcan_transmit(CAN_ID_AMS_STATUS, data, sizeof(data)); } diff --git a/Core/Src/imd_monitoring.c b/Core/Src/imd_monitoring.c new file mode 100644 index 0000000..4588ecd --- /dev/null +++ b/Core/Src/imd_monitoring.c @@ -0,0 +1,86 @@ +#include "imd_monitoring.h" + +#include "main.h" + +#define FREQ_TIMER 1000 // Hz + +#define FREQ_TOLERANCE 1 // Hz +#define FREQ_NORMAL 10 // Hz +#define FREQ_UNDERVOLTAGE 20 // Hz +#define FREQ_SST 30 // Hz +#define FREQ_DEV_ERROR 40 // Hz +#define FREQ_GND_FAULT 50 // Hz + +#define RISO_MIN_DUTY_CYCLE 8 // % +#define RISO_MAX 50000 // kOhm + +#define PWM_TIMEOUT 200 // ms + +IMDData imd_data; + +static TIM_HandleTypeDef *htim; + +void imd_init(TIM_HandleTypeDef *handle) { + htim = handle; + HAL_TIM_IC_Start_IT(htim, TIM_CHANNEL_1); + HAL_TIM_IC_Start(htim, TIM_CHANNEL_2); + + imd_data.state = IMD_STATE_UNKNOWN; +} + +void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *handle) { + if (handle != htim || htim->Channel != HAL_TIM_ACTIVE_CHANNEL_1) { + return; + } + uint32_t period = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); + if (period == 0) { + // First edge, ignore + return; + } + imd_data.last_high = HAL_GetTick(); + + imd_data.freq = FREQ_TIMER / period; + uint32_t high_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); + imd_data.duty_cycle = (100 * high_time) / period; + + // Check PWM frequency for state determination + if (imd_data.freq > FREQ_NORMAL - FREQ_TOLERANCE && + imd_data.freq < FREQ_NORMAL + FREQ_TOLERANCE) { + imd_data.state = IMD_STATE_NORMAL; + } else if (imd_data.freq > FREQ_UNDERVOLTAGE - FREQ_TOLERANCE && + imd_data.freq < FREQ_UNDERVOLTAGE + FREQ_TOLERANCE) { + imd_data.state = IMD_STATE_UNDERVOLTAGE; + } else if (imd_data.freq > FREQ_SST - FREQ_TOLERANCE && + imd_data.freq < FREQ_SST + FREQ_TOLERANCE) { + imd_data.state = IMD_STATE_SST; + } else if (imd_data.freq > FREQ_DEV_ERROR - FREQ_TOLERANCE && + imd_data.freq < FREQ_DEV_ERROR + FREQ_TOLERANCE) { + imd_data.state = IMD_STATE_DEV_ERROR; + } else if (imd_data.freq > FREQ_GND_FAULT - FREQ_TOLERANCE && + imd_data.freq < FREQ_GND_FAULT + FREQ_TOLERANCE) { + imd_data.state = IMD_STATE_GND_FAULT; + } else { + imd_data.state = IMD_STATE_UNKNOWN; + } + + // Calculate R_iso + if (imd_data.state == IMD_STATE_NORMAL || + imd_data.state == IMD_STATE_UNDERVOLTAGE) { + if (imd_data.duty_cycle < RISO_MIN_DUTY_CYCLE) { + imd_data.r_iso = RISO_MAX; + } else { + imd_data.r_iso = (90 * 1200) / (imd_data.duty_cycle - 5) - 1200; + } + } +} + +void imd_update() { + imd_data.ok = HAL_GPIO_ReadPin(IMD_OK_GPIO_Port, IMD_OK_Pin); + if (HAL_GetTick() - imd_data.last_high > PWM_TIMEOUT) { + if (HAL_GPIO_ReadPin(IMD_M_GPIO_Port, IMD_M_Pin) == GPIO_PIN_SET) { + imd_data.state = IMD_STATE_SHORTCIRCUIT_SUPPLY; + } else { + imd_data.state = IMD_STATE_SHORTCIRCUIT_GND; + } + } +} diff --git a/Core/Src/main.c b/Core/Src/main.c index 260cbc5..8372409 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -22,14 +22,15 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "can.h" -#include "soc_estimation.h" -#include "stm32f3xx_hal.h" -#include "stm32f3xx_hal_gpio.h" - +#include "imd_monitoring.h" #include "shunt_monitoring.h" #include "slave_monitoring.h" +#include "soc_estimation.h" #include "ts_state_machine.h" +#include "stm32f3xx_hal.h" +#include "stm32f3xx_hal_gpio.h" + /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -130,6 +131,7 @@ int main(void) { shunt_init(); ts_sm_init(); soc_init(); + imd_init(&htim15); HAL_GPIO_WritePin(AMS_NERROR_GPIO_Port, AMS_NERROR_Pin, GPIO_PIN_SET); /* USER CODE END 2 */ @@ -147,6 +149,7 @@ int main(void) { shunt_check(); ts_sm_update(); soc_update(); + imd_update(); can_send_status(); loop_delay(); @@ -349,7 +352,7 @@ static void MX_TIM15_Init(void) { /* USER CODE END TIM15_Init 1 */ htim15.Instance = TIM15; - htim15.Init.Prescaler = 0; + htim15.Init.Prescaler = 16000 - 1; htim15.Init.CounterMode = TIM_COUNTERMODE_UP; htim15.Init.Period = 65535; htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; diff --git a/Core/Src/stm32f3xx_hal_msp.c b/Core/Src/stm32f3xx_hal_msp.c index a1f776a..ca4a8d3 100644 --- a/Core/Src/stm32f3xx_hal_msp.c +++ b/Core/Src/stm32f3xx_hal_msp.c @@ -303,13 +303,16 @@ void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* htim_ic) /**TIM15 GPIO Configuration PA2 ------> TIM15_CH1 */ - GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Pin = IMD_M_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF9_TIM15; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_GPIO_Init(IMD_M_GPIO_Port, &GPIO_InitStruct); + /* TIM15 interrupt Init */ + HAL_NVIC_SetPriority(TIM1_BRK_TIM15_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn); /* USER CODE BEGIN TIM15_MspInit 1 */ /* USER CODE END TIM15_MspInit 1 */ @@ -336,8 +339,10 @@ void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef* htim_ic) /**TIM15 GPIO Configuration PA2 ------> TIM15_CH1 */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2); + HAL_GPIO_DeInit(IMD_M_GPIO_Port, IMD_M_Pin); + /* TIM15 interrupt DeInit */ + HAL_NVIC_DisableIRQ(TIM1_BRK_TIM15_IRQn); /* USER CODE BEGIN TIM15_MspDeInit 1 */ /* USER CODE END TIM15_MspDeInit 1 */ diff --git a/Core/Src/stm32f3xx_it.c b/Core/Src/stm32f3xx_it.c index 2c26531..ee4576d 100644 --- a/Core/Src/stm32f3xx_it.c +++ b/Core/Src/stm32f3xx_it.c @@ -56,6 +56,7 @@ /* External variables --------------------------------------------------------*/ extern CAN_HandleTypeDef hcan; +extern TIM_HandleTypeDef htim15; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -217,6 +218,20 @@ void USB_LP_CAN_RX0_IRQHandler(void) /* USER CODE END USB_LP_CAN_RX0_IRQn 1 */ } +/** + * @brief This function handles TIM1 break and TIM15 interrupts. + */ +void TIM1_BRK_TIM15_IRQHandler(void) +{ + /* USER CODE BEGIN TIM1_BRK_TIM15_IRQn 0 */ + + /* USER CODE END TIM1_BRK_TIM15_IRQn 0 */ + HAL_TIM_IRQHandler(&htim15); + /* USER CODE BEGIN TIM1_BRK_TIM15_IRQn 1 */ + + /* USER CODE END TIM1_BRK_TIM15_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/STM32Make.make b/STM32Make.make index 9e78481..ed043ae 100644 --- a/STM32Make.make +++ b/STM32Make.make @@ -38,6 +38,7 @@ BUILD_DIR = build C_SOURCES = \ Core/Lib/can-halal/can-halal.c \ Core/Src/can.c \ +Core/Src/imd_monitoring.c \ Core/Src/main.c \ Core/Src/shunt_monitoring.c \ Core/Src/slave_monitoring.c \ diff --git a/ams-master-23.ioc b/ams-master-23.ioc index 50367be..5b8b3a3 100644 --- a/ams-master-23.ioc +++ b/ams-master-23.ioc @@ -86,6 +86,7 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false +NVIC.TIM1_BRK_TIM15_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.USB_LP_CAN_RX0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false PA0.GPIOParameters=GPIO_Label @@ -113,6 +114,8 @@ PA14.Mode=Trace_Asynchronous_SW PA14.Signal=SYS_JTCK-SWCLK PA15.Mode=I2C PA15.Signal=I2C1_SCL +PA2.GPIOParameters=GPIO_Label +PA2.GPIO_Label=IMD_M PA2.Locked=true PA2.Signal=S_TIM15_CH1 PA3.GPIOParameters=GPIO_Label @@ -237,7 +240,7 @@ ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=Makefile ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC2_Init-ADC2-false-HAL-true,4-MX_CAN_Init-CAN-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC2_Init-ADC2-false-HAL-true,4-MX_CAN_Init-CAN-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true,6-MX_I2C1_Init-I2C1-false-HAL-true,7-MX_TIM15_Init-TIM15-false-HAL-true RCC.ADC12outputFreq_Value=16000000 RCC.AHBFreq_Value=16000000 RCC.APB1Freq_Value=16000000 @@ -274,6 +277,8 @@ RCC.USBFreq_Value=16000000 RCC.VCOOutput2Freq_Value=4000000 SH.S_TIM15_CH1.0=TIM15_CH1,PWM_Input_1 SH.S_TIM15_CH1.ConfNb=1 +TIM15.IPParameters=Prescaler +TIM15.Prescaler=16000-1 USART1.IPParameters=VirtualMode-Asynchronous USART1.VirtualMode-Asynchronous=VM_ASYNC VP_SYS_VS_Systick.Mode=SysTick