树莓派+LinuxCNC+Web HMI:开源数控系统AI故障诊断架构实践
2026/9/3 20:06:52 网站建设 项目流程

如果你做数控、做非标自动化,大概率会有这样一个困惑:为什么传统 HMI 总是越用越难受?

界面封闭、授权费贵、想加一个 AI 故障诊断功能,连基础 API 都不开放。供应商告诉你"这个要定制开发",报价单递过来,项目利润直接少掉一截。与此同时,树莓派加 LinuxCNC 的组合,已经让数控系统的控制层彻底开源了,从运动控制、IO 逻辑到脉冲输出都能自己掌控。但这两者之间其实还隔着一层:人机交互层怎么办?

如果 HMI 本身也开源、也软件化,同时把 AI 大模型作为"对话式诊断入口"嵌入进去,整套系统的玩法就会完全不一样。这也是本文想探讨并且实际搭建的方案:

用树莓派做底层运动控制平台,运行 LinuxCNC 实时控制;HMI 层独立成一个 Web 服务,不依赖任何商业组态软件;再把本地大模型接入 HMI,让操作员可以直接用自然语言问"主轴报错怎么办"、让 AI 给出诊断建议,甚至把 AI 输出的建议转成可确认执行的 MDI 命令。

换句话说:控制层用 LinuxCNC,交互层用 Web HMI,智能层用本地大模型。这套框架跑通之后,你就拥有了一套低成本、可扩展、带 AI 能力的数控 HMI 原型。

这篇文章会从痛点分析、架构设计、环境准备、LinuxCNC 配置、Web HMI 开发、AI 接入、完整示例、常见排错到工程建议,完整走一遍。不管你是树莓派爱好者、数控行业工程师,还是做工业软件的开发者,都不用照着抄,重点理解思路,然后换成自己的硬件和场景去落。

1. 这篇文章真正要解决的问题

先想清楚一个问题:我们到底为什么要做一个开源 HMI,而不是直接用现成的商业 HMI?

因为传统工控场景里,HMI 的价值不是"显示屏幕",而是"人对设备状态的感知入口"。而传统 HMI 软件最大的三个痛点恰恰卡在这里:

  • 封闭:组态软件有自己的私有格式,想要换掉、升级、接入外部数据非常难。
  • 定制成本高:界面改一个按钮,在开源 Web 框架里是分钟级改动,在商业 HMI 里可能要重新走一轮开发、测试、部署流程。
  • AI 能力难以接入:市面上多数 HMI 不具备开放 API,即使有,也主要针对数据采集,而不是面向"语义理解"。

这些问题叠加在一起,导致一个很现实的局面:工厂里最需要智能诊断的数控设备,反而最不容易用上 AI。

这篇文章要做的,就是拆掉这堵墙。具体目标有三个:

  1. 让 LinuxCNC 的控制能力通过 Web HMI 暴露出来,包括读取坐标、主轴状态、发送 MDI 命令。
  2. 把本地大模型接入 HMI,让它可以基于 LinuxCNC 报警号、系统日志和运维知识库做故障诊断。
  3. 给 AI 加上执行边界——AI 只做分析和建议,真正的控制命令由操作员确认后发送,避免"大模型直接操作设备"这种不安全的设计。

这篇文章适合谁?

  • 正在做树莓派数控项目,需要一个人机交互界面的开发者;
  • 在做工业 HMI 选型,想评估"Web HMI + AI"路线是否可行的工程师;
  • 对 LinuxCNC 感兴趣,想了解它除了 Axis 之外还能怎么接上层应用的嵌入式/自动化爱好者;
  • 以及想找一个真实的"AI + 工业控制"落地案例的产品经理。

一句话总结:这是一套能从零跑通、能演示、能继续往生产方向扩展的开源 HMI 框架原型。

2. 三个关键概念:LinuxCNC、HMI、AI 在数控系统里的位置

在写代码之前,先把三个核心概念讲清楚。很多初学者容易把 LinuxCNC 当成一个"上位机软件",其实它的定位要复杂得多。

2.1 LinuxCNC 是什么

LinuxCNC 是一套基于 Linux 的开放式数控系统软件,前身是 EMC(Enhanced Machine Controller)。它不只做运动规划,还包括:

  • 实时运动控制:通过实时内核(RT-PREEMPT 或 Xenomai)保证插补和脉冲输出的时序确定性;
  • PLC 逻辑:通过 ClassicLadder 或 HAL 中的逻辑组件实现简单的梯形图、逻辑控制;
  • 硬件抽象:通过 HAL(Hardware Abstraction Layer)把软件信号和物理引脚连接起来。

通俗理解:LinuxCNC 像是数控机床里的"大脑 + 脊髓",大脑负责 G 代码解释和轨迹规划,脊髓负责把运动指令通过引脚发到伺服驱动或步进驱动。

2.2 HMI 在数控系统里的位置

HMI(Human Machine Interface)是操作人员和数控系统之间的交互层。传统的数控 HMI 通常是一台嵌入式屏或者工控机上的组态软件,负责:

  • 显示坐标、主轴转速、报警信息、加工状态;
  • 提供按钮、输入框、程序列表等操作入口;
  • 记录历史报警和操作日志。

在 LinuxCNC 系统里,最常用的 HMI 是 Axis 界面,一种基于 Tcl/Tk 的桌面 GUI。Axis 对单机用户够用,但如果你想做远程监控、多终端访问、或者在界面上嵌入 AI 对话功能,桌面 GUI 的方案就不够灵活了。

所以这套框架会把 HMI 单独提出来,做成一个 Web 应用。控制层不变,交互层独立,这是现代数控软件架构里的一个重要设计思路。

2.3 AI 在数控 HMI 里能做什么

AI 接入 HMI 不等于"放一个聊天框"。在工业场景里,真正有价值的三个方向是:

  1. 故障辅助诊断:操作员输入报警代码或描述现象,大模型结合运维知识库给出排查步骤。这是最容易落地、风险最低的方向。
  2. 自然语言转操作建议:操作员说"把 X 轴移动到 10 毫米",AI 解析成对应的 MDI 命令,显示给操作员确认后执行。中间有人为确认环节,安全可控。
  3. 基于历史数据的维护预测:通过分析伺服电流、温度、振动数据,预测丝杠、轴承的寿命。这个需要一定数据积累,适合作为后期方向。

本文重点实现前两个,第三个只作为后续思路扩展写在第 12 节。注意一个边界:AI 在工业控制里的角色是"副驾驶",不是"自动驾驶",控制权必须保留在操作员手里。

下面用一张表格对比三个概念的分工:

层次核心软件功能类比
控制层LinuxCNC运动规划、插补、IO 控制、G 代码执行数控系统的大脑
交互层Web HMI状态显示、操作入口、报警展示数控系统的仪表盘
智能层本地大模型故障诊断、命令解析建议、知识问答数控系统的 AI 副驾驶

3. 总体架构设计:树莓派如何把三层串起来

整个框架的架构可以概括为一句话:一个树莓派,承载三层服务

[浏览器/移动端] | | (HTTP / WebSocket) v [Web HMI 服务] <-------> [AI 服务] | | | (linuxcnc python API) | (HTTP / Ollama API) v v [LinuxCNC 实时控制层] [本地大模型 + 知识库] | v [步进/伺服驱动、IO]

不需要一级标题,文章直接从正文开始,这里的图用代码块或列表形式描述。

说明一下数据流:

  • 下行控制链路:浏览器点击按钮 → Web HMI 服务 → LinuxCNC Python API → HAL 引脚 → 驱动;
  • 上行状态链路:LinuxCNC 实时状态 → Web HMI 服务 → WebSocket 推送 → 浏览器实时刷新坐标;
  • AI 诊断链路:操作员输入故障描述 → Web HMI 把上下文发给 AI 服务 → AI 结合知识库返回建议 → HMI 展示给操作员 → 操作员决定是否执行。

3.1 为什么选择树莓派作为硬件平台

树莓派不是唯一的选项,但在这个场景里它有明显优势:

  • 成本低:一块树莓派 4B 或 5,加一张 TF 卡,几百元就能跑起整个框架;
  • 生态成熟:Linux 系统的包管理机制,安装 Python、Node.js、Docker、Ollama 都非常方便;
  • GPIO 可用:虽然实时性是弱项,但在低速步进控制、教学演示、原型验证场景里够用;
  • 社区资料丰富:树莓派 + 数控、树莓派 + Linux 实时控制都有大量折腾记录。

它不适合大规模生产级数控改造。原因非常具体:树莓派的 GPIO 脉冲输出依赖软件定时器,在高频脉冲下会出现抖动;CPU 要同时处理实时控制、Web 服务和 AI 推理,压力很大。所以生产环境建议把 AI 服务拆到另一台机器,或者用外接运动控制卡。这一点在第 11 节还会展开。

3.2 为什么 AI 选本地大模型而不是云端 API

在工业环境里,"本地部署"不是偏好,而是需求。工厂车间网络往往封闭,数据不能随便出内网;操作员的使用场景要求低延迟;运维手册和报警代码属于内部知识,不适合传云端。所以选用 Ollama 部署本地大模型,既保证数据边界,也方便后续做成离线系统。

如果硬件条件允许,AI 服务也可以部署在局域网内的另一台 x86 机器上(带独显更好),树莓派只保留控制层和交互层。这个拆分方式对于实际项目非常重要。

4. 环境准备与前置条件

在开始配置之前,先把环境准备好。整个系统的软件栈如下:

  • 硬件:树莓派 4B 或 5,推荐 4GB 以上内存;一张 32GB 以上 TF 卡;电源建议使用官方电源;
  • 操作系统:Raspberry Pi OS(Bookworm 或更新版本,64 位);
  • LinuxCNC:请以官方发布版本为准,树莓派等 ARM 平台可关注社区或官方提供的安装包/镜像;
  • AI 推理:Ollama,在树莓派上优先选择支持 ARM 架构的模型(如 qwen2.5:3b、llama3.2:3b);
  • 后端框架:Python 3 + Flask/FastAPI;
  • 前端:HTML + JavaScript,不依赖大型前端框架,方便新手理解。

4.1 系统初始化

烧录系统后,开机进入终端,先更新系统并安装基础工具:

sudo apt update && sudo apt upgrade -y sudo apt install -y python3 python3-pip git curl

4.2 安装 LinuxCNC

LinuxCNC 在 x86 平台上有成熟的一键安装脚本。树莓派等 ARM 平台建议先查询 LinuxCNC 官方文档或社区是否有对应发行包。

如果安装包不可用,另一个常见思路是使用 LinuxCNC 的派生项目 Machinekit,它专门针对 ARM 平台做过移植。不过要注意,两个项目的配置语法和模块名有差异,本文以 LinuxCNC 官方用法为主线,ARM 平台的具体安装过程请以实际文档为准。

装完之后,验证一下命令是否可用:

linuxcnc --version

如果终端能正常输出版本信息,说明 LinuxCNC 已经进入系统路径。

4.3 安装 Ollama 与模型

Ollama 的安装脚本:

curl -fsSL https://ollama.com/install.sh | sh

拉取一个适合树莓派资源的小模型:

ollama pull qwen2.5:3b

启动 Ollama 服务:

ollama serve

验证模型可以正常对话:

ollama run qwen2.5:3b "请用一句话说明什么是 G 代码"

在树莓派上跑 7B 模型会比较吃力,3B 级别是性能和效果之间的折中。

4.4 安装 Python 依赖

Web HMI 服务需要的 Python 包:

pip3 install flask flask-socketio requests

如果 LinuxCNC 的 Python 模块没有安装到系统 Python 路径,需要检查安装方式。通常安装 LinuxCNC 时会自带linuxcnc这个 Python 模块,位置可能在/usr/lib/python3/dist-packages/或者安装目录下。

5. LinuxCNC 基础配置:INI 与 HAL

LinuxCNC 的核心配置由两类文件组成:INI 文件定义机床的基本参数和启动设置,HAL 文件定义硬件信号之间的连接关系。理解这两个文件,是后续一切开发的前提。

5.1 INI 文件的核心结构

INI 文件用段落(Section)组织,常见的段落包括:

  • [EMC]:基本名称和调试级别;
  • [DISPLAY]:选择显示界面;
  • [TRAJ]:轴数量、最大速度、最大加速度;
  • [AXIS_x]:每个轴的参数;
  • [EMCMOT]:运动控制模块参数;
  • [HAL]:指定 HAL 文件的路径。

下面是一个最小示例,三轴雕刻机配置:

# 文件路径:~/linuxcnc/configs/pi_cnc/mill.ini [EMC] MACHINE = Pi CNC Demo DEBUG = 0 [DISPLAY] DISPLAY = axis CYCLE_TIME = 0.100 [TRAJ] AXES = 3 COORDINATES = X Y Z MAX_LINEAR_VELOCITY = 50.0 DEFAULT_LINEAR_VELOCITY = 20.0 [EMCMOT] EMCMOT = motmod [HAL] HALFILE = mill.hal [AXIS_0] TYPE = LINEAR MAX_VELOCITY = 50.0 MAX_ACCELERATION = 100.0 MIN_LIMIT = -100.0 MAX_LIMIT = 100.0 [AXIS_1] TYPE = LINEAR MAX_VELOCITY = 50.0 MAX_ACCELERATION = 100.0 MIN_LIMIT = -100.0 MAX_LIMIT = 100.0 [AXIS_2] TYPE = LINEAR MAX_VELOCITY = 50.0 MAX_ACCELERATION = 100.0 MIN_LIMIT = -50.0 MAX_LIMIT = 50.0

这段配置的核心含义是:系统包含 X、Y、Z 三个直线轴,最大速度 50 毫米每秒,每个轴都有软限位。注意速度单位取决于你的运动控制配置,在实际项目中需要结合电机步距角、驱动器细分数和丝杠导程重新计算。

5.2 HAL 文件的核心结构

HAL 是 LinuxCNC 的一大特色,它的设计理念类似于硬件的"连线"。每个组件有引脚(pin),信号(signal)负责把组件的引脚连起来。比如把运动控制器的步进输出引脚连到并口或 GPIO 引脚上:

# 文件路径:~/linuxcnc/configs/pi_cnc/mill.hal loadrt trivkins loadrt stepgen step_type=0,0,0 loadrt hal_parport cfg="0x378 out" setp stepgen.0.position-scale 8000.0 setp stepgen.1.position-scale 8000.0 setp stepgen.2.position-scale 8000.0 addf stepgen.update-servo addf stepgen.make-pulses base-thread addf parport.0.write base-thread net x-step stepgen.0.step parport.0.pin-02-out net x-dir stepgen.0.dir parport.0.pin-03-out

这里position-scale的值表示"多少个脉冲对应 1 毫米",取决于你的驱动细分数和丝杠导程。上面只是一个连接示意,不同硬件对应的驱动模块名称差异很大。

5.3 用文本方式启动 LinuxCNC

LinuxCNC 自带图形启动器,但为了后续通过 HMI 自动拉起来,可以用命令行方式直接启动:

linuxcnc ~/linuxcnc/configs/pi_cnc/mill.ini

启动后,你应该能看到 Axis 图形界面。如果能看到坐标界面,说明 INI 和 HAL 至少语法上没有大问题。

这里就出现了一个很重要的判断:LinuxCNC 能正常启动,只代表配置语法正确,不代表硬件链路正确。第一次接电机时,一定要先手动转动电机轴,观察坐标变化方向,再测试使能、限位和急停。

6. 构建 Web HMI 服务:让控制能力浮出水面

LinuxCNC 本身提供了 Python API,这是 Web HMI 能接上去的关键。官方提供三个主要对象:

  • linuxcnc.command():发送运动命令、切换模式、执行 MDI;
  • linuxcnc.stat():读取状态,如坐标、主轴转速、报警;
  • linuxcnc.error_channel():读取错误消息。

6.1 后端服务的核心代码

下面用一个 Flask 应用,实现两个基本 API:读取坐标和发送 MDI 命令。

# 文件路径:hmi_service/app.py from flask import Flask, request, jsonify import linuxcnc app = Flask(__name__) c = linuxcnc.command() s = linuxcnc.stat() def get_position(): """读取当前机械坐标和机床坐标""" s.poll() return { "joint_0": s.joint_position[0], "joint_1": s.joint_position[1], "joint_2": s.joint_position[2], } @app.route("/api/status") def status(): """HMI 轮询或 WebSocket 推送的状态接口""" s.poll() return jsonify({ "position": get_position(), "state": s.state, "exec_state": s.exec_state, "task_mode": s.task_mode, "spindle_speed": s.spindle_speed, "current_vel": s.current_vel, }) @app.route("/api/mdi", methods=["POST"]) def send_mdi(): """发送 MDI 命令,例如 G0 X10 Y10""" data = request.get_json(force=True) mdi_cmd = data.get("cmd", "").strip() if not mdi_cmd: return jsonify({"error": "cmd is required"}), 400 # 切换到 MDI 模式并执行 c.mode(linuxcnc.MODE_MDI) c.wait_for_completion() c.mdi(mdi_cmd) c.wait_for_completion() return jsonify({"ok": True, "cmd": mdi_cmd}) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=False)

这段代码完成了两件最核心的事:把 LinuxCNC 状态变成 HTTP JSON 接口,把 MDI 命令变成可调用的 HTTP API。有了这两个能力,前端界面的自由度就完全打开了。

6.2 前端页面:一个能跑的最小 HMI

为了让示例完整,下面给一个极简 HTML 页面,包含状态显示、坐标显示、MDI 输入和 AI 诊断入口。

<!-- 文件路径:hmi_service/templates/index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Pi CNC HMI</title> <style> body { font-family: system-ui, sans-serif; margin: 2rem; } .card { border: 1px solid #ddd; border-radius: 8px; padding: 1rem; margin-bottom: 1rem; } button { padding: 0.5rem 1rem; cursor: pointer; } </style> </head> <body> <h1>树莓派数控 HMI</h1> <div class="card"> <h2>状态</h2> <div id="state">---</div> <div id="pos">X: --- Y: --- Z: ---</div> <div id="spindle">主轴转速: ---</div> </div> <div class="card"> <h2>MDI 命令</h2> <input type="text" id="mdi_cmd" value="G0 X5 Y5" size="40"> <button onclick="sendMdi()">发送</button> </div> <div class="card"> <h2>AI 辅助诊断</h2> <input type="text" id="ask" placeholder="例如:X轴报警,可能是哪些原因?" size="60"> <button onclick="askAi()">提问</button> <pre id="answer">等待提问...</pre> </div> <script> async function refreshStatus() { const resp = await fetch('/api/status'); const data = await resp.json(); const p = data.position; document.getElementById('state').innerText = '状态: ' + data.state; document.getElementById('pos').innerText = 'X: ' + p.joint_0.toFixed(3) + ' Y: ' + p.joint_1.toFixed(3) + ' Z: ' + p.joint_2.toFixed(3); document.getElementById('spindle').innerText = '主轴转速: ' + data.spindle_speed; } async function sendMdi() { const cmd = document.getElementById('mdi_cmd').value; const resp = await fetch('/api/mdi', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({cmd: cmd}) }); const data = await resp.json(); alert('已发送: ' + data.cmd); } async function askAi() { const question = document.getElementById('ask').value; const resp = await fetch('/api/ai', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({question: question}) }); const data = await resp.json(); document.getElementById('answer').innerText = data.answer || '无回答'; } setInterval(refreshStatus, 1000); </script> </body> </html>

前端用轮询方式每秒刷新一次状态,对小型原型完全够用。如果想做更流畅的实时体验,可以把轮询改成 WebSocket,LinuxCNC 状态变化时主动推送,但这不是核心重点。

7. 接入 AI:本地大模型与知识库

HMI 页面已经能显示状态、发命令了,接下来接入 AI。这里采用一个务实的思路:AI 服务单独作为一层,不直接和 LinuxCNC 对话,HMI 是唯一的中间人

7.1 为什么需要知识库

直接让大模型回答数控问题,效果很可能不理想。原因是大模型训练数据里虽然有机械加工、G 代码方面的通用知识,但它并不知道你的 LinuxCNC 配置、你用的报警代码含义、你的机床丝杠规格。要想得到真正可用的诊断建议,需要把运维手册、报警代码表、历史维修记录整理成知识库,让 AI 在回答时先检索相关内容。

这个做法在技术上叫 RAG(Retrieval-Augmented Generation,检索增强生成)。在原型阶段,不一定要用复杂的向量数据库,可以先把知识库文本按章节切成片段,根据关键词简单匹配后拼进 Prompt。

7.2 AI 后端接口实现

下面是一个简单的 AI 服务接口,调用 Ollama 的/api/generate接口,并把系统提示词设为"数控运维专家":

# 文件路径:hmi_service/ai_service.py import requests import json from flask import Blueprint, request, jsonify ai_bp = Blueprint("ai", __name__, url_prefix="/api") OLLAMA_URL = "http://localhost:11434/api/generate" MODEL_NAME = "qwen2.5:3b" SYSTEM_PROMPT = """你是一名数控机床运维专家。请根据用户提供的故障现象或报警代码,给出: 1. 可能的原因 2. 排查步骤 3. 处理建议 注意: - 如果问题描述不明确,先请用户补充信息; - 不要直接生成可能造成设备损坏的操作建议; - 涉及安全操作时,提醒用户确认急停和限位状态。 """ def search_knowledge_base(question): """从本地知识库检索相关片段。原型阶段用简单的关键词匹配。""" # 实际项目中可以替换为向量数据库检索 db_text = "" try: with open("knowledge_base.txt", "r", encoding="utf-8") as f: db_text = f.read() except FileNotFoundError: return "" paragraphs = db_text.split("\n\n") matched = [] for para in paragraphs: if any(keyword in para for keyword in question.split()): matched.append(para) return "\n\n".join(matched[:3]) @ai_bp.route("/ai", methods=["POST"]) def ask_ai(): data = request.get_json(force=True) question = data.get("question", "") context = search_knowledge_base(question) prompt = SYSTEM_PROMPT if context: prompt += f"\n\n以下是运维知识库中的相关内容:\n{context}" payload = { "model": MODEL_NAME, "prompt": prompt + f"\n\n用户的问题:{question}\n\n请使用中文回答。", "stream": False, } try: resp = requests.post(OLLAMA_URL, json=payload, timeout=60) result = resp.json() answer = result.get("response", "AI 服务无返回") except Exception as e: answer = f"调用 AI 服务失败: {str(e)}" return jsonify({"answer": answer})

这段代码里,知识库还是一个非常朴素的关键词匹配实现。生产环境可以换成 Chroma、Milvus 或 Elasticsearch 做向量检索,效果会更好。框架层面只需要替换search_knowledge_base函数内部实现。

7.3 AI 结果如何转化成可执行操作

很多读者会问:AI 回答了故障原因,然后呢?它能不能自己去执行 MDI 命令?

这里有一个非常关键的安全设计判断:不建议让 AI 直接执行命令。更稳妥的方式是"AI 转成建议命令 → 人工确认 → 执行"。比如操作员问"把主轴转速设为 1000",AI 输出:

建议执行的 MDI 命令:M3 S1000

随后 HMI 弹出一条确认框:"AI 建议执行 M3 S1000,是否确认?",操作员确认后才真正调用send_mdi接口。这套流程叫"human-in-the-loop",是 AI 进入工业控制领域的基本安全准则。

8. 完整示例:把 HMI 和 AI 串起来

前面各节分别实现了控制层配置、HMI 后端、前端页面、AI 服务。这一节把它们组合成一个完整的项目结构,并给出启动流程。

8.1 项目目录结构

hmi_service/ ├── app.py # Flask 主应用 ├── ai_service.py # AI 路由模块 ├── knowledge_base.txt # 运维知识库 ├── templates/ │ └── index.html # HMI 前端页面 └── requirements.txt # Python 依赖

8.2 修改主应用注册 AI 路由

app.py中注册 AI 服务蓝图:

# 文件路径:hmi_service/app.py(补充部分) from ai_service import ai_bp app.register_blueprint(ai_bp)

8.3 运维知识库示例

知识库文件的内容格式可以是纯文本,按段落组织,每个段落尽量围绕一个主题:

铝件加工时主轴高速运转,出现共振现象。 可能原因:1. 主轴转速与刀具齿数匹配不当;2. 刀柄伸出过长;3. 工件装夹刚性不足。 排查建议:先降低转速,检查刀具伸出长度,再检查装夹是否牢固。 伺服驱动器报警:过流。 可能原因:1. 电机线短路;2. 驱动器参数错误;3. 机械卡死。 排查建议:断开电机,测量电机线相间电阻;检查机械负载是否卡滞;查看驱动器参数是否被误修改。

8.4 启动流程

按下面顺序启动三个服务:

# 终端 1:启动 LinuxCNC linuxcnc ~/linuxcnc/configs/pi_cnc/mill.ini # 终端 2:启动 Ollama ollama serve # 终端 3:启动 Web HMI cd hmi_service python3 app.py

启动完成后,在浏览器访问:

http://<树莓派IP>:5000

如果能在浏览器看到状态页面,并且坐标值能随 LinuxCNC 状态变化,说明整条链路已经打通。

9. 运行结果与效果验证

框架搭建完成不等于项目完成,必须做一轮完整的验证。我建议按照下面的顺序逐项确认。

9.1 验证 HMI 能读取实时状态

在 LinuxCNC Axis 界面里手动移动 X 轴,观察浏览器 HMI 页面中的 X 坐标是否同步变化。

判断标准:

  • 坐标值在 1 秒内刷新;
  • 数值变化方向与手动移动方向一致;
  • 无报错信息出现在 Flask 终端。

如果刷新慢,先检查树莓派的负载;如果方向相反,需要检查 HAL 中 stepgen 的方向引脚逻辑,不要在软件里强行改符号。

9.2 验证 MDI 命令链路

在 HMI 页面的 MDI 输入框输入:

G0 Z5

点击发送,观察 Axis 界面中的 Z 轴是否运动到 5 毫米位置。

注意:执行前请确保机床处于"机器上电"且"急停复位"状态,否则任务没有进入执行队列。

9.3 验证 AI 问答

在 AI 诊断输入框输入:

X 轴报警,可能是哪些原因?

判断标准:

  • AI 在 10 到 30 秒内给出回答;
  • 回答包含可能的故障原因和排查步骤;
  • 回答中没有给出明显危险的操作建议。

如果模型回答质量不佳,可以换更大的模型,或者优化知识库内容。树莓派上首选 3B 级别的量化模型,资源上更现实。

10. 常见问题与排查思路

在实际搭建过程中,几乎每个环节都会遇到问题。下面把最常见的场景列成表格,方便按图索骥。

问题现象可能原因排查方式解决方案
LinuxCNC 启动失败INI 文件路径错误或 HAL 模块不匹配查看启动日志,确认 HAL 文件路径逐行检查 INI 中的 HALFILE 路径,确认驱动模块存在
Axis 界面里坐标无响应未完成机器使能,或者急停生效检查 Axis 界面左下角状态先点"机器上电",再复位急停
步进电机不转HAL 引脚连接错误或驱动板电源问题在 LinuxCNC 的 HAL 监控面板查看 step 引脚是否有脉冲确认 stepgen 输出连接到正确引脚,检查驱动板供电
树莓派 GPIO 无法访问权限不足或设备树覆盖未启用查看 GPIO 设备节点是否存在使用sudo启动测试,并配置 udev 规则
HMI 页面无法打开Flask 服务未启动或端口被占用在树莓派本机访问localhost:5000查看 Flask 日志,杀掉占用端口的进程
坐标刷新很慢浏览器轮询频率太高导致树莓派负载过高观察top命令输出把轮询时间从 1 秒改为 2 到 3 秒,或改用 WebSocket
AI 回答速度很慢模型参数过大,或 CPU 推理能力不足查看 Ollama 日志,观察模型加载时间换成 3B 以下量化模型,或把 AI 服务部署到局域网 x86 机器
AI 回答经常不靠谱知识库内容不足或 Prompt 设计不清晰检查知识库片段能否被检索到扩充知识库,优化检索方式,测试不同 Prompt 模板

这里要特别强调一下 GPIO 和驱动板的安全问题。树莓派的 GPIO 引脚是 3.3V 电平,直接接到 5V 步进驱动板可能损坏 GPIO。必须通过光耦隔离模块,或者使用专门的 CNC 扩展板。我不建议直接用杜邦线把 GPIO 拉出来接驱动器,这个操作风险比较高。

11. 最佳实践与工程建议

原型跑通之后,如果想往真实项目上推进,下面这几条建议值得认真对待。

11.1 安全边界必须前置设计

AI 接入工业控制最容易犯的错误,是把演示 demo 的设计直接搬进生产环境。工业系统里任何一条错误的运动指令都可能造成撞机、断刀甚至人身伤害。因此,在生产环境中必须做到:

  • AI 永不直接执行命令,所有 AI 生成的 MDI 命令必须经过操作员确认;
  • MDI 命令白名单化:在 HMI 后端限制可执行的命令范围,比如只允许G0G1M3M5等安全指令;
  • 急停和限位信号优先于所有软件逻辑,这是硬件层面的事,不能依赖软件层做兜底。

11.2 把 AI 服务拆出去

树莓派的 CPU 要跑 LinuxCNC 实时任务,还要跑 Web 服务和 AI 推理,负载会非常紧张。更合理的生产架构是:

  • 树莓派只跑 LinuxCNC 和 HMI 后端;
  • AI 服务部署在局域网内一台 x86 机器上,通过 HTTP 接口调用;
  • 知识库检索也放到 AI 那台机器上,避免树莓派 IO 压力过高。

这样也方便后续升级 GPU,把大模型从 3B 升级到 7B 甚至更大。

11.3 日志与审计

AI 诊断是一回事,AI 建议背后的责任边界是另一回事。生产环境中,每条 AI 生成的建议和操作员是否确认执行,都应该记录日志。格式建议包含:

  • 时间戳;
  • 用户输入的问题;
  • AI 的完整输出;
  • 确认状态(已确认 / 已忽略);
  • 如果执行了,执行的 MDI 命令和最终结果。

这既能帮助优化 Prompt 和知识库,也能在出问题时快速复盘。

11.4 从原型到生产的演进路径

基于这套框架,你可以逐步叠加更多能力:

  1. 把 LinuxCNC 从 GPIO 脉冲方案换成 Mesa 运动控制卡,提升脉冲稳定性和轴数;
  2. 在 HMI 前端加入远程监控、加工进度曲线、历史报警图表;
  3. 引入真正的向量数据库,把知识库规模做大;
  4. 在树莓派上接入摄像头模块,做基于视觉的加工状态检测;
  5. 把 AI 故障诊断升级为基于历史数据的预测性维护。

12. 总结与后续学习方向

这套框架跑通下来,你会发现真正重要的不是"Python 代码怎么写",而是你怎么理解数控系统各层之间的边界。LinuxCNC 管好实时运动控制,Web HMI 管好状态展示和操作入口,AI 管好知识理解和辅助决策。每一层各司其职,再通过清晰的 API 连接,整个系统就是可维护、可扩展的。

本文给出的也不只是一个 demo,而是一种思路:开源控制层 + 独立交互层 + 本地智能层。这个组合非常适合树莓派爱好者、数控行业工程师做技术预研,也适合作为公司内部"AI 改造传统数控"的验证原型。

如果你想继续深入,建议按这个顺序学习:

  1. 把 LinuxCNC 文档完整过一遍,重点看 HAL 和 INI 的官方说明,理解运动控制的数据流动;
  2. 读一读 LinuxCNC 的 Python 模块源码,知道除了坐标和 MDI,还能读取哪些状态字段;
  3. 把 RAG 知识库升级成向量检索,收集更多报警代码和维修经验,让 AI 的诊断能力真正可用;
  4. 尝试在 HMI 里接入摄像头模块,把机器视觉和 AI 诊断结合起来,向"智能数控终端"的方向走。

最后提醒一句:所有涉及真实设备运转的测试,务必在安全环境、合法授权、有急停保护的前提下进行。先把框架放在教学实验台上跑稳,再谈改造真正的机床。技术和安全,这两件事永远要一起考虑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询