基质喷涂
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.

497 lines
17 KiB

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