Files
2026-06-09 12:42:15 +08:00

8.3 KiB
Raw Permalink Blame History

板卡运动控制适配说明

本文档说明如何把当前 C++ Modbus RTU 协议库迁移到真实驱动板,并对接板卡已有的运动控制模块。

迁移结论

你不需要重写 Modbus 协议层。板卡侧主要实现 MotionControlAdapter 接口,然后在串口收齐一帧 RTU 数据后调用 MotionControlBridge::process_request()

flowchart LR
    UartRx["UART/RS-485 收完整 RTU 帧"] --> Bridge["MotionControlBridge"]
    Bridge --> Server["DeviceServer"]
    Server --> Bank["RegisterBank"]
    Bridge --> Adapter["MotionControlAdapter 接口"]
    Adapter --> Motion["板卡已有运动控制模块"]
    Motion --> Adapter
    Bridge --> UartTx["UART/RS-485 发响应帧"]

需要实现的接口

接口定义在 include/line_laser_modbus/motion_adapter.hpp

class MotionControlAdapter {
 public:
  virtual ~MotionControlAdapter() = default;

  virtual void on_mode_changed(WorkMode mode) = 0;
  virtual void on_target_pose(const Pose6D& pose) = 0;
  virtual void on_correction(const Pose6D& correction) = 0;

  [[nodiscard]] virtual Pose6D current_pose() const = 0;
  [[nodiscard]] virtual DeviceState current_state() const = 0;
};

每个函数的含义:

  • on_mode_changed():上位机写入 0xD000 模式命令字,且模式值和切换规则合法后调用。
  • on_target_pose():上位机写入 0xD020 ~ 0xD02D 目标示教位姿后调用。
  • on_correction():上位机写入 0xD036 ~ 0xD043 六轴纠偏量后调用。
  • current_pose():返回板卡当前实际位姿,桥接层会写入 0xD00A ~ 0xD017
  • current_state():返回板卡当前状态字,桥接层会写入 0xD001

推荐固件主循环

sequenceDiagram
    participant UART as UART_RS485
    participant Main as 固件主循环
    participant Bridge as MotionControlBridge
    participant Adapter as 你的板卡适配器
    participant Motion as 运动控制模块

    Motion-->>Adapter: 更新当前位姿和状态
    UART-->>Main: 收到完整 RTU 请求帧
    Main->>Bridge: process_request(request)
    Bridge->>Adapter: current_pose()
    Bridge->>Adapter: current_state()
    Bridge->>Bridge: 写入当前位姿和状态寄存器
    Bridge->>Bridge: DeviceServer 处理读写请求
    Bridge->>Adapter: 写请求成功后回调模式/目标/纠偏
    Adapter->>Motion: 转发给板卡运动控制逻辑
    Bridge-->>Main: response
    Main-->>UART: response 非空则发送

伪代码:

#include "line_laser_modbus/motion_adapter.hpp"

class BoardMotionAdapter final : public line_laser_modbus::MotionControlAdapter {
 public:
  void on_mode_changed(line_laser_modbus::WorkMode mode) override {
    // 调用你的板卡模式切换函数,例如 motion_set_mode(...)
  }

  void on_target_pose(const line_laser_modbus::Pose6D& pose) override {
    // 把目标示教位姿送入轨迹/插补/记录模块
  }

  void on_correction(const line_laser_modbus::Pose6D& correction) override {
    // 把实时纠偏量送入跟踪控制模块
  }

  line_laser_modbus::Pose6D current_pose() const override {
    // 从板卡轴控反馈读取当前实际 XYZABC
    return {};
  }

  line_laser_modbus::DeviceState current_state() const override {
    // 从板卡报警、运行、急停、标定等状态生成协议状态字
    return line_laser_modbus::DeviceState::StandbyReady;
  }
};

line_laser_modbus::DeviceServer server;
BoardMotionAdapter adapter;
line_laser_modbus::MotionControlBridge bridge(server, adapter);

void on_complete_rtu_frame(const line_laser_modbus::ByteVector& request) {
  const auto response = bridge.process_request(request);
  if (!response.empty()) {
    uart_send(response.data(), response.size());
  }
}

数据流

flowchart TD
    HostWriteMode["上位机写模式 0xD000"] --> ServerCheck["DeviceServer 校验模式合法性"]
    ServerCheck --> AdapterMode["on_mode_changed(mode)"]
    AdapterMode --> BoardMode["板卡切换运动模式"]

    HostWriteTarget["上位机写目标位姿 0xD020"] --> BankTarget["RegisterBank 保存目标位姿"]
    BankTarget --> AdapterTarget["on_target_pose(pose)"]
    AdapterTarget --> BoardTarget["板卡轨迹/示教模块"]

    HostWriteCorrection["上位机写纠偏量 0xD036"] --> BankCorrection["RegisterBank 保存纠偏量"]
    BankCorrection --> AdapterCorrection["on_correction(correction)"]
    AdapterCorrection --> BoardCorrection["板卡实时跟踪模块"]

    BoardFeedback["板卡轴控反馈"] --> AdapterFeedback["current_pose/current_state"]
    AdapterFeedback --> BridgePublish["MotionControlBridge 发布到寄存器"]
    BridgePublish --> HostRead["上位机读取当前位姿/状态"]

模式和状态映射建议

flowchart LR
    subgraph WorkMode["WorkMode 模式命令"]
        M0["0 待机复位"]
        M1["1 系统标定"]
        M2["2 焊前扫描示教"]
        M3["3 在线全轴跟踪"]
        M4["4 轨迹批量复现"]
        M5["5 紧急停止"]
    end

    subgraph BoardAction["板卡动作"]
        A0["清空轨迹/纠偏/停机待命"]
        A1["执行标定流程"]
        A2["接收并记录目标轨迹点"]
        A3["启用实时纠偏叠加"]
        A4["调用已保存标准轨迹"]
        A5["断使能/急停制动"]
    end

    M0 --> A0
    M1 --> A1
    M2 --> A2
    M3 --> A3
    M4 --> A4
    M5 --> A5

current_state() 建议从板卡真实状态生成:

  • 无故障待命:DeviceState::StandbyReady
  • 运动中:DeviceState::MotionRunning
  • 示教完成:DeviceState::TeachingComplete
  • 在线跟踪正常:DeviceState::OnlineTrackingNormal
  • 任意报警:DeviceState::Alarm
  • 标定完成:DeviceState::CalibrationComplete
  • 急停触发:DeviceState::EmergencyTriggered

线程和中断注意事项

如果板卡上通信任务和运动控制任务不是同一个线程,需要处理共享数据同步。

flowchart TB
    UartTask["通信任务<br/>调用 MotionControlBridge"] --> Shared["共享运动数据快照"]
    MotionTask["运动控制任务<br/>更新轴位姿和状态"] --> Shared
    Shared --> Lock["互斥锁 / 临界区 / 双缓冲"]

建议:

  • 不要在串口中断里直接执行复杂运动控制逻辑;中断只收字节,完整帧交给通信任务处理。
  • current_pose()current_state() 应尽量只读取快照,避免阻塞。
  • on_correction() 如果运行在通信任务中,应把纠偏量写入线程安全队列或双缓冲,再由运动控制周期消费。
  • 如果驱动板不支持 C++ 异常,当前实现仍可使用,因为协议和适配层没有依赖异常流程。

与现有代码的关系

classDiagram
    class MotionControlAdapter {
        <<interface>>
        +on_mode_changed(mode)
        +on_target_pose(pose)
        +on_correction(correction)
        +current_pose() Pose6D
        +current_state() DeviceState
    }

    class MotionControlBridge {
        -DeviceServer server_
        -MotionControlAdapter adapter_
        +process_request(request)
        +publish_feedback()
    }

    class DeviceServer {
        +process_request(request)
        +bank()
    }

    class RegisterBank {
        +read(address, quantity)
        +write(address, registers)
        +set_current_pose(pose)
        +set_state(state)
    }

    MotionControlBridge --> MotionControlAdapter
    MotionControlBridge --> DeviceServer
    DeviceServer --> RegisterBank

Demo

apps/adapter_demo.cpp 提供了一个模拟板卡适配器:

  • DemoBoardMotion 实现 MotionControlAdapter
  • 上位机 demo 写入在线跟踪模式、目标位姿和纠偏量。
  • 桥接层把这些写请求回调给 DemoBoardMotion
  • 读取当前位姿时,桥接层先从 DemoBoardMotion::current_pose() 发布反馈,再返回 Modbus 响应。

构建后可运行:

cmake --build cpp/build --config Release
cpp/build/Release/adapter_demo.exe

最小迁移清单

  • 实现一个继承 MotionControlAdapter 的板卡适配类。
  • 在 UART/RS-485 层实现完整 RTU 帧接收和响应发送。
  • MotionControlBridge::process_request() 连接协议处理。
  • on_mode_changed() 中接入板卡模式切换。
  • on_target_pose() 中接入轨迹示教/记录模块。
  • on_correction() 中接入实时纠偏模块。
  • current_pose()current_state() 中返回板卡真实反馈。