一、摘要
本文主要介绍微电网模拟系统功率电路的设计,辅助电路和控制电路设计在以前的文章,三相逆变模块分别由辅助电路供电,系统利用STM32产生SPWM波控制半桥驱动器EG2104实现三相逆变功能。其中MOSFET驱动电路选用自带死区的桥式驱动芯片EG2104驱动,开环输出线电压稳定在24V,相电压输出为24V/根号3=14V,14X跟号2=19.6V,所以供电电压应大于40V,为留有余量本作品取45V。
基于STM32G474RET6的微电网模拟系统辅助电源设计 (qq.com)
基于STM32G474RET6的微电网模拟系统控制电路设计 (qq.com)
二、理论分析与计算
1.选择适当的开关频率。
较高的开关频率可以减少变换器的体积和重量,提高输出电压THD,但是随着频率的提高开关管的损耗也会随之增加,开关管的损耗与频率成正比,开关频率越大,损耗也随之升高。因此,综合考虑下逆变器的开关频率为30kHz。
2.选择栅极电容与导通电阻较小的开关管NCE6080K
减小开关管的栅极串联电阻,可改变控制脉冲上升/下降时间、防止震荡,减小开关管的漏极的冲击电压,本作品用的电阻是3.3欧姆和10姆并联,在栅极串联电阻反接一个二极管可以加速栅极的放电,本作品用的二极管是1N4148;同时在开关管的栅极和源极之间并联较大阻值电阻,本作品用的电阻是10K,减小开关管断开时的静态电流。在开关管的漏极和源极反接一个二极管可以防止MOS管因过压、过流、短路等情况损坏,本作品用的二极管是SS5200(耐压200V),开关管NCE6080K耐压60V。semiee.com/file2/b3808a6c95c74a9dda1fec2c245bf276/Ncepower/Ncepower-NCE6080K.pdf
3.驱动芯片用自带死区时间的EG2104
EG2104 是一款高性价比的带SD̅̅̅̅功能的 MOS 管、IGBT 管栅极驱动专用芯片,内部集成了逻辑信号输入处 理电路、死区时控制电路、电平位移电路、脉冲滤波电路及输出驱动电路,专用于无刷电机控制器、电源 DC-DC 中的驱动电路。 EG2104 高端的工作电压可达 600V,低端 Vcc 的电源电压范围宽 2.8V~20V,静态功耗小于 1uA。该芯 片输入通道 IN 内建了一个 200K 下拉电阻,SD̅̅̅̅内建了一个 200K 下拉电阻,在输入悬空时使上、下功率 MOS 管处于关闭状态,输出电流能力 IO+/- 1/1.5A,采用 SOP8 封装。
图1:eg2104引脚描述图
图2:eg2104典型电路
本作品的驱动电路是按照芯片手册来设计的。EG2104芯片数据手册V1.0 (dianyuan.com)
4. 谐波失真的测量
THD:指输出信号比输入信号多出的谐波成分。谐波失真是系统不完全线性造成的。所有附加谐波电平之和称为总谐波失真。总谐波失真与频率有关。一般说来,1000Hz频率处的总谐波失真最小,因此不少产品均以该频率的失真作为它的指标。同时由于THD的计算比较麻烦,故我们直接用专门的电子仪器来测量THD的值。
5.逆变器滤波器设计
LC滤波器(正弦波滤波器):由串联电抗L和并联电容C构成。通常电流源的逆变器会使用LCL滤波器,电压源的逆变器会使用LC滤波器。原因是电流源逆变器一般都是与电网相连接,如果使用LC滤波器就会为电网注入开关次谐波,当然这是在电网很强的情况下,如果电网就弱,即系统阻抗较大,其实使用LC滤波器也是没有问题的。
图3:正弦波电路结构图
图4:正弦波生成变化图
正弦波滤波器的电抗和电容必须和电动机的容量精确匹配,否则达不到预期的效果。对于滤波电抗,增大电抗值可以降低输出电压的畸变率,但是当带载情况不变时增大电抗值无益会降低输出电压,甚至会出现拖不动电动机的情况。增大电容值同样可以提高输出电压质量,但是输出电压也会有所降低,并且成本也会相应增加。因此必须寻求平衡点,既能满足滤波要求又能降低成本。
正弦波滤波器的电抗和电容必须和电动机的容量精确匹配,否则达不到预期的效果。对于滤波电抗,增大电抗值可以降低输出电压的畸变率,但是当带载情况不变时增大电抗值无益会降低输出电压,甚至会出现拖不动电动机的情况。增大电容值同样可以提高输出电压质量,但是输出电压也会有所降低,并且成本也会相应增加。因此必须寻求平衡点,既能满足滤波要求又能降低成本。逆变器输出会带有基波的奇数次谐波,我们需要滤除这些谐波或者抑制这些谐波输出。逆变器输出是作为供电所用,输出电阻要小,所以不用 RC 无源滤波器选择用 LC 无源滤波器。
滤波器参数计算:LC 无源低通滤波器是滤除高次谐波分量,使电压输出波形为正弦波。本系统的 SPWM 调制信号为 30K。而输出需要的频率是 50Hz,滤波容易实现。
滤波器截止频率:
设置截止频率f=1.3KHz ,CCB电容 取 10μF。得电路中 L= 1.5mH,满足滤波器的要求。振荡电路(LC振荡器)谐振频率,周期在线计算器 (23bei.com)
三、电路设计
微电网模拟系统由两个三相逆变器并联构成,作为系统的核心部分,三相逆变电路采用半桥并联结构,完成直流电到三相交流电的转换。两部分三相逆变器电路完全一样,其中一个三相逆变器电路如下图5所示。
图5:主功率电路图
图6:LC电路图
微电网模拟系统由三相逆变主电路、驱动电路、电压电流采样电路和控制电路组成,三相逆变电路由 6 个 N 沟道 MOS 管构成一个三相逆变桥,驱动电路采用六输出高压驱动器EG2104。三相逆变电路由三路半桥电路和LC滤波电路组成。半桥电路中,驱动器EG2104在SVPWM波控制下驱动NCE6080K通断,完成逆变。逆变输出电压经LC低通滤波器滤除高频载波,得到正弦交流电压。
四、程序设计
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "i2c.h"
#include "usart.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "oled.h"
uint8_t flag=0,flag1=0;
uint32_t i;
uint16_t PhaseA=0,PhaseB=0,PhaseC=0;
//周期为180,幅值为2834的SPWM表
#define USET 1386
short spwm[180] = {0,98,197,296,394,492,589,685,781,875,969,1061,1152,1242,1330,1416,
1501,1584,1665,1744,1821,1896,1968,2038,2106,2170,2233,2292,2349,2403,2454,2502,
2547,2588,2627,2663,2695,2724,2749,2772,2790,2806,2818,2827,2832,2834,2832,2827,
2818,2806,2790,2772,2749,2724,2695,2663,2627,2588,2547,2502,2454,2403,2349,2292,
2233,2170,2106,2038,1968,1896,1821,1744,1665,1584,1501,1417,1330,1242,1152,1061,
969,875,781,685,589,492,394,296,197,98,0,-98,-197,-296,-394,-492,
-589,-685,-781,-875,-969,-1061,-1152,-1242,-1330,-1417,-1501,-1584,-1665,-1744,-1821,-1896,
-1968,-2038,-2106,-2170,-2233,-2292,-2349,-2403,-2454,-2502,-2547,-2588,-2627,-2663,-2695,-2724,
-2749,-2772,-2790,-2806,-2818,-2827,-2832,-2834,-2832,-2827,-2818,-2806,-2790,-2772,-2749,-2724,
-2695,-2663,-2627,-2588,-2547,-2502,-2454,-2403,-2349,-2292,-2233,-2170,-2106,-2038,-1968,-1896,
-1821,-1744,-1665,-1584,-1501,-1417,-1330,-1242,-1152,-1061,-969,-875,-781,-685,-589,-492,
-394,-296,-197,-98};
/* 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 */
/* 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 */
void GPIO_Init(void);
void TIM_Init(void);//定时器端口初始化
//更新逆变器1的PWM数据
void SPWM1_Refresh(uint8_t EN,uint16_t SPWMA,uint16_t SPWMB,uint16_t SPWMC);
//更新逆变器2的PWM数据
void SPWM2_Refresh(uint8_t EN,uint16_t SPWMA,uint16_t SPWMB,uint16_t SPWMC);
//控制函数
void control(void);
void dianyaxs(void) //电压显示
{
uint16_t temp;
temp=VIN/1.45;
OLED_ShowStr(0,4,"VIN:", 1);
OLED_ShowNum(24,4,temp/1000,1,1);
OLED_ShowNum(30,4,temp%1000/100,1,1);//
OLED_ShowChar(36,4,'.',1);//
OLED_ShowNum(42,4,temp%10/10,1,1);//
OLED_ShowNum(48,4,temp%10,1,1);//
OLED_ShowChar(54,4,'V',1);//
OLED_ShowStr(66,4,"UA1:", 1);
OLED_ShowNum(90,4,UA.DCvalue/10000,1,1);
OLED_ShowNum(96,4,UA.DCvalue %10000/1000,1,1);//
OLED_ShowChar(102,4,'.',1);//
OLED_ShowNum(108,4,UA.DCvalue %1000/100,1,1);//
OLED_ShowNum(114,4,UA.DCvalue %100/10,1,1);//
OLED_ShowChar(120,4,'V',1);//
OLED_ShowStr(0,5,"UB1:", 1);
OLED_ShowNum(24,5,UB.DCvalue/10000,1,1);//
OLED_ShowNum(30,5,UB.DCvalue%10000/1000,1,1);//
OLED_ShowChar(36,5,'.',1);//
OLED_ShowNum(42,5,UB.DCvalue%1000/100,1,1);//
OLED_ShowNum(48,5,UB.DCvalue%100/10,1,1);//
OLED_ShowChar(54,5,'V',1);//
OLED_ShowStr(66,5,"UC1:", 1);
OLED_ShowNum(90,5,UC.DCvalue/10000,1,1);
OLED_ShowNum(96,5,UC.DCvalue %10000/1000,1,1);//
OLED_ShowChar(102,5,'.',1);//
OLED_ShowNum(108,5,UC.DCvalue %1000/100,1,1);//
OLED_ShowNum(114,5,UC.DCvalue %100/10,1,1);//
OLED_ShowChar(120,5,'V',1);//
}
void dianliuxs(void) //电流显示
{
OLED_ShowStr(0,6,"IA1:", 1);
OLED_ShowNum(24,6,IA1.DCvalue/10000,1,1);
OLED_ShowNum(30,6,IA1.DCvalue %10000/1000,1,1);//
OLED_ShowChar(36,6,'.',1);//
OLED_ShowNum(42,6,IA1.DCvalue %1000/100,1,1);//
OLED_ShowNum(48,6,IA1.DCvalue %100/10,1,1);//
OLED_ShowChar(54,6,'A',1);//
OLED_ShowStr(0,7,"IB1:", 1);
OLED_ShowNum(24,7,IB1.DCvalue/10000,1,1);//
OLED_ShowNum(30,7,IB1.DCvalue%10000/1000,1,1);//
OLED_ShowChar(36,7,'.',1);//
OLED_ShowNum(42,7,IB1.DCvalue%1000/100,1,1);//
OLED_ShowNum(48,7,IB1.DCvalue%100/10,1,1);//
OLED_ShowChar(54,7,'A',1);//
OLED_ShowStr(66,7,"IC1:", 1);
OLED_ShowNum(90,7,IC1.DCvalue/10000,1,1);
OLED_ShowNum(96,7,IC1.DCvalue %10000/1000,1,1);//
OLED_ShowChar(102,7,'.',1);//
OLED_ShowNum(108,7,IC1.DCvalue %1000/100,1,1);//
OLED_ShowNum(114,7,IC1.DCvalue %100/10,1,1);//
OLED_ShowChar(120,7,'A',1);//
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface 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_DMA_Init();
MX_TIM3_Init();
MX_TIM2_Init();
MX_LPUART1_UART_Init();
MX_ADC1_Init();
MX_TIM4_Init();
MX_USART1_UART_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
GPIO_Init();
TIM_Init();//定时器端口初始化
OLED_Init();
OLED_CLS();//清屏
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 20);//20数据量
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED); // 校准ADC
OLED_ShowStr(0, 0,"OLED_TEXT", 2);
OLED_ShowStr(0, 2, "OLED_TEXT2", 2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
char str[255];
dianyaxs(); //电压显示
dianliuxs(); //电流显示
//__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,1500);
// 点亮LED
if(i>=7000)
{
sprintf(str,"%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f, %1.2f\r\n", ((float)ADC_Value[0]*3.3F/4096.0F),((float)ADC_Value[1]*3.3F/4096.0F),
((float)ADC_Value[2]*3.3F/4096.0F),((float)ADC_Value[3]*3.3F/4096.0F),((float)ADC_Value[4]*3.3F/4096.0F),((float)ADC_Value[5]*3.3F/4096.0F),
((float)ADC_Value[6]*3.3F/4096.0F),((float)ADC_Value[7]*3.3F/4096.0F),((float)ADC_Value[8]*3.3F/4096.0F),((float)ADC_Value[9]*3.3F/4096.0F),
((float)ADC_Value[10]*3.3F/4096.0F),((float)ADC_Value[11]*3.3F/4096.0F),((float)ADC_Value[12]*3.3F/4096.0F),((float)ADC_Value[13]*3.3F/4096.0F),
((float)ADC_Value[14]*3.3F/4096.0F),((float)ADC_Value[15]*3.3F/4096.0F),((float)ADC_Value[16]*3.3F/4096.0F),((float)ADC_Value[17]*3.3F/4096.0F),
((float)ADC_Value[18]*3.3F/4096.0F),((float)ADC_Value[19]*3.3F/4096.0F));
HAL_UART_Transmit(&hlpuart1, (uint8_t *)str, strlen(str) , 0xffff);
i=0;
}
}
/* 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_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6;
RCC_OscInitStruct.PLL.PLLN = 85;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses 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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();
}
/* USER CODE BEGIN 4 */
void TIM_Init(void)//定时器端口初始化
{
// 清除定时器初始化过程中的更新中断标志,避免定时器一启动就中断
__HAL_TIM_CLEAR_IT(&htim4, TIM_IT_UPDATE);
// 使能定时器4更新中断并启动定时器
HAL_TIM_Base_Start_IT(&htim4);
// 使能定时器2更新中断并启动定时器
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
// 使能定时器4更新中断并启动定时器
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
}
//控制函数
void control(void)
{
static uint16_t SPWMA1,SPWMB1,SPWMC1,SPWMA2,SPWMB2,SPWMC2;
static double MD_A1,MD_B1,MD_C1,MD_A2,MD_B2,MD_C2;
static float Upid_A,Upid_B,Upid_C;
static float U_Ki = 0.000136,I_Kp = 0.0001,I_Ki = 0.000005;
static short err_sum_A,err_sum_B,err_sum_C;
static short sum_IA,sum_IB,sum_IC,IA2_target,IB2_target,IC2_target;
static short rms_IA,rms_IB,rms_IC,rms_IA2_target,rms_IB2_target,rms_IC2_target;
static short err_IA,err_IB,err_IC;
static int err_IA_sum,err_IB_sum,err_IC_sum;
static uint16_t u_target;
//欠压保护
if(VIN > 3000)
ON_Flag = 1;
else if(VIN < 1000)
ON_Flag = 0;
if(ON_Flag==1)//开启输出
{
//计算相位
if(++PhaseC >= 180) //C相的相位加法器
{
PhaseC = 0;
SYNC_flag = 1;
}
PhaseB = PhaseC + 60 ;//计算B相相位
PhaseA = PhaseC + 120;//计算C相相位
if(PhaseB >= 180)//B相位限幅
PhaseB -= 180;
if(PhaseA >= 180)//C相位限幅
PhaseA -= 180;
//软启动
if(u_target < USET)
u_target ++;
//计算开环调制深度
MD_A1=MD_B1=MD_C1=MD_A2=MD_B2=MD_C2=(u_target*2.8284/VIN);
//PID算法
if(u_target == USET && 1 == PhaseC)
{
//计算误差积分
err_sum_A += u_target - UA.rms;
err_sum_B += u_target - UB.rms;
err_sum_C += u_target - UC.rms;
//误差积分限幅
if(err_sum_A > 2000) err_sum_A = 2000;
else if(err_sum_A < -2000) err_sum_A = -2000;
if(err_sum_B > 2000) err_sum_B = 2000;
else if(err_sum_B < -2000) err_sum_B = -2000;
if(err_sum_C > 2000) err_sum_C = 2000;
else if(err_sum_C < -2000) err_sum_C = -2000;
//积分控制
Upid_A = U_Ki * err_sum_A;
Upid_B = U_Ki * err_sum_B;
Upid_C = U_Ki * err_sum_C;
}
//计算稳压PID后的调制深度
MD_A1 += Upid_A;
MD_B1 += Upid_B;
MD_C1 += Upid_C;
MD_A2 += Upid_A;
MD_B2 += Upid_B;
MD_C2 += Upid_C;
// MD_A1 += 0.5;
// MD_B1 += 0.5;
// MD_C1 += 0.5;
// MD_A2 += 0.5;
// MD_B2 += 0.5;
// MD_C2 += 0.5;
/**************************
以下是电流比例控制程序
***************************/
// //计算总电流
// sum_IA = IA1.ACvalue + IA2.ACvalue ;
// sum_IB = IB1.ACvalue + IB2.ACvalue ;
// sum_IC = IC1.ACvalue + IC2.ACvalue ;
// rms_IA = IA1.rms + IA2.rms;
// rms_IB = IB1.rms + IB2.rms;
// rms_IC = IC1.rms + IC2.rms;
//
// //计算目标电流
// IA2_target = sum_IA * 10 / (10 + Curr_bili);
// IB2_target = sum_IB * 10 / (10 + Curr_bili);
// IC2_target = sum_IC * 10 / (10 + Curr_bili);
// rms_IA2_target = rms_IA * 10 / (10 + Curr_bili);
// rms_IB2_target = rms_IB * 10 / (10 + Curr_bili);
// rms_IC2_target = rms_IC * 10 / (10 + Curr_bili);
//
// //判断逆变器2的并联状态
// if(Binglian_flag)
// {
// if((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)==0) || (IA2.rms < 30 && IB2.rms < 30 && IC2.rms < 30)) //电流都小于30mA,判定并联断开
// Binglian_flag = 0;
// }
// else
// {
// if((1 == HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)==0) && (IA2.rms > 200 || IB2.rms > 200 || IC2.rms > 200)) //电流都大于200mA,判定并联
// Binglian_flag = 1;
// }
//
// //逆变器并联且非空载状态
// if(Binglian_flag && rms_IA > 200 && rms_IB > 200 && rms_IC > 200)
// {
// //均流工作,指示灯量
//
// //计算电流误差
// err_IA = (PhaseA < 90)? IA2.ACvalue - IA2_target : IA2_target - IA2.ACvalue ;//实际输出电流和目标输出电流的差值
// err_IB = (PhaseB < 90)? IB2.ACvalue - IB2_target : IB2_target - IB2.ACvalue ;
// err_IC = (PhaseC < 90)? IC2.ACvalue - IC2_target : IC2_target - IC2.ACvalue ;
// if(1 == PhaseC)
// {
// err_IA_sum += rms_IA2_target - IA2.rms;
// err_IB_sum += rms_IB2_target - IB2.rms;
// err_IC_sum += rms_IC2_target - IC2.rms;
//
// //积分限幅
// if(err_IA_sum > 10000) err_IA_sum = 10000;
// else if(err_IA_sum < -10000) err_IA_sum = -10000;
// if(err_IB_sum > 10000) err_IB_sum = 10000;
// else if(err_IB_sum < -10000) err_IB_sum = -10000;
// if(err_IC_sum > 10000) err_IC_sum = 10000;
// else if(err_IC_sum < -10000) err_IC_sum = -10000;
// }
//
// //均流PI控制
// MD_A2 += I_Kp * err_IA + err_IA_sum * I_Ki;
// MD_B2 += I_Kp * err_IB + err_IB_sum * I_Ki;
// MD_C2 += I_Kp * err_IC + err_IC_sum * I_Ki;
//
// }
// else
// {
// //逆变器2没并联或空载,不执行均流PID
// err_IA_sum = err_IB_sum = err_IC_sum = 0;
// }
//调制深度限幅
if(MD_A1 > 1)MD_A1 = 1;
if(MD_A2 > 1)MD_A2 = 1;
if(MD_B1 > 1)MD_B1 = 1;
if(MD_B2 > 1)MD_B2 = 1;
if(MD_C1 > 1)MD_C1 = 1;
if(MD_C2 > 1)MD_C2 = 1;
//计算逆变器的SPWM值
SPWMA1 = 2834 + MD_A1*spwm[PhaseA];
SPWMB1 = 2834 + MD_B1*spwm[PhaseB];
SPWMC1 = 2834 + MD_C1*spwm[PhaseC];
SPWMA2 = 2834 + MD_A2*spwm[PhaseA];
SPWMB2 = 2834 + MD_B2*spwm[PhaseB];
SPWMC2 = 2834 + MD_C2*spwm[PhaseC];
//更新SPWM
if(Binglian_flag)//逆变器处于并联状态
{
SPWM1_Refresh(1,SPWMA1,SPWMB1,SPWMC1);
SPWM2_Refresh(1,SPWMA2,SPWMB2,SPWMC2);
}
else//逆变器没并联,关闭逆变器2
{
SPWM1_Refresh(1,SPWMA1,SPWMB1,SPWMC1);
SPWM2_Refresh(0,0,0,0);
}
}
else//关闭输出
{
u_target = err_sum_A = err_sum_B = err_sum_C = 0;
SPWM1_Refresh(1,2834,2834,2834);
SPWM2_Refresh(0,0,0,0);
}
// //按键调节输出电流比例
// key_ctrl();
}
按键调节输出电流比例
//void key_ctrl(void)
//{
// static u8 key;
// key = KEY_Scan(1);//支持连按的按键扫描
// if(1 == key)
// {
// if(Curr_bili > 5)//最小电流比为1:2
// Curr_bili --;
// }
// else if(2 == key)
// {
// if(Curr_bili < 20)//最大电流比为2:1
// Curr_bili ++;
// }
//}
//更新逆变器1的PWM数据
void SPWM1_Refresh(uint8_t EN,uint16_t SPWMA,uint16_t SPWMB,uint16_t SPWMC)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,SPWMA);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,SPWMB);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,SPWMC);
}
//更新逆变器2的PWM数据
void SPWM2_Refresh(uint8_t EN,uint16_t SPWMA,uint16_t SPWMB,uint16_t SPWMC)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,SPWMA);
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_3,SPWMB);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_4,SPWMC);
}
void GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 打开GPIOB时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
// 配置GPIOB引脚为通用推挽输出
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == htim4.Instance)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
control();
get_value();
//书写我们想要执行的功能
}
if(htim->Instance == htim2.Instance)
{
i++;
//书写我们想要执行的功能
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
上面的代码是部分代码,还没有用到PID算法,只是开环的测试。
五、效果测试
图7:输入电压图
图8:输出电压和波形图
图9:输出电压和波形图
六、总结
从测试结果可以看出输出电压24V,峰峰值67.7V,频率50Hz,输出的正弦波也很完美!
本文已同步发表在微信公众号:基于STM32G474RET6微电网模拟系统功率电路设计 (qq.com)