|
双极固态功率继电器,能够换向而不产生电弧和/或过流事件。
这个项目中使用的东西 硬件组件 英飞凌CoolMOS C7 Gold SJ MOSFET 使用了Mosfet × 4 STMicroelectronics STM32 Nucleo-64板 逻辑控制单元 × 1 ACS720 电流隔离电流传感器 × 1 ACPL-335J 光电门驱动器 × 1 概观 连接到交流电源时,不同的负载表现不同。工业和自动化中使用的传统机电继电器/接触器在制造或断开连接时不能与电网电量同步。结果,发生电弧和/或过电流,减少了继电器触点的寿命并且不必要地对换向负载施加应力。 系统描述 该项目包括双极智能功率固态继电器(SSR)的设计,能够在不接通负载(电阻,电感或电容)的情况下进行换向,而不会在导通阶段引入过电流,并在关断阶段避免电压尖峰。双极拓扑允许将负载与AC电源完全隔离。 当负载主要是电容型时,导通换向在输入电压正弦波的过零点处执行。这样可以大大降低浪涌电流。 当负载主要是电感型时,在输入电压正弦波的峰值处执行导通,以避免磁芯饱和,然后在驱动例如大型变压器时减小浪涌电流。 在关断期间,在boh情况下,换向发生在电流过零点上,以避免由电源线的杂散电感引起的电压尖峰。 下图显示了功能方案。交流电网直接连接在SSR的输入端。该系统由两个主要PCB组成:SSR板和Nucleo-64逻辑单元板。
功能方案 电源固态继电器(SSR) 功率SSR是使用EAGLE PCB CAD软件开发的。SSR采用四个600 V CoolMOS™C7进行反接口连接,以实现双极开关拓扑。MOSFET由光栅驱动器控制。输入电压由光学绝缘电压传感器ACPL-C87B测量。输入电流由电流绝缘电流传感器ACS720测量。
俯视图
底视图 Nucleo-64逻辑单元 逻辑单元由开发板Nucleo-64实现。输入电压/电流的检测和门信号的产生由板载微控制器STM32F446执行。
逻辑单元:开发板Nucleo-64 GPIO和所有外设均使用STM32CubeMX工具进行配置。
STM32CubeMX引脚配置
Nucleo-F446RE引脚配置 控制和操作模式 下图显示了代码实现的控制系统流程图。
控制流程图 开始:在此状态下,代码被初始化。所有微控制器外设均已正确配置。每次按下复位按钮时,都会在开机时调用此状态。 峰值电压测量:如果按下Nucleo-64 B1蓝色开关按钮,控制器将查找开启模式。开启模式由Mode Selctor引脚(PA15 GPIO)设置。如果引脚连接到地,则将选择电容模式。如果它被上拉,将选择感应模式。 电容模式:在电容模式下,栅极信号的导通处于输入正弦波电压(ZVS)的过零点。 电感模式:在电感模式下,栅极信号的导通处于输入正弦波电压的峰值。 禁用SSR :如果按下B1按钮,则禁用SSR。栅极信号在电流过零时关闭。如果检测到故障事件,则立即发生关闭而没有延迟。 故障事件: 监控三种不同的故障事件: 1)由光电驱动器实现的欠压锁定和过流故障的自诊断。微控制器监视报告故障的预定义GPIO。故障事件由中断服务程序管理。 2)软件负载过流。 3)软件输入过压。 实验结果 SSR在感应模式和电容模式下进行测试。
被测系统 示波器图例捕获: 蓝色迹线:一个CoolMOS的门信号 绿色迹线:栅极正弦波电压 红色迹线:负载正弦波电压 紫色痕迹:当前负载 在纯阻性负载上进行初步测试,以验证实施的不同负载换向策略。 以下捕获显示当选择电感模式时,输入电压峰值处的SSR导通。
在感应模式下输入电压峰值时导通 以下捕获显示当选择电容模式时,输入电压过零时SSR导通。
在电容模式下输入电压过零时导通。 以下捕获显示输入电流过零时的SSR关断。
在负载电流过零时关闭 代码 /** ****************************************************************************** *@file : main.c *@brief : Main program body ****************************************************************************** **This notice applies to any and all portions of this file *that are not between comment pairs USER CODE BEGIN and *USER CODE END. Other portions of this file, whether *inserted by the user or by software development tools *are owned by their respective copyright owners. * *COPYRIGHT(c) 2019 STMicroelectronics * *Redistribution and use in source and binary forms, with or withoutmodification, *are permitted provided that the following conditions are met: * 1. Redistributions of sourcecode must retain the above copyright notice, * this list of conditions andthe following disclaimer. * 2. Redistributions in binaryform must reproduce the above copyright notice, * this list of conditions andthe following disclaimer in the documentation * and/or other materialsprovided with the distribution. * 3. Neither the name ofSTMicroelectronics nor the names of its contributors * may be used to endorse orpromote products derived from this software * without specific priorwritten permission. * *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "ASIS" *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR *SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "dac.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stm32f4xx.h" #include "DWT_Delay.h" /* USER CODE END Includes */ /* Private typedef-----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro-------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables---------------------------------------------------------*/ /* USER CODE BEGIN PV */ uint8_t Fault = DISABLE; uint32_t Value_ADC1[2]; //Global structure typedef struct { floatADC1_val; //ADC1 Value floatADC2_val; //ADC2 Value floatI_IN; //Grid Current doubleV_IN; //Grid Voltage floatCor_ADC1; //Correction factor ADC1 floatCor_ADC2; //Correction factor ADC2 floatV_IN_Peak_MAX; //Peak Grid Voltage uint8_tStatus_Switch; //OPERATING Status uint8_tTick_TIM; //Time peak voltage detection uint8_tFault; //State Faults uint8_tStart_conversion; //Start peak voltage detection uint8_tOPERATING_MODE; //OPERATING MODE uint16_tV_IN_Limit; //Voltage limit uint8_tI_IN_Limit; //Current limit }t_SystemStruct; t_SystemStruct SysStruct; t_SystemStruct *p = &SysStruct; #define INDUCTIVE_MODE 0 //INDUCTIVE MODE #define CAPACITIVE_MODE 1 //CAPACITIVE MODE #define IDLE 0 // State of System #define START 1 // State of System #define STOP 2 // State of System /* USER CODE END PV */ /* Private function prototypes-----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** *@brief The application entry point. *@retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCUConfiguration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flashinterface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ADC1_Init(); MX_USART2_UART_Init(); MX_ADC2_Init(); MX_DAC_Init(); MX_TIM6_Init(); MX_TIM7_Init(); /* USER CODE BEGIN 2 */ HAL_ADC_Start(&hadc1); HAL_ADC_Start(&hadc2); HAL_DAC_Start(&hdac,DAC1_CHANNEL_1); InitParameter(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { if(p->Start_conversion== ENABLE) {// Start conversion if(HAL_ADC_PollForConversion(&hadc1,100) == HAL_OK) //timeout di 100ms {//I_in p->ADC1_val= HAL_ADC_GetValue(&hadc1); p->I_IN = ((p->ADC1_val*0.00081)-1.65)*(p->Cor_ADC1); //Logic Volt -> Grid Current } if(HAL_ADC_PollForConversion(&hadc2,100) == HAL_OK) //timeout di 100ms { //Vin p->ADC2_val = HAL_ADC_GetValue(&hadc2); p->V_IN = (p->ADC2_val*0.00081)*(p->Cor_ADC2); //Logic Volt -> Grid Volt } if(p->V_IN_Peak_MAX< p->V_IN) { p->V_IN_Peak_MAX=p->V_IN; } } if((p->V_IN_Peak_MAX>=p->V_IN_Limit || p->V_IN_Peak_MAX <=-(p->V_IN_Limit) ) ||(p->I_IN>= p->I_IN_Limit|| p->I_IN<= -(p->I_IN_Limit))) {// Over Current & Over Voltage Fault p->Fault=ENABLE; HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(PWM_1_GPIO_Port,PWM_1_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(PWM_2_GPIO_Port,PWM_2_Pin,GPIO_PIN_RESET); HAL_TIM_Base_Stop_IT(&htim6); HAL_TIM_Base_Start_IT(&htim7); } switch (p->Status_Switch) { case START: //Enable Switch if(p->V_IN>=p->V_IN_Peak_MAX ) { if(p->OPERATING_MODE== CAPACITIVE_MODE) { HAL_Delay(12); // Delay ms DWT_Delay(500); // Delay us } HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(PWM_1_GPIO_Port,PWM_1_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(PWM_2_GPIO_Port,PWM_2_Pin,GPIO_PIN_SET); } break; case STOP: //Disable Switch if (p->I_IN <= 0.1 && p->I_IN>= -0.1 ) { HAL_TIM_Base_Stop_IT(&htim6); HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(PWM_1_GPIO_Port,PWM_1_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(PWM_2_GPIO_Port,PWM_2_Pin,GPIO_PIN_RESET); InitParameter(); } break; } } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /* USER CODE END 3 */ } /** *@brief System Clock Configuration *@retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /**Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 16; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 2; if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void InitParameter(void) { p->Cor_ADC1 =58; // Correction Number for ADC1 p->Cor_ADC2 =10; // Correction Number for ADC2 p->V_IN_Peak_MAX=0; // Reset Voltage Peak Detection p->Status_Switch=DISABLE; // Reset Status Switch p->Tick_TIM=0; // Reset TickTimer p->Fault=DISABLE; // Reset Faults p->Start_conversion =DISABLE; // Reset Status Conversion p->V_IN_Limit = 300; // Max peak Voltage p->I_IN_Limit =20; // Max peak Current if((HAL_GPIO_ReadPin(Mode_Selector_GPIO_Port,Mode_Selector_Pin))) { p->OPERATING_MODE = INDUCTIVE_MODE; } else { p->OPERATING_MODE = CAPACITIVE_MODE; } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance ==TIM6) { p->Start_conversion = ENABLE; //Start peack voltage detection if(p->Tick_TIM<=3) { p->Tick_TIM++; } if(p->Tick_TIM==2) { p->Status_Switch = START; //Enable Switch } } if (htim->Instance ==TIM7) { HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); // LED Blink if(p->Status_Switch==START) { p->Status_Switch = STOP;} // -> StateSTOP } } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if((GPIO_Pin==B1_Pin)&& (p->Status_Switch==START) ) { //STOP p->Status_Switch= STOP; } else if((GPIO_Pin==B1_Pin)&& (p->Status_Switch==IDLE) && p->Fault==DISABLE) { //Start HAL_TIM_Base_Start_IT(&htim6); HAL_TIM_Base_Stop_IT(&htim7); } if(((HAL_GPIO_ReadPin(FAULT_N_GPIO_Port,FAULT_N_Pin))==RESET || (HAL_GPIO_ReadPin(UVLO_N_GPIO_Port,UVLO_N_Pin))== RESET||(HAL_GPIO_ReadPin(FAULT_L_GPIO_Port,FAULT_L_Pin))== RESET ||(HAL_GPIO_ReadPin(UVLO_L_GPIO_Port,UVLO_L_Pin))== RESET ) ) { // Faults & Diable Switch p->Fault=ENABLE; HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(PWM_1_GPIO_Port,PWM_1_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(PWM_2_GPIO_Port, PWM_2_Pin,GPIO_PIN_RESET); HAL_TIM_Base_Stop_IT(&htim6); HAL_TIM_Base_Start_IT(&htim7); //Active LED } } /* USER CODE END 4 */ |
| 这个厉害了 |
| 成本太高了 |
微信公众号
手机版