设备OEE/稼动率分析系统
设备状态采集 + OEE三要素计算(可用率×性能率×合格率)+ 停机原因自动分类 + 瓶颈设备识别 + 实时大屏看板。开源方案替代昂贵MES系统,帮你找到设备效率瓶颈,OEE提升15-25%
01 为什么中小企业最需要OEE分析
没有OEE系统的中小企业,普遍存在这4个问题
OEE是什么?为什么它是制造业通用管理语言
OEE(Overall Equipment Effectiveness,设备综合效率)= 可用率 × 性能率 × 合格率,是国际通用的设备效率衡量指标。
- 可用率(Availability)= 实际运行时间 / 计划生产时间 —— 反映设备有多少时间在"能生产"的状态,损失来自故障停机/换型/待料
- 性能率(Performance)= 实际产量 / 理论产量 —— 反映设备运行时的速度是否达标,损失来自降速运行/小停机/空转
- 合格率(Quality)= 合格数量 / 总数量 —— 反映生产的产品有多少是好的,损失来自不良品/返工
OEE的价值不在于"算出一个数字",而在于"通过三要素分解,找到效率损失到底发生在哪一环"——可用率低说明停机多,性能率低说明速度慢,合格率低说明质量差。对症下药,才能真正提升效率。
02 系统架构
五层架构:采集→判定→存储→计算→可视化,全链路开源方案
- 状态判定是核心:OEE计算最关键的不是公式,而是"设备状态判定"——什么算运行、什么算待机、什么算故障。用Node-RED做可配置状态机,不用硬编码
- 时序+关系双数据库:高频状态数据存TDengine(时序),停机事件/班次配置/OEE结果存PostgreSQL(关系型),各取所长
- 自动+人工双轨制:停机原因自动分类(故障代码映射)+ 人工补录(操作员选原因),前1个月强制人工补录,1个月后自动分类准确率>80%
- 数据完整性优先:三级缓存(网关本地+PLC备份+缺失标记),OEE数据不能缺,缺了就要标出来,不能假装完整
03 核心软件选型理由
为什么选它:设备状态数据是典型时序数据(每秒一条,一年3000万条/设备),需要高写入吞吐和快速时间范围查询。TDengine是专为物联网时序数据设计的数据库,写入性能是InfluxDB的2-5倍,查询性能是通用数据库的10-100倍。自带降采样和数据保留策略,自动管理历史数据生命周期。单机就能支撑100台设备的每秒采集,2核4G服务器无压力。
对比过:对比过InfluxDB(写入性能弱,企业版收费)、MySQL(时序查询慢,数据量大了以后查询要几十秒)、MongoDB(不适合时序聚合查询)
为什么选它:OEE计算最核心的不是公式,而是"状态判定"——什么算运行、什么算待机、什么算故障,不同工厂定义不同。用硬编码写死状态判定逻辑,改一次要重新部署。Node-RED可视化拖拽配置状态机,现场工程师可以根据实际情况调整判定规则(比如有的设备待机电流是2A,有的是5A)。停机原因分类也可以配置规则(故障代码→停机原因映射表),不用改代码。
对比过:对比过硬编码C#/Python逻辑(改一次要编译部署,现场无法快速调整)、规则引擎(太重,学习成本高,小团队用不起来)
为什么选它:OEE看板需要实时刷新、多维度下钻、历史趋势对比,Grafana是开源可视化领域最成熟的方案。支持TDengine数据源插件,直接查询时序数据。自带报警引擎(OEE低于阈值发钉钉/企业微信)。仪表盘可以导出PDF,报表可以用Data Source API自动生成Excel。社区有大量工业看板模板可以参考。比自己写Web前端开发效率高10倍。
对比过:对比过自研Web前端(开发周期长,维护成本高,图表库要自己调)、商业BI工具(Tableau/Power BI授权贵,和TDengine集成不如Grafana原生)
为什么选它:中小企业设备品牌杂(三菱/西门子/汇川/欧姆龙都有),协议不统一。ThingsGateway支持100+工业协议,一个网关统一采集所有设备。支持断线缓存(网络断了数据存在本地,恢复后补传),这对OEE数据完整性至关重要——OEE计算不能缺数据,缺了就不准。支持数据预处理(在网关端就做状态判定和产量计数,减少上行数据量)。开源免费,比商业网关(如Kepware)省几万授权费。
对比过:对比过Kepware(授权费贵,按驱动套件收费,多协议和高级功能要逐级加钱)、自研采集程序(每个品牌要写一套驱动,维护成本高)、Node-RED直接采集(工业协议支持不如ThingsGateway全,断线缓存弱)
04 部署要点(关键配置)
OEE口径对齐与规范制定
和生产经理/老板开"口径对齐会",确认5个关键定义(计划生产时间/运行状态判定/理论节拍/合格率定义/停机原因分类),写进《OEE计算规范文档》。这是最关键的一步,口径不对,后面全白做。建议花1-2天时间,把规范文档写细,包括每个定义的具体计算方法和特殊情况处理规则
设备数据点表规划
每台设备需要采集的数据点:运行信号(布尔)、故障信号(布尔+故障代码)、产量脉冲(计数器)、当前程序号/产品号、报警代码。写在Excel里,PLC和采集系统共用同一份表。注意:产量脉冲要用上升沿触发计数,不能用电平状态(否则会重复计数)。故障信号要区分"故障中"和"故障已发生但已复位"两种状态
ThingsGateway采集部署
配置ThingsGateway连接每台设备(Modbus TCP/OPC UA/三菱MC/西门子S7),配置采集点表,设置100ms采集频率。配置断线缓存(SQLite本地存储,保留7天数据)。配置数据预处理(在网关端做脉冲计数和状态去抖,减少上行数据量)。测试:断开网络5分钟,恢复后检查数据是否完整补传
Node-RED状态判定与停机分类
用Node-RED实现状态机:运行/待机/故障/离线/换型/保养6种状态,状态变更持续超过10秒才确认(去抖)。停机原因自动分类:有故障代码的按映射表分类,无故障代码的根据时间段和上下文推断(午休→计划停机,换型时间段→换型)。配置人工补录接口(REST API,供工位终端/手机调用)。状态变更事件写入PostgreSQL的停机事件表
OEE计算引擎与数据库
TDengine建表:设备状态表(每秒一条,设备ID+状态+产量增量)、产量脉冲表。PostgreSQL建表:停机事件表(设备ID+开始时间+结束时间+持续时长+停机原因+是否人工确认)、班次配置表(班次名称+开始时间+结束时间+计划生产时间)、产品参数表(产品号+理论节拍+计数方式)、OEE结果表(设备ID+班次+日期+可用率+性能率+合格率+OEE+数据完整度)。定时任务(每15分钟)计算当前班次OEE,每天下班计算全天OEE
Grafana看板与报警
3个核心看板:①实时大屏(当前班次OEE大数字+三要素仪表盘+设备状态分布饼图+当前停机事件列表+今日产量趋势),挂车间65寸大屏;②历史分析(OEE趋势折线图+停机原因柏拉图+瓶颈设备排行+按产品/班次/设备多维度筛选);③班次报表(自动生成Excel,含OEE三要素+停机明细+产量统计+合格率,每天下班自动发邮件)。配置报警:OEE<60%触发钉钉/企业微信通知,设备故障停机>10分钟通知维修班组
05 踩过的坑(真实问题与解决方案)
OEE系统最容易失败的不是技术,而是"数据不被信任"和"系统没人用",这里是真实踩过的6个坑
06 关键代码片段
OEE计算核心逻辑(Node.js定时任务示例)
// 计算某设备某班次的OEE
// OEE = 可用率 × 性能率 × 合格率
async function calculateOEE(deviceId, shiftId, date) {
const shift = await getShiftConfig(shiftId); // 班次配置(开始/结束时间/计划生产时间)
// 1. 从PostgreSQL查询该班次内的所有状态变更事件
const events = await pool.query(
'SELECT * FROM downtime_events WHERE device_id=$1 AND start_time>=$2 AND end_time<=$3 ORDER BY start_time',
[deviceId, shift.startTime, shift.endTime]
);
// 2. 计算实际运行时间(状态为"运行"的总时长,去抖后)
let runTime = 0; // 秒
let downtimeByReason = {}; // 按停机原因分类
for (const ev of events.rows) {
const duration = (ev.end_time - ev.start_time) / 1000;
if (ev.status === 'running') {
runTime += duration;
} else if (duration >= 30) { // 最小停机时间过滤(<30秒不计)
const reason = ev.reason || 'unknown';
downtimeByReason[reason] = (downtimeByReason[reason] || 0) + duration;
}
}
// 3. 可用率 = 实际运行时间 / 计划生产时间
const availability = runTime / shift.plannedProductionTime;
// 4. 从TDengine查询该班次产量(合格数+总数)
const production = await taos.query(
`SELECT SUM(good_count) as good, SUM(total_count) as total
FROM production_data
WHERE device_id='${deviceId}' AND ts>=${shift.startTime} AND ts<=${shift.endTime}`
);
const goodCount = production[0].good || 0;
const totalCount = production[0].total || 0;
// 5. 性能率 = 实际产量 / 理论产量(理论产量=运行时间×理论节拍)
const product = await getCurrentProduct(deviceId, shift.startTime);
const theoreticalCycle = product.theoreticalCycle; // 秒/件
const theoreticalOutput = runTime / theoreticalCycle;
const performance = totalCount > 0 ? totalCount / theoreticalOutput : 0;
// 6. 合格率 = 合格数 / 总数
const quality = totalCount > 0 ? goodCount / totalCount : 0;
// 7. OEE = 可用率 × 性能率 × 合格率
const oee = availability * performance * quality;
// 8. 数据完整度检查(缺失数据超过5%标记为不完整)
const dataCompleteness = calculateDataCompleteness(deviceId, shift);
const isComplete = dataCompleteness >= 0.95;
// 9. 写入OEE结果表
await pool.query(
`INSERT INTO oee_results (device_id, shift_id, date, availability, performance, quality, oee,
run_time, good_count, total_count, downtime_by_reason, data_completeness, is_complete)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)`,
[deviceId, shiftId, date, availability, performance, quality, oee,
runTime, goodCount, totalCount, JSON.stringify(downtimeByReason), dataCompleteness, isComplete]
);
return { oee, availability, performance, quality, downtimeByReason, isComplete };
} 07 实际效果
08 相关软件与工具
需要设备OEE/稼动率分析系统?
丁丁做过多个工厂的设备监控和OEE分析项目,熟悉设备状态采集、OEE计算口径对齐、停机原因分类、Grafana看板开发。可以帮你做方案设计、设备选型、系统开发、现场调试,帮你找到设备效率瓶颈。