基质喷涂
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
16 KiB

3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
  1. //
  2. // Created by iflyt on 2025/3/3.
  3. //
  4. #include "elc_motor.h"
  5. #include <base/apphal.hpp>
  6. #include <base/apphardware.hpp>
  7. #include <can_control/can_protocol_factory.h>
  8. #include <cmath>
  9. #include "elc_motor_helper.h"
  10. #define TEST 1
  11. #define TAG "ECL MOTOR"
  12. #define TIMER_IS_FINE 0
  13. using namespace iflytop;
  14. // 定时器回调函数
  15. void ECLMotor::readTimerCallback(void *arg) {
  16. ECLMotor *motor = static_cast<ECLMotor *>(arg);
  17. motor->readMotorPosition();
  18. }
  19. // 读取电机位置
  20. void ECLMotor::readMotorPosition() {
  21. // 清除标志位
  22. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  23. if (motor == nullptr) {
  24. return;
  25. }
  26. osMutexAcquire(mutex_, osWaitForever);
  27. bool last_is_move_finished = is_move_finished_;
  28. osMutexRelease(mutex_);
  29. int32_t x_actual = 0;
  30. int32_t enc_val = 0;
  31. int32_t rt_speed = 0;
  32. enc_val = motor->getEncVal(); // 获取编码器值
  33. x_actual = motor->getXACTUAL(); // 获取实时位置
  34. rt_speed = motor->getVACTUAL(); // 获取实时速度
  35. TMC5130RampStat ramp_stat = motor->getRampStat();
  36. bool is_move_finished = motor->isReachTarget(&ramp_stat);
  37. int32_t postion = 0;
  38. if (0 == enc_val) {
  39. postion = x_actual;
  40. } else {
  41. postion = enc_val;
  42. }
  43. // 移动中
  44. osMutexAcquire(mutex_, osWaitForever);
  45. is_move_finished_ = is_move_finished;
  46. x_actual_ = x_actual;
  47. enc_val_ = enc_val;
  48. rt_speed_ = rt_speed;
  49. osMutexRelease(mutex_);
  50. if (!last_is_move_finished && is_move_finished) {
  51. //处理移动结束的问题
  52. if (isRunHomingTask) {
  53. ZLOGI(TAG, "[TIMER] HOMING EVENT_MOTOR_MOVE_FINISHED");
  54. osMutexAcquire(mutex_, osWaitForever);
  55. home_event_.event_type = EVENT_MOTOR_MOVE_FINISHED;
  56. osMutexRelease(mutex_);
  57. osMessageQueuePut(homeEventQueue, &home_event_, 0U, 0U);
  58. }
  59. // 发送CAN 消息
  60. {
  61. #if CAN_MODULE_ENABLE
  62. CanMessage msg = CanProtocolFactory::createUploadEvent(seq_id_move_finished_, Motor_Move_Finished, index_);
  63. AppHardware::ins()->can0Controller.sendMessage(msg);
  64. #endif
  65. }
  66. ZLOGI(TAG, "【FIRST DETECT】 MOVE FINISHED");
  67. }
  68. }
  69. // 设置读取速率
  70. void ECLMotor::startReadTimer() {
  71. osTimerStart(readTimer, 50); // // 50毫秒
  72. }
  73. ECLMotor::ECLMotor() {
  74. // 创建互斥锁
  75. mutex_ = osMutexNew(NULL);
  76. if (mutex_ == NULL) {
  77. // 处理互斥锁创建失败
  78. ZLOGI(TAG, "mutex_ create failed");
  79. }
  80. // 初始化电机位置和目标位置
  81. x_actual_ = 0;
  82. target_pos_ = 0;
  83. target_speed_ = 10; // 10 / 60 * 6s ==== 6 S 可以转一圈
  84. is_move_finished_ = false;
  85. enc_val_ = 0;
  86. is_home_init_ = false;
  87. is_home_suc_ = false;
  88. home_state_ = STATE_INIT;
  89. isRunHomingTask = false;
  90. // 创建定时器
  91. osTimerAttr_t timerAttr = {
  92. .name = "MotorReadTimer",
  93. .attr_bits = 0U,
  94. .cb_mem = NULL,
  95. .cb_size = 0U
  96. };
  97. readTimer = osTimerNew(readTimerCallback, osTimerPeriodic, this, &timerAttr);
  98. if (readTimer == NULL) {
  99. // 处理定时器创建失败
  100. }
  101. // 创建消息队列
  102. homeEventQueue = osMessageQueueNew(10, sizeof(HomeEvent), NULL);
  103. if (homeEventQueue == NULL) {
  104. // 处理消息队列创建失败的情况
  105. ZLOGE(TAG, "Failed to create home event message queue");
  106. }
  107. // 创建任务并获取线程句柄
  108. home_task_attr.name = "HomeStateTask";
  109. home_task_attr.stack_size = 256 * 8;
  110. home_task_attr.priority = osPriorityHigh;
  111. homingStateMachineThreadId = osThreadNew(homingTask, this, &home_task_attr);
  112. if (homingStateMachineThreadId == NULL) {
  113. // 处理线程创建失败的情况
  114. ZLOGE(TAG, "THREAD INDEX %d Create Failed", index_);
  115. }
  116. // 启动定时器
  117. startReadTimer();
  118. }
  119. ECLMotor::~ECLMotor() {
  120. isRunHomingTask = false;
  121. if (homingStateMachineThreadId != NULL) {
  122. osThreadTerminate(homingStateMachineThreadId);
  123. }
  124. if (homeEventQueue != NULL) {
  125. osMessageQueueDelete(homeEventQueue);
  126. }
  127. osMutexDelete(mutex_);
  128. osTimerDelete(readTimer);
  129. }
  130. // 读取电机的位置
  131. int32_t ECLMotor::getPosition() {
  132. osMutexAcquire(mutex_, osWaitForever);
  133. const int32_t pos = x_actual_;
  134. osMutexRelease(mutex_);
  135. const int32_t py_pos = ELCMotorHelper::isFlip(index_) ? -pos : pos;
  136. return py_pos;
  137. }
  138. // 设置电机的目标位置
  139. void ECLMotor::setTargetPosition(int32_t target) {
  140. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  141. if (motor == nullptr) {
  142. return;
  143. }
  144. if (ELCMotorHelper::isFlip(index_)) {
  145. target = -target;
  146. ZLOGI(TAG, "【MOTOR 【%d】TARGET FLIP】", index_);
  147. }
  148. motor->moveTo(target, this->target_speed_);
  149. osMutexAcquire(mutex_, osWaitForever);
  150. target_pos_ = target;
  151. osMutexRelease(mutex_);
  152. }
  153. void ECLMotor::setShiftPosition(int32_t shift_target) {
  154. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  155. if (motor == nullptr) {
  156. return;
  157. }
  158. if (ELCMotorHelper::isFlip(index_)) {
  159. shift_target = -shift_target;
  160. ZLOGI(TAG, "【MOTOR 【%d】SHIFT TARGET FLIP】", index_);
  161. }
  162. motor->moveBy(shift_target, abs(target_speed_));
  163. osMutexAcquire(mutex_, osWaitForever);
  164. target_pos_ = target_pos_ + shift_target;
  165. osMutexRelease(mutex_);
  166. }
  167. void ECLMotor::moveToWithSpeed(int32_t target, int32_t speed) {
  168. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  169. if (motor == nullptr) {
  170. return;
  171. }
  172. if (ELCMotorHelper::isFlip(index_)) {
  173. target = -target;
  174. ZLOGI(TAG, "【MOTOR 【%d】TARGET FLIP】", index_);
  175. }
  176. motor->moveTo(target, abs(speed));
  177. osMutexAcquire(mutex_, osWaitForever);
  178. target_pos_ = target;
  179. osMutexRelease(mutex_);
  180. }
  181. // 设置电机速度
  182. void ECLMotor::setSpeed(int32_t speed) {
  183. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  184. if (motor == nullptr) {
  185. return;
  186. }
  187. osMutexAcquire(mutex_, osWaitForever);
  188. this->target_speed_ = speed;
  189. // 当前正在移动
  190. if (!is_move_finished_) {
  191. motor->setVMax(this->target_speed_);
  192. }
  193. osMutexRelease(mutex_);
  194. }
  195. // 获取电机速度
  196. int32_t ECLMotor::getRTSpeed() {
  197. osMutexAcquire(mutex_, osWaitForever);
  198. const int32_t spd = rt_speed_;
  199. osMutexRelease(mutex_);
  200. return spd;
  201. }
  202. // 获取电机运动状态
  203. bool ECLMotor::isMoveFinished() {
  204. osMutexAcquire(mutex_, osWaitForever);
  205. bool is_move_finshed = is_move_finished_;
  206. osMutexRelease(mutex_);
  207. return is_move_finshed;
  208. }
  209. // 获取编码器位置
  210. int32_t ECLMotor::getEncoderPosition() {
  211. osMutexAcquire(mutex_, osWaitForever);
  212. int32_t encPos = enc_val_;
  213. osMutexRelease(mutex_);
  214. const int32_t py_pos = ELCMotorHelper::isFlip(index_) ? -encPos : encPos;
  215. return py_pos;
  216. }
  217. // 设置编码器位置
  218. void ECLMotor::setEncoderPosition(int32_t encoderPos) {
  219. osMutexAcquire(mutex_, osWaitForever);
  220. enc_val_ = encoderPos;
  221. osMutexRelease(mutex_);
  222. }
  223. void ECLMotor::setMotorIndex(int32_t index) {
  224. this->index_ = index;
  225. }
  226. bool ECLMotor::isHomeSuc() {
  227. osMutexAcquire(mutex_, osWaitForever);
  228. bool is_home_suc = is_home_suc_;
  229. osMutexRelease(mutex_);
  230. return is_home_suc;
  231. }
  232. void ECLMotor::runhomeSuc() {
  233. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  234. if (motor == nullptr) {
  235. return;
  236. }
  237. // 发送 CAN 信息
  238. motor->setEncVal(0);
  239. motor->setXACTUAL(0);
  240. // 置标志位
  241. osMutexAcquire(mutex_, osWaitForever);
  242. this->is_home_init_ = true;
  243. this->is_home_suc_ = true;
  244. this->home_state_ = STATE_INIT;
  245. isRunHomingTask = false;
  246. osMutexRelease(mutex_);
  247. ZLOGI(TAG, "【 MOVE TO HOME SUC 】");
  248. {
  249. #if CAN_MODULE_ENABLE
  250. CanMessage msg = CanProtocolFactory::createUploadEvent(seq_id_home_, Motor_Home_Finished, index_);
  251. AppHardware::ins()->can0Controller.sendMessage(msg);
  252. #endif
  253. }
  254. }
  255. void ECLMotor::startMoveHome() {
  256. osMutexAcquire(mutex_, osWaitForever);
  257. this->is_home_suc_ = false;
  258. isRunHomingTask = true;
  259. osMutexRelease(mutex_);
  260. const bool isAtOrigin = ELCMotorHelper::isAtOrigin(this->index_);
  261. // 当前是否在原点
  262. if (isAtOrigin) {
  263. osMutexAcquire(mutex_, osWaitForever);
  264. home_event_.event_type = EVENT_IN_ORIGIN;
  265. osMutexRelease(mutex_);
  266. ZLOGI(TAG, "[PUT] EVENT IN ORIGIN");
  267. osStatus_t status = osMessageQueuePut(homeEventQueue, &home_event_, 0U, 0U);
  268. if (status != osOK) {
  269. ZLOGE(TAG, "EVENT IN ORIGIN SEND FAIL, status: %d", status);
  270. }
  271. } else {
  272. osMutexAcquire(mutex_, osWaitForever);
  273. home_event_.event_type = EVENT_START_HOMING;
  274. osMutexRelease(mutex_);
  275. ZLOGI(TAG, "[PUT] EVENT_START_HOMING");
  276. osStatus_t status = osMessageQueuePut(homeEventQueue, &home_event_, 0U, 0U);
  277. if (status != osOK) {
  278. ZLOGE(TAG, "EVENT_START_HOMING SEND FAIL, status: %d", status);
  279. }
  280. }
  281. }
  282. void ECLMotor::setHomeSeqId(uint8_t seq_id) {
  283. this->seq_id_home_ = seq_id;
  284. }
  285. void ECLMotor::setMoveFinishSeqId(uint8_t seq_id) {
  286. this->seq_id_move_ = seq_id;
  287. }
  288. void ECLMotor::homingTask(void *arg) {
  289. ECLMotor *eclMotor = static_cast<ECLMotor *>(arg);
  290. HomeEvent home_event;
  291. while (true) {
  292. osStatus status = osMessageQueueGet(eclMotor->homeEventQueue, &home_event, NULL, osWaitForever);
  293. if(!eclMotor->isRunHomingTask) {
  294. continue;
  295. }
  296. if (status == osOK) {
  297. TMC51X0 *motor = AppHardware::ins()->getPump(eclMotor->index_);
  298. if (motor == nullptr) {
  299. return;
  300. }
  301. #if 1
  302. switch (home_event.event_type) {
  303. case EVENT_START_HOMING: {
  304. osMutexAcquire(eclMotor->mutex_, osWaitForever);
  305. eclMotor->home_state_ = STATE_BACK_TO_ORIGIN_MIDDLE;
  306. osMutexRelease(eclMotor->mutex_);
  307. // 中速倒转
  308. int speed = ELCMotorHelper::getRPerMinMiddleSpeed(eclMotor->index_);
  309. int absSpeed = abs(speed);
  310. eclMotor->ECL_Rotate(-absSpeed);
  311. ZLOGI(TAG, "【HOME】 BACK TO ORIGIN MIDDLE 中速回原点");
  312. break;
  313. }
  314. case EVENT_ORIGIN_ENTER: {
  315. // if first enter
  316. if(eclMotor->home_state_ == STATE_BACK_TO_ORIGIN_MIDDLE) {
  317. // 停止
  318. // 中速向前10mm
  319. osMutexAcquire(eclMotor->mutex_, osWaitForever);
  320. eclMotor->home_state_ = STATE_LEAVE_ORIGIN_MIDDLE;
  321. osMutexRelease(eclMotor->mutex_);
  322. // 位置清零
  323. motor->setEncVal(0);
  324. motor->setXACTUAL(0);
  325. const int32_t speed = ELCMotorHelper::getRPerMinMiddleSpeed(eclMotor->index_);
  326. eclMotor->moveToWithSpeed(ELCMotorHelper::getForwordMoveStep(eclMotor->index_), speed);
  327. // 4000 4 圈
  328. ZLOGI(TAG, "【HOME】 [EVENT_ORIGIN_ENTER] FORWARD TO ORIGIN MIDDLE 中速向前10mm");
  329. }
  330. // if second enter
  331. if (eclMotor->home_state_ == STATE_BACK_TO_ORIGIN_LOW) {
  332. // 位置清零
  333. // 电机停止
  334. // 回归原点成功
  335. eclMotor->runhomeSuc();
  336. ZLOGI(TAG, "【HOME】 [EVENT_ORIGIN_ENTER] HOME SUC 回原点成功");
  337. }
  338. break;
  339. }
  340. case EVENT_IN_ORIGIN: {
  341. ZLOGI(TAG, "[]EVENT IN ORIGIN 进入原点");
  342. // 中速向前10mm
  343. motor->setEncVal(0);
  344. motor->setXACTUAL(0);
  345. // 前向移动 1mm
  346. osMutexAcquire(eclMotor->mutex_, osWaitForever);
  347. eclMotor->home_state_ = STATE_LEAVE_ORIGIN_MIDDLE;
  348. osMutexRelease(eclMotor->mutex_);
  349. const int32_t speed = ELCMotorHelper::getRPerMinMiddleSpeed(eclMotor->index_);
  350. eclMotor->moveToWithSpeed(ELCMotorHelper::getForwordMoveStep(eclMotor->index_), speed);
  351. ZLOGI(TAG, "【HOME】 FORWARD TO ORIGIN MIDDLE 中速向前10mm");
  352. break;
  353. }
  354. case EVENT_MOTOR_MOVE_FINISHED: {
  355. ZLOGI(TAG, "[]EVENT MOTOR MOVE FINISHED 移动结束");
  356. osMutexAcquire(eclMotor->mutex_, osWaitForever);
  357. HomeState home_state =eclMotor->home_state_;
  358. bool is_move_finished = eclMotor->is_move_finished_;
  359. osMutexRelease(eclMotor->mutex_);
  360. if(!is_move_finished) {
  361. // 电机没有移动结束
  362. ZLOGI(TAG, "【HOME】 MOTOR NOT MOVE FINISHED 电机没有移动结束");
  363. break;
  364. }
  365. if (home_state == STATE_LEAVE_ORIGIN_MIDDLE) {
  366. // 低速回归
  367. osMutexAcquire(eclMotor->mutex_, osWaitForever);
  368. eclMotor->home_state_ = STATE_BACK_TO_ORIGIN_LOW;
  369. osMutexRelease(eclMotor->mutex_);
  370. const int speed = ELCMotorHelper::getRPerMinLowSpeed(eclMotor->index_);
  371. eclMotor->ECL_Rotate(-speed);
  372. ZLOGI(TAG, "【HOME】 BACK TO ORIGIN LOW 低速回原点");
  373. }
  374. break;
  375. }
  376. default:
  377. ZLOGI(TAG, "【HOME】 未处理事件类型 EVENT TYPE %d", home_event.event_type);
  378. break;
  379. }
  380. #endif
  381. } else {
  382. }
  383. }
  384. }
  385. void ECLMotor::moveToHome() {
  386. this->startMoveHome();
  387. }
  388. void ECLMotor::runZeroLimit(bool isEnter) {
  389. // 处理回home 位逻辑
  390. if (isRunHomingTask) {
  391. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  392. if (motor == nullptr) {
  393. return;
  394. }
  395. if (isEnter) {
  396. home_event_.event_type = EVENT_ORIGIN_ENTER;
  397. motor->stop();
  398. } else {
  399. home_event_.event_type = EVENT_ORIGIN_LEAVE;
  400. }
  401. osMessageQueuePut(homeEventQueue, &home_event_, 0U, 0U);
  402. return;
  403. }
  404. if (!isEnter) {
  405. return;
  406. }
  407. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  408. if (motor == nullptr) {
  409. return;
  410. }
  411. motor->stop();
  412. {
  413. #if CAN_MODULE_ENABLE
  414. CanMessage msg = CanProtocolFactory::createUploadEvent(seq_id_move_, Motor_Move_Finished, index_);
  415. AppHardware::ins()->can0Controller.sendMessage(msg);
  416. #endif
  417. }
  418. // 重置编码器 和 位置
  419. motor->setXACTUAL(0);
  420. motor->setEncVal(0);
  421. osMutexAcquire(mutex_, osWaitForever);
  422. this->x_actual_ = 0;
  423. this->enc_val_ = 0;
  424. this->target_pos_ = 0;
  425. osMutexRelease(mutex_);
  426. ZLOGI("ECL", "MOTOR [%d] runZeroLimit", this->index_);
  427. }
  428. void ECLMotor::runEndLimit(bool isEnter) {
  429. // 发送CAN 消息
  430. if (!isEnter) {
  431. return;
  432. }
  433. this->runStop();
  434. }
  435. void ECLMotor::runE_Stop() {
  436. // 发送CAN 消息
  437. this->runStop();
  438. }
  439. void ECLMotor::runPause() {
  440. // 发送CAN 消息
  441. this->runStop();
  442. }
  443. void ECLMotor::runStop() {
  444. osMutexAcquire(mutex_, osWaitForever);
  445. this->isRunHomingTask = false;
  446. osMutexRelease(mutex_);
  447. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  448. if (motor == nullptr) {
  449. return;
  450. }
  451. motor->stop();
  452. // 发送CAN 消息
  453. #if CAN_MODULE_ENABLE
  454. CanMessage msg = CanProtocolFactory::createUploadEvent(seq_id_home_, Motor_Move_Finished, index_);
  455. AppHardware::ins()->can0Controller.sendMessage(msg);
  456. #endif
  457. }
  458. void ECLMotor::ECL_Rotate(int32_t speed, const bool is_flip) {
  459. TMC51X0 *motor = AppHardware::ins()->getPump(index_);
  460. if (motor == nullptr) {
  461. return;
  462. }
  463. if (ELCMotorHelper::isFlip(index_) && is_flip) {
  464. speed = -speed;
  465. ZLOGI(TAG, "ECL MOTOR ECL REAL INDEX 【%d】 FLIP", index_);
  466. }
  467. motor->rotate(speed);
  468. ZLOGI(TAG, "ECL MOTOR %d SPEED %d", index_, speed);
  469. }