尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于V2G的电动汽车充电站调度模型:从线性规划到工程校准

基于V2G的电动汽车充电站调度模型:从线性规划到工程校准 简介V2GVehicle-to-Grid技术允许电动汽车反向放电将动力电池作为分布式储能参与电网互动是新型电力系统中充电站实现削峰填谷、降低需量电费的关键路径。构建一个可落地的充电站调度模型需要同时处理车辆电池SOC边界、双向充电桩效率不对称、站级功率平衡以及电网馈电限制等约束并显式纳入电池退化成本以避免过度放电。在工程实践中通常用线性规划快速求解最优充放电功率再通过保底SOC、离场时间掩码和爬坡速率限制使结果具备可执行性。最后利用单桩放电试验和关口表数据校准模型可显著提升净购电功率与SOC跟踪精度。本文以Python为例从建模粒度、约束推导到参数校准完整说明基于V2G的电动汽车充电站模型的实现要点为园区能源管理和配网评估提供参考。1. 为什么要“基于V2G的电动汽车充电站模型”从一个高峰期的场景说起傍晚 6 点一栋办公楼的停车场里 20 辆电动汽车同时插上充电枪园区变压器负荷瞬间逼近上限半小时后部分车辆要离开可它们的 SOC 才刚过 50%。如果充电站只做“有序充电”车队只能在低谷时段用电车辆到高峰时段就变成昂贵的闲置储能而“基于V2G的电动汽车充电站模型”要解决的正是这类让每辆车按电价和行程反向往电网放电、再在低谷补电的调度问题。它不是一个拓扑结构图纸而是一套既能回答“哪辆车在哪一刻充多少千瓦、放多少千瓦”又能算出放电损耗和电池退化成本的优化模型。对做充电站运营、园区能源管理或者配网评估的工程师来说这个模型的颗粒度直接决定后续投资回报测算和变压器扩容申请的准确度所以值得把它的边界、参数和实现方式一次讲透。2. 拆解V2G充电站模型的四层结构车辆、桩、站级调度与电网边界常见做法是把一天按 15 分钟切分形成 96 个时隙模型在每个时隙里给出每辆车的充放电功率、站内净购电功率和变压器峰值。V2G 与普通有序充电的本质差别在于多了“反向放电”这个自由度因此建模时如果只把充电桩额定功率填进去结果会与实际运行差得很远。2.1 车、桩、站、电网四类对象的建模粒度一个可落地的 V2G 充电站模型通常分四层处理车端电池、双向充电桩、站级聚合器、电网计量点。每一层的建模粒度不同需要的输入参数也不同下面这张表可以当作建模清单层级典型对象核心参数电场/网络需要输出的东西车辆层动力电池、出行计划电池容量、初始SOC、最小/最大SOC、到达离开时隙每个时隙可充、可放的最大功率桩端层双向DC/DC变换器额定充/放电功率、充放电效率、待机损耗净功率 充电功率 / 放电效率站级层站控系统/EMS变压器容量、其他固定负荷、电价总购电功率、总放电功率上限电网层关口计量、需求响应信号尖峰电价、需量电价、并网约束净购电功率曲线、最大需量预测车辆层不建议用一个固定“平均SOC”去代表所有车至少要把每辆车的到达时刻、离开时刻和保底SOC单独记录。因为V2G调度能否执行取决于车停在站内的时间窗口一辆只在早上 8 点到下午 5 点停着的办公车和一辆晚间 1 点入场的网约车它们的放电可用性完全相反。我一般会在输入参数里加两个硬边界leave_soc_min表示车主离场时要求的最低SOCsoc_min表示电池运行安全下限前者通常比后者高。桩端层最容易忽略的是“充放电效率不对称”。直流快充桩的效率通常在 0.92 左右但放电时电能不能直接等于充电效率的倒数因为DC/DC变换器在轻载或重载下的损耗曲线不同。做规划模型时用恒定效率没问题用于容量设计则需要把每个功率段实测效率拟合进去否则晚高峰放电收益会被严重高估。站级层的核心约束是“净功率等于负荷加充电减放电”。有些模型会把放电功率直接当成负负荷写在功率平衡里这种做法在数学上没有错但不利于分别限制充放电功率。更严谨的写法是P_grid[t] P_base[t] Σ P_AC_charge[i,t] - Σ P_AC_discharge[i,t]其中电网功率可以是负值负值表示向电网馈电。电网层的电价模型同样要拆成购电价和上网电价。大多数园区没有现货市场所谓V2G收益其实是节省的需量电费加上峰谷套利如果模型里只写分时电价而不写需量电费就会低估V2G的价值。2.2 电池退化成本如何进入目标函数很多人看到V2G的第一反应是“低谷充、高峰放”但真正拦住项目落地的不是技术而是电池寿命。放电会带来额外循环次数而充电站运营商并不一定承担电池损耗成本导致模型算出来的最优策略总是“尽量多放”在现实中却没人愿意配合。为了让结果可信目标函数中必须显式加入放电退化惩罚。常用做法是给每千瓦时放电设定一个单位成本经验值在 0.08 到 0.3 元/kWh 之间具体与电池循环寿命和电芯成本相关。比如某车型电池循环寿命在 1000 次时衰减到 80%可用电量 60kWh对应总吞吐能量约 60000kWh若更换成本按 6 万元估算退化成本就大约是 1 元/kWh。这个数看着很高所以实际项目中常用半经验公式把放电深度也考虑进去放电深度越深单次循环造成的容量衰减越大。在模型里可以给degradation_cost_per_kwh乘上一个与放电功率和 SOC 区间有关的系数虽然没有电化学模型那么精准但足以让优化器不要在浅谷时段频繁放电。2.3 功率边界与通信时延的取舍建模时还有一个容易被忽略的边界车端BMS与充电桩之间每次下发功率指令都需要握手时间。V2G 调度周期通常取 15 分钟但真正的功率响应是分钟级以内的如果模型按 1 分钟仿真会陷入大量短期随机波动算出的变压器峰值反而偏悲观。建议把时间尺度分成两层电网调度层用 15 分钟或 1 小时充电桩执行层用秒级时间常数去校核电压和频率控制。这两个模型不需要合并成一个超级模型V2G充电站模型的核心是能量调度不是在数字孪生里复刻每个IGBT的开关过程。3. 用Python写一个可运行的最小V2G充电站调度模型下面用一个简化案例演示完整建模过程假设站内有 4 辆电动汽车全天 96 个时隙都在站内电价采用峰谷两段式变压器上限为 100 kW充电桩双向功率最大为 30 kW。这个案例屏蔽了到达离开窗口先把电压、控制逻辑放在一边专注把目标函数和约束写成可运行的线性规划。3.1 准备车辆、电价和变压器容量参数先用 NumPy 定义输入。注意所有功率单位统一为 kW能量单位 kWh时间步长 0.25 小时。import numpy as np from scipy.optimize import linprog T 96 # 一天96个时隙15分钟一个 dt 0.25 # 时隙长度单位小时 N 4 # 车辆数 P_grid_max 100.0 # 变压器允许最大净购电功率 kW P_feed_max 60.0 # 允许向电网反向馈电的功率上限 kW eta_c 0.92 # 充电效率 eta_d 0.90 # 放电效率 degradation_cost 0.15 # 每放1kWh电的电池退化成本元/kWh # 分时电价元/kWh前48个时隙为谷段后面为峰段 buy_price np.where(np.arange(T) 48, 0.35, 0.85).astype(float) sell_price np.full(T, 0.20) # 固定上网电价远低于购电价 # 车辆电池参数 E_battery np.array([75.0, 60.0, 90.0, 50.0]) # 电池容量 kWh E_init np.array([65.0, 50.0, 80.0, 40.0]) # 初始SOC kWh soc_min 0.10 soc_max 0.90 E_min E_battery * soc_min E_max E_battery * soc_max Pc_max np.full(N, 30.0) # 每辆车最大充电功率 kW Pd_max np.full(N, 30.0) # 每辆车最大放电功率 kW P_base np.full(T, 40.0) # 充电站其他负荷 kW代码里的buy_price和sell_price是两个独立的数组不要合并成一个净电价。因为在约束条件里购电和馈电是同一个电网节点的正负两个方向分开写便于后续修改电力市场规则。E_min和E_max不是给同一辆车的所有时隙共用同一个上下限而是每辆车在每个时隙都必须满足的一个能量窗口。3.2 构建线性规划的目标函数与约束为了简化使用分段线性电价处理购电和馈电。设置两个变量net_power[t]是站内净购电功率正数表示从电网买电负数表示向电网放电再引入辅助变量grid_cost[t]让它既大于等于buy_price[t] * net_power[t]又大于等于sell_price[t] * net_power[t]。这样优化器会恰好取两者中的较大值从而在用线性规划的同时避开“购电和馈电同时为正”的建模陷阱。n_c N * T n_d N * T n_net T n_cost T n_vars n_c n_d n_net n_cost def cvar(i, t): return i * T t def dvar(i, t): return n_c i * T t def netvar(t): return n_c n_d t def costvar(t): return n_c n_d n_net t # 目标函数系数 c np.zeros(n_vars) c[n_c:n_cn_d] degradation_cost # 放电惩罚 c[n_cn_dn_net:] 1.0 # grid_cost 系数 bounds [(0, None)] * n_vars for i in range(N): for t in range(T): bounds[cvar(i,t)] (0, Pc_max[i]) bounds[dvar(i,t)] (0, Pd_max[i]) for t in range(T): bounds[netvar(t)] (-P_feed_max, P_grid_max) bounds[costvar(t)] (0, None) A_ub [] b_ub [] for t in range(T): for i in range(N): row np.zeros(n_vars) row[netvar(t)] buy_price[t] row[costvar(t)] -1.0 A_ub.append(row); b_ub.append(0) row np.zeros(n_vars) row[netvar(t)] sell_price[t] row[costvar(t)] -1.0 A_ub.append(row); b_ub.append(0)上面这段先构建目标函数和辅助约束。这里给每个时隙都加了两条不等式grid_cost buy_price * net和grid_cost sell_price * net。由于网络净功率为负时卖电收益高buy_price * net是负的sell_price * net也是负的取两者较大值刚好等于向电网馈电的收益也就是负成本。边界条件里给net设置了上下限确保变压器反送功率不超过并网许可。接下来是电量平衡和能量上下限约束A_eq [] b_eq [] # 功率平衡净购电 总放电 底座负荷 总充电 for t in range(T): row np.zeros(n_vars) row[netvar(t)] 1.0 for i in range(N): row[cvar(i,t)] -1.0 # 充电作为负荷 row[dvar(i,t)] 1.0 # 放电抵消负荷 A_eq.append(row) b_eq.append(P_base[t]) # 电池能量约束每个时隙SOC上下限 for i in range(N): for t in range(T): row np.zeros(n_vars) row[cvar(i,t)] eta_c * dt row[dvar(i,t)] -dt / eta_d # 累计充电能量不能超过最大容量 A_ub.append(row); b_ub.append(E_max[i] - E_init[i]) # 累计放电能量不能超过最低保底 row np.zeros(n_vars) row[cvar(i,t)] -eta_c * dt row[dvar(i,t)] dt / eta_d A_ub.append(row); b_ub.append(E_init[i] - E_min[i])这段是模型正确性的关键。功率平衡约束的符号不能写反否则充电变成了放电。能量约束用累加形式不需要额外引入SOC状态变量因为每个时隙的累计充放能量就等于当前SOC变化量。E_max[i] - E_init[i]表示从初始SOC到满电还能充进多少能量E_init[i] - E_min[i]表示从初始SOC还能放出多少能量。这里的上下界约束在每一个时隙都成立比只在离开时检查更严格能避免中间时刻电池过充或过放。调用求解器并输出结果res linprog(c, A_ubA_ub, b_ubb_ub, A_eqA_eq, b_eqb_eq, boundsbounds, methodhighs) if res.success: net res.x[n_cn_d:n_cn_dT] total_cost res.fun print(f总运行成本: {total_cost:.2f} 元) print(f最大净购电功率: {net.max():.2f} kW) print(f最大馈电功率: {-net.min():.2f} kW)求解结果里最值得看的是net曲线。峰电价时段如果net出现负值说明模型在安排放电谷电价时段net升高说明调度策略在做储能补电。如果在结果里看到变压器峰值没有突破P_grid_max说明功率约束生效了。3.3 最小模型中容易被忽略的参数设置上面的最小模型需要特别注意三个参数eta_d、degradation_cost和P_feed_max。eta_d是直流侧放电效率工程上建议取充电效率的 0.950.98不要直接用充电效率因为两个方向的损耗不完全相同。degradation_cost如果设置成 0模型会把放电当成免费服务峰时段很可能把每辆车放到 SOC 下限结果虽然报表好看实际无法执行。P_feed_max是充电站与电网之间的馈电上限由当地并网政策决定。有些园区不允许反向馈电这时把它设为 0模型就会退化成单向有序充电模型这也验证了模型结构兼容 V1G。4. 从数学解到执行计划保底SOC、削峰填谷与充放电切换线性规划求出的结果只是一组最优功率序列真正下发到充电桩之前还要检查车辆离开时间、保底SOC和通信时延。这一章从不那么数学的角度讲三个工程化问题。4.1 用保底SOC与离场时间避免“空头调度”上面最小模型假设所有车全天候连接现实中车辆在任意时隙都可能离开。如果一辆车在 16:00 离开模型却安排它在 15:30 放电到最低SOC司机回来时直接没法上路。解决办法是把“可用时间窗口”做成硬约束。具体做法不是把到达和离开写进代码枚举而是把每辆车允许放电的时隙集合提前过滤掉在放电变量上乘一个available[i,t]布尔矩阵不允许放电的时隙直接置为 0。同时设置离场SOC目标例如要求离开时电量不低于电池容量的 70%否则模型只能为这辆车安排充电不能安排放电。# 假设每辆车的离场SOC目标kWh leave_soc_target np.array([60.0, 48.0, 72.0, 40.0]) for i in range(N): last_t 95 row np.zeros(n_vars) total_energy_corr 0.0 for t in range(last_t 1): if available[i, t]: row[cvar(i,t)] eta_c * dt row[dvar(i,t)] -dt / eta_d # 离开时刻前累加量 初始电量 离场目标 A_ub.append(row) b_ub.append(leave_soc_target[i] - E_init[i])这里把available[i,t]作为掩码提前过滤。注意离开时刻当天的最后可用时隙不要多取否则会把车辆已经开走之后的“虚拟充电”算进去。4.2 削峰填谷把需量电费写进目标函数很多园区V2G项目的核心收益不是峰谷电价差而是容量电费或需量电费。变压器容量按最大需量收费因此哪怕一个月只有一次晚高峰超限整月基础电费都会被抬高。要让模型自动削峰需要给目标函数增加一个变压器峰值变量M并满足M net_power[t]对所有时隙成立。在目标函数中给M放大一个比较大的权重例如每千瓦每月收费 30 元折算到一天就是 1 元/kW。M_var n_vars n_vars_new n_vars 1 c_new np.append(c, 30.0) # 峰值需量电费权重 元/kW/天 bounds.append((0, P_grid_max)) for t in range(T): row np.zeros(n_vars_new) row[netvar(t)] 1.0 row[M_var] -1.0 A_ub.append(row) b_ub.append(0)加入这个约束后模型会在“峰时放电”和“压低一个月峰值”之间做权衡。如果需量电费权重远大于峰谷电价收益模型甚至会安排一些 SOC 较高的车辆在非峰时段也微放电目的是不让峰值出现在任意一个时隙。这种行为的代价是电池退化成本上升所以权重不能拍脑袋要按当地供电公司的实际计费条款换算成日成本。4.3 充放电切换的工程限制模型输出的功率序列可能在两个相邻时隙出现“先充电后放电”的频繁切换这种切换对车端继电器和站内直流母线电容都有寿命影响。工程上一般会给功率调度增加一个最小持续时长约束或者用指数平滑把功率指令滤波之后再下发。常见做法是在模型后面加一个速率限制例如相邻时隙充放电功率变化不大于 15 kW/15minfor t in range(T - 1): row np.zeros(n_vars_new) row[netvar(t)] 1.0 row[netvar(t1)] -1.0 A_ub.append(row); b_ub.append(15.0) row np.zeros(n_vars_new) row[netvar(t1)] 1.0 row[netvar(t)] -1.0 A_ub.append(row); b_ub.append(15.0)这一组约束同时限制了向上和向下爬坡速率。15 kW 是示例值具体根据充电桩厂商的功率响应速度来定太大会让模型频繁来回切换太小会损失峰谷套利机会。5. 用一场实际放电试验校准基于V2G的电动汽车充电站模型V2G模型落地前建议先做一次“单桩单车的 3 小时放电标定”不要直接整站上线。标定的目标不是验证调度算法而是把充电桩效率、BMS SOC估算误差和站内控制器时延这三个最容易带偏模型的环节校准到可接受范围。具体操作选一辆 SOC 在 80% 以上、桩端功率最大能到 30 kW 的车辆用固定功率 20 kW 连续放电三小时记录每 15 分钟的桩端交流侧电量、车端BMS累计放电能量和反向电表读数。然后对比桩端软件上报的放电功率和电表实测值算出该功率点下的真实放电效率。整理成下表功率点BMS显示放电能量(kWh)电表实测放电能量(kWh)等效效率10 kW30.027.60.9220 kW60.054.00.9030 kW90.079.20.88得到三个离散效率点后不直接替换eta_d而是把模型里的恒定效率改成分段线性表。离散点越多效果越好至少从 10 kW、20 kW、30 kW 三个功率点开始低于 10 kW 的放电场景在工程上很少使用可以不参与拟合。标定完效率后再把实际某一天的电价、车辆SOC和离场时间带进模型重新计算比较模型预测的整站净购电功率曲线与当天实际关口表曲线。关键误差指标有两个净功率曲线的平均绝对百分比误差应小于 15%SOC跟踪误差小于 5%。如果SOC误差偏大先检查BMS车辆端上报SOC是否在充电和放电两个方向使用了不同滤波策略如果净功率误差大但SOC误差小问题通常出在站内其他负荷可能混入空调、监控等设备。此时我给每个时隙增加一个unknown_base_load待定系数用前一周的负荷数据做最小二乘回归把固定负荷和随机负荷拆开。这个方法比盲目调整效率系数更可靠。校准后的模型再去跑削峰填谷策略输出的曲线才有资格作为申报需求响应容量和变压器扩容的依据。本文还有配套的精品资源点击获取
返回列表