17 changed files with 2096 additions and 12 deletions
-
3components/datastructure/datastructure.hpp
-
0components/datastructure/loopqueue.cpp
-
67components/datastructure/loopqueue.hpp
-
51components/datastructure/static_loop_queue.hpp
-
49components/iflytop_can_slave_modules/device_base_control_service.cpp
-
42components/iflytop_can_slave_modules/device_base_control_service.hpp
-
195components/iflytop_can_slave_modules/idcard_reader_service.cpp
-
89components/iflytop_can_slave_modules/idcard_reader_service.hpp
-
110components/iflytop_can_slave_modules/pri/state_machine.cpp
-
79components/iflytop_can_slave_modules/pri/state_machine.hpp
-
24components/m3078/m3078_code_scaner.cpp
-
16components/m3078/m3078_code_scaner.hpp
-
373components/single_axis_motor_control_v2/i_iflytop_can_slave_module.cpp
-
276components/single_axis_motor_control_v2/i_iflytop_can_slave_module.hpp
-
537components/single_axis_motor_control_v2/single_axis_motor_control_v2.cpp
-
191components/single_axis_motor_control_v2/single_axis_motor_control_v2.hpp
-
6hal/gpio.hpp
@ -0,0 +1,3 @@ |
|||
#pragma once
|
|||
#include "loopqueue.hpp"
|
|||
#include "static_loop_queue.hpp"
|
@ -0,0 +1,67 @@ |
|||
#pragma once
|
|||
#include <stdio.h>
|
|||
#include <string.h>
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
|
|||
template <typename T> |
|||
class LoopQueue { |
|||
private: |
|||
T *arr; |
|||
int maxSize; |
|||
int rear; |
|||
int front; |
|||
|
|||
public: |
|||
LoopQueue(/* args */) { |
|||
maxSize = 1; |
|||
rear = 0; |
|||
front = 0; |
|||
} |
|||
~LoopQueue() {} |
|||
|
|||
void initialize(int size) { |
|||
arr = (T *)malloc(size * sizeof(T)); |
|||
ZASSERT(arr != NULL); |
|||
maxSize = size; |
|||
} |
|||
|
|||
bool push(T *data) { |
|||
if (isFull()) { |
|||
return false; |
|||
} |
|||
memcpy(&arr[rear], data, sizeof(T)); |
|||
rear = (rear + 1) % maxSize; |
|||
return true; |
|||
} |
|||
bool pop(T *data) { |
|||
if (isEmpty()) { |
|||
return false; |
|||
} |
|||
memcpy(data, &arr[front], sizeof(T)); |
|||
front = (front + 1) % maxSize; |
|||
return true; |
|||
} |
|||
|
|||
bool popMuti(T *data, int numdata) { |
|||
if (numdata > numElements()) return false; |
|||
for (int i = 0; i < numdata; i++) { |
|||
pop(&data[i]); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool getHeader(T *data) { |
|||
if (isEmpty()) { |
|||
return false; |
|||
} |
|||
memcpy(data, &arr[front], sizeof(T)); |
|||
return true; |
|||
} |
|||
int size() { return maxSize; } |
|||
int numElements() { return (rear + maxSize - front) % maxSize; } |
|||
bool isEmpty() { return rear == front; } |
|||
bool isFull() { return (rear + 1) % maxSize == front; } |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -0,0 +1,51 @@ |
|||
#pragma once
|
|||
#include <stdio.h>
|
|||
#include <string.h>
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
|
|||
template <typename T, unsigned int num> |
|||
class StaticLoopQueue { |
|||
private: |
|||
T arr[num]; |
|||
int maxSize; |
|||
int rear; |
|||
int front; |
|||
|
|||
public: |
|||
StaticLoopQueue(/* args */) { |
|||
maxSize = num; |
|||
rear = 0; |
|||
front = 0; |
|||
} |
|||
~StaticLoopQueue() {} |
|||
bool push(T *data) { |
|||
if (isFull()) { |
|||
return false; |
|||
} |
|||
memcpy(&arr[rear], data, sizeof(T)); |
|||
rear = (rear + 1) % maxSize; |
|||
return true; |
|||
} |
|||
bool pop(T *data) { |
|||
if (isEmpty()) { |
|||
return false; |
|||
} |
|||
memcpy(data, &arr[front], sizeof(T)); |
|||
front = (front + 1) % maxSize; |
|||
return true; |
|||
} |
|||
bool getHeader(T *data) { |
|||
if (isEmpty()) { |
|||
return false; |
|||
} |
|||
memcpy(data, &arr[front], sizeof(T)); |
|||
return true; |
|||
} |
|||
int size() { return num; } |
|||
int numElements() { return (rear + maxSize - front) % maxSize; } |
|||
bool isEmpty() { return rear == front; } |
|||
bool isFull() { return (rear + 1) % maxSize == front; } |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -0,0 +1,49 @@ |
|||
#include "device_base_control_service.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
using namespace std; |
|||
using namespace iflytop; |
|||
void DeviceBaseControlService::initialize(IflytopCanProtocolStackProcesser* protocol_processer, uint8_t deviceId) { |
|||
m_protocol_processer = protocol_processer; |
|||
m_deviceId = deviceId; |
|||
ZASSERT(m_protocol_processer != NULL); |
|||
activeRegs(); |
|||
} |
|||
void DeviceBaseControlService::activeRegs() { |
|||
m_protocol_processer->activeReg(REG_DEVICE_ID, icps::kr, m_deviceId); |
|||
m_protocol_processer->activeReg(REG_DEVICE_REBOOT, icps::kwr, 1); |
|||
m_protocol_processer->activeReg(REG_DEVICE_ENGINEER_MODE_MODE, icps::kwr, 0); |
|||
} |
|||
|
|||
bool DeviceBaseControlService::isThisRegOwnToMe(icps::Reg_t* reg) { |
|||
switch (reg->add) { |
|||
case REG_DEVICE_ID: |
|||
case REG_DEVICE_REBOOT: |
|||
case REG_DEVICE_ENGINEER_MODE_MODE: |
|||
return true; |
|||
default: |
|||
break; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
icps::error_t DeviceBaseControlService::processIflytopCanRegisterWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent) { |
|||
switch (writeEvent->reg->add) { |
|||
case REG_DEVICE_ID: |
|||
return icps::kRegNotWritable; |
|||
case REG_DEVICE_REBOOT: |
|||
NVIC_SystemReset(); |
|||
return icps::kSuccess; |
|||
case REG_DEVICE_ENGINEER_MODE_MODE: |
|||
if (m_listener != NULL) { |
|||
m_listener(writeEvent->newvalue); |
|||
return icps::kSuccess; |
|||
} |
|||
return icps::kSuccess; |
|||
default: |
|||
break; |
|||
} |
|||
return icps::kRegNotFound; |
|||
} |
|||
|
|||
bool DeviceBaseControlService::isInEngineerMode() { return m_protocol_processer->readRegValue(REG_DEVICE_ENGINEER_MODE_MODE) != 0; } |
|||
#endif
|
@ -0,0 +1,42 @@ |
|||
#pragma once
|
|||
#include "sdk/hal/zhal.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
#include <stdlib.h>
|
|||
|
|||
#include "sdk\components\iflytop_can_slave_v1\iflytop_can_slave.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
#define REG_DEVICE_ID (0) // 设备ID
|
|||
#define REG_DEVICE_REBOOT (1) // 重启标识
|
|||
#define REG_DEVICE_ENGINEER_MODE_MODE (2) // 工程师模式标识
|
|||
class DeviceBaseControlService; |
|||
// class DeviceBaseControlServiceListener {
|
|||
// public:
|
|||
// virtual icps::error_t onSetEngineerMode(DeviceBaseControlService* service, int32_t engineer_mode) = 0;
|
|||
// };
|
|||
class DeviceBaseControlService { |
|||
public: |
|||
typedef function<void(int32_t engineer_mode)> SetEngineerModeCallback_t; |
|||
|
|||
private: |
|||
IflytopCanProtocolStackProcesser* m_protocol_processer; |
|||
SetEngineerModeCallback_t m_listener; |
|||
uint8_t m_deviceId; |
|||
|
|||
public: |
|||
DeviceBaseControlService() {} |
|||
virtual ~DeviceBaseControlService() {} |
|||
|
|||
void initialize(IflytopCanProtocolStackProcesser* protocol_processer, uint8_t deviceId); |
|||
void setListener(SetEngineerModeCallback_t listener) { m_listener = listener; } |
|||
|
|||
bool isThisRegOwnToMe(icps::Reg_t* reg); |
|||
icps::error_t processIflytopCanRegisterWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent); |
|||
|
|||
private: |
|||
void activeRegs(); |
|||
bool isInEngineerMode(); |
|||
}; |
|||
} // namespace iflytop
|
|||
#endif
|
@ -0,0 +1,195 @@ |
|||
#include "idcard_reader_service.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
|
|||
#include "idcard_reader_service.hpp"
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "IDCardReaderService"
|
|||
|
|||
static int32_t getPacketNumByBytesNum(int num) { return num / 4 + (num % 4 == 0 ? 0 : 1); } |
|||
static int32_t littleEndianBigEnd(int32_t data) { |
|||
int32_t ret = 0; |
|||
ret |= (data & 0xff) << 24; |
|||
ret |= (data & 0xff00) << 8; |
|||
ret |= (data & 0xff0000) >> 8; |
|||
ret |= (data & 0xff000000) >> 24; |
|||
return ret; |
|||
} |
|||
|
|||
void IDCardReaderService::initialize(const char* name, IflytopCanProtocolStackProcesser* protocolProcesser, int32_t regStartOff, |
|||
M3078CodeScanner* codeScanner) { |
|||
/*******************************************************************************
|
|||
* 通用成员变量初始化 * |
|||
*******************************************************************************/ |
|||
m_name = name; |
|||
m_protocolProcesser = protocolProcesser; |
|||
m_exceptionId = 0; |
|||
m_regStartOff = regStartOff; |
|||
m_stateMachine.initialize(m_name, 10, &IDCardReaderService::onProcessState, this); |
|||
|
|||
/*******************************************************************************
|
|||
* 专用成员变量初始化 * |
|||
*******************************************************************************/ |
|||
m_codeScanner = codeScanner; |
|||
|
|||
m_protocolProcesser->activeReg(m_regStartOff + REG_CODE_SCANER_ACT_CTRL, icps::kwr, 0); |
|||
m_protocolProcesser->activeReg(m_regStartOff + REG_CODE_SCANER_ACT_CLEAR_EXCEPTION, icps::kwr, 0); |
|||
m_protocolProcesser->activeReg(m_regStartOff + REG_CODE_SCANER_STAT_STATUS, icps::kr, 0); |
|||
m_protocolProcesser->activeReg(m_regStartOff + REG_CODE_SCANER_STAT_EXCEPTION, icps::kr, 0); |
|||
m_codeReg = m_protocolProcesser->activeReg(m_regStartOff + REG_CODE_SCANER_CODE, icps::kr | icps::kextreg, 0); |
|||
} |
|||
|
|||
icps::error_t IDCardReaderService::processWriteEvent(icps::WriteEvent* event) { |
|||
int regoff = event->reg->add - m_regStartOff; |
|||
int val = event->newvalue; |
|||
switch (regoff) { |
|||
case REG_CODE_SCANER_ACT_CTRL: |
|||
if (val == 0) { // 停止扫码
|
|||
m_stateMachine.triggerEvent(kEvent_stopEvent, 0); |
|||
ZLOGI(TAG, "stop scan"); |
|||
} else if (val == 1) { // 单次扫码
|
|||
m_stateMachine.triggerEvent(kEvent_oneShutScanEvent, 0); |
|||
ZLOGI(TAG, "start one shut scan"); |
|||
} else if (val == 2) { // 连续扫码
|
|||
m_stateMachine.triggerEvent(kEvent_continueScanEvent, 0); |
|||
ZLOGI(TAG, "start continue scan"); |
|||
return icps::kIllegalValue; |
|||
} else { |
|||
return icps::kIllegalValue; |
|||
} |
|||
return icps::kSuccess; |
|||
case REG_CODE_SCANER_ACT_CLEAR_EXCEPTION: |
|||
m_stateMachine.triggerEvent(kEvent_clearExceptionEvent, 0); |
|||
return icps::kSuccess; |
|||
} |
|||
return icps::kRegNotWritable; |
|||
} |
|||
icps::error_t IDCardReaderService::processReportEvent(icps::ReportEvent* event) { |
|||
int regoff = event->reg->add - m_regStartOff; |
|||
int32_t* val = &event->value; |
|||
|
|||
/**
|
|||
* @brief 上报扩展控制点的信息 |
|||
*/ |
|||
if (regoff == REG_CODE_SCANER_CODE) { |
|||
if (event->extRegSubOff == 0) { // 第一包上报当前包长度
|
|||
*val = m_codeScanner->getIdinfoLen(); |
|||
} else { // 上报数据
|
|||
int32_t* data = (int32_t*)m_codeScanner->getIdinfo(); |
|||
*val = data[event->extRegSubOff - 1]; |
|||
} |
|||
} |
|||
return icps::kSuccess; |
|||
} |
|||
|
|||
void IDCardReaderService::onProcessState(StateMachine::StateProcessContext* context, StateMachine::Event* event) { |
|||
int nowState = m_stateMachine.getNowState(); |
|||
switch (nowState) { |
|||
case kidle: |
|||
return processIdleState(context, event); |
|||
case kcodeScanning: |
|||
return processCodeScanning(context, event); |
|||
case kCodeReporting: |
|||
return processCodeReporting(context, event); |
|||
case kexception: |
|||
return processExceptionState(context, event); |
|||
} |
|||
return; |
|||
} |
|||
|
|||
void IDCardReaderService::processExceptionState(StateMachine::StateProcessContext* context, StateMachine::Event* event) { |
|||
if (event->eventIndex == StateMachine::kEnterState) { // 进入异常状态
|
|||
writeRegVal(REG_CODE_SCANER_STAT_EXCEPTION, m_exceptionId); |
|||
} else if (event->eventIndex == StateMachine::kExitState) { // 退出异常状态
|
|||
m_exceptionId = 0; |
|||
writeRegVal(REG_CODE_SCANER_STAT_EXCEPTION, m_exceptionId); |
|||
} else if (event->eventIndex == kEvent_clearExceptionEvent) { // 单次扫码
|
|||
m_exceptionId = 0; |
|||
// context->changeToStateIndex = kidle;
|
|||
context->changeToState(kidle, 0); |
|||
} |
|||
} |
|||
/*******************************************************************************
|
|||
* 空闲状态 * |
|||
*******************************************************************************/ |
|||
void IDCardReaderService::processIdleState(StateMachine::StateProcessContext* context, StateMachine::Event* event) { |
|||
if (event->eventIndex == kEvent_oneShutScanEvent) { // 单次扫码
|
|||
// context->changeToStateIndex = kcodeScanning;
|
|||
context->changeToState(kcodeScanning, 0); |
|||
m_oneShutScan = true; |
|||
} else if (event->eventIndex == kEvent_continueScanEvent) { |
|||
// context->changeToStateIndex = kcodeScanning;
|
|||
context->changeToState(kcodeScanning, 0); |
|||
m_oneShutScan = false; |
|||
} |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* 扫码中 * |
|||
*******************************************************************************/ |
|||
void IDCardReaderService::processCodeScanning(StateMachine::StateProcessContext* context, StateMachine::Event* event) { |
|||
if (event->eventIndex == StateMachine::kEnterState) { // 开始一次扫码
|
|||
m_codeScanner->trigger(); |
|||
} else if (event->eventIndex == StateMachine::kExitState) { // 电平拉低
|
|||
m_codeScanner->stopTrigger(); |
|||
} else if (event->eventIndex == StateMachine::kPeriodicCallEvent) { // 周期调用
|
|||
if (m_codeScanner->idInfoIsReady() && // 等待扫码完成
|
|||
!m_codeReg->is(icps::kreadyReport) // 等待上一次上报完成
|
|||
) { |
|||
m_protocolProcesser->writeRegValue(m_codeReg, m_codeScanner->getIdinfoLen(), false); |
|||
m_protocolProcesser->setRegReadyToReport(m_codeReg); |
|||
// context->changeToStateIndex = kCodeReporting;
|
|||
context->changeToState(kCodeReporting, 0); |
|||
} |
|||
} else if (event->eventIndex == kEvent_stopEvent) { // 停止扫码
|
|||
// context->changeToStateIndex = kidle;
|
|||
context->changeToState(kidle, 0); |
|||
} else if (event->eventIndex == kEvent_oneShutScanEvent) { // 单次扫码
|
|||
m_oneShutScan = true; |
|||
} else if (event->eventIndex == kEvent_continueScanEvent) { |
|||
m_oneShutScan = false; |
|||
} |
|||
} |
|||
/*******************************************************************************
|
|||
* 扫码上报中 * |
|||
*******************************************************************************/ |
|||
void IDCardReaderService::processCodeReporting(StateMachine::StateProcessContext* context, StateMachine::Event* event) { |
|||
if (event->eventIndex == StateMachine::kEnterState) { |
|||
} else if (event->eventIndex == StateMachine::kExitState) { |
|||
} else if (event->eventIndex == StateMachine::kPeriodicCallEvent) { |
|||
if (!m_codeReg->is(icps::kreadyReport)) { |
|||
// 上报完成
|
|||
if (m_oneShutScan) { |
|||
// context->changeToStateIndex = kidle;
|
|||
context->changeToState(kidle, 0); |
|||
} else { |
|||
// context->changeToStateIndex = kcodeScanning;
|
|||
context->changeToState(kcodeScanning, 0); |
|||
} |
|||
} |
|||
} else if (event->eventIndex == kEvent_stopEvent) { // 停止扫码
|
|||
// context->changeToStateIndex = kidle;
|
|||
context->changeToState(kidle, 0); |
|||
} else if (event->eventIndex == kEvent_oneShutScanEvent) { // 单次扫码
|
|||
m_oneShutScan = true; |
|||
} else if (event->eventIndex == kEvent_continueScanEvent) { |
|||
m_oneShutScan = false; |
|||
} |
|||
} |
|||
void IDCardReaderService::onProcessState(void* module, StateMachine::StateProcessContext* context, StateMachine::Event* event) { //
|
|||
((IDCardReaderService*)module)->onProcessState(context, event); |
|||
} |
|||
/*******************************************************************************
|
|||
* 通用方法 * |
|||
*******************************************************************************/ |
|||
void IDCardReaderService::writeRegVal(uint16_t regoff, uint16_t regval) { m_protocolProcesser->writeRegValue(uint16_t(m_regStartOff + regoff), regval, false); } |
|||
bool IDCardReaderService::isThisRegOwnToMe(icps::Reg_t* reg) { |
|||
int regoff = reg->add; |
|||
if (regoff >= m_regStartOff && regoff < m_regStartOff + REG_CODE_SCANER_SIZE) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void IDCardReaderService::periodicJob() { m_stateMachine.periodicCall(); } |
|||
#endif
|
@ -0,0 +1,89 @@ |
|||
|
|||
#pragma once
|
|||
// #include "libiflytop_micro\stm32\basic\stm32_header.h"
|
|||
#include "sdk\components\iflytop_can_slave_v1\iflytop_can_slave.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
#include <stdlib.h>
|
|||
|
|||
#include "pri/state_machine.hpp"
|
|||
#include "sdk/components/datastructure/datastructure.hpp"
|
|||
#include "sdk/components/m3078/m3078_code_scaner.hpp"
|
|||
|
|||
#define REG_CODE_SCANER_ACT_CTRL (0) // 扫码器控制 写0停止扫码,写1开始扫码
|
|||
#define REG_CODE_SCANER_ACT_CLEAR_EXCEPTION (1) // 清除异常
|
|||
#define REG_CODE_SCANER_STAT_STATUS (5) // 设备状态
|
|||
#define REG_CODE_SCANER_STAT_EXCEPTION (6) // 异常状态
|
|||
#define REG_CODE_SCANER_CODE (7) // 码存放的地方
|
|||
|
|||
#define REG_CODE_SCANER_SIZE (20) //
|
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
using namespace iflytop_can_slave_modules_pri; |
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* 协议参考: |
|||
* https://iflytop1.feishu.cn/wiki/OYZFwSNf2i0Hyek1zouc8eSsnsg
|
|||
* |
|||
*/ |
|||
class IDCardReaderService { |
|||
public: |
|||
typedef enum { |
|||
kidle = 0, |
|||
kcodeScanning = 1, |
|||
kCodeReporting = 2, |
|||
kexception = 65535, |
|||
} state_t; |
|||
|
|||
typedef enum { |
|||
kEvent_stopEvent = 1, |
|||
kEvent_oneShutScanEvent, |
|||
kEvent_continueScanEvent, |
|||
kEvent_clearExceptionEvent, |
|||
} event_t; |
|||
|
|||
private: |
|||
/*******************************************************************************
|
|||
* 通用成员变量 * |
|||
*******************************************************************************/ |
|||
const char* m_name; |
|||
IflytopCanProtocolStackProcesser* m_protocolProcesser; |
|||
StateMachine m_stateMachine; |
|||
int32_t m_exceptionId; |
|||
int32_t m_regStartOff; |
|||
|
|||
/*******************************************************************************
|
|||
* 专用成员变量 * |
|||
*******************************************************************************/ |
|||
M3078CodeScanner* m_codeScanner; |
|||
icps::Reg_t* m_codeReg; |
|||
|
|||
bool m_oneShutScan; |
|||
|
|||
public: |
|||
void initialize(const char* name, IflytopCanProtocolStackProcesser* protocolProcesser, int32_t regStartOff, |
|||
M3078CodeScanner* codeScanner); |
|||
|
|||
bool isThisRegOwnToMe(icps::Reg_t* reg); |
|||
|
|||
icps::error_t processWriteEvent(icps::WriteEvent* event); |
|||
icps::error_t processReportEvent(icps::ReportEvent* event); |
|||
|
|||
void periodicJob(); |
|||
|
|||
public: |
|||
private: |
|||
static void onProcessState(void* module, StateMachine::StateProcessContext* context, StateMachine::Event* event); |
|||
|
|||
void onProcessState(StateMachine::StateProcessContext* context, StateMachine::Event* event); |
|||
void processIdleState(StateMachine::StateProcessContext* context, StateMachine::Event* event); |
|||
void processCodeScanning(StateMachine::StateProcessContext* context, StateMachine::Event* event); |
|||
void processCodeReporting(StateMachine::StateProcessContext* context, StateMachine::Event* event); |
|||
void processExceptionState(StateMachine::StateProcessContext* context, StateMachine::Event* event); |
|||
|
|||
void writeRegVal(uint16_t regoff, uint16_t regval); |
|||
}; |
|||
} // namespace iflytop
|
|||
#endif
|
@ -0,0 +1,110 @@ |
|||
#include "state_machine.hpp"
|
|||
using namespace iflytop; |
|||
using namespace std; |
|||
using namespace iflytop_can_slave_modules_pri; |
|||
|
|||
StateMachine::StateMachine() { |
|||
m_name = NULL; |
|||
// m_eventCache
|
|||
|
|||
m_onProcessState = NULL; |
|||
m_father_module = NULL; |
|||
|
|||
m_nowStateIndex = 0; |
|||
m_nowStateTicket = 0; |
|||
|
|||
m_lastCallTicket = 0; |
|||
m_stateMachineTicket = 0; |
|||
|
|||
isChangeState = false; |
|||
m_changeToStateIndex = 0; |
|||
} |
|||
StateMachine::~StateMachine() {} |
|||
void StateMachine::initialize(const char* name, int32_t periodicCallPeriod, onProcessState_t onProcessState, void* module) { |
|||
m_name = name; |
|||
m_periodicCallPeriod = periodicCallPeriod; |
|||
m_onProcessState = onProcessState; |
|||
m_father_module = module; |
|||
} |
|||
void StateMachine::triggerEvent(int evenIndex, int32_t eventVal) { |
|||
Event event; |
|||
event.eventIndex = evenIndex; |
|||
event.eventVal = eventVal; |
|||
bool push = m_eventCache.push(&event); |
|||
if (!push) { |
|||
ZLOGE(m_name, "StateMachine::triggerEvent failed, event cache is full"); |
|||
} |
|||
} |
|||
void StateMachine::regOnProcessState(void* module, onProcessState_t onProcessState) { |
|||
m_father_module = module; |
|||
m_onProcessState = onProcessState; |
|||
} |
|||
int32_t StateMachine::getNowState() { return m_nowStateIndex; } |
|||
|
|||
void StateMachine::periodicCall() { |
|||
/**
|
|||
* @brief 从队列中取出事件处理事件 |
|||
*/ |
|||
if (isChangeState) { |
|||
isChangeState = false; |
|||
int changeToStateIndex = m_changeToStateIndex; |
|||
m_changeToStateIndex = 0; |
|||
changeState(changeToStateIndex, m_changeToStateVal); |
|||
} else if (!m_eventCache.isEmpty()) { |
|||
Event event; |
|||
m_eventCache.pop(&event); |
|||
callProcessState(&event); |
|||
} else { |
|||
// if (m_lastCallTicket != m_os->getTicket()) {
|
|||
if (haspassedms(m_lastCallTicket) >= (uint32_t)m_periodicCallPeriod) { |
|||
m_lastCallTicket = chip_get_ticket(); |
|||
m_stateMachineTicket++; |
|||
m_nowStateTicket++; |
|||
|
|||
Event event; |
|||
event.eventIndex = kPeriodicCallEvent; |
|||
event.eventVal = m_nowStateTicket; |
|||
callProcessState(&event); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void StateMachine::changeState(int32_t stateIndex, int32_t enterStateVal) { |
|||
{ |
|||
StateMachine::StateProcessContext context; |
|||
Event event(kExitState, 0); |
|||
if (m_onProcessState) { |
|||
m_onProcessState(m_father_module, &context, &event); |
|||
} |
|||
} |
|||
|
|||
ZLOGI(m_name, "change state from %d to %d", m_nowStateIndex, stateIndex); |
|||
m_nowStateIndex = stateIndex; |
|||
m_stateMachineTicket = 0; |
|||
|
|||
{ |
|||
StateMachine::StateProcessContext context; |
|||
Event event(kEnterState, enterStateVal); |
|||
if (m_onProcessState) { |
|||
m_onProcessState(m_father_module, &context, &event); |
|||
} |
|||
if (context.getChangeToStateIndex() != -1) { |
|||
isChangeState = true; |
|||
m_changeToStateIndex = context.getChangeToStateIndex(); |
|||
m_changeToStateVal = context.getEnterStateVal(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void StateMachine::callProcessState(Event* event) { //
|
|||
StateMachine::StateProcessContext context; |
|||
if (m_onProcessState) { |
|||
m_onProcessState(m_father_module, &context, event); |
|||
} |
|||
|
|||
if (context.getChangeToStateIndex() != -1) { |
|||
isChangeState = true; |
|||
m_changeToStateIndex = context.getChangeToStateIndex(); |
|||
m_changeToStateVal = context.getEnterStateVal(); |
|||
} |
|||
} |
@ -0,0 +1,79 @@ |
|||
#pragma once
|
|||
#include <stdint.h>
|
|||
#include <stdlib.h>
|
|||
|
|||
#include "sdk/components/datastructure/datastructure.hpp"
|
|||
#include "sdk/hal/zhal.hpp"
|
|||
|
|||
namespace iflytop_can_slave_modules_pri { |
|||
using namespace std; |
|||
|
|||
class StateMachine { |
|||
public: |
|||
typedef enum { |
|||
kEnterState = 10001, |
|||
kExitState = 10002, |
|||
kPeriodicCallEvent = 10003, |
|||
} EventIndex_t; |
|||
|
|||
class Event { |
|||
public: |
|||
int32_t eventIndex; |
|||
int32_t eventVal; |
|||
Event() : eventIndex(0), eventVal(0) {} |
|||
Event(int32_t index, int32_t val) : eventIndex(index), eventVal(val) {} |
|||
}; |
|||
|
|||
class StateProcessContext { |
|||
int32_t changeToStateIndex; |
|||
int32_t enterStateVal; |
|||
|
|||
public: |
|||
void changeToState(int32_t stateIndex, int32_t enterStateVal) { changeToStateIndex = stateIndex; } |
|||
|
|||
int32_t getChangeToStateIndex() { return changeToStateIndex; } |
|||
int32_t getEnterStateVal() { return enterStateVal; } |
|||
|
|||
void setEnterStateVal(int32_t val) { enterStateVal = val; } |
|||
|
|||
StateProcessContext() : changeToStateIndex(-1) {} |
|||
}; |
|||
|
|||
typedef void (*onProcessState_t)(void* module, StateMachine::StateProcessContext* context, Event* event); |
|||
|
|||
private: |
|||
const char* m_name; |
|||
iflytop::StaticLoopQueue<Event, 5> m_eventCache; |
|||
|
|||
onProcessState_t m_onProcessState; |
|||
void* m_father_module; |
|||
|
|||
int m_nowStateIndex; |
|||
int m_nowStateTicket; |
|||
|
|||
int32_t m_lastCallTicket; |
|||
int32_t m_stateMachineTicket; |
|||
|
|||
bool isChangeState; |
|||
int32_t m_changeToStateIndex; |
|||
int32_t m_changeToStateVal; |
|||
|
|||
int32_t m_periodicCallPeriod; |
|||
|
|||
public: |
|||
StateMachine(); |
|||
~StateMachine(); |
|||
|
|||
void initialize(const char* name, int32_t periodicCallPeriod, onProcessState_t onProcessState, void* module); |
|||
|
|||
void triggerEvent(int evenIndex, int32_t eventVal); |
|||
void regOnProcessState(void* module, onProcessState_t onProcessState); |
|||
void periodicCall(); |
|||
|
|||
int32_t getNowState(); |
|||
|
|||
private: |
|||
void callProcessState(Event* event); |
|||
void changeState(int32_t stateIndex, int32_t enterStateVal); |
|||
}; |
|||
} // namespace iflytop
|
@ -0,0 +1,373 @@ |
|||
#include "i_iflytop_can_slave_module.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
|
|||
using namespace iflytop; |
|||
#define STATE_NULL -1
|
|||
|
|||
static bool s_dumpConfig; |
|||
|
|||
/*******************************************************************************
|
|||
* ConfigPara * |
|||
*******************************************************************************/ |
|||
void icsm::ConfigPara::initialize(IIflytopCanSlaveModule* module, uint32_t regoff, uint16_t mask, int32_t defaultValue) { |
|||
//
|
|||
m_module = module; |
|||
m_regAddOff = regoff; |
|||
m_val = defaultValue; |
|||
m_name = "unset"; |
|||
|
|||
int32_t regstart = module->getRegStartAdd(); |
|||
IflytopCanProtocolStackProcesser* processer = module->getProtocolProcesser(); |
|||
processer->activeReg(regstart + regoff, mask, defaultValue); |
|||
} |
|||
|
|||
icps::error_t icsm::ConfigPara::processIflytopCanRegisterWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent) { |
|||
int32_t val = writeEvent->newvalue; |
|||
if (!m_module->getEngineerMode() && m_enableLimit) { |
|||
if (val > m_limitMax) { |
|||
val = m_limitMax; |
|||
} else if (val < m_limitMin) { |
|||
val = m_limitMin; |
|||
} |
|||
} |
|||
m_val = val; |
|||
writeEvent->newvalue = m_val; |
|||
return icps::kSuccess; |
|||
} |
|||
|
|||
icps::error_t icsm::ConfigPara::setValWitchLimit(int32_t initVal, int32_t min, int32_t max) { |
|||
m_limitMin = min; |
|||
m_limitMax = max; |
|||
m_enableLimit = true; |
|||
return setVal(initVal); |
|||
} |
|||
|
|||
icps::error_t icsm::ConfigPara::setVal(int32_t val) { |
|||
val = val; |
|||
if (s_dumpConfig) { |
|||
ZLOGI(m_module->m_name, "set %s = %d", m_name, val); |
|||
} |
|||
if (!m_module->getEngineerMode() && m_enableLimit) { |
|||
if (val > m_limitMax) { |
|||
val = m_limitMax; |
|||
} else if (val < m_limitMin) { |
|||
val = m_limitMin; |
|||
} |
|||
} |
|||
m_val = val; |
|||
m_module->writeRegValueByRegOff(m_regAddOff, val); |
|||
return icps::kSuccess; |
|||
} |
|||
int32_t icsm::ConfigPara::getVal() { return m_val; } |
|||
|
|||
icps::error_t icsm::ConfigPara::setEnableLimit(bool enable) { |
|||
m_enableLimit = enable; |
|||
return icps::kSuccess; |
|||
} |
|||
bool icsm::ConfigPara::getEnableLimit() { return m_enableLimit; } |
|||
|
|||
icps::error_t icsm::ConfigPara::setLimitMin(int32_t val) { |
|||
m_limitMin = val; |
|||
return icps::kSuccess; |
|||
} |
|||
int32_t icsm::ConfigPara::getLimitMin() { return m_limitMin; } |
|||
icps::error_t icsm::ConfigPara::setLimitMax(int32_t val) { |
|||
m_limitMax = val; |
|||
return icps::kSuccess; |
|||
} |
|||
int32_t icsm::ConfigPara::getLimitMax() { return m_limitMax; } |
|||
int32_t icsm::ConfigPara::getRegAddOff() { return m_regAddOff; } |
|||
|
|||
icps::error_t icsm::ConfigPara::enableLimit(bool enable, int32_t min, int32_t max) { |
|||
m_enableLimit = enable; |
|||
m_limitMin = min; |
|||
m_limitMax = max; |
|||
return icps::kSuccess; |
|||
} |
|||
|
|||
void icsm::ConfigPara::setName(const char* name) { m_name = name; } |
|||
|
|||
/*******************************************************************************
|
|||
* ACTION * |
|||
*******************************************************************************/ |
|||
|
|||
void icsm::Action::initialize(IIflytopCanSlaveModule* module, uint32_t regoff) { |
|||
//
|
|||
m_module = module; |
|||
m_regAddOff = regoff; |
|||
m_name = "unkownaction"; |
|||
|
|||
int32_t regstart = module->getRegStartAdd(); |
|||
IflytopCanProtocolStackProcesser* processer = module->getProtocolProcesser(); |
|||
processer->activeReg(regstart + regoff, icps::kw, 0); |
|||
} |
|||
void icsm::Action::setName(const char* name) { m_name = name; } |
|||
const char* icsm::Action::getName() { return m_name; } |
|||
icps::error_t icsm::Action::setVal(int32_t val) { |
|||
m_val = val; |
|||
return icps::kSuccess; |
|||
} |
|||
int32_t icsm::Action::getVal() { return m_val; } |
|||
int32_t icsm::Action::getRegAddOff() { return m_regAddOff; } |
|||
|
|||
/*******************************************************************************
|
|||
* IIflytopCanSlaveModule * |
|||
*******************************************************************************/ |
|||
void IIflytopCanSlaveModule::stateMachine_periodicJob(int ticket) { |
|||
if (m_lastcallticket != chip_get_ticket()) { |
|||
m_lastcallticket = chip_get_ticket(); |
|||
m_module_ticket++; |
|||
m_stateticket++; |
|||
//
|
|||
stateMachine_onPeriodic(m_module_ticket); |
|||
stateMachine_triggerEvent(icsm::Event(icsm::kPublicEvent, icsm::kevent_periodicJob)); |
|||
} |
|||
stateMachine_onAsFarAsPossibleCall(); |
|||
if (!m_eventCacheIsEmpty) { |
|||
stateMachine_triggerEvent(m_eventCache); |
|||
m_eventCacheIsEmpty = true; |
|||
} |
|||
} |
|||
void IIflytopCanSlaveModule::setListener(IIflytopCanSlaveModuleListener* listener) { m_listener = listener; } |
|||
|
|||
void IIflytopCanSlaveModule::initialize(const char* name, IflytopCanProtocolStackProcesser* processer, int32_t regoff, int32_t regNum) { |
|||
m_name = name; |
|||
|
|||
m_regStart = regoff; |
|||
m_regNum = regNum; |
|||
|
|||
m_statusRegOff = -1; |
|||
m_ExceptionRegOff = -1; |
|||
|
|||
m_configParas = NULL; |
|||
m_configParaNum = 0; |
|||
|
|||
m_action = NULL; |
|||
m_actionNum = 0; |
|||
|
|||
engineer_mode = false; |
|||
|
|||
m_eventCacheIsEmpty = true; |
|||
// m_eventCache;
|
|||
|
|||
m_protocolProcesser = processer; |
|||
|
|||
m_lastState = 0; |
|||
m_state = 0; |
|||
m_exceptionId = 0; |
|||
|
|||
m_lastcallticket = 0; |
|||
m_periodms = 10; |
|||
m_module_ticket = 0; |
|||
|
|||
m_stateticket = 0; |
|||
|
|||
m_listener = NULL; |
|||
} |
|||
|
|||
void IIflytopCanSlaveModule::regConfigParas(icsm::ConfigPara* configParas, int configParaNum) { |
|||
m_configParas = configParas; |
|||
m_configParaNum = configParaNum; |
|||
} |
|||
void IIflytopCanSlaveModule::regActions(icsm::Action* action, int actionNum) { |
|||
m_action = action; |
|||
m_actionNum = actionNum; |
|||
} |
|||
void IIflytopCanSlaveModule::setStatusRegOff(int32_t regoff) { |
|||
m_statusRegOff = regoff; |
|||
IIflytopCanSlaveModule::activeReg(regoff, icps::kr, 0); |
|||
} |
|||
void IIflytopCanSlaveModule::setExceptionRegOff(int32_t regoff) { |
|||
m_ExceptionRegOff = regoff; |
|||
IIflytopCanSlaveModule::activeReg(m_ExceptionRegOff, icps::kr, 0); |
|||
} |
|||
|
|||
void IIflytopCanSlaveModule::setIdelStateIndex(int32_t stateIndex) { m_idle_state_index = stateIndex; } |
|||
void IIflytopCanSlaveModule::setExceptionStateIndex(int32_t stateIndex) { m_exception_state_index = stateIndex; } |
|||
|
|||
void IIflytopCanSlaveModule::periodicJob() { stateMachine_periodicJob(chip_get_ticket()); } |
|||
|
|||
void IIflytopCanSlaveModule::setEngineerMode(bool engineer_mode) { this->engineer_mode = engineer_mode; } |
|||
bool IIflytopCanSlaveModule::getEngineerMode() { return engineer_mode; } |
|||
void IIflytopCanSlaveModule::writeRegValueByRegOff(uint16_t regaddoff, int32_t value, bool forceupdate) { |
|||
m_protocolProcesser->writeRegValue(m_regStart + regaddoff, value, forceupdate); |
|||
} |
|||
uint32_t IIflytopCanSlaveModule::getRegOff(IflytopCanProtocolStackWriteEvent* writeEvent) { return writeEvent->reg->add - m_regStart; } |
|||
bool IIflytopCanSlaveModule::isMyWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent) { |
|||
if (writeEvent->reg->add >= getRegStartAdd() && //
|
|||
writeEvent->reg->add <= getRegEndAdd()) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
void IIflytopCanSlaveModule::stateMachine_pushEvent(icsm::Event event) { |
|||
m_eventCacheIsEmpty = false; |
|||
m_eventCache = event; |
|||
} |
|||
|
|||
int32_t IIflytopCanSlaveModule::stateMachine_getStateIndex() { return m_state; } |
|||
int32_t IIflytopCanSlaveModule::stateMachine_getStateDuration() { return m_stateticket; } |
|||
int32_t IIflytopCanSlaveModule::getExceptionId() { return m_exceptionId; } |
|||
bool IIflytopCanSlaveModule::stateMachine_isIdle() { return m_state == m_idle_state_index; } |
|||
|
|||
void IIflytopCanSlaveModule::disablePermission(int32_t actionRegoff, uint32_t permission) { |
|||
m_protocolProcesser->disablePermission(m_regStart + actionRegoff, permission); |
|||
} |
|||
|
|||
icsm::ConfigPara* IIflytopCanSlaveModule::getConfig(int regoff) { |
|||
for (size_t i = 0; i < m_configParaNum; i++) { |
|||
if (m_configParas[i].getRegAddOff() == regoff) { |
|||
return &m_configParas[i]; |
|||
} |
|||
} |
|||
ZLOGE(m_name, "Can't find config by reg,reg == %d", regoff); |
|||
return &m_zeroCfg; |
|||
} |
|||
icsm::Action* IIflytopCanSlaveModule::getAction(int regoff) { |
|||
for (size_t i = 0; i < m_actionNum; i++) { |
|||
if (m_action[i].getRegAddOff() == regoff) { |
|||
return &m_action[i]; |
|||
} |
|||
} |
|||
ZLOGE(m_name, "Can't find action by reg,reg == %d", regoff); |
|||
|
|||
return &m_zeroaction; |
|||
} |
|||
void IIflytopCanSlaveModule::initializeCfg(icsm::ConfigPara* cfg, icsm::ConfigPara** shadowcfg, IIflytopCanSlaveModule* module, uint32_t regoff, uint16_t mask, |
|||
int32_t defaultValue) { |
|||
cfg->initialize(module, regoff, mask, defaultValue); |
|||
*shadowcfg = cfg; |
|||
} |
|||
void IIflytopCanSlaveModule::initializeCfg(const char* name, icsm::ConfigPara* cfg, icsm::ConfigPara** shadowcfg, IIflytopCanSlaveModule* module, |
|||
uint32_t regoff, uint16_t mask, int32_t defaultValue) { |
|||
initializeCfg(cfg, shadowcfg, module, regoff, mask, defaultValue); |
|||
cfg->setName(name); |
|||
} |
|||
icsm::Action* IIflytopCanSlaveModule::initializeAction(icsm::Action* action, IIflytopCanSlaveModule* module, const char* actionName, uint32_t regoff) { |
|||
action->initialize(module, regoff); |
|||
action->setName(actionName); |
|||
return action; |
|||
} |
|||
|
|||
void IIflytopCanSlaveModule::activeReg(uint16_t mappingAdd, uint16_t mask, int32_t defaultValue) { |
|||
if (m_protocolProcesser) { |
|||
m_protocolProcesser->activeReg(mappingAdd + m_regStart, mask, defaultValue); |
|||
} |
|||
} |
|||
|
|||
icps::error_t IIflytopCanSlaveModule::processIflytopCanRegisterWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent) { |
|||
/**
|
|||
* @brief |
|||
* 1.遍历所有配置参数,如果是配置地址,则进行配置 |
|||
* 2.遍历所有动作参数,如果是动作地址,则检查动作参数后,则执行相应的动作。 |
|||
* 3.如果是状态参数,则返回非法操作。 |
|||
*/ |
|||
icps::error_t err; |
|||
int regoff = writeEvent->reg->add - m_regStart; |
|||
for (size_t i = 0; i < m_configParaNum; i++) { |
|||
if (m_configParas[i].getRegAddOff() == regoff) { |
|||
err = m_configParas[i].processIflytopCanRegisterWriteEvent(writeEvent); |
|||
ZLOGI(m_name, "update Config %d %d", m_configParas[i].getRegAddOff(), writeEvent->newvalue); |
|||
return err; |
|||
} |
|||
} |
|||
|
|||
for (size_t i = 0; i < m_actionNum; i++) { |
|||
if (m_action[i].getRegAddOff() == regoff) { |
|||
/**
|
|||
* @brief |
|||
* 1. 判断是否可以执行Action |
|||
* 2. 执行Action |
|||
*/ |
|||
err = stateMachine_onTryDoAction(&m_action[i], writeEvent->newvalue); |
|||
if (err != icps::kSuccess) { |
|||
return err; |
|||
} |
|||
m_actionVal = writeEvent->newvalue; |
|||
// m_action[i].getRegAddOff();
|
|||
ZLOGI(m_name, "Action %d %d", m_action[i].getRegAddOff(), writeEvent->newvalue); |
|||
stateMachine_pushEvent(icsm::Event(icsm::kPublicEvent, icsm::kevent_doAction, m_action[i].getRegAddOff(), writeEvent->newvalue)); |
|||
return icps::kSuccess; |
|||
} |
|||
} |
|||
return icps::kRegNotFound; |
|||
} |
|||
|
|||
void IIflytopCanSlaveModule::_stateMachine_onPocessEvent(icsm::StateMachineEventContext* context) { //
|
|||
bool processed = stateMachine_onPocessEvent(context); |
|||
if (!processed) { |
|||
stateMachine_onPocessRemindEvent(context); |
|||
} |
|||
} |
|||
// int32_t IIflytopCanSlaveModule::stateMachine_getIdelStateIndex() { return 0; }
|
|||
// int32_t IIflytopCanSlaveModule::stateMachine_getExceptionStateIndex() { return 1; }
|
|||
void IIflytopCanSlaveModule::_stateMachine_processChangeStateEvent(icsm::StateMachineEventContext* oldcontext, icsm::StateMachineEventContext* newcontext) { |
|||
// 触发退出状态事件
|
|||
icsm::StateMachineEventContext exit_event_context; |
|||
exit_event_context.event.eventType = icsm::kPublicEvent; |
|||
exit_event_context.event.eventIndex = icsm::kevent_exitState; |
|||
exit_event_context.changeToState = STATE_NULL; |
|||
exit_event_context.exceptionId = 0; |
|||
_stateMachine_onPocessEvent(&exit_event_context); |
|||
|
|||
// 更新状态
|
|||
m_lastState = m_state; |
|||
m_state = oldcontext->changeToState; |
|||
|
|||
ZLOGI(m_name, "state change from %s to %s", stateMachine_stateToString(m_lastState), stateMachine_stateToString(m_state)); |
|||
|
|||
if (m_statusRegOff >= 0) { |
|||
writeRegValueByRegOff(m_statusRegOff, m_state, false); |
|||
} |
|||
// 更新异常
|
|||
if (m_state == m_exception_state_index) { |
|||
m_exceptionId = oldcontext->exceptionId; |
|||
} else { |
|||
m_exceptionId = 0; |
|||
} |
|||
if (m_ExceptionRegOff >= 0) { |
|||
writeRegValueByRegOff(m_ExceptionRegOff, m_exceptionId, false); |
|||
} |
|||
|
|||
// 处理切换到新的状态任务
|
|||
newcontext->event.eventType = icsm::kPublicEvent; |
|||
newcontext->event.eventIndex = icsm::kevent_enterstate; |
|||
newcontext->changeToState = STATE_NULL; |
|||
newcontext->exceptionId = 0; |
|||
m_stateticket = 0; |
|||
_stateMachine_onPocessEvent(newcontext); |
|||
} |
|||
|
|||
void IIflytopCanSlaveModule::stateMachine_triggerEvent(icsm::Event event) { //
|
|||
icsm::StateMachineEventContext context; |
|||
icsm::StateMachineEventContext newcontext; |
|||
context.event = event; |
|||
context.changeToState = STATE_NULL; |
|||
context.exceptionId = 0; |
|||
_stateMachine_onPocessEvent(&context); |
|||
if (context.changeToState == STATE_NULL) { |
|||
return; |
|||
} |
|||
|
|||
while (true) { |
|||
_stateMachine_processChangeStateEvent(&context, &newcontext); |
|||
if (newcontext.changeToState == STATE_NULL) { |
|||
return; |
|||
} |
|||
memcpy(&context, &newcontext, sizeof(newcontext)); |
|||
memset(&newcontext, 0, sizeof(newcontext)); |
|||
} |
|||
} |
|||
int32_t IIflytopCanSlaveModule::getModuleTicket() { return m_module_ticket; } |
|||
|
|||
void IIflytopCanSlaveModule::stateMachine_triggerPrivateEvent(int32_t eventIndex) { |
|||
icsm::Event event; |
|||
event.eventIndex = eventIndex; |
|||
event.eventType = icsm::kPrivateEvent; |
|||
stateMachine_triggerEvent(event); |
|||
} |
|||
|
|||
void IIflytopCanSlaveModule::setDumpConfig(bool dumpConfig) { s_dumpConfig = dumpConfig; } |
|||
#endif
|
@ -0,0 +1,276 @@ |
|||
#pragma once
|
|||
#include "sdk/hal/zhal.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
#include <stdlib.h>
|
|||
|
|||
#include "sdk\components\iflytop_can_slave_v1\iflytop_can_slave.hpp"
|
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
|
|||
#define CONFIG_PARA_REG_NUM
|
|||
|
|||
class IIflytopCanSlaveModule; |
|||
namespace icsm { |
|||
|
|||
class ConfigPara { |
|||
IIflytopCanSlaveModule* m_module; |
|||
const char* m_name; |
|||
|
|||
uint32_t m_regAddOff; |
|||
int32_t m_val; |
|||
|
|||
bool m_enableLimit; |
|||
int32_t m_limitMax; |
|||
int32_t m_limitMin; |
|||
|
|||
public: |
|||
void initialize(IIflytopCanSlaveModule* module, uint32_t regoff, uint16_t mask, int32_t defaultValue); |
|||
|
|||
icps::error_t processIflytopCanRegisterWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent); |
|||
|
|||
icps::error_t setVal(int32_t val); |
|||
int32_t getVal(); |
|||
icps::error_t setEnableLimit(bool enable); |
|||
bool getEnableLimit(); |
|||
icps::error_t setLimitMax(int32_t val); |
|||
int32_t getLimitMax(); |
|||
icps::error_t setLimitMin(int32_t val); |
|||
int32_t getLimitMin(); |
|||
|
|||
icps::error_t enableLimit(bool enable, int32_t min, int32_t max); |
|||
icps::error_t setValWitchLimit(int32_t initVal, int32_t min, int32_t max); |
|||
|
|||
void setName(const char* name); |
|||
|
|||
int32_t getRegAddOff(); |
|||
}; |
|||
|
|||
class Action { |
|||
IIflytopCanSlaveModule* m_module; |
|||
|
|||
uint32_t m_regAddOff; |
|||
int32_t m_val; |
|||
const char* m_name; |
|||
|
|||
public: |
|||
void initialize(IIflytopCanSlaveModule* module, uint32_t regoff); |
|||
|
|||
void setName(const char* name); |
|||
const char* getName(); |
|||
|
|||
icps::error_t setVal(int32_t val); |
|||
int32_t getVal(); |
|||
|
|||
int32_t getRegAddOff(); |
|||
}; |
|||
|
|||
typedef enum { |
|||
kevent_enterstate, |
|||
kevent_exitState, |
|||
kevent_periodicJob, |
|||
kevent_doAction, |
|||
} PublicEventIndex_t; |
|||
|
|||
typedef enum { |
|||
kPublicEvent, |
|||
kPrivateEvent, |
|||
} EventType_t; |
|||
|
|||
class Event { |
|||
public: |
|||
EventType_t eventType; |
|||
int32_t eventIndex; |
|||
|
|||
private: |
|||
int32_t eventVal0; |
|||
int32_t eventVal1; |
|||
|
|||
public: |
|||
Event(){}; |
|||
Event(EventType_t eventType, int32_t eventIndex) { |
|||
this->eventType = eventType; |
|||
this->eventIndex = eventIndex; |
|||
this->eventVal0 = 0; |
|||
this->eventVal1 = 0; |
|||
} |
|||
|
|||
Event(EventType_t eventType, int32_t eventIndex, int32_t action, int32_t actionVal) { |
|||
this->eventType = eventType; |
|||
this->eventIndex = eventIndex; |
|||
this->eventVal0 = action; |
|||
this->eventVal1 = actionVal; |
|||
} |
|||
|
|||
bool isEq(EventType_t eventType, int32_t eventIndex) { //
|
|||
return (this->eventType == eventType) && (this->eventIndex == eventIndex); |
|||
} |
|||
bool isPublicEvent(PublicEventIndex_t eventIndex) { //
|
|||
return (this->eventType == kPublicEvent) && (this->eventIndex == (int32_t)eventIndex); |
|||
} |
|||
bool isPrivateEvent(int32_t eventIndex) { //
|
|||
return (this->eventType == kPrivateEvent) && (this->eventIndex == eventIndex); |
|||
} |
|||
|
|||
int32_t getAction() { return this->eventVal0; } |
|||
int32_t getActionVal() { return this->eventVal1; } |
|||
}; |
|||
|
|||
class StateMachineEventContext { |
|||
public: |
|||
Event event; |
|||
int32_t changeToState; |
|||
int32_t exceptionId; |
|||
}; |
|||
|
|||
} // namespace icsm
|
|||
|
|||
/*******************************************************************************
|
|||
* IIflytopCanSlaveModule * |
|||
*******************************************************************************/ |
|||
class IIflytopCanSlaveModule; |
|||
class IIflytopCanSlaveModuleListener { |
|||
public: |
|||
virtual void onStateChange(IIflytopCanSlaveModule* service, int32_t state) = 0; |
|||
virtual void onException(IIflytopCanSlaveModule* service, int32_t exceptionId) = 0; |
|||
}; |
|||
|
|||
class IIflytopCanSlaveModule { |
|||
public: |
|||
const char* m_name; |
|||
|
|||
private: |
|||
|
|||
int32_t m_regStart; |
|||
int32_t m_regNum; |
|||
|
|||
int32_t m_statusRegOff; |
|||
int32_t m_ExceptionRegOff; |
|||
|
|||
icsm::ConfigPara* m_configParas; |
|||
int m_configParaNum; |
|||
|
|||
icsm::Action* m_action; |
|||
int m_actionNum; |
|||
|
|||
bool engineer_mode; |
|||
|
|||
bool m_eventCacheIsEmpty; |
|||
icsm::Event m_eventCache; |
|||
|
|||
IflytopCanProtocolStackProcesser* m_protocolProcesser; |
|||
|
|||
int32_t m_lastState; |
|||
int32_t m_state; |
|||
int32_t m_exceptionId; |
|||
|
|||
int32_t m_lastcallticket; |
|||
int32_t m_periodms; |
|||
int32_t m_module_ticket; |
|||
|
|||
int32_t m_stateticket; |
|||
|
|||
IIflytopCanSlaveModuleListener* m_listener; |
|||
|
|||
icsm::Action m_zeroaction; |
|||
icsm::ConfigPara m_zeroCfg; |
|||
|
|||
int32_t m_actionVal; |
|||
|
|||
int32_t m_idle_state_index; |
|||
int32_t m_exception_state_index; |
|||
|
|||
public: |
|||
IIflytopCanSlaveModule(/* args */){}; |
|||
virtual ~IIflytopCanSlaveModule(){}; |
|||
|
|||
protected: |
|||
void initialize(const char* name, IflytopCanProtocolStackProcesser* processer, int32_t regoff, int32_t retNum); |
|||
void regConfigParas(icsm::ConfigPara* configParas, int configParaNum); |
|||
void regActions(icsm::Action* action, int actionNum); |
|||
|
|||
void setStatusRegOff(int32_t regoff); |
|||
void setExceptionRegOff(int32_t regoff); |
|||
|
|||
void setIdelStateIndex(int32_t stateIndex); |
|||
void setExceptionStateIndex(int32_t stateIndex); |
|||
|
|||
public: |
|||
void setListener(IIflytopCanSlaveModuleListener* listener); |
|||
void periodicJob(); |
|||
|
|||
static void setDumpConfig(bool dumpConfig); |
|||
|
|||
/*******************************************************************************
|
|||
* 子类复写 * |
|||
*******************************************************************************/ |
|||
|
|||
virtual icps::error_t stateMachine_onTryDoAction(icsm::Action* action, int32_t actionVal) = 0; |
|||
virtual bool stateMachine_onPocessEvent(icsm::StateMachineEventContext* context) = 0; |
|||
virtual void stateMachine_onPocessRemindEvent(icsm::StateMachineEventContext* context) = 0; |
|||
virtual void stateMachine_onPeriodic(int stateMachineTicket) = 0; |
|||
virtual void stateMachine_onAsFarAsPossibleCall() = 0; |
|||
|
|||
virtual const char* stateMachine_stateToString(int32_t state) = 0; |
|||
|
|||
/*******************************************************************************
|
|||
* 通用状态 * |
|||
*******************************************************************************/ |
|||
|
|||
void setEngineerMode(bool engineer_mode); |
|||
bool getEngineerMode(); |
|||
|
|||
int32_t getExceptionId(); |
|||
|
|||
int32_t getModuleTicket(); |
|||
|
|||
|
|||
/*******************************************************************************
|
|||
* 协议对接 * |
|||
*******************************************************************************/ |
|||
bool isMyWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent); |
|||
icps::error_t processIflytopCanRegisterWriteEvent(IflytopCanProtocolStackWriteEvent* writeEvent); |
|||
/*******************************************************************************
|
|||
* 协议助手 * |
|||
*******************************************************************************/ |
|||
|
|||
const char* getActionNameByState(int32_t state); |
|||
int getActionByState(int32_t state); |
|||
int getActionStateIndexByState(int32_t state); |
|||
IflytopCanProtocolStackProcesser* getProtocolProcesser() { return m_protocolProcesser; } |
|||
|
|||
icsm::ConfigPara* getConfig(int regoff); |
|||
icsm::Action* getAction(int regoff); |
|||
|
|||
void initializeCfg(icsm::ConfigPara* cfg, icsm::ConfigPara** shadowcfg, IIflytopCanSlaveModule* module, uint32_t regoff, uint16_t mask, int32_t defaultValue); |
|||
void initializeCfg(const char* name, icsm::ConfigPara* cfg, icsm::ConfigPara** shadowcfg, IIflytopCanSlaveModule* module, uint32_t regoff, uint16_t mask, |
|||
int32_t defaultValue); |
|||
icsm::Action* initializeAction(icsm::Action* action, IIflytopCanSlaveModule* module, const char* actionName, uint32_t regoff); |
|||
|
|||
uint32_t getRegOff(IflytopCanProtocolStackWriteEvent* writeEvent); |
|||
uint32_t getRegStartAdd() { return m_regStart; } |
|||
uint32_t getRegEndAdd() { return m_regStart + m_regNum; } |
|||
|
|||
void writeRegValueByRegOff(uint16_t regaddoff, int32_t value, bool forceupdate = false); |
|||
void activeReg(uint16_t mappingAdd, uint16_t mask, int32_t defaultValue); |
|||
/*******************************************************************************
|
|||
* StateMachine * |
|||
*******************************************************************************/ |
|||
int32_t stateMachine_getStateIndex(); |
|||
int32_t stateMachine_getStateDuration(); |
|||
void stateMachine_triggerEvent(icsm::Event event); |
|||
void stateMachine_triggerPrivateEvent(int32_t eventIndex); |
|||
bool stateMachine_isIdle(); |
|||
|
|||
void disablePermission(int32_t actionRegoff, uint32_t permission); |
|||
void stateMachine_pushEvent(icsm::Event event); |
|||
|
|||
private: |
|||
// void stateMachine_triggerChangeStateEvent(int32_t state);
|
|||
void stateMachine_periodicJob(int ticket); |
|||
void _stateMachine_processChangeStateEvent(icsm::StateMachineEventContext* oldcontext, icsm::StateMachineEventContext* newcontext); |
|||
void _stateMachine_onPocessEvent(icsm::StateMachineEventContext* context); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
|||
#endif
|
@ -0,0 +1,537 @@ |
|||
|
|||
#include "single_axis_motor_control_v2.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
using namespace iflytop; |
|||
#define TAG "SingleAxisMotorControlerV2"
|
|||
|
|||
void SingleAxisMotorControlerV2::initialize(const char* name, IflytopCanProtocolStackProcesser* processer, int regaddoff, //
|
|||
ZGPIO* homegpio, //
|
|||
ZGPIO* mingpio, //
|
|||
ZGPIO* maxgpio, //
|
|||
IStepperMotor* motor) { |
|||
IIflytopCanSlaveModule::initialize(name, processer, regaddoff, SINGLE_AXIS_MOTOR_CTRL_REG_NUM); |
|||
|
|||
m_homegpio = homegpio; |
|||
m_minlimitgpio = mingpio; |
|||
m_maxlimitgpio = maxgpio; |
|||
m_motor = motor; |
|||
|
|||
if (m_homegpio) { |
|||
ZASSERT(m_homegpio->isItRisingAndItFallingEXITGPIO()); |
|||
} |
|||
|
|||
IIflytopCanSlaveModule::setStatusRegOff(SAMC_REG_STAT_STATUS); |
|||
IIflytopCanSlaveModule::setExceptionRegOff(SAMC_REG_STAT_EXCEPTION); |
|||
IIflytopCanSlaveModule::setIdelStateIndex(kstate_idle); |
|||
IIflytopCanSlaveModule::setExceptionStateIndex(kstate_exception); |
|||
/*******************************************************************************
|
|||
* 注册状态 * |
|||
*******************************************************************************/ |
|||
|
|||
IIflytopCanSlaveModule::activeReg(SAMC_REG_STAT_CURRENT_VELOCITY, icps::kr, 0); |
|||
IIflytopCanSlaveModule::activeReg(SAMC_REG_STAT_CURRENT_POS, icps::kr, 0); |
|||
IIflytopCanSlaveModule::activeReg(SAMC_REG_STAT_STATUS, icps::kr, 0); |
|||
IIflytopCanSlaveModule::activeReg(SAMC_REG_STAT_EXCEPTION, icps::kr, 0); |
|||
/**
|
|||
* @brief |
|||
*/ |
|||
int i = 0; |
|||
/*******************************************************************************
|
|||
* 注册动作 * |
|||
*******************************************************************************/ |
|||
i = 0; |
|||
act_velocity_ctrl = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "velocity_ctrl", SAMC_REG_ACT_ROTATE); |
|||
act_position_ctrl = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "position_ctrl", SAMC_REG_ACT_MOVE_TO); |
|||
act_rela_position_ctrl = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "rela_position_ctrl", SAMC_REG_ACT_MOVE_BY); |
|||
act_zero_ctrl = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "zero_ctrl", SAMC_REG_ACT_RUN_TO_HOME); |
|||
act_calibrezero = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "calibrezero", SAMC_REG_ACT_DO_NOTHING); |
|||
act_stop_ctrl = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "stop_ctrl", SAMC_REG_ACT_STOP); |
|||
act_clear_error = IIflytopCanSlaveModule::initializeAction(&actions[i++], this, "clear_error", SAMC_REG_ACT_CLEAR_EXCEPTION); |
|||
ZASSERT(ZARRAY_SIZE(actions) == i); |
|||
IIflytopCanSlaveModule::regActions(actions, i); |
|||
|
|||
/*******************************************************************************
|
|||
* 注册配置 * |
|||
*******************************************************************************/ |
|||
i = 0; |
|||
IIflytopCanSlaveModule::initializeCfg("acc", &cfgs[i++], &cfg_acc, this, SAMC_REG_CFG_ACC, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("dec", &cfgs[i++], &cfg_dec, this, SAMC_REG_CFG_DEC, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("velocity", &cfgs[i++], &cfg_velocity, this, SAMC_REG_CFG_VELOCITY, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("zero_shift", &cfgs[i++], &cfg_zero_shift, this, SAMC_REG_CFG_ZERO_SHIFT, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("runhome_velocity", &cfgs[i++], &cfg_runhome_velocity, this, SAMC_REG_CFG_RUNHOME_VELOCITY, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("runtohome_dec", &cfgs[i++], &cfg_runtohome_dec, this, SAMC_REG_CFG_RUNTOHOME_DEC, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("runtohome_max_distance", &cfgs[i++], &cfg_runtohome_max_distance, this, SAMC_REG_CFG_RUNTOHOME_MAX_DISTANCE, icps::kwr, |
|||
0); |
|||
IIflytopCanSlaveModule::initializeCfg("runtohome_leave_zero_point_distance", &cfgs[i++], &cfg_runtohome_leave_zero_point_distance, this, |
|||
SAMC_REG_CFG_RUNTOHOME_LEAVE_ZERO_POINT_DISTANCE, icps::kwr, 0); |
|||
IIflytopCanSlaveModule::initializeCfg("min_pos", &cfgs[i++], &cfg_min_pos, this, SAMC_REG_CFG_MIN_POS, icps::kwr, INT32_MIN); |
|||
IIflytopCanSlaveModule::initializeCfg("max_pos", &cfgs[i++], &cfg_max_pos, this, SAMC_REG_CFG_MAX_POS, icps::kwr, INT32_MAX); |
|||
IIflytopCanSlaveModule::initializeCfg("runtohome_min_distance", &cfgs[i++], &cfg_runtohome_keep_move_distance, this, |
|||
SAMC_REG_CFG_RUNTOHOME_KEEP_MOVE_DISTANCE, icps::kwr, 0); |
|||
|
|||
ZASSERT(ZARRAY_SIZE(cfgs) == i); |
|||
IIflytopCanSlaveModule::regConfigParas(cfgs, i); |
|||
// ZGPIO::regListener(this);
|
|||
|
|||
if (m_homegpio) m_homegpio->regListener([this](ZGPIO* GPIO_Pin, ZGPIO::IrqTypeEvent_t irqevent) { STM32_GPIO_onIRQ(GPIO_Pin, irqevent); }); |
|||
if (m_minlimitgpio) m_minlimitgpio->regListener([this](ZGPIO* GPIO_Pin, ZGPIO::IrqTypeEvent_t irqevent) { STM32_GPIO_onIRQ(GPIO_Pin, irqevent); }); |
|||
if (m_maxlimitgpio) m_maxlimitgpio->regListener([this](ZGPIO* GPIO_Pin, ZGPIO::IrqTypeEvent_t irqevent) { STM32_GPIO_onIRQ(GPIO_Pin, irqevent); }); |
|||
m_moveToHomeCheck = true; |
|||
|
|||
ZHALCORE::getInstance()->regPeriodJob([this](ZHALCORE::Context& context) { periodicJob(); }, 1); |
|||
} |
|||
int32_t SingleAxisMotorControlerV2::getPos() { return m_motor->getXACTUAL(); } |
|||
|
|||
void SingleAxisMotorControlerV2::lock() { m_lock = true; } |
|||
void SingleAxisMotorControlerV2::unlock() { m_lock = false; } |
|||
bool SingleAxisMotorControlerV2::islock() { return m_lock; } |
|||
|
|||
const char* SingleAxisMotorControlerV2::stateMachine_stateToString(int32_t state) { |
|||
switch (state) { |
|||
case kstate_idle: |
|||
return "state_idle"; |
|||
case kstate_exception: |
|||
return "state_exception"; |
|||
|
|||
case kstate_findZero_runToZero: |
|||
return "state_findZero_runToZero"; |
|||
case kstate_findZero_keepRunningToZero: |
|||
return "state_findZero_keepRunningToZero"; |
|||
case kstate_findZero_leaveFromZero: |
|||
return "state_findZero_leaveFromZero"; |
|||
case kstate_findZero_waittingToStop: |
|||
return "state_findZero_waittingToStop"; |
|||
|
|||
case kstate_moveTo: |
|||
return "state_moveTo"; |
|||
case kstate_moveBy: |
|||
return "state_moveBy"; |
|||
case kstate_rotating: |
|||
return "state_rotating"; |
|||
default: |
|||
break; |
|||
} |
|||
return "state_unkown"; |
|||
} |
|||
/*******************************************************************************
|
|||
* 参数检查 * |
|||
*******************************************************************************/ |
|||
icps::error_t SingleAxisMotorControlerV2::checkTargetPos(int32_t targetPos) { |
|||
if (getEngineerMode()) { |
|||
return icps::kSuccess; |
|||
} |
|||
if (targetPos > cfg_max_pos->getVal()) { |
|||
// ZLOGI(m_name, "targetPos:%d, cfg_max_pos:%d", targetPos, cfg_max_pos->getVal());
|
|||
return icps::kParameterOutOfLimit; |
|||
} else if (targetPos < cfg_min_pos->getVal()) { |
|||
// ZLOGI(m_name, "targetPos:%d, cfg_max_pos:%d", targetPos, cfg_min_pos->getVal());
|
|||
return icps::kParameterOutOfLimit; |
|||
} |
|||
return icps::kSuccess; |
|||
} |
|||
icps::error_t SingleAxisMotorControlerV2::stateMachine_onTryDoAction(icsm::Action* action, int32_t actionVal) { |
|||
if (m_lock) { |
|||
return icps::kDeviceLockByInternalControler; |
|||
} |
|||
|
|||
if (action->getRegAddOff() != SAMC_REG_ACT_CLEAR_EXCEPTION && getExceptionId() != 0) { |
|||
return icps::kDeviceException; |
|||
} |
|||
switch (action->getRegAddOff()) { |
|||
case SAMC_REG_ACT_ROTATE: |
|||
if (m_homegpio && m_moveToHomeCheck) { |
|||
if (!m_hasRunToHomed && !getEngineerMode()) { |
|||
return icps::kmotorNotRunToHome; |
|||
} |
|||
} |
|||
return icps::kSuccess; |
|||
case SAMC_REG_ACT_MOVE_TO: |
|||
if (m_homegpio && m_moveToHomeCheck) { |
|||
if (!m_hasRunToHomed && !getEngineerMode()) { |
|||
return icps::kmotorNotRunToHome; |
|||
} |
|||
} |
|||
return checkTargetPos(actionVal); |
|||
case SAMC_REG_ACT_MOVE_BY: |
|||
if (m_homegpio && m_moveToHomeCheck) { |
|||
if (!m_hasRunToHomed && !getEngineerMode()) { |
|||
return icps::kmotorNotRunToHome; |
|||
} |
|||
} |
|||
return checkTargetPos(getPos() + actionVal); |
|||
case SAMC_REG_ACT_RUN_TO_HOME: |
|||
if (!m_homegpio) { |
|||
return icps::kIllegalOperation; |
|||
} |
|||
return icps::kSuccess; |
|||
case SAMC_REG_ACT_DO_NOTHING: |
|||
return icps::kSuccess; |
|||
case SAMC_REG_ACT_STOP: |
|||
return icps::kSuccess; |
|||
case SAMC_REG_ACT_CLEAR_EXCEPTION: |
|||
return icps::kSuccess; |
|||
default: |
|||
return icps::kSuccess; |
|||
} |
|||
} |
|||
|
|||
void SingleAxisMotorControlerV2::runToHome() { |
|||
if (stateMachine_onTryDoAction(act_zero_ctrl, 0) != icps::kSuccess) { |
|||
return; |
|||
} |
|||
stateMachine_pushEvent(icsm::Event(icsm::kPublicEvent, icsm::kevent_doAction, act_zero_ctrl->getRegAddOff(), 0)); |
|||
} |
|||
void SingleAxisMotorControlerV2::rotate(int direction) { |
|||
m_actionVal = direction; |
|||
if (stateMachine_onTryDoAction(act_velocity_ctrl, direction) != icps::kSuccess) { |
|||
return; |
|||
} |
|||
stateMachine_pushEvent(icsm::Event(icsm::kPublicEvent, icsm::kevent_doAction, act_velocity_ctrl->getRegAddOff(), direction)); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* 状态更新&事件生成 * |
|||
*******************************************************************************/ |
|||
void SingleAxisMotorControlerV2::stateMachine_onPeriodic(int stateMachineTicket) { |
|||
if (stateMachineTicket % 100 == 0) { |
|||
writeRegValueByRegOff(SAMC_REG_STAT_CURRENT_VELOCITY, getActuralVelocity(), false); |
|||
writeRegValueByRegOff(SAMC_REG_STAT_CURRENT_POS, getActuralPosition(), false); |
|||
} |
|||
|
|||
if (stateMachine_getStateIndex() != kstate_idle && stateMachine_getStateIndex() != kstate_exception) { |
|||
if (stateMachineTicket % 33 == 0 && m_motor->isReachTarget()) { |
|||
stateMachine_triggerPrivateEvent(kevent_reachTarget); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void SingleAxisMotorControlerV2::stateMachine_onAsFarAsPossibleCall() { |
|||
if (m_zeroSwitchTrigged) { |
|||
ZLOGI(m_name, "zero switch trigged"); |
|||
m_zeroSwitchTrigged = false; |
|||
stateMachine_triggerPrivateEvent(kevent_triggerZeroSwitch); |
|||
} |
|||
if (m_minlimitgpioSwitchTrigged) { |
|||
ZLOGI(m_name, "min switch trigged"); |
|||
m_minlimitgpioSwitchTrigged = false; |
|||
stateMachine_triggerPrivateEvent(kevent_triggerRightSwitch); |
|||
} |
|||
if (m_maxlimitgpioSwitchTrigged) { |
|||
ZLOGI(m_name, "max switch trigged"); |
|||
m_maxlimitgpioSwitchTrigged = false; |
|||
stateMachine_triggerPrivateEvent(kevent_triggerLelfSwitch); |
|||
} |
|||
} |
|||
void SingleAxisMotorControlerV2::STM32_GPIO_onIRQ(ZGPIO* gpio, ZGPIO::IrqTypeEvent_t irqevent) { |
|||
if (gpio == m_homegpio) { |
|||
m_zeroSwitchTrigged = true; |
|||
stateMachine_triggerPrivateEvent(kevent_triggerZeroSwitchIrq); |
|||
} else if (gpio == m_minlimitgpio) { |
|||
m_minlimitgpioSwitchTrigged = true; |
|||
stateMachine_triggerPrivateEvent(kevent_triggerRightSwitchIrq); |
|||
} else if (gpio == m_maxlimitgpio) { |
|||
m_maxlimitgpioSwitchTrigged = true; |
|||
stateMachine_triggerPrivateEvent(kevent_triggerLelfSwitchIrq); |
|||
} |
|||
} |
|||
/*******************************************************************************
|
|||
* 事件处理 * |
|||
*******************************************************************************/ |
|||
bool SingleAxisMotorControlerV2::stateMachine_onPocessEvent(icsm::StateMachineEventContext* context) { |
|||
int nowstate = IIflytopCanSlaveModule::stateMachine_getStateIndex(); |
|||
if (nowstate == kstate_idle) { |
|||
return process_state_idle(context); |
|||
} else if (nowstate == kstate_exception) { |
|||
return process_state_exception(context); |
|||
} else if (nowstate == kstate_findZero_runToZero) { |
|||
return process_state_findZero_runToZero(context); |
|||
} else if (nowstate == kstate_findZero_keepRunningToZero) { |
|||
return process_state_findZero_keepRunningToZero(context); |
|||
} else if (nowstate == kstate_findZero_leaveFromZero) { |
|||
return process_state_findZero_leaveFromZero(context); |
|||
} else if (nowstate == kstate_findZero_waittingToStop) { |
|||
return process_state_findZero_waittingToStop(context); |
|||
} else if (nowstate == kstate_moveTo) { |
|||
return process_state_moveTo(context); |
|||
} else if (nowstate == kstate_moveBy) { |
|||
return process_state_moveBy(context); |
|||
} else if (nowstate == kstate_rotating) { |
|||
return process_state_rotating(context); |
|||
} |
|||
return false; |
|||
} |
|||
/*******************************************************************************
|
|||
* 公共事件处理 * |
|||
*******************************************************************************/ |
|||
void SingleAxisMotorControlerV2::stateMachine_onPocessRemindEvent(icsm::StateMachineEventContext* context) { |
|||
icsm::Event& event = context->event; |
|||
if (event.isPublicEvent(icsm::kevent_doAction)) { |
|||
ZLOGI(m_name, "doAction %d,%d", event.getAction(), event.getActionVal()); |
|||
m_actionVal = event.getActionVal(); |
|||
switch (event.getAction()) { |
|||
case SAMC_REG_ACT_ROTATE: |
|||
context->changeToState = kstate_rotating; |
|||
break; |
|||
case SAMC_REG_ACT_MOVE_TO: |
|||
context->changeToState = kstate_moveTo; |
|||
break; |
|||
case SAMC_REG_ACT_MOVE_BY: |
|||
context->changeToState = kstate_moveBy; |
|||
break; |
|||
case SAMC_REG_ACT_RUN_TO_HOME: |
|||
context->changeToState = kstate_findZero_runToZero; |
|||
break; |
|||
case SAMC_REG_ACT_DO_NOTHING: |
|||
context->changeToState = kstate_idle; |
|||
break; |
|||
case SAMC_REG_ACT_STOP: |
|||
context->changeToState = kstate_idle; |
|||
break; |
|||
case SAMC_REG_ACT_CLEAR_EXCEPTION: |
|||
context->changeToState = kstate_idle; |
|||
context->exceptionId = 0; |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
// ZLOGI(m_name, "xxxxcontext->changeToState %d", context->changeToState);
|
|||
} |
|||
} |
|||
bool SingleAxisMotorControlerV2::process_state_idle(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
ZLOGI(m_name, "change state -> idle"); |
|||
m_motor->stop(); |
|||
return true; |
|||
} else if (context->event.isPublicEvent(icsm::kevent_periodicJob)) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/**
|
|||
* @brief |
|||
* 归零逻辑 |
|||
* 0. 如果设备没有处于零点,则设备往反方向移动,靠近零点,当零点触发时,停止运动,然后执行步骤1 |
|||
* 如果设备处于零点则直接执行步骤1. |
|||
* 1. 设备往正方向移动,远离零点,当中断触发时,记录当前零点位置,校准零点 |
|||
*/ |
|||
|
|||
bool SingleAxisMotorControlerV2::process_state_findZero_runToZero(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
// 如果当前在零点,则直接进入下一步
|
|||
ZLOGI(m_name, "change state -> findZero_runToZero"); |
|||
if (m_homegpio->getState()) { |
|||
ZLOGI(m_name, "try search home point falling edge"); |
|||
motor_moveBy(cfg_runtohome_max_distance->getVal(), //
|
|||
cfg_runhome_velocity->getVal() * 2, //
|
|||
cfg_acc->getVal(), //
|
|||
cfg_runtohome_dec->getVal()); |
|||
m_runToHomeContext_runDirection = 1; |
|||
} else { |
|||
// 回到零点
|
|||
ZLOGI(m_name, "try search home point rising edge"); |
|||
motor_moveBy(-cfg_runtohome_max_distance->getVal(), //
|
|||
cfg_runhome_velocity->getVal() * 2, //
|
|||
cfg_acc->getVal(), //
|
|||
cfg_runtohome_dec->getVal()); |
|||
m_runToHomeContext_runDirection = -1; |
|||
} |
|||
return true; |
|||
} else if (context->event.isPrivateEvent(kevent_triggerZeroSwitchIrq)) { |
|||
// 锁存当前零点位置,且立马停止设备
|
|||
m_motor->stop(); |
|||
return true; |
|||
} else if (context->event.isPrivateEvent(kevent_triggerZeroSwitch)) { |
|||
m_runToHomeContext_zeroTriggerPos = m_motor->getXACTUAL(); |
|||
context->changeToState = kstate_findZero_keepRunningToZero; |
|||
return true; |
|||
} else if (m_motor->isReachTarget() && context->event.isPrivateEvent(kevent_reachTarget)) { |
|||
// 移动了最大位移后,依然找不到原点,报告异常
|
|||
ZLOGE(TAG, "run to home failed %d", stateMachine_getStateIndex()); |
|||
context->exceptionId = kexcep_loseZeroPoint; |
|||
context->changeToState = kstate_exception; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool SingleAxisMotorControlerV2::process_state_findZero_keepRunningToZero(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
// 如果当前在零点,则直接进入下一步
|
|||
ZLOGI(m_name, "change state -> runToHomeStep0"); |
|||
|
|||
int32_t hasMovedDistance = m_motor->getXACTUAL() - m_runToHomeContext_zeroTriggerPos; |
|||
|
|||
if (abs(hasMovedDistance) >= cfg_runtohome_keep_move_distance->getVal()) { |
|||
context->changeToState = kstate_findZero_leaveFromZero; |
|||
} else { |
|||
int32_t reminddistance = cfg_runtohome_keep_move_distance->getVal() - abs(hasMovedDistance); |
|||
if (m_runToHomeContext_runDirection > 0) { |
|||
motor_moveBy(reminddistance, cfg_runhome_velocity->getVal() * 2, cfg_acc->getVal(), cfg_runtohome_dec->getVal()); |
|||
} else { |
|||
motor_moveBy(-reminddistance, cfg_runhome_velocity->getVal() * 2, cfg_acc->getVal(), cfg_runtohome_dec->getVal()); |
|||
} |
|||
} |
|||
return true; |
|||
} else if (m_motor->isReachTarget() && context->event.isPrivateEvent(kevent_reachTarget)) { |
|||
context->changeToState = kstate_findZero_leaveFromZero; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool SingleAxisMotorControlerV2::process_state_findZero_leaveFromZero(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
// 进入状态
|
|||
ZLOGI(m_name, "change state -> runToHomeStep1"); |
|||
if (m_runToHomeContext_runDirection < 0) { |
|||
motor_moveBy(cfg_runtohome_leave_zero_point_distance->getVal(), //
|
|||
cfg_runhome_velocity->getVal(), //
|
|||
cfg_acc->getVal(), //
|
|||
cfg_runtohome_dec->getVal()); // 此时处于零点位置,先离开原点一定位置
|
|||
} else { |
|||
motor_moveBy(-cfg_runtohome_leave_zero_point_distance->getVal(), //
|
|||
cfg_runhome_velocity->getVal(), //
|
|||
cfg_acc->getVal(), //
|
|||
cfg_runtohome_dec->getVal()); // 此时处于零点位置,先离开原点一定位置
|
|||
} |
|||
return true; |
|||
} else if (context->event.isPrivateEvent(kevent_triggerZeroSwitchIrq)) { |
|||
// 锁存当前零点位置,且立马停止设备
|
|||
m_zeroPointPosition = m_motor->getXACTUAL(); |
|||
m_motor->stop(); |
|||
return true; |
|||
} else if (context->event.isPrivateEvent(kevent_triggerZeroSwitch)) { |
|||
// 找到原点,停止设备,进入idle状态,之所以没有在IRQ切换状态,是为了避免异步操作带来的问题
|
|||
m_motor->stop(); |
|||
context->changeToState = kstate_findZero_waittingToStop; |
|||
return true; |
|||
} else if (m_motor->isReachTarget() && context->event.isPrivateEvent(kevent_reachTarget)) { |
|||
// 移动了最大位移后,依然找不到原点,报告异常
|
|||
ZLOGE(TAG, "run to home failed %d", stateMachine_getStateIndex()); |
|||
context->exceptionId = kexcep_loseZeroPoint; |
|||
context->changeToState = kstate_exception; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool SingleAxisMotorControlerV2::process_state_findZero_waittingToStop(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_periodicJob)) { |
|||
if (m_zeroPointPosition != 0) { |
|||
if (m_motor->getVACTUAL() == 0) { |
|||
int32_t nowposition = m_motor->getXACTUAL(); |
|||
int32_t nowposition_real = nowposition - m_zeroPointPosition; |
|||
ZLOGI(m_name, "nowposition:%d,zeroPointPosition:%d", nowposition, m_zeroPointPosition); |
|||
m_motor->setXACTUAL(nowposition_real - cfg_zero_shift->getVal()); |
|||
m_zeroPointPosition = 0; |
|||
motor_moveTo(0, cfg_runhome_velocity->getVal(), cfg_acc->getVal(), cfg_acc->getVal()); |
|||
m_hasRunToHomed = true; |
|||
// context->changeToState = kstate_idle;
|
|||
} |
|||
} else { |
|||
if (m_motor->getVACTUAL() == 0) { |
|||
context->changeToState = kstate_idle; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool SingleAxisMotorControlerV2::process_state_moveTo(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
// 进入状态b
|
|||
ZLOGI(m_name, "change state -> moveTo %d", m_actionVal); |
|||
motor_moveTo(m_actionVal, cfg_velocity->getVal(), cfg_acc->getVal(), cfg_dec->getVal()); |
|||
return true; |
|||
|
|||
} else if (m_motor->isReachTarget() && context->event.isPrivateEvent(kevent_reachTarget)) { |
|||
context->changeToState = kstate_idle; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
bool SingleAxisMotorControlerV2::process_state_moveBy(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
// 进入状态
|
|||
ZLOGI(m_name, "change state -> moveBy %d", m_actionVal); |
|||
motor_moveBy(m_actionVal, cfg_velocity->getVal(), cfg_acc->getVal(), cfg_dec->getVal()); |
|||
return true; |
|||
|
|||
} else if (m_motor->isReachTarget() && context->event.isPrivateEvent(kevent_reachTarget)) { |
|||
context->changeToState = kstate_idle; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
bool SingleAxisMotorControlerV2::process_state_rotating(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
// 进入状态
|
|||
ZLOGI(m_name, "change state -> rotating %d", cfg_velocity->getVal()); |
|||
if (m_actionVal > 0) { |
|||
motor_rotate(cfg_velocity->getVal(), cfg_acc->getVal(), cfg_dec->getVal()); |
|||
} else if (m_actionVal < 0) { |
|||
motor_rotate(-cfg_velocity->getVal(), cfg_acc->getVal(), cfg_dec->getVal()); |
|||
} else { |
|||
context->changeToState = kstate_idle; |
|||
} |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
bool SingleAxisMotorControlerV2::process_state_exception(icsm::StateMachineEventContext* context) { |
|||
if (context->event.isPublicEvent(icsm::kevent_enterstate)) { |
|||
ZLOGI(m_name, "change state -> exception %d", getExceptionId()); |
|||
m_motor->stop(); |
|||
return true; |
|||
} else if (context->event.isPublicEvent(icsm::kevent_doAction) && m_actionVal == SAMC_REG_ACT_CLEAR_EXCEPTION) { |
|||
context->exceptionId = 0; |
|||
context->changeToState = kstate_idle; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void SingleAxisMotorControlerV2::motor_moveTo(int32_t pos, int32_t velocity, int32_t acc, int32_t dec) { |
|||
ZLOGI(m_name, "motor_moveTo %d %d %d %d", pos, velocity, acc, dec); |
|||
int32_t position = m_motor->getXACTUAL(); |
|||
position >= pos ? m_direction = 1 : m_direction = -1; |
|||
m_motor->setAcceleration(acc); |
|||
m_motor->setDeceleration(dec); |
|||
m_motor->moveTo(pos, velocity); |
|||
} |
|||
void SingleAxisMotorControlerV2::motor_moveBy(int32_t pos, int32_t velocity, int32_t acc, int32_t dec) { |
|||
ZLOGI(m_name, "motor_moveBy %d %d %d %d", pos, velocity, acc, dec); |
|||
pos >= 0 ? m_direction = 1 : m_direction = -1; |
|||
m_motor->setAcceleration(acc); |
|||
m_motor->setDeceleration(dec); |
|||
m_motor->moveBy(pos, velocity); |
|||
} |
|||
void SingleAxisMotorControlerV2::motor_rotate(int32_t velocity, int32_t acc, int32_t dec) { |
|||
ZLOGI(m_name, "motor_rotate %d %d %d", velocity, acc, dec); |
|||
velocity >= 0 ? m_direction = 1 : m_direction = -1; |
|||
m_motor->setAcceleration(acc); |
|||
m_motor->setDeceleration(dec); |
|||
m_motor->rotate(velocity); |
|||
} |
|||
int32_t SingleAxisMotorControlerV2::getActuralVelocity() { return m_motor->getVACTUAL(); } |
|||
int32_t SingleAxisMotorControlerV2::getActuralPosition() { return m_motor->getXACTUAL(); } |
|||
|
|||
IStepperMotor* SingleAxisMotorControlerV2::getMotor() { return m_motor; } |
|||
|
|||
int SingleAxisMotorControlerV2::getDirection() { return m_direction; } |
|||
|
|||
icps::error_t SingleAxisMotorControlerV2::stop() { |
|||
IflytopCanProtocolStackWriteEvent writeEvent; |
|||
icps::Reg_t* reg = getProtocolProcesser()->findReg(getRegStartAdd() + SAMC_REG_ACT_STOP); |
|||
ZASSERT(reg != NULL); |
|||
|
|||
writeEvent.reg = reg; |
|||
writeEvent.newvalue = 1; |
|||
writeEvent.oldvalue = reg->getValue(); |
|||
processIflytopCanRegisterWriteEvent(&writeEvent); |
|||
return icps::kSuccess; |
|||
} |
|||
#endif
|
@ -0,0 +1,191 @@ |
|||
#pragma once
|
|||
#include "sdk/hal/zhal.hpp"
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
#include <stdlib.h>
|
|||
|
|||
#include "i_iflytop_can_slave_module.hpp"
|
|||
#include "sdk\components\tmc\basic\tmc_ic_interface.hpp"
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* service: SingleAxisMotorControlerV2 |
|||
* |
|||
*/ |
|||
#define SINGLE_AXIS_MOTOR_CTRL_REG_NUM 99
|
|||
|
|||
#define SAMC_REG_ACT_ROTATE (0) // 速度模式控制
|
|||
#define SAMC_REG_ACT_MOVE_TO (1) // 位置模式控制
|
|||
#define SAMC_REG_ACT_MOVE_BY (2) // 相对位置模式控制
|
|||
#define SAMC_REG_ACT_RUN_TO_HOME (3) // 归零
|
|||
#define SAMC_REG_ACT_DO_NOTHING (4) // __
|
|||
#define SAMC_REG_ACT_STOP (8) // 停止
|
|||
#define SAMC_REG_ACT_CLEAR_EXCEPTION (9) // 清空异常
|
|||
|
|||
#define SAMC_REG_STAT_STATUS (10) // 设备状态
|
|||
#define SAMC_REG_STAT_CURRENT_VELOCITY (12) // 当前转速
|
|||
#define SAMC_REG_STAT_CURRENT_POS (13) // 当前位置
|
|||
#define SAMC_REG_STAT_EXCEPTION (14) // 异常状态
|
|||
|
|||
#define SAMC_REG_CFG_ACC (20) // 加速度pps^2
|
|||
#define SAMC_REG_CFG_DEC (21) // 减速度pps^2
|
|||
#define SAMC_REG_CFG_VELOCITY (22) // 速度
|
|||
#define SAMC_REG_CFG_ZERO_SHIFT (23) // 零点偏移
|
|||
#define SAMC_REG_CFG_RUNHOME_VELOCITY (24) // 归零速度
|
|||
#define SAMC_REG_CFG_RUNTOHOME_DEC (25) // 归零减速度
|
|||
#define SAMC_REG_CFG_RUNTOHOME_MAX_DISTANCE (26) // 归零最大移动距离
|
|||
#define SAMC_REG_CFG_RUNTOHOME_LEAVE_ZERO_POINT_DISTANCE (27) // 归零阶段1移动距离
|
|||
#define SAMC_REG_CFG_MIN_POS (28) // 最小位置
|
|||
#define SAMC_REG_CFG_MAX_POS (29) // 最大位置
|
|||
#define SAMC_REG_CFG_RUNTOHOME_KEEP_MOVE_DISTANCE (30) // 最大位置
|
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
|
|||
class SingleAxisMotorControlerListener; |
|||
class SingleAxisMotorControlerV2 : public IIflytopCanSlaveModule { |
|||
private: |
|||
// res
|
|||
ZGPIO* m_homegpio; |
|||
ZGPIO* m_maxlimitgpio; |
|||
ZGPIO* m_minlimitgpio; |
|||
IStepperMotor* m_motor; |
|||
|
|||
typedef enum { |
|||
kevent_reachTarget, |
|||
kevent_triggerZeroSwitch, |
|||
kevent_triggerZeroSwitchIrq, |
|||
kevent_triggerRightSwitch, |
|||
kevent_triggerRightSwitchIrq, |
|||
kevent_triggerLelfSwitch, |
|||
kevent_triggerLelfSwitchIrq, |
|||
} event_t; |
|||
|
|||
typedef enum { |
|||
kstate_idle = 0, |
|||
kstate_exception = 65535, |
|||
|
|||
kstate_findZero_runToZero = 10, // 向零点移动
|
|||
kstate_findZero_keepRunningToZero = 11, // 继续向原点移动,保证电机没有刚好停在零点, 因为如果刚好停在零点,零点电平可能是跳动的)
|
|||
kstate_findZero_leaveFromZero = 12, // 远离零点
|
|||
kstate_findZero_waittingToStop = 13, // 等待电机停止运动,校准零点偏移
|
|||
|
|||
kstate_moveTo = 20, |
|||
kstate_moveBy = 30, |
|||
kstate_rotating = 40, |
|||
} state_t; |
|||
|
|||
typedef enum { |
|||
kexcep_motorBlocking = 1, |
|||
kexcep_loseZeroPoint = 2, |
|||
} exception_id_t; |
|||
|
|||
public: |
|||
icsm::ConfigPara cfgs[11]; // 状态
|
|||
icsm::Action actions[7]; |
|||
|
|||
icsm::Action* act_velocity_ctrl; |
|||
icsm::Action* act_position_ctrl; |
|||
icsm::Action* act_rela_position_ctrl; |
|||
icsm::Action* act_zero_ctrl; |
|||
icsm::Action* act_calibrezero; |
|||
icsm::Action* act_stop_ctrl; |
|||
icsm::Action* act_clear_error; |
|||
|
|||
icsm::ConfigPara* cfg_acc; |
|||
icsm::ConfigPara* cfg_dec; |
|||
icsm::ConfigPara* cfg_velocity; |
|||
icsm::ConfigPara* cfg_zero_shift; |
|||
icsm::ConfigPara* cfg_runhome_velocity; |
|||
icsm::ConfigPara* cfg_runtohome_dec; |
|||
icsm::ConfigPara* cfg_runtohome_max_distance; |
|||
icsm::ConfigPara* cfg_runtohome_leave_zero_point_distance; |
|||
icsm::ConfigPara* cfg_min_pos; |
|||
icsm::ConfigPara* cfg_max_pos; |
|||
icsm::ConfigPara* cfg_runtohome_keep_move_distance; // 归零零点触发后,继续移动的距离
|
|||
|
|||
bool m_hasRunToHomed; |
|||
int m_direction; |
|||
bool m_zeroSwitchTrigged; |
|||
bool m_maxlimitgpioSwitchTrigged; |
|||
bool m_minlimitgpioSwitchTrigged; |
|||
int32_t m_zeroPointPosition; |
|||
|
|||
int32_t m_actionVal; |
|||
bool m_lock; |
|||
|
|||
int32_t m_runToHomeContext_moveDirection; |
|||
int32_t m_runToHomeContext_zeroTriggerPos; |
|||
int32_t m_runToHomeContext_startPos; |
|||
int32_t m_runToHomeContext_runDirection; |
|||
|
|||
bool m_moveToHomeCheck; |
|||
|
|||
public: |
|||
SingleAxisMotorControlerV2(){}; |
|||
virtual ~SingleAxisMotorControlerV2(){}; |
|||
|
|||
void initialize(const char* name, IflytopCanProtocolStackProcesser* processer, int regaddoff, //
|
|||
ZGPIO* homegpio, //
|
|||
ZGPIO* mingpio, //
|
|||
ZGPIO* rightgpio, //
|
|||
IStepperMotor* motor); |
|||
|
|||
public: |
|||
/**
|
|||
* @brief 内部模块接管电机时,需要调用此函数 |
|||
*/ |
|||
void lock(); |
|||
void unlock(); |
|||
bool islock(); |
|||
|
|||
void disableMoveHomeCheck() { m_moveToHomeCheck = false; }; |
|||
|
|||
IStepperMotor* getMotor(); |
|||
|
|||
void runToHome(); |
|||
void rotate(int direction); |
|||
bool hasRunToHomed() { return m_hasRunToHomed; }; |
|||
|
|||
virtual icps::error_t stateMachine_onTryDoAction(icsm::Action* action, int32_t actionVal); |
|||
virtual bool stateMachine_onPocessEvent(icsm::StateMachineEventContext* context); |
|||
virtual void stateMachine_onPocessRemindEvent(icsm::StateMachineEventContext* context); |
|||
virtual void stateMachine_onPeriodic(int stateMachineTicket); |
|||
virtual void stateMachine_onAsFarAsPossibleCall(); |
|||
virtual const char* stateMachine_stateToString(int32_t state); |
|||
|
|||
bool process_state_idle(icsm::StateMachineEventContext* context); |
|||
|
|||
bool process_state_findZero_runToZero(icsm::StateMachineEventContext* context); |
|||
bool process_state_findZero_keepRunningToZero(icsm::StateMachineEventContext* context); |
|||
bool process_state_findZero_leaveFromZero(icsm::StateMachineEventContext* context); |
|||
bool process_state_findZero_waittingToStop(icsm::StateMachineEventContext* context); |
|||
|
|||
bool process_state_moveTo(icsm::StateMachineEventContext* context); |
|||
bool process_state_moveBy(icsm::StateMachineEventContext* context); |
|||
bool process_state_rotating(icsm::StateMachineEventContext* context); |
|||
bool process_state_exception(icsm::StateMachineEventContext* context); |
|||
|
|||
/*******************************************************************************
|
|||
* GPIO LISTENER * |
|||
*******************************************************************************/ |
|||
void STM32_GPIO_onIRQ(ZGPIO *GPIO_Pin, ZGPIO::IrqTypeEvent_t irqevent); |
|||
icps::error_t checkTargetPos(int32_t targetPos); |
|||
|
|||
/*******************************************************************************
|
|||
* UTILS * |
|||
*******************************************************************************/ |
|||
int getDirection(); |
|||
icps::error_t stop(); |
|||
|
|||
private: |
|||
int32_t getActuralVelocity(); |
|||
int32_t getActuralPosition(); |
|||
void motor_moveTo(int32_t pos, int32_t velocity, int32_t acc, int32_t dec); |
|||
void motor_moveBy(int32_t pos, int32_t velocity, int32_t acc, int32_t dec); |
|||
void motor_rotate(int32_t velocity, int32_t acc, int32_t dec); |
|||
int32_t getPos(); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
|||
#endif
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue