|
副标题 : 让数据"留得住、查得到、用得好" 一、PLC与数据库通信的本质 数据库是工业数据的"仓库"——PLC采集数据,数据库存储数据。 [tr][td]传统方式[/td][td]数据库方式[/td][/tr][tr][td]数据存储在PLC[/td][td]数据存储在数据库[/td][/tr][tr][td]掉电数据丢失[/td][td]掉电数据保留[/td][/tr][tr][td]查询困难[/td][td]SQL查询,灵活高效[/td][/tr][tr][td]无历史追溯[/td][td]完整历史记录[/td][/tr]核心价值: 数据持久化:掉电不丢失 历史追溯:查询任意时间点的数据 数据分析:SQL聚合、统计、趋势分析 多系统共享:MES/ERP/SCADA都可以访问 合规性:满足ISO/FDA等合规要求 二、通信架构 2.1 常见架构 架构1:PLC → OPC UA → 数据库 PLC ──OPC UA── 数据采集服务 ──SQL── 数据库 架构2:PLC → 边缘网关 → 数据库 PLC ──Ethernet── 边缘网关 ──SQL/HTTP── 数据库 架构3:PLC → SCADA → 数据库 PLC ──SCADA── SCADA服务器 ──内置── 数据库 2.2 数据库选型 [tr][td]数据库[/td][td]特点[/td][td]适用场景[/td][/tr][tr][td]MySQL[/td][td]开源,易用[/td][td]一般场景[/td][/tr][tr][td]PostgreSQL[/td][td]开源,功能强[/td][td]复杂查询[/td][/tr][tr][td]SQL Server[/td][td]商业,集成好[/td][td]Windows生态[/td][/tr][tr][td]InfluxDB[/td][td]时序数据库[/td][td]时序数据[/td][/tr][tr][td]TimescaleDB[/td][td]时序+SQL[/td][td]时序+关系[/td][/tr]2.3 数据表设计 生产数据表: CREATE TABLE production_data ( id INT PRIMARY KEY AUTO_INCREMENT, timestamp DATETIME NOT NULL, device_id VARCHAR(50) NOT NULL, temperature FLOAT, pressure FLOAT, speed FLOAT, status VARCHAR(20), quality_flag INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_timestamp ON production_data(timestamp); CREATE INDEX idx_device ON production_data(device_id); 报警数据表: CREATE TABLE alarm_data ( id INT PRIMARY KEY AUTO_INCREMENT, timestamp DATETIME NOT NULL, device_id VARCHAR(50) NOT NULL, alarm_code INT NOT NULL, alarm_level INT, alarm_message VARCHAR(255), acknowledged INT DEFAULT 0, acknowledged_at DATETIME, acknowledged_by VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); 三、数据采集方式 3.1 轮询采集 优点:简单可靠 缺点:实时性差,带宽占用大 import mysql.connector import time 连接数据库 conn = mysql.connector.connect( host='192.168.3.100', user='plc_user', password='password', database='factory_db' ) cursor = conn.cursor() 轮询采集 while True: # 读取PLC数据 temp = read_plc_register('D100') pressure = read_plc_register('D101') status = read_plc_register('M100') # 写入数据库 sql = """ INSERT INTO production_data (timestamp, device_id, temperature, pressure, status) VALUES (%s, %s, %s, %s, %s) """ cursor.execute(sql, ( time.strftime('%Y-%m-%d %H:%M:%S'), 'PLC01', temp, pressure, 'running' if status else 'stopped' )) conn.commit() time.sleep(1) # 1秒采集一次 3.2 事件触发采集 优点:实时性好,节省带宽 缺点:实现复杂 # 事件触发采集 def on_alarm(alarm_code, alarm_level, message): sql = """ INSERT INTO alarm_data (timestamp, device_id, alarm_code, alarm_level, alarm_message) VALUES (%s, %s, %s, %s, %s) """ cursor.execute(sql, ( time.strftime('%Y-%m-%d %H:%M:%S'), 'PLC01', alarm_code, alarm_level, message )) conn.commit() PLC报警时触发 PLC_OnAlarm(on_alarm) 3.3 批量采集 优点:效率高,减少数据库压力 缺点:实时性稍差 # 批量采集(每10秒一次) data_buffer = [] def collect_data(): data_buffer.append({ 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'), 'device_id': 'PLC01', 'temperature': read_plc_register('D100'), 'pressure': read_plc_register('D101'), 'speed': read_plc_register('D102'), 'status': 'running' }) if len(data_buffer) >= 10: # 满10条批量插入 sql = """ INSERT INTO production_data (timestamp, device_id, temperature, pressure, speed, status) VALUES %s """ cursor.executemany(sql, data_buffer) conn.commit() data_buffer.clear() 每秒调用一次 every_second(collect_data) 四、PLC侧实现 4.1 三菱PLC + 边缘网关 边缘网关配置: [tr][td]参数[/td][td]设置[/td][/tr][tr][td]PLC连接[/td][td]Ethernet, IP=192.168.3.1[/td][/tr][tr][td]数据库连接[/td][td]MySQL, IP=192.168.3.100[/td][/tr][tr][td]采集周期[/td][td]1秒[/td][/tr][tr][td]批量大小[/td][td]10条[/td][/tr][tr][td]重试次数[/td][td]3次[/td][/tr]4.2 ST语言实现(边缘网关) ( 数据采集到数据库 ) VAR ( 数据库连接 ) DB_Conn: MySQL_Connection; DB_Status: INT; ( 采集数据 ) Temp_Current: REAL; Pressure_Current: REAL; Speed_Current: REAL; Motor_Status: BOOL; ( 缓冲区 ) Data_Buffer: ARRAY[0..9] OF STRUCT Timestamp: STRING; Device_ID: STRING; Temperature: REAL; Pressure: REAL; Speed: REAL; Status: STRING; END_STRUCT; Buffer_Count: INT := 0; ( 定时器 ) Collect_Timer: TON; Batch_Timer: TON; END_VAR ( 每秒采集数据 ) Collect_Timer(IN:=TRUE, PT:=T#1s); IF Collect_Timer.Q THEN ( 读取PLC数据 ) Temp_Current := PLC_ReadReal('D100'); Pressure_Current := PLC_ReadReal('D101'); Speed_Current := PLC_ReadReal('D102'); Motor_Status := PLC_ReadBool('M100'); ( 存入缓冲区 ) Data_Buffer[Buffer_Count].Timestamp := Get_TimeString(); Data_Buffer[Buffer_Count].Device_ID := 'PLC01'; Data_Buffer[Buffer_Count].Temperature := Temp_Current; Data_Buffer[Buffer_Count].Pressure := Pressure_Current; Data_Buffer[Buffer_Count].Speed := Speed_Current; Data_Buffer[Buffer_Count].Status := IF(Motor_Status, 'running', 'stopped'); Buffer_Count := Buffer_Count + 1; IF Buffer_Count >= 10 THEN ( 批量写入数据库 ) DB_BatchInsert(DB_Conn, 'production_data', Data_Buffer, 10); Buffer_Count := 0; END_IF; Collect_Timer(IN:=FALSE); END_IF; 五、深度案例分析:注塑机生产数据追溯 5.1 背景 某注塑厂需要满足ISO9001要求,实现生产数据完整追溯。 5.2 问题经过 [tr][td]问题[/td][td]表现[/td][td]影响[/td][/tr][tr][td]数据丢失[/td][td]PLC掉电数据丢失[/td][td]无法追溯[/td][/tr][tr][td]查询困难[/td][td]无统一数据库[/td][td]效率低[/td][/tr][tr][td]无历史趋势[/td][td]无法分析[/td][td]无法优化[/td][/tr][tr][td]合规风险[/td][td]无完整记录[/td][td]ISO审核不通过[/td][/tr]5.3 解决方案 数据采集架构: ┌─────────────────────────────────────────────────────────┐ │ 数据采集层 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │注塑机1 │ │注塑机2 │ │注塑机3 │ │ │ │ (PLC) │ │ (PLC) │ │ (PLC) │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │ │ │边缘网关 │ │边缘网关 │ │边缘网关 │ │ │ │(数据采集)│ │(数据采集)│ │(数据采集)│ │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ ├───────┼────────────┼────────────┼──────────────────────┤ │ │ │ │ │ │ ┌────┴────────────┴────────────┴────┐ │ │ │ MySQL 数据库 │ │ │ │ - 生产数据表 - 报警数据表 │ │ │ │ - 质量数据表 - 配方数据表 │ │ │ └───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌───────────────────────────────────┐ │ │ │ Web追溯系统 │ │ │ │ - 生产记录查询 - 质量追溯 │ │ │ │ - 趋势分析 - 报表生成 │ │ │ └───────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ 数据表设计: -- 生产记录表 CREATE TABLE injection_production ( id INT PRIMARY KEY AUTO_INCREMENT, machine_id VARCHAR(20) NOT NULL, product_id VARCHAR(50) NOT NULL, batch_no VARCHAR(50) NOT NULL, cycle_time FLOAT, injection_pressure FLOAT, holding_pressure FLOAT, mold_temp FLOAT, product_weight FLOAT, quality_flag INT, start_time DATETIME, end_time DATETIME, operator VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 质量检验表 CREATE TABLE quality_inspection ( id INT PRIMARY KEY AUTO_INCREMENT, production_id INT, check_time DATETIME, dimension_1 FLOAT, dimension_2 FLOAT, surface_quality INT, result INT, -- 0:合格, 1:不合格 inspector VARCHAR(50), remark VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); 5.4 效果对比 [tr][td]指标[/td][td]优化前[/td][td]优化后[/td][td]提升[/td][/tr][tr][td]数据保留[/td][td]掉电丢失[/td][td]永久保存[/td][td]100%[/td][/tr][tr][td]查询时间[/td][td]30分钟[/td][td]<10秒[/td][td]-99%[/td][/tr][tr][td]追溯精度[/td][td]无法追溯[/td][td]精确到每个产品[/td][td]100%[/td][/tr][tr][td]ISO审核[/td][td]不通过[/td][td]通过[/td][td]通过[/td][/tr][tr][td]质量分析[/td][td]无法分析[/td][td]实时分析[/td][td]显著提升[/td][/tr]六、SQL查询示例 6.1 实时查询 -- 查询当前生产状态 SELECT machine_id, product_id, cycle_time, quality_flag FROM injection_production WHERE end_time > NOW() - INTERVAL 1 HOUR ORDER BY end_time DESC; 6.2 历史查询 -- 查询某批次生产记录 SELECT * FROM injection_production WHERE batch_no = 'B20260604001' ORDER BY start_time; 6.3 统计分析 -- 查询各机台产量 SELECT machine_id, COUNT(*) as total, AVG(cycle_time) as avg_cycle FROM injection_production WHERE DATE(start_time) = '2026-06-04' GROUP BY machine_id; -- 查询质量合格率 SELECT machine_id, COUNT(*) as total, SUM(CASE WHEN quality_flag = 0 THEN 1 ELSE 0 END) as passed, SUM(CASE WHEN quality_flag = 0 THEN 1 ELSE 0 END) 100.0 / COUNT() as pass_rate FROM injection_production WHERE DATE(start_time) = '2026-06-04' GROUP BY machine_id; 6.4 趋势分析 -- 查询温度趋势 SELECT DATE_FORMAT(start_time, '%Y-%m-%d %H:%i') as time_slot, AVG(mold_temp) as avg_temp, MIN(mold_temp) as min_temp, MAX(mold_temp) as max_temp FROM injection_production WHERE start_time BETWEEN '2026-06-04 00:00:00' AND '2026-06-04 23:59:59' GROUP BY time_slot ORDER BY time_slot; 七、常见问题排查 7.1 连接问题 [tr][td]问题[/td][td]可能原因[/td][td]解决方案[/td][/tr][tr][td]无法连接[/td][td]网络不通[/td][td]检查网络连通性[/td][/tr][tr][td]认证失败[/td][td]用户名密码错误[/td][td]检查数据库认证[/td][/tr][tr][td]数据库不存在[/td][td]库名错误[/td][td]检查数据库名[/td][/tr]7.2 数据问题 [tr][td]问题[/td][td]可能原因[/td][td]解决方案[/td][/tr][tr][td]数据不写入[/td][td]SQL错误[/td][td]检查SQL语法[/td][/tr][tr][td]数据重复[/td][td]重复提交[/td][td]增加唯一约束[/td][/tr][tr][td]数据缺失[/td][td]采集中断[/td][td]检查采集服务[/td][/tr]八、核心工具推荐 8.1 数据库 [tr][td]数据库[/td][td]适用场景[/td][/tr][tr][td]MySQL[/td][td]通用,开源[/td][/tr][tr][td]PostgreSQL[/td][td]复杂查询,开源[/td][/tr][tr][td]InfluxDB[/td][td]时序数据,开源[/td][/tr][tr][td]SQL Server[/td][td]Windows生态,商业[/td][/tr]8.2 开发工具 [tr][td]工具[/td][td]用途[/td][/tr][tr][td]MySQL Workbench[/td][td]MySQL管理[/td][/tr][tr][td]DBeaver[/td][td]通用数据库管理[/td][/tr][tr][td]Navicat[/td][td]通用数据库管理[/td][/tr]九、金句集锦 本文基于三菱PLC与MySQL数据库通信实战经验整理,涵盖数据采集、表设计、SQL查询、注塑机追溯案例等核心主题。 推荐阅读 三菱GX Works3 028:安全PLC编程——SIL2/SIL3安全功能实战 发布于 2026-05-27 三菱 PLC 教程 02:iQ-R 系列硬件组成 发布于 202603 NACHI 机械手教程第 4 章:编程基础 发布于 202603 KEYWORDS PLC, plc, SCADA, 三菱 如果你觉得这篇文章有帮助,请点个在看,分享给更多需要的人! 关注我,获取更多实用干货~ 有问题欢迎评论区留言交流! 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |