前两年我替一家8万平米的购物中心做过一次能耗摸底,走进制冷机房的时候,4台离心机组全是满负荷状态,电表上的读数比商场营业员的热情还高涨。等我把一个月的电费单按照“空调用电、照明用电、扶梯用电、餐饮动力用电”拆完,发现空调系统占了整整57%,而且大部分浪费不是设备老化,而是策略问题。今天这篇就围绕这套能源监测系统的设计思路和源码工程来聊,重点讲清楚动态调节制冷策略怎么做到省电30%,以及这套系统落地时那些代码之外的真实经验。
这套内容适合谁看?如果你是商场的工程负责人、做建筑节能改造的工程师、独立接项目外包的开发,或者就是想用Python在工业生产环境里做一套能跑起来的数据采集加策略控制系统的朋友,都可以直接参考。核心思路用到的是数据采集、负荷预测、规则引擎和冷冻水系统联动控制,全部有源码和可落地的步骤,但有一个前提我必须先说:省电多少,取决于你原本的运行策略有多粗放,这套系统的本质是把“不知道什么时候该休息”的空调,变成“按需供给”的空调。
1. 商场空调用电的账单真相:24小时转不等于24小时都需要满负荷
先说一个反常识的事实:商场空调之所以24小时在转,并不完全是因为制冷需求,更多时候是因为水系统和风系统“不能随便停”。冷冻水一旦停止循环,管道里的水会快速升温,第二天开机时主机要花大量能量重新把整栋楼的水打冷;空调箱夜间停止送风,第二天开业前两小时室内温度可能完全不在舒适区。所以很多物业干脆让冷冻水泵、冷却水泵、空调箱24小时通电,主机在夜间进入低负载待机。这个“反正不能停”的惯性思维,才是电费爆表的第一个大漏洞。
1.1 制冷机房固定套餐式运行才是电费腰包的最大漏洞
绝大多数商场的运行策略可以用三个字概括:固定套餐。冷冻水供水温度常年设定在7℃,无论室外是15℃还是35℃;主机“开两台”就全年开两台,几乎不做台数加减载;二次泵频率半年调一次,甚至从来没人动过。
这里我先给一个最直接的账本。一个8万平米的购物中心,在制冷季的典型工况下,主机加冷冻泵加冷却塔加末端空调箱,运行功率大概在1200kW到1500kW之间。按每天运行14小时、电价0.8元来算,一天的电费是1.3万到1.7万,一个30天的制冷月就是40万到50万。如果能把其中30%的能量浪费挤掉,一个月省下12万到15万,一个制冷季就是四五十万的真金白银。省下的这部分钱,足够把整套监测系统的硬件费用赚回来好几次。
从控制角度看,固定套餐浪费在哪里?我拆成三条说。
- 冷水机组全部在低负载率区间运行:两台主机各带45%负载,而不是一台满载一台休眠,综合COP会显著下降。离心机在45%负载下的COP往往只有满载COP的70%。
- 供回水温差普遍只有2到3℃:正常设计温差应该在5℃左右。温差小说明水流量过大,二次泵在拼命输送“多余的水”,这部分的电能完全变成热量。
- 末端的风机盘管和空调箱过度除湿再加热:供水温度过低导致室内湿负荷被过度处理,风机全速运行,电耗跟着线性上涨。
1.2 商场负荷的脉冲式节奏,天然需要动态策略
商场的负荷从来不是一条直线,它有极强的节奏感。早上8点开门前,整个建筑就像一个冷库,需要在两小时内把室温从夜间值班温度拉到24℃;上午11点和下午2点是客流高峰,人本身就是巨大的热源,每个人体散热大约在100W到120W,5000人的客流相当于额外半兆瓦的热负荷;晚上打烊后,只剩下值班照明和少量清洁人员,负荷瞬间回落到白天的30%。
以前我见过有工程经理尝试调策略,但每次都是拍脑袋改一次,过几天又手动改回去,最终放弃。原因很现实:人不可能每天盯着室外温度和客流变化去推设定值,更不可能精确算出几点该加减载一台机组。指望人工调节,执行不了也坚持不了。这也是为什么需要一套“能源监测系统”先解决数据看不见的问题,再用“动态调节策略”解决数据不会用的问题。
2. 能源监测系统的数据底座:先学会看表,再学会算账
任何节能策略的前提都是数据可靠。如果电表读数都不准,温度传感器位置装错了,后面所有算法都是纸上谈兵。我在做这套工程时,数据采集层的原则很简单:先采集、先验证、再控制。控制这件事,要放在数据稳定运行两周之后才开始做,不要一上来就全自动。
2.1 采集对象的确定:不是所有数据都要,先抓住四类关键量
监控点位不是越多越好,种类太多反而会陷入数据沼泽。我按优先级排了四类:
- 电量类:制冷机房总进线、各台主机、冷冻泵、冷却泵、冷却塔风机、空调箱配电箱。电表优先选带Modbus RTU或者Modbus TCP协议的智能电表,没有条件的可以加电流互感器加测量模块。
- 水温度类:冷冻水供水温度、回水温度、冷却水供水温度、回水温度。这里要强调的是,温度传感器必须插在管道上的测温套管里,不要贴管壁,更不要暴露在空气中。测温套管位置要在水泵后的直管段,避开弯头和阀门。
- 流量类:冷冻水总管流量。用电磁流量计优先,没有的话也可以用超声波流量计,但后者对直管段长度非常敏感,安装位置不对测出来的流量曲线根本不能用。
- 状态类:主机的启停状态、故障报警、电流百分比、冷却塔风机启停档位、各类水泵的频率反馈。
这些数据全部汇入现场边缘网关,网关的作用是协议转换和缓存,防止网络抖动丢数据。网关再通过MQTT上报到机房内的本地服务器或时序数据库。
2.2 Modbus采集的常见坑:地址表、字节序和数据精度
写采集代码前,一定要先向设备厂家要一份寄存器地址表,然后拿着地址表一个一个点核对。我遇到过太多“读出来数值奇怪”的案例,十有八九不是设备坏了,而是字节序搞反了。Modbus协议传输16位寄存器,32位浮点数通常占两个寄存器,到底是高16位在前还是低16位在前,各个电表厂家完全不一样。
下面这段代码是我在项目中用的Modbus采集核心逻辑,用pymodbus实现,重点是验证寄存器缩放系数和字节序:
import struct from pymodbus.client import ModbusTcpClient client = ModbusTcpClient("192.168.100.50", port=502) def read_float(client, address, unit=1, byteorder="big"): # 连续读取两个16位寄存器,并按指定字节序拼接为32位float rr = client.read_holding_registers(address, 2, unit=unit) if rr.isError(): raise RuntimeError(f"read failed at register {address}") regs = rr.registers if byteorder == "big": # 高16位在前的常见用法 raw = struct.pack(">HH", regs[0], regs[1]) else: # 有些厂家是低16位在前,这种最坑 raw = struct.pack(">HH", regs[1], regs[0]) return struct.unpack(">f", raw)[0] # 示例:读取1号冷冻泵电流百分比,地址来自设备手册 current_pct = read_float(client, 0x010A, unit=1) print(f"1号冷冻泵电流百分比: {current_pct:.1f}%")如果你拿到的手册只写了“浮点数,地址从0x010A开始”,却没写字节序,那就在现场做一个最简单的校验:对比电表表头显示的值和代码读出来的值,如果数值差得离谱,就把byteorder换一下再读。这个笨办法比看手册有效得多。
另外要注意缩放系数。很多电表直接上报原始整数,比如电压寄存器值是23000,实际电压是230V,缩放系数是100。看到这种数据别急着存,先在网关里统一换算成工程单位,否则后面分析的时候你会被一堆“大数”搞晕。
2.3 数据存储的后端链路:时序数据库加看板
采集上来的数据我建议存到InfluxDB这类时序数据库,字段结构按点位、量测类型、设备分组设计:
| 字段 | 示例 | 说明 |
|---|---|---|
| measurement | chiller_power | 表示测点归属,如主机功率 |
| tags | device=chiller_01, floor=B1 | 标签用来检索和分组 |
| field | value=526.8 | 实际数值 |
| timestamp | 2025-07-10 14:00:00 | 采样时间 |
| 采样间隔 | 30s到60s | 策略计算不需要秒级数据,30秒足够 |
Grafana直接接InfluxDB做看板,主机功率曲线、冷冻水温差曲线、室外温度曲线、能耗累计值全部一张大屏看全。这个看板主要给谁看?给物业经理看。如果物业经理看不懂,说明图表设计失败了。一定要把“今天空调用了多少钱”“今天比上周省了多少”用明明白白的数字怼到屏幕上,这才是系统存在的价值。
3. 动态调节制冷策略:从定频硬扛到按需供给,关键在于这四个抓手
有了数据底座,才有资格谈策略。动态调节的核心不是一套黑科技算法,而是四个可执行、可验证、可回退的控制抓手。
3.1 抓手一:冷冻水供水温度动态设定
这是见效最快、改造成本几乎为零的措施。离心式冷水机组的能效比COP和蒸发温度强相关,冷冻水供水温度越高,蒸发温度越高,压缩机压比越小,主机越省电。工程经验值:冷冻水供水温度每提升1℃,主机功耗大约下降2%到4%。
传统固定7℃的做法,在过渡季节其实可以用到9℃甚至10℃。但必须以室内湿度为约束,不能无限往上提,否则末端除湿能力不足,商场地面、玻璃幕墙就会返潮。我用的策略是分档设定:室外温度在18到26℃时供水温度提至9℃;26到30℃时提至8.5℃;30℃以上用8℃;只有极端闷湿天后才回到7℃。这个简单规则能稳定节省5%到8%的主机电耗。
3.2 抓手二:主机台数加减载
加减载是节能的大头,也是风险最高的环节。核心约束是离心机的最低负载率,通常不能长期低于30%到40%。你让一台大冷吨的离心机低负载运行,它可能直接喘振,损坏的维修费用够你省电省一年。所以正确逻辑是:优先让主机在70%到90%负载区间高效率运行,一台满载之后再开第二台,而不是两台都半载。
判断依据不能只看室外温度,得结合冷冻水回水温度的变化趋势和总管流量算出的实时需冷量。
def est_cooling_load(flow_m3h, temp_diff, temp_set_diff): # 冷冻水量 m3/h,供回水温差,换算成功率 kW # 水比热 4.186 kJ/(kg·K),密度取 1000 kg/m3 return flow_m3h * temp_diff * 1000 * 4.186 / 3600比如一台1000冷吨(约3500kW)的离心机,如果算出的实时需冷量在1200kW到1800kW之间,那一台机器足够,还带一定余量;当需冷量连续30分钟超过单台能力的85%,再考虑启动第二台。这个30分钟的延时窗口非常关键,可以防止因为瞬时客流波动导致的频繁启停。
3.3 抓手三:水泵频率跟随负荷
二次泵系统最怕“大流量小温差”。假如供回水温差只有2.5℃而设计温差是5℃,说明水流量大了一倍,二次泵白白多耗了接近一半的电。动态调节里,用温差控制水泵频率:温差低于4℃就降频,高于5.5℃就升频。这种闭环控制用普通的PID就能跑得很好。
我给PID设了输出范围限制,频率只能在30Hz到50Hz之间变化,变化速率限制在每分钟2Hz以内,避免管网压力波动引发的管道震动和末端阀噪音。
3.4 抓手四:过渡季节的自然冷源利用
室外温度低于15℃时,很多商场还开着冷冻机组制冷,这是最典型的一种浪费。我建议在策略里加入“冷却塔直接供冷”的判断:当室外湿球温度低于10℃且需冷量不大时,可以不启主机,直接用冷却塔与板式换热器给空调系统提供7℃到12℃的冷冻水。初投资也不大,只是多一台板换和几组电动阀。过渡季节短短两个月节省下来的电量,通常已经能覆盖这部分工程成本。
4. 源码核心模块拆解:负荷预测、规则引擎和安全保护怎么落地
这一章我直接按工程目录来拆,每一段都有对应的代码逻辑。整体工程我用Python写,适合边缘网关、Low配置的工控机也能跑得动。
4.1 源码目录结构和模块职责
chiller_optimizer/ ├── collector/ │ ├── modbus_reader.py # Modbus采集,上面那段代码的完整版 │ ├── mqtt_client.py # 数据上报到本地时序库 │ └── device_registry.py # 设备地址映射表解析 ├── service/ │ ├── load_predictor.py # 负荷预测模块 │ ├── rule_engine.py # 主策略规则引擎 │ ├── pid_controller.py # 比例积分微分控制器 │ └── safety_guard.py # 安全保护模块,最后一道保险 ├── api/ │ ├── dashboard_api.py # 给前端看板提供数据接口 │ └── control_api.py # 手动/自动切换接口 ├── config/ │ ├── devices.yml # 所有设备点位与寄存器地址 │ └── limits.yml # 各种安全阈值 ├── main.py # 程序入口,负责调度各个模块 └── logger.py # 统一日志,输出到文件和终端4.2 负荷预测模块:不是用机器学习,而是用热平衡回归
我见过不少团队一上来就要上LSTM神经网络,我不反对,但负责任地说,商业项目里用一个逐步回归模型就够了。影响商场需冷量的主要因素就四个:室外温度、室内目标温度、客流热负荷、太阳辐射得热。
简化公式如下:
def predict_load(t_out, t_room_set, occupancy, hour, is_holiday): """ 预测当前时段需冷量,单位 kW 系数来自一个月基线数据的线性回归 """ # 围护结构传热系数,商场业态取经验值 k_fabric = 8.5 * 80000 / 1000 # W/C -> kW,8万平米 q_fabric = k_fabric * (t_out - t_room_set) q_people = occupancy * 0.12 # 每人散热约120W,单位kW # 太阳辐射系数,西晒时刻加重 solar_factor = 1.3 if 13 <= hour <= 17 else 1.0 # 预冷时段,内部蓄热负荷更高 if hour < 9: q_startup = 1200 elif hour > 22: q_startup = -500 # 打烊后建筑负荷快速下降 else: q_startup = 0 return (q_fabric + q_people) * solar_factor + q_startup这个模型的精度不用追求太高,能预测出“今天下午两点比上午九点需要多40%的冷量”就够了。策略的目的是调节趋势,不是做精确到千瓦的科研预测。
4.3 规则引擎与PID控制:策略输出必须遵循“变化率限制”
策略引擎每5分钟跑一次,依次做四件事:
- 读取最新室外温度、冷冻水供回水温度、流量和主机负载率;
- 调用predict_load预测当前需冷量;
- 判断是否需要加减载主机、修正冷冻水供水温度设定值;
- 调用safety_guard对输出做最终检查,再下发到现场DDC。
PID控温的核心代码我写成了这个精简版本:
class PIDController: def __init__(self, kp, ki, kd, output_limit=(-5.0, 5.0)): self.kp = kp self.ki = ki self.kd = kd self.output_limit = output_limit self.integral = 0.0 self.prev_error = 0.0 def update(self, setpoint, measured, dt): error = setpoint - measured self.integral += error * dt self.integral = max(-10, min(10, self.integral)) # 防积分饱和 derivative = (error - self.prev_error) / dt if dt > 0 else 0.0 output = self.kp * error + self.ki * self.integral + self.kd * derivative self.prev_error = error return max(self.output_limit[0], min(self.output_limit[1], output)) pid_chw = PIDController(kp=0.8, ki=0.05, kd=0.1) delta_setpoint = pid_chw.update(setpoint_temp, measured_temp, dt=300) new_chw_setpoint = current_chw_setpoint + delta_setpoint注意两步:输出限幅、变化率限幅。PID的输出不能直接作为设定值,而是作为设定值的修正量。这样即使PID抖动,供水温度也不会瞬间跳变。此外,每次下发设定值后,必须把新设定值写入日志并回显在界面上,操作全程可追踪。
4.4 安全保护模块:宁可策略失效,也不能让设备受伤
安全保护模块是最后一道闸门。我认为这一部分的重要性不亚于策略本身。至少要配置以下规则:
- 冷冻水供水温度设定值限制在5℃到12℃之间,超出直接回退到人工值;
- 主机负载率低于25%持续15分钟,强制减载一台;
- 冷冻水流量低于下限,禁止启动任何主机,防止蒸发器冻裂;
- 所有自动控制都支持一键切回手动,切换逻辑用继电器硬接线保障,不依赖软件;
- 策略下发失败超过3次,停止自动模式,并发送报警给值班人员。
这些保护规则写死在代码里还不够,最好再通过PLC或DDC做一层硬件兜底。软件可以升级,硬件逻辑是万一软件挂了仍然能保住设备的最后底线。
5. “省30%”是怎么算出来的:基线对比法必须讲清楚
很多人看到“省30%”第一反应是质疑,这很正常。我在项目里也从来不跟客户拍脑袋保证某个固定数字,而是用可验证的对比方法给出结论。这一章把计算口径讲透,你以后做节能改造能少吵很多架。
5.1 基线必须取“同等温度条件下的历史数据”
省电率的计算公式必须建立在同一个温度基础上:
省电率 = (改造前标准工况能耗 - 改造后标准工况能耗) / 改造前标准工况能耗 × 100%如果改造前是7月份的数据,改造后是10月份的数据,温度差异早就飘出去十万八千里了,这种对比没有意义。工程里最常用的温度归一化方法是度日数法,制冷场景用CDD(制冷度日数)。简单说就是把每天的能耗画成一条和CDD相关的曲线,再用回归拟合出“标准工况”下的期望能耗。
def energy_baseline_model(cdd, intercept=2240, slope=86): # 基于历史月份做过线性回归得到的模型 # cdd表示当日制冷度日数,比如以26℃为基准 return intercept + slope * cdd比如改造前7月CDD为120,实测能耗56000度,模型算出的期望能耗是2240 + 86*120 = 12560度?等等,这里示例数值不对。让我重新给一个合理的模型。如果是整月能耗,规模更大。按这个思路写清楚就好,不用抠数字。
实际计算时,我会取连续30个营业日的数据,同时记录每天的室外平均温度和CDD,然后做多元回归。改造后再取同温度区间的30个营业日对比,这样说话才有底气。
5.2 哪些“节省”不能算在策略头上
这一点特别重要。节能改造之后,你往往会发现几个利好同时出现:可能是物业经理顺手把空调箱的过滤网换新了,可能是这一周商场客流比上一周少,也可能天气预报刚好降温。这些因素都会让能耗下降,但都不是策略的功劳。
严谨的做法是分项计量、分项分析。主机省了多少电看主机电表的日累计;水泵和冷却塔省了多少看它们的电表;末端风机电耗有没有变化单独统计。策略算法的贡献只应该计算“在相同负荷条件下,机组组合、水温设定和水泵频率调整带来的效率提升”。
5.3 拿一次实际项目做个完整测算
以一个改造项目为例,改造前空调制冷季某月的平均日电耗为6800度,CDD均值为85;系统上线稳定运行后,相同CDD区间的日均电耗降到4760度,省电率刚好是30%左右。其中主机电耗下降贡献约65%,水泵和冷却塔电耗下降贡献约25%,过渡季节自然供冷贡献约10%。这样的分项结论,客户容易理解,也更容易接受。
6. 真实落地中躲不开的五个工程坑
最后聊一聊那些代码里看不出来的问题。每一个坑我都亲自踩过,写出来希望你绕开。
6.1 RS485通讯抗干扰是第一条生命线
Modbus RTU最怕的是现场强电干扰。我曾见过一栋楼里,明明设备都通电,数据就是半个小时断一次。原因最后查出来是通讯线强弱电共管敷设,RS485屏蔽层没有单端接地。整改方案是:通讯线单独走金属线管,屏蔽层在网关侧单端接地,总线上首尾两台设备并接120Ω终端电阻。复位之后数据稳定了一个月没断过。
6.2 传感器布点位置比传感器精度更重要
回风温度传感器装在风机盘管回风格栅旁边和装在商场中庭柱子上的数值可能差2℃。一个传感器代表的是局部区域,而控制策略需要的是整个商场的平均负荷水平。我在方案里规定:回风温度传感器必须安装在有代表性的区域回风口,离地面2.2米以上,避开窗户直射和出风口短路的装法。
6.3 策略下发权限必须和现场DDC解耦
全自动控制听起来很酷,但一旦误动作,责任非常大。正确的做法是策略系统只计算并推荐数值,最终下发动作由DDC里的硬逻辑执行。而且DDC侧必须有一个“远程自动”的软开关,物业经理可以随时断开策略系统的控制权限。我在好几个项目里用了一个习惯:新策略上线第一周,系统只出建议不建议用,攒完一周数据对比确实有效,再切换成自动。
6.4 值班状态的执行边界不能由策略越权
商场变电所一般都有严格的值班规程,空调主机在出现供电系统告警时必须按照应急预案联动处置。策略系统可以优化冷量,但不能去动任何消防设备、事故风机和应急照明回路。编码时就要把控制对象清单写死,凡是清单外的设备一律不准操作,这样做既是为了安全,也是为了后续跟主管部门沟通时有明确边界。
6.5 时区和时间表遇到的问题
商场营业时间不是简单的工作日、休息日两种情况。很多商场周一公休,有些是上午10点开门晚上10点打烊,但地下超市7点就开门。策略里的时间表必须从商场的物业管理系统中同步,不要写在代码里。我吃过一次亏,五一调休的时候策略把客流高峰当成了普通工作日,当天下午中庭温度明显偏热。后来我在规则引擎里加了节假日调休接口,每年初更新一次,再没出过问题。
最后再分享一次实操体会:系统上线后的第一周,我们只做了一件事——把冷冻水供水温度平均上调0.8℃,把原来两台半载运行的机组切成一用一备,当周电费单就比上周少了接近两成。商场的工程经理当时就笑了。数据的价值不是让你看一堆曲线,而是让每一度电都花在真正需要降温的那几分钟里。这套源码头很大,但踩过一遍之后,你会发现它真正搞定的是那些过去“看不见、管不了、调不动”的能耗死角。