1. 项目概述
这个基于STM32F103的绝缘检测方案,是我在充电桩项目中实际应用过的一个成熟设计。它采用不平衡电桥法测量高压系统的绝缘电阻,通过隔离RS485与主控板通信,已经在多个充电桩项目中稳定运行超过两年。
绝缘检测是高压电气系统安全的核心保障。当正极或负极对地绝缘电阻下降到危险值时,系统需要快速检测并切断电源。传统方案要么成本过高,要么精度不足。这个设计在性价比和可靠性之间找到了很好的平衡点。
2. 硬件设计解析
2.1 核心电路架构
整个硬件系统由三个关键部分组成:
-
高压采样电路:采用不平衡电桥结构,包含两个300kΩ精密电阻(误差1%)作为已知电阻,与被测绝缘电阻构成测量电桥。考虑到高压安全,所有高压走线都保持了足够的爬电距离(>5mm)。
-
STM32F103控制单元:负责ADC采样、计算绝缘电阻、控制继电器切换测量路径。选择这款MCU是因为它内置12位ADC,性价比高,且开发资源丰富。
-
隔离通信模块:使用ADM2587隔离型RS485芯片,确保高压侧与低压控制系统完全隔离。通信协议采用简单的ASCII文本协议,方便调试和兼容不同主控。
关键提示:高压侧的电阻必须选择耐高压型号(如1206封装),普通0805电阻在长期高压下可能发生击穿。
2.2 PCB设计要点
从提供的PCB图可以看出几个关键设计细节:
-
分层布局:高压采样电路(红色区域)集中在板子左侧,数字电路在右侧,中间通过光耦和隔离电源完全隔离。
-
安全间距:
- 初级侧(高压)与次级侧(低压)间距>8mm
- 高压走线线宽>1mm,与其他信号间距>2mm
- 所有高压焊盘都做了开窗处理,避免爬电
-
EMC设计:
- 每个IC的电源引脚都就近放置了去耦电容
- RS485接口端接120Ω匹配电阻
- 所有数字信号线都做了阻抗控制
3. 软件实现详解
3.1 核心算法实现
绝缘电阻的计算是整个系统的核心,算法实现在insulation_algo.c中。基本原理是利用基尔霍夫定律建立方程组:
c复制void INS_Calculate_Resistor(float v_mid_pos, float v_mid_neg, float v_bus, Insulation_Result_t *Result) {
// 输入有效性检查
if (v_bus < 10.0f) { // 母线电压低于10V视为无效
Result->status = 2;
return;
}
// 核心计算公式
float Rp = (R_BRIDGE_HIGH * (v_bus - v_mid_pos * 2.0f)) / (v_mid_pos * 2.0f);
float Rn = (R_BRIDGE_HIGH * (v_bus - v_mid_neg * 2.0f)) / (v_mid_neg * 2.0f);
// 结果处理
Result->r_positive = (Rp > 0) ? (Rp / 1000.0f) : 999.9f; // 转换为MΩ
Result->r_negative = (Rn > 0) ? (Rn / 1000.0f) : 999.9f;
// 报警判断(根据GB/T 18487.1-2015标准)
float threshold = v_bus / 500.0f; // 500Ω/V标准
Result->alarm_flag = (Result->r_positive < threshold) || (Result->r_negative < threshold);
}
3.2 主控程序流程
主程序采用状态机设计,确保实时性和可靠性:
c复制void Main_Loop(void) {
static uint32_t last_sample_time = 0;
// 1. 定时采样(1Hz)
if (HAL_GetTick() - last_sample_time >= 1000) {
last_sample_time = HAL_GetTick();
// 2. 切换继电器测量正负极电压
HAL_GPIO_WritePin(RELAY_POS_GPIO_Port, RELAY_POS_Pin, GPIO_PIN_SET);
HAL_Delay(10); // 等待稳定
float v_pos = Read_ADC(ADC_CH_POS);
HAL_GPIO_WritePin(RELAY_POS_GPIO_Port, RELAY_POS_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RELAY_NEG_GPIO_Port, RELAY_NEG_Pin, GPIO_PIN_SET);
HAL_Delay(10);
float v_neg = Read_ADC(ADC_CH_NEG);
// 3. 计算绝缘电阻
float v_bus = Read_Bus_Voltage();
INS_Calculate_Resistor(v_pos, v_neg, v_bus, &g_ins_result);
// 4. 处理报警
if (g_ins_result.alarm_flag) {
Safety_Shutdown();
}
// 5. 上报数据
RS485_Send_Result(&g_ins_result);
}
// 其他后台任务...
}
4. 通信协议设计
采用简单的ASCII协议,便于调试和兼容:
code复制格式:$INS,Rp=<值>,Rn=<值>,Ubus=<值>,Alarm=<状态>*<校验和>\r\n
示例:
$INS,Rp=1.25,Rn=0.98,Ubus=400.0,Alarm=0*7A\r\n
校验和计算:
c复制uint8_t Calc_Checksum(const char *str) {
uint8_t sum = 0;
while (*str) {
sum ^= *str++;
}
return sum;
}
5. 实测数据与优化
在实际应用中,我们发现几个关键点需要特别注意:
-
温度补偿:精密电阻值会随温度变化,我们在算法中增加了温度补偿系数:
c复制// 温度补偿公式(需根据实际电阻温度系数调整) float temp_comp = 1.0f + 0.0005f * (current_temp - 25.0f); R_BRIDGE_HIGH = R_BRIDGE_HIGH_NOMINAL * temp_comp; -
ADC滤波:高压环境下噪声较大,采用滑动平均滤波:
c复制#define FILTER_SIZE 8 float ADC_Filter(float new_val) { static float buffer[FILTER_SIZE] = {0}; static uint8_t index = 0; buffer[index++] = new_val; if (index >= FILTER_SIZE) index = 0; float sum = 0; for (int i = 0; i < FILTER_SIZE; i++) { sum += buffer[i]; } return sum / FILTER_SIZE; } -
继电器寿命:频繁切换会降低继电器寿命,我们优化为:
- 正常状态下每10秒测量一次
- 检测到绝缘下降时提高到每秒一次
- 使用高质量汽车级继电器(>100万次寿命)
6. 常见问题排查
在实际部署中遇到的典型问题及解决方案:
-
测量值跳动大
- 检查高压侧电源稳定性
- 增加ADC采样次数和滤波
- 确保继电器接触良好
-
通信中断
- 检查RS485终端电阻(120Ω)
- 确认隔离电源工作正常
- 测试A/B线是否反接
-
误报警
- 检查温度补偿是否启用
- 验证电阻精度(建议使用0.1%精密电阻)
- 调整报警阈值(根据具体应用场景)
7. 生产测试方案
为确保批量生产质量,我们设计了专门的测试流程:
-
高压测试:
- 施加500VDC测试电压
- 验证测量精度(±5%以内)
- 测试绝缘耐压(2000VAC/1min)
-
通信测试:
- 连续发送1000帧测试数据
- 验证误码率(<0.001%)
- 测试抗干扰能力
-
环境测试:
- 高温(85℃)和低温(-40℃)测试
- 湿热循环测试
- 振动测试(模拟车载环境)
这个方案已经成功应用于多个充电桩项目,累计运行超过50万小时,证明了其可靠性和稳定性。对于想开发类似产品的工程师,这个设计提供了完整的参考实现,可以根据具体需求进行调整和优化。
