冷阴极 X 射线源球壳钛合金焊缝检测装置(下位机)

国家重点研发项目下位机:STM32F429 + FreeRTOS,RS485 二进制协议栈、统一运动控制 API、四大逻辑任务与多级异常保护,Modbus RTU 驱动伺服完成弧形轨道焊缝扫查。

项目概述

国家重点研发项目子课题:冷阴极 X 射线源球壳钛合金焊缝检测装置的运动控制系统(下位机部分)。

装置通过 X 射线源与平板探测器沿弧形轨道协同扫查,对球壳钛合金焊缝成像检测。下位机负责对 X 射线源、探测器的协同控制与远程控制:配合 QT 上位机调整射线源与探测器的速度与动作,完成单段焊缝、截面焊缝两种检测模式,并实时上报系统状态。

系统组成

检测装置整机:弧形轨道与伺服驱动系统

整机实拍:左侧为提升立柱与弧形齿轮轨道,右侧为探测器载滑车,地面为多路禾川伺服驱动器与供电线缆。

软件分层与模块

软件分为两层:APP 应用层承载对外协议、运动语义与任务调度;驱动层提供寄存器级能力(Modbus 协议模板与 CRC、电机寄存器配置序列、OLED/菜单/按键、FLASH 参数存储)。

模块职责
app_conf.h全部可调参数集中管理:协议常量、超时、限幅、软限位、任务栈与优先级、RS485 开关
host_proto.h/.cRS485/USART6 二进制协议栈:TX DMA + 环形缓冲 + 组包 CRC;RX IDLE+DMA + 环形缓冲 + 字节状态机解析;命令分发回调;心跳时间戳;收发统计
motion_api.h/.c统一运动控制接口:轴状态机(IDLE/READY/MOVING/FAULT)、方向(速度符号)/速度(±3000 限幅)/动作时序(松闸稳定→运动→清速减速→抱闸)、编码器事务三重校验、软限位、安全关断收敛入口、故障复位
dev_task.h/.c四大逻辑任务:motionTask(动作执行+ACK)、statusTask(50ms 状态轮询+100ms 状态帧)、monitorTask(心跳超时/故障沿上报/IWDG 喂狗点)、装配函数 APP_TasksInit()

软件架构

数据流(下行指令 → 上行状态)

任务划分

任务CMSIS 优先级栈阻塞点职责
parseTaskAboveNormal2KB线程标志(50ms 超时)协议解析(状态机+CRC)
motionTaskHigh2KB消息队列(100ms 超时)动作执行 + 定时动作截止判定
statusTaskNormal2KBosDelay(50)编码器轮询 + 状态反馈
monitorTaskNormal1.5KBosDelay(100)心跳超时/故障沿/安全关断触发
oledShowMenuTaskLow512B事件标志菜单显示(按键扫描定时器 10ms)
defaultTaskNormal512BosDelay(1000)LED 心跳

两个关键的执行体设计:

  • 协议解析与动作执行分离:解析出指令后经 8 深消息队列投递给 motionTask 按序执行,队列削峰保证解析节奏不受动作耗时拖累;
  • 编码器轮询放在任务而非软件定时器中:定时器回调与任务可能并发访问同一 Modbus 通道,统一到任务上下文并配合轴级互斥锁后,「请求-应答」事务被彻底串行化。

任务优先级设计依据

优先级不是按“功能重要性”排的,而是按三条工程准则:

  1. 截止期与后果:动作执行(清速/抱闸/安全关断)有硬时序且后果不可逆 → 最高应用优先级;
  2. 阻塞特性:事件驱动型任务平时全部阻塞在同步原语上,高优先级只影响唤醒延迟,不产生 CPU 争抢;
  3. 依赖方向:数据流上游不能被下游长时间阻塞(parse 喂 motion 的队列;status 的编码器数据被 motion 的轴锁依赖)。

完整优先级谱系(NVIC 中断优先级与任务优先级是两套量纲,勿混):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
NVIC 中断 (任何 ISR 可抢占任何任务)
  ├─ UART4/5/6/8 抢占优先级=5(恰好等于 FreeRTOS 可调用 API 的阈值,
  │    ISR 内允许 FromISR API;只做批量入环形缓冲 + flagsSet,µs 级)
任务 (FreeRTOS 原生优先级,抢占式 + 同级时间片轮转)
  ├─ 38 High        motionTask   ← 安全动作的执行权最高
  ├─ 31 AboveNormal parseTask    ← 必须高于周期型任务,否则状态轮询可推迟命令解析
  ├─ 23 Normal      statusTask / monitorTask / defaultTask
  ├─  8 Low         oledShowMenuTask(人机界面,空闲余量处理)
  ├─  2              Timer Service(按键扫描定时器,CubeMX 默认值)
  └─  0 Idle

几个关键取舍:

  • 为什么 motion(38) > parse(31):命令队列已削峰(8 深),解析晚 1–2ms 不影响正确性;反之若 parse 更高,解析长帧期间到达的停止/安全命令会被推迟执行——安全动作的执行权高于协议的解析权。
  • status/monitor 同级 Normal:两者都是周期型软实时(50ms/100ms),判定窗口(软限位/心跳 500ms)远大于调度延迟;它们持锁时间短(单次 Modbus 事务约 6ms),motion 高优先级被轴锁阻塞时由互斥量优先级继承临时提升持锁任务,消除优先级反转。
  • 关中断快照 vs 互斥量:跨任务读轴状态用 __disable_irq() 短临界区(µs 级、无反转风险);锁只用于必须串行化的 Modbus 事务(同一 UART 的请求-应答配对)。
  • 一个已知限制:定时器守护任务优先级为 CubeMX 默认值 2,低于所有应用任务——当前成立的条件是所有任务都有周期阻塞点,定时器总能在间隙运行;若未来把安全逻辑放进软件定时器(如限位去抖),必须提高该优先级。
  • Realtime(47) 刻意留空:为硬实时扩展预留(5–20ms 节拍的位置环、限位 EXTI 的紧急处理链)。

轴状态机

任何异常都收敛到单一安全关断入口 MOTION_SafeShutdown():清速 → 等 150ms(驱动器 100ms 减速斜坡完成,避免高速抱闸冲击)→ 断抱闸继电器 → 锁定 FAULT + 故障码 → monitorTask 沿检测上报。恢复必须显式故障复位指令。

下位机主控板:STM32F429 + 多路 RS485(RJ45 座)与继电器输出

上位机帧协议

帧格式

1
2
3
4
┌──────┬──────┬─────┬──────┬─────────────┬─────────────┬──────────────┐
│ 0xA5 │ 0x5A │ SEQ │ LEN  │ CMD         │ DATA[LEN]   │ CRC16_LO/HI  │
└──────┴──────┴─────┴──────┴─────────────┴─────────────┴──────────────┘
 帧头1   帧头2  序号  载荷长  命令字        0~64B 小端     查表 CRC16,低字节先
  • 双帧头 A5 5A:误同步率 1/65536;A5/5A 位翻转丰富,示波器上可辨;
  • SEQ 序号:下行主机自增(ACK 回显 → 去重/丢帧检测),上行设备独立自增;
  • LEN 显式变长:状态机据此收数,天然支持命令扩展;
  • CRC16 覆盖 SEQ..DATA(不含帧头与自身),算法与 Modbus 完全一致(同一张查表),全协议栈一套 CRC;
  • 帧开销 7 字节;载荷中可能出现假帧头,由 CRC 兜底丢弃(更高可靠场景可选 COBS 变长编码)。

命令集

CMD方向载荷语义
0x01下行轴号 + 开关抱闸控制
0x02下行轴号 + rpm(int16)速度指令(符号=方向,±3000 限幅)
0x03下行轴号 + rpm + 时长(100ms 单位)定时动作(动作时序演示)
0x04下行轴号(0xFF=全轴)停止
0x05下行seq 回显心跳(200ms 周期,不回 ACK)
0x06下行轴号(0xFF=全部)故障复位
0x07下行无立即请求状态帧(回 0x82)
0x81上行回显命令/序号 + status命令应答(OK/BUSY/REJECT/BAD_ARG)
0x82上行状态字×2 + 双轴速度 + 故障码周期状态帧(100ms)
0x8F上行故障码 + 轴号 + 保留故障上报(故障沿触发一次)

实例帧(CRC 实算,可直接用于联调)

帧字节
轴1 速度 -500rpmA5 5A 01 03 02 01 FE 0C 55 D7
轴2 800rpm 转 3.0sA5 5A 02 04 03 02 20 03 1E FD CE
心跳A5 5A 03 01 05 5A D2 CB
状态帧(READY/MOVING,sp1=1500,fault=0x0001)A5 5A 10 08 82 01 02 DC 05 00 00 01 00 97 A8
故障帧(驱动器无应答,轴1)A5 5A 11 05 8F 02 00 01 00 00 E2 F4

解析鲁棒性(7 态状态机 + 三重防护)

  1. LEN > 64 → 丢弃回找头(防超长帧打爆缓冲);
  2. 帧内字节间隔 > 50ms → 强制回找头(防半帧卡死);
  3. CRC 失败 → 丢当前帧回找头(假同步自愈);RX 环满 → 丢最新并计数上报统计。

接收链路硬件侧使用 UART 中断 + DMA 不定长接收,以 IDLE 总线空闲事件判帧:

1
2
__HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
/* 帧长 = 接收缓冲区大小 - __HAL_DMA_GET_COUNTER(&hdma_usart6_rx) */

ISR 只做批量搬移入环形缓冲(SPSC 免锁)+ 置线程标志,解析全部在 parseTask 完成——ISR 保持极短是实时性的关键:若在中断里做逐字节处理甚至打印,9600 波特率下一帧即可阻塞几十 ms。

统一运动控制 API

对上层屏蔽多电机与 Modbus 细节,全部运动能力收敛为一组 MOTION_* 接口:

API语义
MOTION_InitAll()伺服参数写入 + 原点捕获 + 松闸(任务上下文)
MOTION_SetSpeed(ax, rpm)方向=符号;自动先松闸再设速
MOTION_MoveTimed(ax, rpm, dur)速度 + 截止期(定时动作)
MOTION_Stop(ax)清速 → 150ms 减速等待 → 抱闸
MOTION_Brake(ax, open)手动抱闸(运动中拒绝)
MOTION_Tick()定时动作到期判定(100ms 粒度)
MOTION_PollFeedback()双轴编码器轮询 + 无应答计数 + 软限位
MOTION_GetSnapshot(ax, &s)状态/速度/位置/故障原子快照
MOTION_SafeShutdown(ax, fault)安全关断唯一入口
MOTION_FaultReset(ax)FAULT → READY:重初始化 + 重捕获原点 + 松闸

底层由一组寄存器级驱动接口支撑:

1
2
3
4
Motor_Init(MOTOR1);              // 初始化:Modbus 链路建立 + 驱动器寄存器配置
openMotor(MOTOR1);               // 电机使能
speed_set(MOTOR1, speed);        // 速度模式设定:负速度转补码写入,±3000rpm 软件限幅
closeMotor(MOTOR1);              // 去使能(配合抱闸继电器安全停机)

Modbus RTU 驱动器接口

功能码用途
0x03读保持寄存器(状态/速度回收)
0x06写单寄存器(速度设定等)
0x10写多寄存器(批量参数下发)
  • 帧结构:地址(1B) + 功能码(1B) + 数据(NB) + CRC16(2B,低字节在前)
  • CRC16 参数:多项式 0x8005(反射 0xA001)、初值 0xFFFF,实现查表法与逐位法两种等价算法——上位机协议栈的 CRC 直接复用同一张表
  • 实例帧:01 06 03 03 05 DC → CRC = 7B 47
  • 错误应答识别:功能码 + 0x80
  • 编码器读事务做功能码 + 长度 + CRC 三重校验,连续无应答即触发单轴安全关断

异常保护体系

保护触发条件动作
心跳丢失500ms 无任何合法帧(首帧后生效)全轴 SafeShutdown + 0x8F 上报
驱动器失联连续 3 次编码器读无应答/校验失败单轴 SafeShutdown
软限位位置超出 ±170°(可配)且运动中单轴 SafeShutdown
硬限位EXTI 接口预留(硬件常闭开关已具备)后续接入 SafeShutdown 链
CRC 错帧校验失败丢帧 + 收发统计
IWDG喂狗点已置于 monitorTask(启用为编译开关)复位兜底
抱闸 failsafe硬件特性:断电即抱死物理兜底

关于伺服三环控制的工程结论

电流环/速度环/位置环要不要在 MCU 里做?——不需要,这是伺服系统的标准级联结构:

  • 位置环(软件,按曲线节拍)→ 速度环(驱动器硬件闭环)→ 电流环(驱动器硬件闭环,µs 级带宽);
  • 若强行在 MCU 做三环:RS485 半双工往返 + RTOS 任务抖动,内环带宽根本撑不起来,反而劣化性能;
  • 本项目 MCU 只做位置外环:协议与运动接口预留位置指令扩展,速度/电流环交给禾川驱动器。

轨迹跟踪业务层的实现方案:双电机按 FLASH 中的 1000 点位置/速度曲线做 S 曲线协同跟踪——位置 PID + 速度前馈 + 双电机交叉耦合补偿,位置环输出直接写驱动器速度寄存器;上位机经 LoRa 链路完成曲线分块下传(块号 ACK 隐含重传)、误差曲线回读、前馈/耦合系数在线整定与点动控制;限位开关走 EXTI 硬件链路。

已知限制与后续项

  1. 驱动器应答等待仍为固定 5ms 盲等,改进方向是信号量 + 超时;
  2. IWDG 未启用(喂狗点与启用步骤已就位,编译开关打开即用);
  3. 硬限位 EXTI 尚未接入软件保护链(常闭开关硬件与 EXTI 驱动已具备,接入方案:ISR 直接抱闸 + 通知任务走 SafeShutdown);
  4. USART6 波特率 9600,协议帧建议提升到 115200;
  5. printf 复用上位机串口,正式版应以编译开关关闭或改用独立调试口;
  6. 位置闭环当前为速度模式的接口预留,轨迹跟踪按上文 S 曲线方案扩展。

项目状态

下位机软件已完成「RS485 协议栈 + 统一运动接口 + 四大逻辑任务 + 多级异常保护」的完整架构实现;驱动层经整机联调实测,Modbus 通信、双轴运动控制、上位机链路稳定工作,支撑完成单段焊缝与截面焊缝检测流程。

使用 Hugo 构建
主题 Stack 由 Jimmy 设计