拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于TIA Portal与Three.js的PLC网页3D监控系统开发实战

在实际工业自动化项目中西门子 TIA Portal博图是广泛使用的 PLC 编程和 HMI 组态软件而将 PLC 控制逻辑与网页端 3D 模型动画进行联动能够直观展示设备运行状态用于远程监控、数字孪生或培训演示。传统做法需要分别开发 PLC 程序、通信接口和前端 3D 渲染步骤繁琐且调试困难。借助 AI 辅助编程工具如 Cursor、GitHub Copilot和 Three.js 库可以快速生成通信桥接代码、3D 场景配置和交互逻辑降低开发门槛。本文将基于 TIA Portal V18/V20、S7-1200 PLC、Node.js 后端和 Three.js 前端搭建一个完整的“PLC 控制网页 3D 模型”的可运行案例。你会学到如何配置博图的数据块、编写 PLC 控制逻辑、使用 Node.js 构建 OPC UA 或 HTTP API 服务、通过 Three.js 加载 GLTF 模型并响应数据变化最后用 AI 工具辅助完成代码补全和调试。本文重点不在于替代底层知识而是提供一条可复现的集成路径帮助你在 2 小时内看到从 PLC 到网页的完整动画效果。1. 理解博图与网页端 3D 交互的技术链路1.1 为什么需要把博图数据同步到网页 3D 模型在工业现场PLC 负责采集传感器数据、执行逻辑控制但传统 HMI 界面只能提供二维图形和简单动画难以直观反映设备三维运动关系。例如一台机械手有多个关节每个关节的角度、速度、限位状态在二维画面上只能通过数字或进度条显示而 3D 模型可以实时还原真实动作。网页端 3D 的优势在于跨平台、易部署、易扩展适合远程监控和移动端访问。技术链路的本质是博图将 PLC 数据块中的变量值通过某种通信协议暴露给外部程序后端服务轮询或订阅这些数据再转发给网页前端前端 Three.js 根据数据更新模型姿态、位置、颜色或动画进度。1.2 关键组件与协议选型组件可选方案本文选择理由PLC 数据源TIA Portal 数据块DB1 中定义布尔、整数、浮点数结构清晰易于调试通信协议OPC UA、HTTP REST、Socket、ProfinetHTTP REST简单易上手无需额外授权适合原型开发后端服务Node.js、Python Flask、Java SpringNode.js Express轻量与前端 JavaScript 生态一致前端 3D 库Three.js、Babylon.js、A-FrameThree.js文档丰富社区活跃模型格式GLTF、OBJ、FBXGLTF二进制格式体积小Three.js 原生支持注意生产环境若需高实时性毫秒级应优先考虑 OPC UA 或 WebSocket本文为简化流程使用 HTTP 轮询适用于秒级刷新场景。1.3 AI 辅助编程在哪些环节能提效PLC 代码段AI 可根据自然语言描述生成 LAD 或 SCL 逻辑片段如“当启动按钮按下且无故障时电机运行”。Node.js 接口根据数据块结构自动生成 REST API 路由和数据类型映射。Three.js 场景描述模型加载、灯光、相机控制需求AI 可输出初始化代码。调试过程遇到通信或动画不生效时AI 能提供常见错误排查建议。本文会在关键步骤给出 AI 提示词prompt示例你可以使用 Cursor、GitHub Copilot 或类似工具尝试。2. 准备开发环境与项目结构2.1 软件版本与依赖清单软件/工具版本要求说明TIA PortalV18 或 V20兼容 S7-1200需授权可使用试用版PLC 型号S7-1200如 1214C实际硬件或 PLCSIM 仿真Node.js16.x 或更高后端运行环境浏览器Chrome 90 / Firefox 88支持 WebGL 和 ES62.2 项目目录结构创建项目文件夹plc-3d-web结构如下plc-3d-web/ ├── plc/ # 博图项目文件 │ └── tia_project.ap15 # 导出的项目归档可选 ├── server/ # Node.js 后端 │ ├── package.json │ ├── index.js # 主入口 │ └── routes/ │ └── plc-data.js # 数据接口路由 ├── client/ # 前端页面与 Three.js │ ├── index.html │ ├── style.css │ ├── script.js # Three.js 主逻辑 │ └── models/ # 存放 GLTF 模型 │ └── robot.glb # 示例机械手模型 └── README.md提示如果暂无实际 GLTF 模型可使用 Three.js 内置几何体如立方体、球体模拟动画效果。2.3 初始化 Node.js 后端在server/目录下执行npm init -y npm install express cors node-fetch创建server/index.js基础模板const express require(express); const cors require(cors); const app express(); const port 3000; app.use(cors()); app.use(express.json()); // 后续添加路由 app.use(/api, require(./routes/plc-data)); app.listen(port, () { console.log(后端服务运行在 http://localhost:${port}); });3. 配置博图项目与 PLC 数据块3.1 创建数据块并定义变量在 TIA Portal 中新建项目选择 S7-1200 PLC进入 OB1 主程序块添加一个全局数据块 DB1定义以下变量变量名数据类型初始值说明StartBoolFalse启动信号StopBoolFalse停止信号Motor_SpeedInt0电机转速0-100Axis_AngleReal0.0关节角度0.0-360.0AlarmBoolFalse故障报警数据块属性中勾选“可从 HMI/OPC UA 访问”。3.2 编写简单控制逻辑在 OB1 中插入 SCL 片段或梯形图实现当 Start 为 True 且 Stop 为 False 时Motor_Speed 逐步升至设定值如 80。当 Stop 为 True 时Motor_Speed 逐步降为 0。Axis_Angle 根据 Motor_Speed 线性增加模拟旋转。SCL 示例代码IF Start AND NOT Stop THEN Motor_Speed : LIMIT(0, Motor_Speed 5, 80); Axis_Angle : Axis_Angle (Motor_Speed * 0.1); ELSIF Stop THEN Motor_Speed : LIMIT(0, Motor_Speed - 5, 80); Axis_Angle : Axis_Angle (Motor_Speed * 0.1); END_IF; IF Axis_Angle 360.0 THEN Axis_Angle : 0.0; END_IF;3.3 配置 PLC 通信 IP 并下载程序设置 PLC 以太网地址如 192.168.0.10编译无误后下载到实际 PLC 或 PLCSIM。确保 PC 能 Ping 通 PLC IP。排查点若 PLCSIM 仿真时 HMI 按钮无反应检查仿真实例是否激活、IP 设置是否一致、数据块是否被正确访问。4. 构建 Node.js 数据桥接服务4.1 使用 S7 协议读取 PLC 数据块安装nodes7库用于西门子 S7 协议通信npm install nodes7创建server/routes/plc-data.jsconst express require(express); const router express.Router(); const nodes7 require(nodes7); const plcOptions { host: 192.168.0.10, // PLC IP rack: 0, slot: 1 }; const conn new nodes7(plcOptions); // 定义要读取的变量字典 const variables { Start: DB1.DBX0.0, // DB1 字节0的位0 Stop: DB1.DBX0.1, Motor_Speed: DB1.DBW2, // 字类型偏移2 Axis_Angle: DB1.DBD4, // 浮点数偏移4 Alarm: DB1.DBX0.2 }; // 连接 PLC conn.initiateConnection(err { if (err) { console.error(PLC 连接失败:, err); return; } console.log(PLC 连接成功); conn.setTranslationCB(tag variables[tag]); }); // 提供数据读取接口 router.get(/data, (req, res) { conn.readAllItems([Start, Stop, Motor_Speed, Axis_Angle, Alarm], (err, values) { if (err) { res.status(500).json({ error: 读取 PLC 数据失败 }); return; } res.json(values); }); }); module.exports router;4.2 添加轮询机制与数据缓存为避免每次请求都直接访问 PLC可在服务端设置定时缓存let cachedData {}; setInterval(() { conn.readAllItems(Object.keys(variables), (err, values) { if (!err) cachedData values; }); }, 1000); // 1 秒更新一次 router.get(/data, (req, res) { res.json(cachedData); });启动服务node server/index.js访问http://localhost:3000/api/data应返回 JSON 格式的 PLC 数据。AI 辅助提示如果你不熟悉 S7 地址偏移可向 AI 描述“我需要读取 DB1 中从字节 0 开始的布尔、整数和浮点数”AI 可帮助计算偏移量和数据类型。5. 使用 Three.js 创建可交互的 3D 场景5.1 初始化场景、相机与渲染器在client/script.js中import * as THREE from three; import { GLTFLoader } from three/examples/jsm/loaders/GLTFLoader.js; const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 添加光源 const ambientLight new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const directionalLight new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(10, 20, 15); scene.add(directionalLight); camera.position.z 5;5.2 加载 GLTF 模型并定位可动画部件假设机械手模型包含一个名为Arm的关节需在 Blender 或建模软件中确保骨骼或空物体命名清晰。const loader new GLTFLoader(); let model, armJoint; loader.load(models/robot.glb, gltf { model gltf.scene; scene.add(model); // 查找关节对象 armJoint model.getObjectByName(Arm); if (!armJoint) { console.warn(未找到名为 Arm 的关节使用默认立方体替代); const geometry new THREE.BoxGeometry(1, 1, 1); const material new THREE.MeshPhongMaterial({ color: 0x00ff00 }); armJoint new THREE.Mesh(geometry, material); scene.add(armJoint); } });5.3 响应 PLC 数据更新模型状态创建更新函数根据 API 返回的Axis_Angle和Alarm改变模型async function updateModelFromPLC() { try { const response await fetch(http://localhost:3000/api/data); const data await response.json(); // 更新关节角度 if (armJoint) { armJoint.rotation.y THREE.MathUtils.degToRad(data.Axis_Angle); } // 报警状态改变颜色 if (model) { model.traverse(child { if (child.isMesh) { child.material.color.setHex(data.Alarm ? 0xff0000 : 0xffffff); } }); } } catch (err) { console.error(获取 PLC 数据失败:, err); } } // 每 1 秒更新一次 setInterval(updateModelFromPLC, 1000); // 动画循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();5.4 添加基础交互控制允许用户通过界面按钮触发 PLC 的 Start/Stop在client/index.html中添加div classcontrols button onclicksetPLCValue(Start, true)启动/button button onclicksetPLCValue(Stop, true)停止/button /div在client/script.js中实现window.setPLCValue async (tag, value) { await fetch(http://localhost:3000/api/write?tag${tag}value${value}, { method: POST }); };后端需补充写入接口需 PLC 支持写操作注意安全router.post(/write, (req, res) { const { tag, value } req.query; conn.writeItems([tag], [value], err { if (err) res.status(500).send(写入失败); else res.send(OK); }); });6. 运行验证与常见问题排查6.1 启动顺序与预期效果启动 PLC或 PLCSIM并确保程序运行。启动 Node.js 服务node server/index.js。用浏览器打开client/index.html需通过 HTTP 服务访问避免跨域问题可使用http-server或 Live Server。点击“启动”按钮观察 PLC 数据块中 Motor_Speed 和 Axis_Angle 变化同时网页中 3D 模型应旋转且颜色随报警状态改变。6.2 常见问题与解决路径现象可能原因检查点解决方式网页无法加载模型路径错误、跨域限制浏览器 Network 标签查看模型请求使用本地服务器启动确认模型路径3D 模型显示为黑色光源不足或材质问题检查光源位置和强度增加环境光或调整光源角度网页无法连接后端端口被占用、IP 错误确认后端服务是否启动端口是否被防火墙阻挡更换端口或配置防火墙PLC 数据读取失败IP 不可达、变量地址错误Ping PLC IP检查变量偏移和数据类型校正 IP 和地址确认 PLC 处于运行模式模型关节不运动关节名称不匹配或旋转轴错误打印模型结构查找正确关节名使用console.log(model)输出结构调整旋转属性6.3 使用 AI 辅助排查的典型场景当遇到 Three.js 模型加载后无法分割选取单个物体时可向 AI 提问“我在 Three.js 中加载了 GLTF 模型但raycaster.intersectObjects返回的是整个模型如何实现单独选取子物体”AI 可能返回确保子物体是独立的 Mesh并为每个 Mesh 设置userData或检查建模软件导出设置。7. 最佳实践与生产环境建议7.1 性能与安全性优化模型优化GLTF 文件使用压缩纹理减少顶点数避免单一模型超过 1MB。通信优化将 HTTP 轮询改为 WebSocket 实现双向实时通信降低延迟。安全措施后端接口添加认证令牌避免未授权写入 PLC生产环境禁用调试接口。错误处理PLC 断线时前端应有重连机制和友好提示。7.2 代码维护与扩展性配置外置化将 PLC IP、变量映射、端口号等提取到配置文件或环境变量。模型与数据解耦使用发布-订阅模式管理数据更新便于添加多个模型或视图。日志记录记录数据通信异常、用户操作关键事件便于故障追溯。7.3 下一步扩展方向集成更多 PLC 数据类型数组、字符串。实现多模型协同动画如传送带与机械手联动。加入相机视角切换、模型剖切clipping等高级 Three.js 特性。将 AI 用于异常检测根据历史数据训练模型实时判断设备状态并提前预警。这个案例展示了如何将工业控制、后端通信和前端 3D 渲染串联起来虽然每个环节都有更专业的深入方向但只有先跑通端到端流程才能在此基础上逐步优化和扩展。实际项目中还需根据设备复杂度、实时性要求和团队技术栈做具体选型调整。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门