ethercat_csp.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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 <stdint.h>
  12. #include <stdlib.h>
  13. #include "ecat_master.h"
  14. #define CSP_TIMEOUTRXM 700000
  15. #pragma pack(push, 1)
  16. struct rpdo_csp
  17. {
  18. uint8_t mode_byte;
  19. uint16_t control_word;
  20. int32_t dest_pos;
  21. int32_t dest_speed;
  22. int16_t dest_torque;
  23. };
  24. struct tpdo_csp
  25. {
  26. uint16_t error_word;
  27. uint16_t status_word;
  28. int32_t cur_pos;
  29. int32_t cur_speed;
  30. int16_t curr_torque;
  31. };
  32. #pragma pack(pop)
  33. #define PDO_SIZE (sizeof(struct rpdo_csp) + sizeof(struct tpdo_csp))
  34. static uint8_t servo_run = 0;
  35. static uint8_t servo_dir = 1;
  36. static uint8_t process_data[4096];
  37. static ec_master_t csp_master = {
  38. .name = "csp-master",
  39. .nic0 = "e1",
  40. .main_cycletime_us = 1000, // 1ms
  41. .sub_cycletime_us = 5000, // 5ms
  42. .recovery_timeout_ms = 3000, // 3s
  43. .process_data = process_data,
  44. .process_data_size = 4096,
  45. .dc_active = 1,
  46. .dc_cycltime0 = 1000000,
  47. .dc_cyclshift = 500000,
  48. .dc_index = 1,
  49. .net_mode = EC_NET_MODE_EXCLUSIVE,
  50. .priority = 1,
  51. .pgain = 0.01f,
  52. .igain = 0.00002f,
  53. };
  54. static ec_pdo_entry_info_t slave1_output_pdo_entries[] = {
  55. { 0x6060, 0x00, 8 }, // 6060h(mode)
  56. { 0x6040, 0x00, 16 }, // 6040h(control)
  57. { 0x607A, 0x00, 32 }, // 607Ah(dest position)
  58. { 0x60FF, 0x00, 32 }, // 60FFh(dest speed)
  59. { 0x6071, 0x00, 16 }, // 6071h(dest torque)
  60. };
  61. static ec_pdo_entry_info_t slave1_input_pdo_entries[] = {
  62. { 0x603F, 0x00, 16 }, // 603Fh(error)
  63. { 0x6041, 0x00, 16 }, // 6041h(status)
  64. { 0x6064, 0x00, 32 }, // 6064h(current postion)
  65. { 0x606C, 0x00, 32 }, // 606Ch(current speed)
  66. { 0x6077, 0x00, 16 }, // 6077h(current torque)
  67. };
  68. ec_pdo_info_t slave_pdos[] = {
  69. { 0x1600, 5, slave1_output_pdo_entries },
  70. { 0x1a00, 5, slave1_input_pdo_entries },
  71. };
  72. ec_sync_info_t slave_syncs[] = {
  73. { 2, EC_DIR_OUTPUT, 1, &slave_pdos[0], EC_WD_DISABLE },
  74. { 3, EC_DIR_INPUT, 1, &slave_pdos[1], EC_WD_DISABLE },
  75. };
  76. static void servo_switch_op(struct rpdo_csp *rmap, struct tpdo_csp *tmap)
  77. {
  78. int sta;
  79. sta = tmap->status_word & 0x3ff;
  80. if (tmap->status_word & 0x8)
  81. {
  82. rmap->control_word = 0x80;
  83. return;
  84. }
  85. switch (sta)
  86. {
  87. case 0x250:
  88. case 0x270: rmap->control_word = 0x6; break;
  89. case 0x231: rmap->control_word = 0x7; break;
  90. case 0x233: rmap->control_word = 0xf; break;
  91. default: break;
  92. }
  93. }
  94. rt_inline struct rpdo_csp *servo_rpdo_get(ec_master_t *mater, int slave)
  95. {
  96. return (struct rpdo_csp *)(mater->process_data + PDO_SIZE * (slave));
  97. }
  98. rt_inline struct tpdo_csp *servo_tpdo_get(
  99. ec_master_t *mater, int slave)
  100. {
  101. return (struct tpdo_csp *)(mater->process_data + PDO_SIZE * slave +
  102. sizeof(struct rpdo_csp));
  103. }
  104. static int sv660n_csp_mode(const char *ifname)
  105. {
  106. int slave_counts;
  107. uint16_t state;
  108. rt_err_t err;
  109. ecat_service_init();
  110. if (ifname)
  111. {
  112. csp_master.nic0 = ifname;
  113. }
  114. err = ecat_master_init(&csp_master);
  115. if (err)
  116. {
  117. rt_kprintf("ethercat master init failed, err:%d\n", err);
  118. return err;
  119. }
  120. slave_counts = ecat_slavecount(&csp_master);
  121. rt_kprintf("Found slaves count:%d\n", slave_counts);
  122. static ec_slave_config_t slave_cia402_config;
  123. slave_cia402_config.dc_assign_activate = 0x300;
  124. slave_cia402_config.dc_sync[0].cycle_time = csp_master.main_cycletime_us * 1000;
  125. slave_cia402_config.dc_sync[0].shift_time = 500000;
  126. slave_cia402_config.dc_sync[1].cycle_time = 0;
  127. slave_cia402_config.dc_sync[1].shift_time = 0;
  128. slave_cia402_config.sync = slave_syncs;
  129. slave_cia402_config.sync_count = sizeof(slave_syncs) / sizeof(ec_sync_info_t);
  130. for(int i = 0; i < slave_counts; i++)
  131. {
  132. ecat_slave_config(&csp_master, i, &slave_cia402_config);
  133. }
  134. ecat_master_start(&csp_master);
  135. state = EC_STATE_OPERATIONAL;
  136. err = ecat_check_state(&csp_master, slave_counts - 1, &state, 20000000 * 3);
  137. if (err != RT_EOK)
  138. {
  139. rt_kprintf("Not all slaves reached operational mode.\n");
  140. return err;
  141. }
  142. rt_kprintf("Motor CSP mode control started...\n");
  143. struct rpdo_csp* rmap;
  144. struct tpdo_csp *tmap;
  145. while (1)
  146. {
  147. if (servo_run == 0)
  148. {
  149. for (size_t slave = 0; slave < slave_counts; slave++)
  150. {
  151. rmap = servo_rpdo_get(&csp_master, slave);
  152. tmap = servo_tpdo_get(&csp_master, slave);
  153. servo_switch_op(rmap, tmap);
  154. rmap->control_word = 0x2;
  155. }
  156. goto stop;
  157. }
  158. for (size_t slave = 0; slave < slave_counts; slave++)
  159. {
  160. rmap = servo_rpdo_get(&csp_master, slave);
  161. tmap = servo_tpdo_get(&csp_master, slave);
  162. servo_switch_op(rmap, tmap);
  163. if (rmap->control_word == 7)
  164. {
  165. rmap->mode_byte = 0x8;
  166. rmap->dest_pos = tmap->cur_pos;
  167. }
  168. if (rmap->control_word == 0xf)
  169. {
  170. rmap->dest_pos = tmap->cur_pos;
  171. if (servo_dir == 0)
  172. {
  173. rmap->dest_pos -= 1000;
  174. }
  175. else
  176. {
  177. rmap->dest_pos += 1000;
  178. }
  179. }
  180. }
  181. stop:
  182. rt_thread_mdelay(5);
  183. }
  184. return 0;
  185. }
  186. static void ethercat_entry(void *pram)
  187. {
  188. sv660n_csp_mode("e1");
  189. }
  190. static void ect_csp(void)
  191. {
  192. rt_thread_t tid = RT_NULL;
  193. tid = rt_thread_create("Ethercat", ethercat_entry, RT_NULL, 20480, 15, 10);
  194. if (tid != RT_NULL)
  195. {
  196. rt_thread_control(tid, RT_THREAD_CTRL_BIND_CPU, (void *)2);
  197. rt_thread_startup(tid);
  198. }
  199. else
  200. {
  201. rt_kprintf("create ethercat thread fail.\n");
  202. }
  203. return;
  204. }
  205. MSH_CMD_EXPORT(ect_csp, ect_csp);
  206. static int motor_run(void)
  207. {
  208. servo_run = 1;
  209. return 0;
  210. }
  211. MSH_CMD_EXPORT(motor_run, motor run);
  212. static int motor_stop(void)
  213. {
  214. servo_run = 0;
  215. return 0;
  216. }
  217. MSH_CMD_EXPORT(motor_stop, motor stop);
  218. void motor_dir(int argc, char *argv[])
  219. {
  220. if (argc == 2)
  221. {
  222. if (atoi(argv[1]) == 0)
  223. {
  224. servo_dir = 0;
  225. }
  226. else
  227. {
  228. servo_dir = 1;
  229. }
  230. }
  231. }
  232. MSH_CMD_EXPORT(motor_dir, motor dir);