#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; } } }