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.

438 lines
15 KiB

12 months ago
12 months ago
12 months ago
  1. #include "tmc51x0.hpp"
  2. #include "reg/TMC5130_Constants.h"
  3. #include "reg/TMC5130_Fields.h"
  4. #include "reg/TMC5130_Register.h"
  5. //
  6. #include "stm32basic/mutex.hpp"
  7. #include "stm32basic/zspi.hpp"
  8. using namespace iflytop;
  9. #if 0
  10. // Register access permissions:
  11. // 0x00: none (reserved)
  12. // 0x01: read
  13. // 0x02: write
  14. // 0x03: read/write
  15. // 0x13: read/write, separate functions/values for reading or writing
  16. // 0x21: read, flag register (read to clear)
  17. // 0x42: write, has hardware presets on reset
  18. static const uint8_t tmc5130_defaultRegisterAccess[TMC5130_REGISTER_COUNT] = {
  19. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  20. 0x03, 0x21, 0x01, 0x02, 0x13, 0x02, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x00 - 0x0F
  21. 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x10 - 0x1F
  22. 0x03, 0x03, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, ____, 0x02, 0x02, 0x02, 0x03, ____, ____, // 0x20 - 0x2F
  23. ____, ____, ____, 0x02, 0x03, 0x21, 0x01, ____, 0x03, 0x03, 0x02, 0x21, 0x01, ____, ____, ____, // 0x30 - 0x3F
  24. ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x40 - 0x4F
  25. ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x50 - 0x5F
  26. 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, // 0x60 - 0x6F
  27. 0x42, 0x01, 0x02, 0x01, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____ // 0x70 - 0x7F
  28. };
  29. #endif
  30. /***********************************************************************************************************************
  31. * *
  32. ***********************************************************************************************************************/
  33. #define FIELD_SET(data, mask, shift, value) (data = (((data) & (~(mask))) | (((value) << (shift)) & (mask))))
  34. #define FIELD_GET(data, mask, shift) (((data) & (mask)) >> (shift))
  35. #define BYTE(value, n) (((value) >> ((n) << 3)) & 0xFF)
  36. #define NIBBLE(value, n) (((value) >> ((n) << 2)) & 0x0F)
  37. #define SHORT(value, n) (((value) >> ((n) << 4)) & 0xFFFF)
  38. #define WORD(value, n) (((value) >> ((n) << 5)) & 0xFFFFFFFF)
  39. #define TMC51x0_ADDRESS(x) ((x) & (TMC5130_ADDRESS_MASK))
  40. #define TAG "TMC51X0"
  41. void TMC51X0::initialize(TMC51X0Cfg cfg) {
  42. m_cfg = cfg;
  43. m_hspi = cfg.hspi;
  44. ZLOGI(TAG, "SPI:%p CSPin:%s,enPIn:%s", cfg.hspi, pinname(cfg.csnpin), pinname(cfg.ennpin));
  45. m_mutex.init();
  46. m_csnpin.initAsOutput(m_cfg.csnpin, kxs_gpio_nopull, false, true);
  47. m_ennpin.initAsOutput(m_cfg.ennpin, kxs_gpio_nopull, false, true);
  48. enable(false);
  49. stop();
  50. writeInt(TMC5130_PWMCONF, 0x000500C8);
  51. writeInt(TMC5130_CHOPCONF, 0x000100c3);
  52. writeInt(TMC5130_IHOLD_IRUN, 0x00051A00);
  53. writeInt(TMC5130_PWMCONF, 0x000401c8);
  54. writeInt(TMC5130_XTARGET, 0);
  55. writeInt(TMC5130_XACTUAL, 0x00000000);
  56. writeInt(TMC5130_VACTUAL, 0x00000000);
  57. writeInt(TMC5130_TZEROWAIT, 0);
  58. setVstart(100);
  59. setA1(30);
  60. setAmax(50);
  61. setV1(500);
  62. setDmax(50);
  63. setD1(30);
  64. setVstop(100);
  65. setTzerowait(100);
  66. setIHOLD_IRUN(0, 30, 100);
  67. enable(false);
  68. }
  69. /*******************************************************************************
  70. * *
  71. *******************************************************************************/
  72. void TMC51X0::readWriteArray(uint8_t *data, size_t length) {
  73. portENTER_CRITICAL();
  74. m_csnpin.write(false);
  75. HAL_SPI_TransmitReceive(m_hspi, data, data, length, 100);
  76. m_csnpin.write(true);
  77. portEXIT_CRITICAL();
  78. }
  79. void TMC51X0::writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) {
  80. uint8_t data[5] = {static_cast<uint8_t>(address | static_cast<uint8_t>(TMC5130_WRITE_BIT)), x1, x2, x3, x4};
  81. readWriteArray(&data[0], 5);
  82. }
  83. void TMC51X0::writeInt(uint8_t address, int32_t value) { //
  84. writeDatagram(address, BYTE(value, 3), BYTE(value, 2), BYTE(value, 1), BYTE(value, 0));
  85. }
  86. void TMC51X0::writeField(uint8_t add, uint32_t mask, uint32_t shift, uint32_t value) {
  87. uint32_t regval = readUInt(add);
  88. regval = (regval & ~mask) | ((value << shift) & mask);
  89. writeInt(add, regval);
  90. }
  91. int32_t TMC51X0::readInt(uint8_t address) {
  92. /**
  93. * @WARNING:
  94. *
  95. */
  96. address = TMC51x0_ADDRESS(address);
  97. uint8_t data[5] = {0, 0, 0, 0, 0};
  98. data[0] = address;
  99. readWriteArray(&data[0], 5);
  100. data[0] = address;
  101. readWriteArray(&data[0], 5);
  102. return ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4];
  103. }
  104. uint32_t TMC51X0::readUInt(uint8_t address) {
  105. int32_t val = readInt(address);
  106. uint32_t ret;
  107. memcpy(&ret, &val, sizeof(uint32_t));
  108. return ret;
  109. }
  110. /***********************************************************************************************************************
  111. * BASIC *
  112. ***********************************************************************************************************************/
  113. bool TMC51X0::ping() {
  114. zlock_guard lkg(m_mutex);
  115. uint32_t regval = readUInt(TMC5130_IOIN);
  116. uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT);
  117. return chipId != 0;
  118. }
  119. void TMC51X0::enable(bool enable) {
  120. zlock_guard lkg(m_mutex);
  121. m_ennpin.write(!enable);
  122. }
  123. int32_t TMC51X0::to_motor_acc(int32_t acc) { //
  124. int32_t val = acc / 60.0 * m_onecirclepulse; // 65535
  125. if (val > 65535) val = 65535;
  126. return val;
  127. }
  128. int32_t TMC51X0::to_motor_vel(int32_t vel) { //
  129. int32_t val = vel / 60.0 * m_onecirclepulse;
  130. if (val > 8388095 /*2^23-512*/) {
  131. val = 8388095;
  132. }
  133. return val;
  134. } // rpm
  135. int32_t TMC51X0::to_motor_pos(int32_t pos) { //
  136. int32_t val = pos * 1.0 / m_scale * m_scale_deceleration * m_onecirclepulse + 0.5;
  137. return val;
  138. } //
  139. int32_t TMC51X0::to_user_pos(int32_t pos) { //
  140. int32_t val = pos / m_onecirclepulse * m_scale / m_scale_deceleration + 0.5;
  141. // ZLOGI("TMC5130", "to_user_pos %d,%d", pos, val);
  142. return val;
  143. } //
  144. int32_t TMC51X0::to_user_vel(int32_t vel) { //
  145. int32_t val = vel * 60.0 / m_onecirclepulse;
  146. return val;
  147. }
  148. /***********************************************************************************************************************
  149. * CTRL *
  150. ***********************************************************************************************************************/
  151. void TMC51X0::stop() {
  152. zlock_guard lkg(m_mutex);
  153. rotate(0);
  154. }
  155. void TMC51X0::rotate(int32_t velocity) {
  156. zlock_guard lkg(m_mutex);
  157. velocity = to_motor_vel(velocity);
  158. writeInt(TMC5130_VMAX, abs(velocity));
  159. writeInt(TMC5130_RAMPMODE, (velocity >= 0) ? TMC5130_MODE_VELPOS : TMC5130_MODE_VELNEG);
  160. }
  161. void TMC51X0::moveTo(int32_t position, uint32_t velocityMax) {
  162. zlock_guard lkg(m_mutex);
  163. position = to_motor_pos(position);
  164. velocityMax = to_motor_vel(velocityMax);
  165. writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  166. writeInt(TMC5130_VMAX, velocityMax);
  167. writeInt(TMC5130_XTARGET, position);
  168. }
  169. void TMC51X0::moveToEnd(int32_t direction, uint32_t velocityMax) {
  170. zlock_guard lkg(m_mutex);
  171. if (direction >= 0) {
  172. writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  173. writeInt(TMC5130_VMAX, to_motor_vel(velocityMax));
  174. writeInt(TMC5130_XTARGET, INT32_MAX / 1.5 - 1000);
  175. } else {
  176. writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  177. writeInt(TMC5130_VMAX, to_motor_vel(velocityMax));
  178. writeInt(TMC5130_XTARGET, INT32_MIN / 1.5 + 1000);
  179. }
  180. }
  181. void TMC51X0::moveBy(int32_t relativePosition, uint32_t velocityMax) { // determine actual position and add numbers of ticks to move
  182. zlock_guard lkg(m_mutex);
  183. int32_t pos = getXACTUAL();
  184. int32_t target = pos + relativePosition;
  185. moveTo(target, velocityMax);
  186. }
  187. /***********************************************************************************************************************
  188. * GET STATE *
  189. ***********************************************************************************************************************/
  190. int32_t TMC51X0::getXACTUAL() {
  191. zlock_guard lkg(m_mutex);
  192. return to_user_pos(readInt(TMC5130_XACTUAL));
  193. }
  194. int32_t TMC51X0::getVACTUAL() {
  195. zlock_guard lkg(m_mutex);
  196. return to_user_pos(readInt(TMC5130_VACTUAL));
  197. }
  198. int32_t TMC51X0::getEncVal() {
  199. zlock_guard lkg(m_mutex);
  200. int32_t enc_val = to_user_pos(readInt(TMC5130_XENC));
  201. if (m_enc_resolution < 0) {
  202. enc_val = -enc_val;
  203. }
  204. return enc_val;
  205. }
  206. TMC5130RampStat TMC51X0::getRampStat() {
  207. zlock_guard lkg(m_mutex);
  208. int32_t val = readInt(TMC5130_RAMPSTAT);
  209. return TMC5130RampStat(val);
  210. }
  211. bool TMC51X0::isReachTarget(TMC5130RampStat *state) {
  212. zlock_guard lkg(m_mutex);
  213. int mode = readInt(TMC5130_RAMPMODE);
  214. if (mode == TMC5130_MODE_POSITION) {
  215. return state->isSetted(TMC5130RampStat::ktmc5130_rs_posreached);
  216. } else {
  217. return state->isSetted(TMC5130RampStat::ktmc5130_rs_vzero) && state->isSetted(TMC5130RampStat::ktmc5130_rs_velreached);
  218. }
  219. }
  220. bool TMC51X0::isTMC5130() {
  221. zlock_guard lkg(m_mutex);
  222. uint32_t regval = readUInt(TMC5130_IOIN);
  223. uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT);
  224. return chipId == kTMC5130;
  225. }
  226. TMC5130DevStatusReg_t TMC51X0::getDevStatus() { // R 读后不清
  227. zlock_guard lkg(m_mutex);
  228. static_assert(sizeof(TMC5130DevStatusReg_t) == 4);
  229. uint32_t value = readInt(TMC5130_DRVSTATUS);
  230. TMC5130DevStatusReg_t val;
  231. memcpy(&val, &value, sizeof(TMC5130DevStatusReg_t));
  232. return val;
  233. }
  234. TMC5130GState_t TMC51X0::getGState() { // R+C 读后自动清除
  235. zlock_guard lkg(m_mutex);
  236. static_assert(sizeof(TMC5130GState_t) == 4);
  237. uint32_t value = readInt(TMC5130_GSTAT);
  238. TMC5130GState_t val;
  239. memcpy(&val, &value, sizeof(TMC5130GState_t));
  240. return val;
  241. }
  242. int32_t TMC51X0::readICVersion() {
  243. zlock_guard lkg(m_mutex);
  244. uint32_t regval = readUInt(TMC5130_IOIN);
  245. uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT);
  246. return chipId;
  247. }
  248. /***********************************************************************************************************************
  249. * set state *
  250. ***********************************************************************************************************************/
  251. void TMC51X0::setXACTUAL(int32_t value) {
  252. zlock_guard lkg(m_mutex);
  253. writeInt(TMC5130_XACTUAL, to_motor_pos(value));
  254. }
  255. void TMC51X0::setMotorShaft(bool reverse) {
  256. zlock_guard lkg(m_mutex);
  257. uint32_t regval = readUInt(TMC5130_GCONF);
  258. FIELD_SET(regval, TMC5130_SHAFT_MASK, TMC5130_SHAFT_SHIFT, reverse ? 1 : 0);
  259. writeInt(TMC5130_GCONF, regval);
  260. // uint32_t readbak = readUInt(TMC5130_GCONF);
  261. // ZLOGI(TAG, "%x,%x", regval, readbak);
  262. }
  263. void TMC51X0::setIHOLD_IRUN(uint8_t ihold, uint8_t irun, uint16_t iholddelay) {
  264. zlock_guard lkg(m_mutex);
  265. writeInt(TMC5130_IHOLD_IRUN, (iholddelay << TMC5130_IHOLDDELAY_SHIFT) | (irun << TMC5130_IRUN_SHIFT) | (ihold << TMC5130_IHOLD_SHIFT));
  266. }
  267. void TMC51X0::setGlobalScale(uint8_t globalscale) {
  268. #define TMC5160_GLOBAL_SCALER 0x0B
  269. #define TMC5160_GLOBAL_SCALER_MASK 0xFF
  270. #define TMC5160_GLOBAL_SCALER_SHIFT 0
  271. zlock_guard lkg(m_mutex);
  272. if (isTMC5130()) {
  273. return;
  274. }
  275. if (globalscale == 0) {
  276. globalscale = 0;
  277. } else if (globalscale <= 31 && globalscale >= 1) {
  278. globalscale = 32;
  279. } else {
  280. globalscale = globalscale;
  281. }
  282. writeInt(TMC5160_GLOBAL_SCALER, (readInt(TMC5160_GLOBAL_SCALER) & ~TMC5160_GLOBAL_SCALER_MASK) | (globalscale << TMC5160_GLOBAL_SCALER_SHIFT));
  283. }
  284. void TMC51X0::setScale(int32_t scale) {
  285. zlock_guard lkg(m_mutex);
  286. m_scale = scale;
  287. }
  288. void TMC51X0::setScaleDenominator(int32_t scale) {
  289. zlock_guard lkg(m_mutex);
  290. m_scale_deceleration = scale;
  291. }
  292. void TMC51X0::setVstart(int32_t val) {
  293. zlock_guard lkg(m_mutex);
  294. writeInt(TMC5130_VSTART, to_motor_vel(val));
  295. }
  296. void TMC51X0::setA1(int32_t val) {
  297. zlock_guard lkg(m_mutex);
  298. writeInt(TMC5130_A1, to_motor_acc(val));
  299. }
  300. void TMC51X0::setAmax(int32_t val) {
  301. zlock_guard lkg(m_mutex);
  302. writeInt(TMC5130_AMAX, to_motor_acc(val));
  303. }
  304. void TMC51X0::setV1(int32_t val) {
  305. zlock_guard lkg(m_mutex);
  306. writeInt(TMC5130_V1, to_motor_vel(val));
  307. }
  308. void TMC51X0::setDmax(int32_t val) {
  309. zlock_guard lkg(m_mutex);
  310. writeInt(TMC5130_DMAX, to_motor_acc(val));
  311. }
  312. void TMC51X0::setD1(int32_t val) {
  313. zlock_guard lkg(m_mutex);
  314. writeInt(TMC5130_D1, to_motor_acc(val));
  315. }
  316. void TMC51X0::setVstop(int32_t val) {
  317. zlock_guard lkg(m_mutex);
  318. writeInt(TMC5130_VSTOP, to_motor_vel(val));
  319. }
  320. void TMC51X0::setTzerowait(int32_t val) {
  321. zlock_guard lkg(m_mutex);
  322. writeInt(TMC5130_TZEROWAIT, val);
  323. }
  324. bool TMC51X0::setEncResolution(int32_t enc_resolution) {
  325. zlock_guard lkg(m_mutex);
  326. /**
  327. * @brief
  328. *
  329. * 1.256
  330. * 2.TMC5130_ENC_CONST是十进制模式
  331. * 3.
  332. */
  333. int32_t enc_resolution_tmp = enc_resolution * 4;
  334. int16_t enc_const_integral = 0;
  335. int16_t enc_const_fractional = 0;
  336. switch (abs(enc_resolution_tmp)) {
  337. case 1000:
  338. enc_const_integral = 51;
  339. enc_const_fractional = 0.2 * 10000;
  340. break;
  341. case 1024:
  342. enc_const_integral = 50;
  343. enc_const_fractional = 0 * 10000;
  344. break;
  345. case 4000:
  346. enc_const_integral = 12;
  347. enc_const_fractional = 0.8 * 10000;
  348. break;
  349. case 4096:
  350. enc_const_integral = 12;
  351. enc_const_fractional = 0.5 * 10000;
  352. break;
  353. case 16384:
  354. enc_const_integral = 3;
  355. enc_const_fractional = 0.125 * 10000;
  356. break;
  357. case 0:
  358. m_enc_resolution = 0;
  359. return true;
  360. default:
  361. return false;
  362. break;
  363. }
  364. m_enc_resolution = enc_resolution;
  365. uint32_t setval = 0;
  366. uint8_t *psetval = (uint8_t *)&setval;
  367. memcpy(psetval + 2, &enc_const_integral, 2);
  368. memcpy(psetval, &enc_const_fractional, 2);
  369. writeInt(TMC5130_ENCMODE, 0x1 << 10);
  370. writeInt(TMC5130_ENC_CONST, setval);
  371. return true;
  372. }
  373. void TMC51X0::setEncVal(int32_t enc_val) {
  374. zlock_guard lkg(m_mutex);
  375. int32_t enc_set_val = to_motor_pos(enc_val);
  376. if (m_enc_resolution < 0) {
  377. enc_set_val = -enc_set_val;
  378. }
  379. writeInt(TMC5130_XENC, enc_set_val);
  380. }
  381. /***********************************************************************************************************************
  382. * reg operation *
  383. ***********************************************************************************************************************/
  384. void TMC51X0::writeIntExt(uint8_t address, int32_t value) {
  385. zlock_guard lkg(m_mutex);
  386. writeInt(address, value);
  387. }
  388. int32_t TMC51X0::readIntExt(uint8_t address) {
  389. zlock_guard lkg(m_mutex);
  390. return readInt(address);
  391. }