ethercat_cst.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /**
  2. * RT-Thread RuiChing
  3. *
  4. * COPYRIGHT (C) 2024-2025 Shanghai Real-Thread Electronic Technology Co., Ltd.
  5. * All rights reserved.
  6. *
  7. * The license and distribution terms for this file may be
  8. * found in the file LICENSE in this distribution.
  9. */
  10. #include <rtthread.h>
  11. #include "ecat_master.h"
  12. #include <stdlib.h>
  13. #define CST_TIMEOUTRXM 700000
  14. #pragma pack(push, 1)
  15. struct rpdo_cst
  16. {
  17. uint16_t control_word; // 0x6040 控制字
  18. int16_t target_torque; // 0x6071 目标转矩
  19. int16_t torque_offset; // 0x60B2 转矩偏置
  20. int8_t mode_of_operation; // 0x6060 模式选择 (CST=10)
  21. uint16_t max_torque; // 0x6072 最大允许转矩 (百分比/额定)
  22. uint32_t max_motor_speed; // 0x607F 最大转速 (rpm)
  23. uint32_t torque_limit_pos; // 0x60E0 正向转矩限制
  24. uint32_t torque_limit_neg; // 0x60E1 反向转矩限制
  25. };
  26. struct tpdo_cst
  27. {
  28. uint16_t status_word; // 0x6041 状态字
  29. int32_t actual_position; // 0x6064 实际位置
  30. int32_t actual_velocity; // 0x606C 实际速度
  31. int16_t actual_torque; // 0x6077 实际转矩
  32. int8_t mode_display; // 0x6061 运行模式显示
  33. };
  34. #pragma pack(pop)
  35. #define PDO_SIZE (sizeof(struct rpdo_cst) + sizeof(struct tpdo_cst))
  36. static uint8_t servo_run = 0;
  37. static uint8_t servo_dir = 0;
  38. static uint8_t process_data[4096];
  39. static ec_master_t cst_master = {
  40. .name = "cst-master",
  41. .nic0 = "e1",
  42. .main_cycletime_us = 1000, // 1ms
  43. .sub_cycletime_us = 5000, // 5ms
  44. .recovery_timeout_ms = 3000, // 3s
  45. .process_data = process_data,
  46. .process_data_size = 4096,
  47. .dc_active = 1,
  48. .dc_cycltime0 = 1000000,
  49. .dc_cyclshift = 500000,
  50. .dc_index = 1,
  51. .net_mode = EC_NET_MODE_EXCLUSIVE,
  52. .priority = 1,
  53. .pgain = 0.01f,
  54. .igain = 0.00002f,
  55. };
  56. static ec_pdo_entry_info_t slave1_rxpdo_entries[] = {
  57. { 0x6040, 0x00, 16 },
  58. { 0x6071, 0x00, 16 },
  59. { 0x60B2, 0x00, 16 },
  60. { 0x6060, 0x00, 8 },
  61. { 0x6072, 0x00, 16 },
  62. { 0x607F, 0x00, 32 },
  63. { 0x60E0, 0x00, 32 },
  64. { 0x60E1, 0x00, 32 },
  65. };
  66. static ec_pdo_entry_info_t slave1_txpdo_entries[] = {
  67. { 0x6041, 0x00, 16 },
  68. { 0x6064, 0x00, 32 },
  69. { 0x606C, 0x00, 32 },
  70. { 0x6077, 0x00, 16 },
  71. { 0x6061, 0x00, 8 },
  72. };
  73. ec_pdo_info_t slave_pdos[] = {
  74. { 0x1600, 8, slave1_rxpdo_entries },
  75. { 0x1a00, 5, slave1_txpdo_entries },
  76. };
  77. ec_sync_info_t cia402_syncs[] =
  78. {
  79. { 2, EC_DIR_OUTPUT, 1, &slave_pdos[0], EC_WD_DISABLE },
  80. { 3, EC_DIR_INPUT, 1, &slave_pdos[1], EC_WD_DISABLE },
  81. };
  82. static void servo_switch_op(struct rpdo_cst *rmap, struct tpdo_cst *tmap)
  83. {
  84. int sta;
  85. sta = tmap->status_word & 0x3ff;
  86. if (tmap->status_word & 0x8)
  87. {
  88. rmap->control_word = 0x80;
  89. return;
  90. }
  91. switch (sta)
  92. {
  93. case 0x250:
  94. case 0x270: rmap->control_word = 0x6; break;
  95. case 0x231: rmap->control_word = 0x7; break;
  96. case 0x233: rmap->control_word = 0xf; break;
  97. default: break;
  98. }
  99. }
  100. rt_inline struct rpdo_cst *servo_rpdo_get(ec_master_t *mater, int slave)
  101. {
  102. return (struct rpdo_cst *)(mater->process_data + PDO_SIZE * (slave));
  103. }
  104. rt_inline struct tpdo_cst *servo_tpdo_get(
  105. ec_master_t *mater, int slave)
  106. {
  107. return (struct tpdo_cst *)(mater->process_data + PDO_SIZE * slave +
  108. sizeof(struct rpdo_cst));
  109. }
  110. static int sv660n_cst_mode(const char *ifname)
  111. {
  112. int slave_counts;
  113. uint16_t state;
  114. rt_err_t err;
  115. ecat_service_init();
  116. if (ifname)
  117. {
  118. cst_master.nic0 = ifname;
  119. }
  120. err = ecat_master_init(&cst_master);
  121. if (err)
  122. {
  123. rt_kprintf("ethercat master init failed, err:%d\n", err);
  124. return err;
  125. }
  126. slave_counts = ecat_slavecount(&cst_master);
  127. rt_kprintf("Found slaves count:%d\n", slave_counts);
  128. static ec_slave_config_t slave_cia402_config;
  129. slave_cia402_config.dc_assign_activate = 0x300;
  130. slave_cia402_config.dc_sync[0].cycle_time = cst_master.main_cycletime_us * 1000;
  131. slave_cia402_config.dc_sync[0].shift_time = 500000;
  132. slave_cia402_config.dc_sync[1].cycle_time = 0;
  133. slave_cia402_config.dc_sync[1].shift_time = 0;
  134. slave_cia402_config.sync = cia402_syncs;
  135. slave_cia402_config.sync_count = sizeof(cia402_syncs) / sizeof(ec_sync_info_t);
  136. for(int i=0;i<slave_counts;i++)
  137. {
  138. ecat_slave_config(&cst_master, i, &slave_cia402_config);
  139. }
  140. ecat_master_start(&cst_master);
  141. state = EC_STATE_OPERATIONAL;
  142. err = ecat_check_state(&cst_master, slave_counts - 1, &state, 20000000 * 3);
  143. if (err != RT_EOK)
  144. {
  145. rt_kprintf("Not all slaves reached operational mode.\n");
  146. return err;
  147. }
  148. rt_kprintf("Motor CST mode control started...\n");
  149. struct rpdo_cst *rmap;
  150. struct tpdo_cst *tmap;
  151. while (1)
  152. {
  153. if (servo_run == 0)
  154. {
  155. for (size_t slave = 0; slave < slave_counts; slave++)
  156. {
  157. rmap = servo_rpdo_get(&cst_master, slave);
  158. tmap = servo_tpdo_get(&cst_master, slave);
  159. servo_switch_op(rmap, tmap);
  160. rmap->control_word = 0x2;
  161. }
  162. goto stop;
  163. }
  164. for (size_t slave = 0; slave < slave_counts; slave++)
  165. {
  166. rmap = servo_rpdo_get(&cst_master, slave);
  167. tmap = servo_tpdo_get(&cst_master, slave);
  168. if (rmap->control_word == 7)
  169. {
  170. rmap->mode_of_operation = 0xA;
  171. }
  172. if (rmap->control_word == 0xf)
  173. {
  174. rmap->torque_limit_pos = -3500;
  175. rmap->torque_limit_neg = 3500;
  176. rmap->max_motor_speed = (1 << 17);
  177. rmap->max_torque = 3500;
  178. if (servo_dir == 0)
  179. {
  180. rmap->target_torque = 200;
  181. }
  182. else
  183. {
  184. rmap->target_torque = -200;
  185. }
  186. }
  187. servo_switch_op(rmap, tmap);
  188. }
  189. stop:
  190. rt_thread_mdelay(5);
  191. }
  192. return 0;
  193. }
  194. static void ethercat_entry(void *pram)
  195. {
  196. sv660n_cst_mode("e1");
  197. }
  198. static void ect_cst(void)
  199. {
  200. rt_thread_t tid = RT_NULL;
  201. tid = rt_thread_create("Ethercat", ethercat_entry, RT_NULL, 20480, 15, 10);
  202. if (tid != RT_NULL)
  203. {
  204. rt_thread_control(tid, RT_THREAD_CTRL_BIND_CPU, (void *)2);
  205. rt_thread_startup(tid);
  206. }
  207. else
  208. {
  209. rt_kprintf("create ethercat thread fail.\n");
  210. }
  211. return;
  212. }
  213. MSH_CMD_EXPORT(ect_cst, ect_cst);
  214. static int motor_run(void)
  215. {
  216. servo_run = 1;
  217. return 0;
  218. }
  219. MSH_CMD_EXPORT(motor_run, motor run);
  220. static int motor_stop(void)
  221. {
  222. servo_run = 0;
  223. return 0;
  224. }
  225. MSH_CMD_EXPORT(motor_stop, motor stop);
  226. void motor_dir(int argc, char *argv[])
  227. {
  228. if (argc == 2)
  229. {
  230. if (atoi(argv[1]) == 0)
  231. {
  232. servo_dir = 0;
  233. }
  234. else
  235. {
  236. servo_dir = 1;
  237. }
  238. }
  239. }
  240. MSH_CMD_EXPORT(motor_dir, motor dir);