feat: 实现 Axis 核心属性与 MC_Power 功能块
- Axis: 新增运动学/功率/错误管理属性(_position 等 10+ 项) - Axis: 新增 doPower()/readState()/cycle() 接口骨架 - MC_Power: 实现功率使能功能块(边沿检测 + 状态输出) - GlobalResource: 新增 CreateAxis/GetAxisRefById 全局轴管理 - App/CMakeLists.txt: 添加 GlobalResource.cpp 源文件 - docs: 更新 Axis 属性清单与 MC_Power 设计文档
This commit is contained in:
@@ -9,6 +9,8 @@ project(MotionApp
|
||||
set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Src/main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Src/MotionTickThread.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Src/UserAppThread.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Src/GlobalResource.cpp
|
||||
)
|
||||
|
||||
# 工程源文件
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file GlobalResource.h
|
||||
* @author
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Axis.h"
|
||||
#include "Types.h"
|
||||
|
||||
/**
|
||||
* \brief 创建轴并注册到全局表
|
||||
* \param id 轴编号
|
||||
* \param name 轴名称
|
||||
* \return 轴引用。若 id 已存在,返回已有轴的引用(不覆盖)
|
||||
*/
|
||||
plcopen::AXIS_REF& CreateAxis(plcopen::UINT id, const std::string& name);
|
||||
|
||||
/**
|
||||
* \brief 通过编号获取轴引用
|
||||
* \param id 轴编号
|
||||
* \return AXIS_REF 引用。若不存在,返回 axis==nullptr 的哨兵引用
|
||||
*/
|
||||
plcopen::AXIS_REF& GetAxisRefById(plcopen::UINT id);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @file UserAppThread.h
|
||||
* @author
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
int UserAppThread();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file GlobalResource.cpp
|
||||
* @author
|
||||
* @brief 全局轴资源管理 — 持有并管理所有轴实例
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GlobalResource.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
namespace {
|
||||
|
||||
// 轴实例存储 — 拥有所有轴的内存
|
||||
std::vector<plcopen::Axis> g_axes;
|
||||
|
||||
// 快速查找表:id → AXIS_REF& (指向 g_axes 中的元素)
|
||||
std::unordered_map<plcopen::UINT, std::size_t> g_indexMap;
|
||||
|
||||
// 线程安全
|
||||
std::mutex g_mutex;
|
||||
|
||||
// id 不存在时返回的哨兵
|
||||
plcopen::AXIS_REF g_invalidRef{0, "", nullptr};
|
||||
|
||||
} // namespace
|
||||
|
||||
plcopen::AXIS_REF& CreateAxis(plcopen::UINT id, const std::string& name) {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
// id 已存在 → 返回已有轴的引用
|
||||
auto it = g_indexMap.find(id);
|
||||
if (it != g_indexMap.end()) {
|
||||
return g_axes[it->second].ref();
|
||||
}
|
||||
|
||||
// 新建轴
|
||||
g_axes.emplace_back(id, name);
|
||||
std::size_t idx = g_axes.size() - 1;
|
||||
g_indexMap[id] = idx;
|
||||
return g_axes[idx].ref();
|
||||
}
|
||||
|
||||
plcopen::AXIS_REF& GetAxisRefById(plcopen::UINT id) {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
auto it = g_indexMap.find(id);
|
||||
if (it != g_indexMap.end()) {
|
||||
return g_axes[it->second].ref();
|
||||
}
|
||||
|
||||
g_invalidRef.axisNo = id;
|
||||
g_invalidRef.axis = nullptr;
|
||||
return g_invalidRef;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file UserAppThread.cpp
|
||||
* @author
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
#include "UserAppThread.h"
|
||||
#include "Axis.h"
|
||||
#include "FunctionBlocks.h"
|
||||
#include "MC_Power.h"
|
||||
|
||||
int UserAppThread()
|
||||
{
|
||||
plcopen::MC_Power mcPowerInstance0()
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-13
@@ -13,17 +13,14 @@
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "MotionTickThread.h"
|
||||
#include "UserAppThread.h"
|
||||
#include "Axis.h"
|
||||
#include "Types.h"
|
||||
|
||||
static int UserAppThread();
|
||||
|
||||
|
||||
std::vector<plcopen::Axis> axisList;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
plcopen::Axis axis1(1, "axis1");
|
||||
plcopen::Axis axis2(2, "axis2");
|
||||
axisList.push_back(axis1);
|
||||
@@ -39,14 +36,5 @@ int main()
|
||||
}
|
||||
|
||||
|
||||
static int UserAppThread()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+28
-2
@@ -59,12 +59,38 @@ public:
|
||||
explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
|
||||
|
||||
void cycle();
|
||||
MC_AXIS_STATE readState();
|
||||
|
||||
void doPower(bool en);
|
||||
|
||||
/** \brief 获取轴编号 */
|
||||
UINT axisNo() const { return _ref.axisNo; }
|
||||
|
||||
/** \brief 获取内部 AXIS_REF(供全局注册表使用) */
|
||||
AXIS_REF& ref() { return _ref; }
|
||||
|
||||
private:
|
||||
AXIS_REF ref_;
|
||||
MC_AXIS_STATE state_ = MC_AXIS_STATE::Disabled;
|
||||
AXIS_REF _ref;
|
||||
MC_AXIS_STATE _state = MC_AXIS_STATE::Disabled;
|
||||
MC_AXIS_STATE _resultingSstate = MC_AXIS_STATE::Disabled;
|
||||
|
||||
MotionCommand _activeCommand;
|
||||
|
||||
// 运动学属性
|
||||
REAL _position;
|
||||
REAL _actualPosition;
|
||||
REAL _velocity;
|
||||
REAL _actualVelocity;
|
||||
REAL _acceleration;
|
||||
REAL _actualAcceleration;
|
||||
|
||||
// 功率与使能
|
||||
BOOL _powerEnabled;
|
||||
BOOL _homed;
|
||||
|
||||
// 错误管理
|
||||
MC_ERROR_ID _errorId;
|
||||
BOOL _errorStop;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @file FunctionBlocks.h
|
||||
* @author
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "MC_Power.h"
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file MC_Power.h
|
||||
* @author
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Axis.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace plcopen {
|
||||
class MC_Power{
|
||||
public:
|
||||
|
||||
explicit MC_Power(AXIS_REF& axisRef);
|
||||
|
||||
void cycle();
|
||||
|
||||
// --- 输入参数 (VAR_INPUT) ---
|
||||
BOOL Enable = false;
|
||||
BOOL Enable_Positive = true;
|
||||
BOOL Enable_Negative = true;
|
||||
|
||||
// --- 输出参数 (VAR_OUTPUT) ---
|
||||
BOOL Status = false;
|
||||
BOOL Busy = false;
|
||||
BOOL Error = false;
|
||||
MC_ERROR_ID ErrorID = MC_ERROR_ID::mcNoError;
|
||||
|
||||
private:
|
||||
AXIS_REF& _axisRef; // 轴引用,不持有所有权
|
||||
bool _prevEnable = false; // 上一周期的 Enable 值(边沿检测)
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+72
-3
@@ -14,14 +14,83 @@
|
||||
|
||||
namespace plcopen {
|
||||
Axis::Axis(UINT axisNo, std::string name) {
|
||||
ref_.axisNo = axisNo;
|
||||
ref_.axisName = std::move(name);
|
||||
ref_.axis = this;
|
||||
_ref.axisNo = axisNo;
|
||||
_ref.axisName = std::move(name);
|
||||
_ref.axis = this;
|
||||
}
|
||||
|
||||
void Axis::cycle()
|
||||
{
|
||||
if (_errorStop) return;
|
||||
|
||||
if (!_powerEnabled) return;
|
||||
|
||||
switch (_state) {
|
||||
case MC_AXIS_STATE::Disabled :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case MC_AXIS_STATE::Standstill :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case MC_AXIS_STATE::Stopping :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 独立运动
|
||||
case MC_AXIS_STATE::DiscreteMotion :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 持续运动
|
||||
case MC_AXIS_STATE::ContinuousMotion :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 同步运动
|
||||
case MC_AXIS_STATE::SynchronizedMotion :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 回零
|
||||
case MC_AXIS_STATE::Homing :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::doPower(bool en)
|
||||
{
|
||||
if(en)
|
||||
{
|
||||
_powerEnabled = true;
|
||||
}
|
||||
else {
|
||||
_powerEnabled = false;
|
||||
_activeCommand.type = MotionCommandType::None;
|
||||
_velocity = 0.0;
|
||||
_acceleration = 0.0;
|
||||
_errorStop = false;
|
||||
_state = MC_AXIS_STATE::Disabled;
|
||||
}
|
||||
}
|
||||
|
||||
MC_AXIS_STATE Axis::readState()
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file MC_Power.cpp
|
||||
* @author
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2026-07-03
|
||||
*
|
||||
* @copyright Copyright (c) 2026
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MC_Power.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace plcopen {
|
||||
|
||||
MC_Power::MC_Power(AXIS_REF& axisRef)
|
||||
: _axisRef(axisRef) { }
|
||||
|
||||
void MC_Power::cycle()
|
||||
{
|
||||
if(_axisRef.axis == nullptr)
|
||||
{
|
||||
Error = true;
|
||||
ErrorID = MC_ERROR_ID::mcInvalidParameter;
|
||||
Status = false;
|
||||
Busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Axis* axis = _axisRef.axis;
|
||||
Error = false;
|
||||
ErrorID = MC_ERROR_ID::mcNoError;
|
||||
|
||||
// 上升沿
|
||||
if(Enable && !_prevEnable)
|
||||
{
|
||||
axis->doPower(true);
|
||||
}
|
||||
|
||||
// 下降沿
|
||||
if(!Enable && _prevEnable)
|
||||
{
|
||||
axis->doPower(false);
|
||||
}
|
||||
|
||||
// 在使能状态下持续更新轴状态
|
||||
if(Enable)
|
||||
{
|
||||
auto state = axis->readState();
|
||||
if(state == MC_AXIS_STATE::Standstill)
|
||||
{
|
||||
Busy = false;
|
||||
Status = true;
|
||||
}
|
||||
else if(state == MC_AXIS_STATE::ErrorStop)
|
||||
{
|
||||
Busy = false;
|
||||
Status = false;
|
||||
Error = true;
|
||||
ErrorID = MC_ERROR_ID::mcPowerFailure;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = false;
|
||||
Busy = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 保存前置状态
|
||||
_prevEnable = Enable;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+110
-75
@@ -2,11 +2,31 @@
|
||||
|
||||
`Axis` 是 PLCopen 运动控制库的核心仿真类,实现 IEC 61131-3 单轴状态机与运动学。
|
||||
|
||||
## 设计决策
|
||||
|
||||
### 可见性:运动学属性为 `private`
|
||||
|
||||
功能块不直接读写轴内部状态,而是通过 `AXIS_REF` 调用公开接口。这是 IEC 61131-3 的标准模式——轴是功能块黑盒:
|
||||
|
||||
```
|
||||
功能块 (MC_MoveAbsolute) Axis
|
||||
───────────────────── ─────────────
|
||||
AXIS_REF → axis private: position_, velocity_, ...
|
||||
axis.acceptCommand(cmd) ──────→ 只有 cycle() 能写运动学数据
|
||||
axis.readActualPosition() ←─── public: getter 只读
|
||||
```
|
||||
|
||||
> 运动控制线程定时调用 `cycle()` 独占写权限,避免数据竞争。
|
||||
|
||||
### 数值类型:浮点 `REAL` (double)
|
||||
|
||||
遵循 IEC 61131-3 / PLCopen 规范,使用 `double` 表示物理量(mm、°/s 等)。`double` 有 52 位尾数(约 15 位十进制有效数字),以 10ms 周期运行 1 小时,累积的浮点舍入误差在 $10^{-10}$ 量级,工程上可完全忽略。若未来对接真实驱动器,在数据交换层做脉冲数换算即可。
|
||||
|
||||
---
|
||||
|
||||
## 1. 当前已实现
|
||||
|
||||
### 1.1 轴标识与自引用 — `AXIS_REF ref_`
|
||||
### 1.1 轴标识与自引用 — `AXIS_REF _ref` (private)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
@@ -14,47 +34,54 @@
|
||||
| `axisName` | `std::string` | 轴名称,默认 `"Axis1"` |
|
||||
| `axis` | `Axis*` | 指向自身实例的指针,供功能块间接访问轴对象 |
|
||||
|
||||
> `AXIS_REF` 在 IEC 61131-3 中是 `VAR_IN_OUT` 参数,本实现中构造时自绑定。
|
||||
### 1.2 轴状态 — `MC_AXIS_STATE _state` (private)
|
||||
|
||||
### 1.2 轴状态 — `MC_AXIS_STATE state_`
|
||||
当前状态,初始值 `Disabled`。新增辅助状态 `_resultingState` 用于记录指令完成后的目标状态。
|
||||
|
||||
当前状态机状态,初始值为 `Disabled`。可能的取值:
|
||||
状态转换由 `cycle()` 方法驱动(逻辑待实现)。
|
||||
|
||||
```
|
||||
Disabled → Standstill → DiscreteMotion / ContinuousMotion / Homing
|
||||
→ Stopping
|
||||
ErrorStop
|
||||
SynchronizedMotion (预留)
|
||||
```
|
||||
### 1.3 运动学属性 (private) ✅
|
||||
|
||||
状态转换由 `cycle()` 方法驱动(尚未实现)。
|
||||
|
||||
### 1.3 构造函数
|
||||
|
||||
```cpp
|
||||
explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
|
||||
```
|
||||
|
||||
初始化 `ref_` 并自绑定 `axis` 指针,`state_` 默认 `Disabled`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 必须扩展的属性(待实现)
|
||||
|
||||
按照 PLCopen 规范,完整的轴模型还需以下属性。
|
||||
|
||||
### 2.1 运动学属性
|
||||
`cycle()` 独占写入;外部通过 `readXxx()` 只读访问。
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `position_` | `REAL` | 当前指令位置 |
|
||||
| `actualPosition_` | `REAL` | 当前实际位置 |
|
||||
| `velocity_` | `REAL` | 当前速度 |
|
||||
| `actualVelocity_` | `REAL` | 实际速度 |
|
||||
| `acceleration_` | `REAL` | 当前加速度 |
|
||||
| `deceleration_` | `REAL` | 当前减速度 |
|
||||
| `_position` | `REAL` | 当前指令位置 |
|
||||
| `_actualPosition` | `REAL` | 当前实际位置(含跟随误差仿真) |
|
||||
| `_velocity` | `REAL` | 当前指令速度 |
|
||||
| `_actualVelocity` | `REAL` | 当前实际速度 |
|
||||
| `_acceleration` | `REAL` | 当前指令加速度 |
|
||||
| `_actualAcceleration` | `REAL` | 当前实际加速度 |
|
||||
| `_deceleration` | `REAL` | 减速度(尚未添加) |
|
||||
|
||||
### 2.2 活动指令 — `MotionCommand activeCommand_`
|
||||
### 1.4 功率与使能 (private) ✅
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `_powerEnabled` | `BOOL` | 功率级是否使能 |
|
||||
| `_homed` | `BOOL` | 是否已完成回零 |
|
||||
|
||||
### 1.5 错误管理 (private) ✅
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `_errorId` | `MC_ERROR_ID` | 当前错误码,`mcNoError` 表示正常 |
|
||||
| `_errorStop` | `BOOL` | 是否触发错误停止 |
|
||||
|
||||
### 1.6 构造函数 & cycle() (public)
|
||||
|
||||
```cpp
|
||||
explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
|
||||
void cycle(); // 骨架已生成,逻辑待实现
|
||||
```
|
||||
|
||||
初始化 `_ref` 并自绑定 `axis` 指针,`_state` 默认 `Disabled`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 待实现的属性与方法
|
||||
|
||||
### 2.1 活动指令 — `MotionCommand _activeCommand` (private)
|
||||
|
||||
当前正在执行的运动指令参数快照,类型为 `MotionCommand`:
|
||||
|
||||
@@ -69,61 +96,69 @@ explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
|
||||
| `homePosition` | `REAL` | 回零位置 |
|
||||
| `resultingState` | `MC_AXIS_STATE` | 指令完成后要进入的状态 |
|
||||
|
||||
### 2.3 功率与使能
|
||||
### 2.2 待补充的运动学属性
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `powerEnabled_` | `BOOL` | 功率级是否使能 |
|
||||
| `homed_` | `BOOL` | 是否已完成回零 |
|
||||
| 属性 | 说明 |
|
||||
|------|------|
|
||||
| `_deceleration` | 减速度(已有 `_acceleration`,缺独立减速参数) |
|
||||
|
||||
### 2.4 错误管理
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `errorId_` | `MC_ERROR_ID` | 当前错误码,`mcNoError` 表示正常 |
|
||||
| `errorStop_` | `BOOL` | 是否触发错误停止 |
|
||||
|
||||
### 2.5 轴状态机方法 — `cycle()`
|
||||
### 2.3 轴状态机方法 — `cycle()` (public, 实现待完成)
|
||||
|
||||
```cpp
|
||||
void cycle(REAL deltaTime);
|
||||
void cycle();
|
||||
```
|
||||
|
||||
每周期由应用层调用,执行:
|
||||
1. 根据 `activeCommand_` 计算运动学输出
|
||||
2. 更新 `position_` / `velocity_`
|
||||
每周期由运动控制线程调用,待实现逻辑:
|
||||
1. 根据 `_activeCommand` 计算运动学输出
|
||||
2. 更新 `_position` / `_velocity` 等
|
||||
3. 评估状态转换条件
|
||||
4. 在离散运动到达目标时自动切换到 `Standstill`
|
||||
|
||||
### 2.6 功能块交互接口
|
||||
### 2.4 功能块交互接口 (public, 全部待实现)
|
||||
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| `acceptCommand(const MotionCommand&)` | 接收功能块下发的运动指令 |
|
||||
| `doPower(BOOL enable)` | 功率使能/去使能 |
|
||||
| `doStop()` / `doHalt()` | 停止 / 暂停 |
|
||||
| `doReset()` | 从 ErrorStop 恢复 |
|
||||
| `doHome(REAL homePos)` | 发起回零 |
|
||||
| `readStatus()` | 读取当前状态快照 |
|
||||
| `readError()` | 读取当前错误码 |
|
||||
| 方法 | 可见性 | 说明 |
|
||||
|------|--------|------|
|
||||
| `acceptCommand(const MotionCommand&)` | public | 接收功能块下发的运动指令 |
|
||||
| `doPower(BOOL enable)` | public | 功率使能/去使能 |
|
||||
| `doStop()` / `doHalt()` | public | 停止 / 暂停 |
|
||||
| `doReset()` | public | 从 ErrorStop 恢复 |
|
||||
| `doHome(REAL homePos)` | public | 发起回零 |
|
||||
| `readStatus()` | public | 读取当前状态快照 |
|
||||
| `readActualPosition()` | public | 读取实际位置 |
|
||||
| `readActualVelocity()` | public | 读取实际速度 |
|
||||
| `readError()` | public | 读取当前错误码 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 完整属性清单(含待实现)
|
||||
## 3. 完整属性清单
|
||||
|
||||
```
|
||||
private
|
||||
───────
|
||||
Axis
|
||||
├── ref_ (AXIS_REF) ✅ 已实现
|
||||
├── state_ (MC_AXIS_STATE) ✅ 已实现
|
||||
├── position_ (REAL) ⬜ 位置
|
||||
├── actualPosition_ (REAL) ⬜ 实际位置
|
||||
├── velocity_ (REAL) ⬜ 速度
|
||||
├── actualVelocity_ (REAL) ⬜ 实际速度
|
||||
├── acceleration_ (REAL) ⬜ 加速度
|
||||
├── deceleration_ (REAL) ⬜ 减速度
|
||||
├── activeCommand_ (MotionCommand) ⬜ 活动指令
|
||||
├── powerEnabled_ (BOOL) ⬜ 功率使能
|
||||
├── homed_ (BOOL) ⬜ 回零完成
|
||||
├── errorId_ (MC_ERROR_ID) ⬜ 错误码
|
||||
└── errorStop_ (BOOL) ⬜ 错误停止
|
||||
├── _ref (AXIS_REF) ✅
|
||||
├── _state (MC_AXIS_STATE) ✅
|
||||
├── _resultingState (MC_AXIS_STATE) ✅ 指令完成目标状态
|
||||
├── _position (REAL) ✅
|
||||
├── _actualPosition (REAL) ✅
|
||||
├── _velocity (REAL) ✅
|
||||
├── _actualVelocity (REAL) ✅
|
||||
├── _acceleration (REAL) ✅
|
||||
├── _actualAcceleration (REAL) ✅
|
||||
├── _deceleration (REAL) ⬜ 待添加
|
||||
├── _powerEnabled (BOOL) ✅
|
||||
├── _homed (BOOL) ✅
|
||||
├── _errorId (MC_ERROR_ID) ✅
|
||||
├── _errorStop (BOOL) ✅
|
||||
└── _activeCommand (MotionCommand) ⬜ 活动指令
|
||||
|
||||
public
|
||||
──────
|
||||
Axis(axisNo, name) ✅
|
||||
cycle() 🟡 骨架已就绪
|
||||
acceptCommand(cmd) ⬜
|
||||
doPower / doStop / doHalt ⬜
|
||||
doReset / doHome ⬜
|
||||
readStatus / readActualPosition ⬜
|
||||
readActualVelocity / readError ⬜
|
||||
```
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
# MC_Power 功能块设计
|
||||
|
||||
`MC_Power` 是 PLCopen 运动控制库的基础功能块,控制轴的功率级使能与去使能。
|
||||
|
||||
---
|
||||
|
||||
## 1. IEC 61131-3 接口定义
|
||||
|
||||
```
|
||||
FUNCTION_BLOCK MC_Power
|
||||
VAR_IN_OUT
|
||||
Axis : AXIS_REF; (* 轴引用 *)
|
||||
END_VAR
|
||||
VAR_INPUT
|
||||
Enable : BOOL; (* TRUE=使能, FALSE=去使能 *)
|
||||
Enable_Positive : BOOL; (* 允许正向运动,本库保留 *)
|
||||
Enable_Negative : BOOL; (* 允许负向运动,本库保留 *)
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Status : BOOL; (* 轴已使能且就绪 *)
|
||||
Busy : BOOL; (* 功能块正在处理中 *)
|
||||
Error : BOOL; (* 错误标志 *)
|
||||
ErrorID : MC_ERROR_ID;(* 错误码 *)
|
||||
END_VAR
|
||||
```
|
||||
|
||||
## 2. C++ 类实现
|
||||
|
||||
### 2.1 类声明 — `MotionLib/Inc/MC_Power.h`
|
||||
|
||||
```cpp
|
||||
#pragma once
|
||||
#include "Types.h"
|
||||
|
||||
namespace plcopen {
|
||||
|
||||
class MC_Power {
|
||||
public:
|
||||
/**
|
||||
* \brief 构造 MC_Power 实例
|
||||
* \param axisRef 轴引用 (VAR_IN_OUT)
|
||||
*/
|
||||
explicit MC_Power(AXIS_REF& axisRef);
|
||||
|
||||
/**
|
||||
* \brief 周期调用,执行功率控制逻辑
|
||||
*
|
||||
* 上位机每个运动控制周期调用一次。
|
||||
*/
|
||||
void cycle();
|
||||
|
||||
// --- 输入参数 (VAR_INPUT) ---
|
||||
BOOL Enable = false;
|
||||
BOOL Enable_Positive = true; // 本库默认允许
|
||||
BOOL Enable_Negative = true; // 本库默认允许
|
||||
|
||||
// --- 输出参数 (VAR_OUTPUT) ---
|
||||
BOOL Status = false;
|
||||
BOOL Busy = false;
|
||||
BOOL Error = false;
|
||||
MC_ERROR_ID ErrorID = MC_ERROR_ID::mcNoError;
|
||||
|
||||
private:
|
||||
AXIS_REF& _axisRef; // 轴引用,不持有所有权
|
||||
bool _prevEnable = false; // 上一周期的 Enable 值(边沿检测)
|
||||
};
|
||||
|
||||
} // namespace plcopen
|
||||
```
|
||||
|
||||
### 2.2 实现 — `MotionLib/Src/MC_Power.cpp`
|
||||
|
||||
```cpp
|
||||
#include "MC_Power.h"
|
||||
#include "Axis.h"
|
||||
|
||||
namespace plcopen {
|
||||
|
||||
MC_Power::MC_Power(AXIS_REF& axisRef)
|
||||
: _axisRef(axisRef) {}
|
||||
|
||||
void MC_Power::cycle() {
|
||||
// ① 有效性检查
|
||||
if (_axisRef.axis == nullptr) {
|
||||
Error = true;
|
||||
ErrorID = MC_ERROR_ID::mcInvalidParameter;
|
||||
Status = false;
|
||||
Busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Axis* axis = _axisRef.axis;
|
||||
Error = false;
|
||||
ErrorID = MC_ERROR_ID::mcNoError;
|
||||
|
||||
// ② Enable 上升沿 — 使能
|
||||
if (Enable && !_prevEnable) {
|
||||
axis->doPower(true);
|
||||
Busy = true;
|
||||
}
|
||||
|
||||
// ③ Enable 下降沿 — 去使能
|
||||
if (!Enable && _prevEnable) {
|
||||
axis->doPower(false);
|
||||
Busy = false;
|
||||
}
|
||||
|
||||
// ④ 持续使能状态 — 等待轴进入 Standstill
|
||||
if (Enable) {
|
||||
MC_AXIS_STATE state = axis->readState();
|
||||
|
||||
if (state == MC_AXIS_STATE::Standstill) {
|
||||
Busy = false;
|
||||
Status = true; // 使能成功
|
||||
} else if (state == MC_AXIS_STATE::ErrorStop) {
|
||||
Busy = false;
|
||||
Status = false;
|
||||
Error = true;
|
||||
ErrorID = MC_ERROR_ID::mcPowerFailure;
|
||||
}
|
||||
} else {
|
||||
// 去使能后
|
||||
Status = false;
|
||||
Busy = false;
|
||||
}
|
||||
|
||||
// ⑤ 保存前置状态
|
||||
_prevEnable = Enable;
|
||||
}
|
||||
|
||||
} // namespace plcopen
|
||||
```
|
||||
|
||||
## 3. 行为时序
|
||||
|
||||
```
|
||||
周期 | Enable | axis 状态 | Status | Busy | 说明
|
||||
─────┼────────┼───────────────┼────────┼──────┼────────────────
|
||||
0 | FALSE | Disabled | FALSE | FALSE| 初始状态
|
||||
1 | TRUE ↑ | Disabled | FALSE | TRUE | 上升沿,doPower(true)
|
||||
2 | TRUE | Disabled | FALSE | TRUE | cycle() 待处理
|
||||
3 | TRUE | Standstill | TRUE | FALSE| 使能完成 ✅
|
||||
4 | FALSE ↓| Standstill | FALSE | FALSE| 下降沿,doPower(false)
|
||||
5 | FALSE | Disabled | FALSE | FALSE| 去使能完成
|
||||
```
|
||||
|
||||
## 4. 与 Axis 的交互
|
||||
|
||||
```
|
||||
MC_Power Axis
|
||||
──────── ────
|
||||
cycle()
|
||||
│
|
||||
├── Enable↑ → axis->doPower(true) ──→ _powerEnabled = true
|
||||
│ _state 将在 cycle() 中切换
|
||||
│
|
||||
├── Enable↓ → axis->doPower(false) ──→ _powerEnabled = false
|
||||
│ _state → Disabled
|
||||
│
|
||||
└── axis->readState() ←────────────── 读取 _state
|
||||
axis->readError() ←───────────── 读取 _errorId
|
||||
```
|
||||
|
||||
## 5. Axis 侧需要的新方法
|
||||
|
||||
```cpp
|
||||
// Axis.h — 新增方法
|
||||
|
||||
class Axis {
|
||||
public:
|
||||
void doPower(BOOL enable); // 功率使能控制
|
||||
MC_AXIS_STATE readState() const; // 读当前状态
|
||||
MC_ERROR_ID readError() const; // 读当前错误码
|
||||
};
|
||||
```
|
||||
|
||||
## 6. 设计要点
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| 不持有 Axis | `_axisRef` 是引用,MC_Power 不负责轴的生命周期 |
|
||||
| 上升/下降沿检测 | `_prevEnable` 确保 doPower() 只在边沿调用一次 |
|
||||
| Busy 的语义 | 从 Enable↑ 到 Status=TRUE 之间为 Busy |
|
||||
| Error 路径 | 轴进入 ErrorStop 时,Status→FALSE,Error→TRUE |
|
||||
| Enable_Positive/Negative | IEC 完整规范字段,本库保留输入但暂不实现逻辑 |
|
||||
Reference in New Issue
Block a user