量产成熟逆变器方案全桥并离网方案STM32F103源代码原理图PCB 主控平台:STM32F103RCT6 逆变拓扑:BOOST+全桥 功率:750W 功能:并网充电、放电;并网离网自动切换;485通讯; 描述1:本方案适用于,提供完善的通讯协议适配BMS和上位机;本方案可实现并网充电、放电;自动判断并离网切换;可实现并机功能;风扇智能控制;提供过流、过压、短路、过温等全方位的保护!!! 描述2:本方案含C源代码、原理图和PCB。
在新能源玩家圈子里混久了,总想搞点硬核的DIY项目。最近折腾了个基于STM32F103的750W全桥逆变器方案,这玩意儿既能并网又能离网运行,还能自动切换模式。电路板上那颗STM32F103RCT6主控芯片虽然年纪大了点,但对付这种实时控制场景依然稳如老狗。
主控初始化时特别注意了PWM模块的配置,毕竟逆变器的命脉全在这里。代码里这段时钟配置是关键:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseInitTypeDef TIM_BaseStruct; TIM_BaseStruct.TIM_Prescaler = 72-1; //1MHz计数频率 TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_BaseStruct.TIM_Period = 1000-1; //1kHz开关频率 TIM_TimeBaseInit(TIM1, &TIM_BaseStruct);这里把TIM1的PWM频率定在1kHz,平衡了开关损耗和输出波形质量。实际测试发现,当负载突变时,这个频率下的动态响应最不容易炸管。
保护机制是逆变器的灵魂,我在中断服务函数里埋了几个彩蛋。比如过流检测的这段骚操作:
void ADC_IRQHandler(void) { if(ADC_GetITStatus(ADC1, ADC_IT_JEOC)) { uint16_t curr_val = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); if(curr_val > 2800) { //对应75A过流阈值 GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); //紧急拉高保护引脚 TIM_CtrlPWMOutputs(TIM1, DISABLE); //瞬间关闭所有PWM输出 Fault_LED_Blink(0x5555); //故障灯特定闪烁模式 } ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); } }用ADC注入通道实现硬件级过流保护,响应时间控制在5μs以内。现场实测时故意拿钳子短路输出端,MOS管安然无恙,倒是鳄鱼夹被烧出个坑...
量产成熟逆变器方案全桥并离网方案STM32F103源代码原理图PCB 主控平台:STM32F103RCT6 逆变拓扑:BOOST+全桥 功率:750W 功能:并网充电、放电;并网离网自动切换;485通讯; 描述1:本方案适用于,提供完善的通讯协议适配BMS和上位机;本方案可实现并网充电、放电;自动判断并离网切换;可实现并机功能;风扇智能控制;提供过流、过压、短路、过温等全方位的保护!!! 描述2:本方案含C源代码、原理图和PCB。
并离网切换的逻辑有点像打地鼠游戏。主循环里有个状态机不断扫描电网参数:
void Grid_Check_Task(void) { static uint8_t grid_status = 0; float grid_voltage = Get_GridVoltage(); if((grid_voltage > 198) && (grid_voltage < 242)) { if(grid_status == 0) { Switch_TO_GridMode(); grid_status = 1; } } else { if(grid_status == 1) { Switch_TO_OffGridMode(); grid_status = 0; } } }这个阈值区间是根据国内电网特性设置的,实际部署时要考虑电压波动的惯性。有次在城中村测试,电网电压像过山车一样在180-250V之间乱跳,加了滑动平均滤波后才稳定下来。
原理图里最烧脑的是Boost+全桥的驱动部分,PCB布局时把驱动环路面积压缩到极致。有个血的教训:最初版本没做隔离电源,上电瞬间MOS管直接表演天女散花。后来改用这种带自举电路的驱动方案,连续满载运行两小时,散热片温度稳定在68℃左右。
这套方案最爽的是支持多机并联,通过485总线可以组个微型电站。协议栈里自定义了轻量级Modbus,实测同时控制8台设备时,500ms的轮询周期依然流畅。不过建议别用标准库自带的串口函数,改用DMA+环形缓冲区才是王道。
风扇控制算法玩了个小心机——根据MOS管温度和电容寿命做动态调整。代码里用PID控制占空比,但加了温度滞回区间防止风扇抽风:
void Fan_Speed_Control(float temp) { static float last_out = 0; float error = SET_TEMP - temp; float p_term = KP * error; float i_term += KI * error * DT; float d_term = KD * (error - last_error) / DT; float output = p_term + i_term + d_term; output = constrain(output, 0, 100); if(fabs(temp - last_temp) > 2) { //温度变化超过2℃才更新PWM TIM_SetCompare2(TIM2, (uint16_t)(output*10)); last_temp = temp; } last_error = error; }实测发现,这种带死区的控制策略能让风扇寿命延长至少30%。现在这台样机已经连续吃灰三个月,再次上电依然健步如飞。