MOTOR_STEP_C_ATY.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /**
  2. * @file MOTOR_STEP_C_ATY.c
  3. *
  4. * @param Project DEVICE_GENERAL_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2026 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief functions of closed loop stepper motor control for C platform
  20. *
  21. * @note Slave Mode: Disable
  22. * Trigger Source: Disable
  23. * Clock Source: Internal Clock
  24. * Channel2: PWM Generation CH2
  25. * Prescaler: 71
  26. * Counter Mode: Up
  27. * Counter Period: 999
  28. * Internal Clock Division: No Division
  29. * auto-reload preload: Disable
  30. * Master/Slave Mode (MSM bit): Disable
  31. * Trigger Event Selection: Update Event
  32. * PWM Generation Channel 2 Mode: PWM mode 2
  33. * Pulse: 499
  34. * Output compare preload: Enable
  35. * Fast Mode: Disable
  36. * CH Polarity: High
  37. * CH Idle State: Reset
  38. *
  39. * htim1.Init.Prescaler = 71;
  40. * htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  41. * htim1.Init.Period = 999;
  42. * htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  43. * htim1.Init.RepetitionCounter = 0;
  44. * htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  45. * sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  46. * sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  47. * sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  48. * sConfigOC.OCMode = TIM_OCMODE_PWM2;
  49. * sConfigOC.Pulse = 499;
  50. * sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  51. * sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  52. * sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  53. * sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  54. * sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  55. * htim2.Init.Prescaler = 0;
  56. * htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  57. * htim2.Init.Period = 65535;
  58. * htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  59. * htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  60. * sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  61. * sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  62. * sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  63. * sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  64. *
  65. * import angle to use COMPENSATE
  66. *
  67. * @version
  68. * - 1_00_260109 > ATY
  69. * -# Preliminary version
  70. ********************************************************************************
  71. */
  72. #ifndef __MOTOR_STEP_C_ATY_C
  73. #define __MOTOR_STEP_C_ATY_C
  74. #include "MOTOR_STEP_C_ATY.h"
  75. #define MOTOR_STEP_C_ATY_TAG "\r\n[MOTOR_STEP_C_ATY] "
  76. /******************************* For user *************************************/
  77. /******************************************************************************/
  78. uint8_t MSC_MoveToAngleSteps(struct MOTOR_STEP_C_ATY_Dev* dev,
  79. float targetAngle, float currentAngle){
  80. uint8_t dir = __ATY_PN_P;
  81. float angleSpace = (360.0 / dev->fullSteps / dev->microstepping);
  82. if(currentAngle > targetAngle + angleSpace){
  83. if(currentAngle - targetAngle > 180.0){
  84. dev->stepCount = (targetAngle + 360.0 - currentAngle) / angleSpace;
  85. }
  86. else{
  87. dir = __ATY_PN_N;
  88. dev->stepCount = (currentAngle - targetAngle) / angleSpace;
  89. }
  90. dev->dirSet(dir);
  91. dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
  92. return 1;
  93. }
  94. else if(targetAngle > currentAngle + angleSpace){
  95. if(targetAngle - currentAngle > 180.0){
  96. dir = __ATY_PN_N;
  97. dev->stepCount = (currentAngle + 360.0 - targetAngle) / angleSpace;
  98. }
  99. else{
  100. dev->stepCount = (targetAngle - currentAngle) / angleSpace;
  101. }
  102. dev->dirSet(dir);
  103. dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
  104. return 1;
  105. }
  106. else{
  107. return 0;
  108. }
  109. }
  110. uint8_t MSC_Cycle(struct MOTOR_STEP_C_ATY_Dev* dev,
  111. uint8_t mode, uint8_t enable, uint8_t direction,
  112. uint16_t stepCount,
  113. float frequency, float dutyCycle, float speed,
  114. float currentAngle, float targetAngle){
  115. float angleSpace = (360.0 / dev->fullSteps / dev->microstepping);
  116. uint8_t regUpdateFlag = 0;
  117. if(mode != dev->mode){
  118. dev->mode = mode;
  119. regUpdateFlag = 1;
  120. }
  121. if(enable != dev->enable){
  122. dev->enable = enable;
  123. if(dev->autoPower == 0) dev->enSet(dev->enable);
  124. }
  125. if(direction != dev->direction){
  126. dev->direction = direction;
  127. dev->dirSet(dev->direction);
  128. }
  129. if(targetAngle != dev->targetAngle){
  130. while(targetAngle >= 360.0) targetAngle -= 360.0;
  131. dev->targetAngle = targetAngle;
  132. if(regUpdateFlag != 1) regUpdateFlag = 2;
  133. }
  134. if(stepCount != dev->stepCount){
  135. dev->stepCount = stepCount;
  136. if(dev->mode == MOTOR_STEP_C_MODE_POST_MOTION)
  137. regUpdateFlag = 1;
  138. }
  139. if(speed != dev->speed){
  140. dev->speed = speed;
  141. dev->frequency = (dev->speed * (dev->fullSteps
  142. * dev->microstepping) / 60.0);
  143. dev->dutyCycle = 50.0;
  144. if(dev->mode == MOTOR_STEP_C_MODE_NOCOUNT){
  145. regUpdateFlag = 1;
  146. }
  147. else{
  148. if(regUpdateFlag != 1) regUpdateFlag = 2;
  149. }
  150. }
  151. else if(frequency != dev->frequency
  152. || dutyCycle != dev->dutyCycle){
  153. dev->frequency = frequency;
  154. dev->dutyCycle = dutyCycle;
  155. if(dev->dutyCycle < 0) dev->dutyCycle = 0;
  156. else if(dev->dutyCycle > 100) dev->dutyCycle = 100;
  157. dev->speed = (dev->frequency * 60.0
  158. / (dev->fullSteps * dev->microstepping));
  159. if(dev->mode == MOTOR_STEP_C_MODE_NOCOUNT){
  160. regUpdateFlag = 1;
  161. }
  162. else{
  163. if(regUpdateFlag != 1) regUpdateFlag = 2;
  164. }
  165. }
  166. if(dev->mode == MOTOR_STEP_C_MODE_POST_MOTION
  167. && dev->stepCount == 0){
  168. if(dev->angleLock == 1){
  169. dev->positionFixFlag++;
  170. }
  171. if(dev->positionFixFlag != 0){
  172. if(MSC_MoveToAngleSteps(dev, dev->targetAngle, currentAngle) == 0){
  173. dev->positionFixFlag = 0;
  174. // dev->startAngle = 0.0;
  175. // dev->targetAngle = 0.0;
  176. }
  177. else{
  178. dev->positionFixFlag++;
  179. }
  180. }
  181. }
  182. if(dev->autoPower == 1){
  183. if(regUpdateFlag == 0
  184. && dev->stepCount == 0
  185. && dev->positionFixFlag == 0
  186. && dev->mode != MOTOR_STEP_C_MODE_NOCOUNT){
  187. dev->enSet(0);
  188. }
  189. else{
  190. dev->enSet(1);
  191. }
  192. }
  193. else{
  194. dev->enSet(dev->enable);
  195. }
  196. if(regUpdateFlag == 1 && dev->mode == MOTOR_STEP_C_MODE_POST_MOTION
  197. && dev->positionFixFlag == 0){
  198. dev->startAngle = currentAngle;
  199. dev->targetAngle = ((dev->stepCount % (dev->fullSteps * dev->microstepping)) * 360.0)
  200. / (dev->fullSteps * dev->microstepping) + dev->startAngle;
  201. while(dev->targetAngle >= 360.0) dev->targetAngle -= 360.0;
  202. dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
  203. dev->positionFixFlag++;
  204. }
  205. else if(regUpdateFlag == 1 && dev->mode == MOTOR_STEP_C_MODE_NOCOUNT){
  206. dev->pwmSet(dev->frequency, dev->dutyCycle);
  207. }
  208. return regUpdateFlag;
  209. }
  210. #endif /* __MOTOR_STEP_C_ATY_C */
  211. /************************************ etc *************************************/
  212. /* init
  213. // MOTOR Close -----------------------------------------------------------------
  214. #include "MOTOR_STEP_C_ATY.h"
  215. uint8_t MOTOR_STEP_C_1_EnSet(uint8_t en){
  216. HAL_GPIO_WritePin(MS_EN_GPIO_Port, MS_EN_Pin,
  217. (en == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  218. return __ATY_OK;
  219. }
  220. uint8_t MOTOR_STEP_C_1_DirSet(uint8_t dir){
  221. HAL_GPIO_WritePin(MS_DIR_GPIO_Port, MS_DIR_Pin,
  222. (dir == __ATY_PN_P) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  223. return __ATY_OK;
  224. }
  225. void MOTOR_STEP_C_1_PWM_NoCount(float freq, float dutycycle){
  226. uint32_t ticksPeriod = 1000000U / freq;
  227. uint32_t ticksPulse = ticksPeriod * dutycycle / 100.0;
  228. HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
  229. __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
  230. __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
  231. __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
  232. HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
  233. }
  234. void MOTOR_STEP_C_1_PWM_Count(float freq, float dutycycle, uint16_t step){
  235. uint32_t ticksPeriod = 1000000U / freq;
  236. uint32_t ticksPulse = ticksPeriod * dutycycle / 100.0;
  237. HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
  238. HAL_TIM_Base_Stop_IT(&htim2);
  239. if(step != 0){
  240. __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
  241. // Set 1 to make sure the system can generate one pulse
  242. __HAL_TIM_SET_COUNTER(&htim2, 1);
  243. // init counter 1, then do not need -1
  244. __HAL_TIM_SET_AUTORELOAD(&htim2, step);
  245. __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
  246. __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
  247. HAL_TIM_Base_Start_IT(&htim2);
  248. HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
  249. }
  250. }
  251. struct MOTOR_STEP_C_ATY_Dev MOTOR_STEP_C_ATY_Dev_1 = {
  252. .enSet = MOTOR_STEP_C_1_EnSet,
  253. .dirSet = MOTOR_STEP_C_1_DirSet,
  254. .pwmSet = MOTOR_STEP_C_1_PWM_NoCount,
  255. .pwmSetCount = MOTOR_STEP_C_1_PWM_Count,
  256. .mode = 0xFF,
  257. .enable = 0xFF,
  258. .direction = 0xFF,
  259. .stepCount = 0xFFFF,
  260. .frequency = -1.0,
  261. .dutyCycle = -1.0,
  262. .speed = -1.0,
  263. .autoPower = 0,
  264. .positionFixFlag = 0,
  265. .startAngle = 0.0,
  266. .targetAngle = 0.0,
  267. .forbidReverseCorrection = 0,
  268. .angleLock = 0,
  269. .fullSteps = 200,
  270. .microstepping = 8,
  271. .lock = __ATY_UNLOCKED
  272. };
  273. void MOTOR_STEP_C_1_ValueUpdateBack(struct MOTOR_STEP_C_ATY_Dev* dev){
  274. RGF_MOTOR_STEP_COUNT = dev->stepCount;
  275. RGF_MOTOR_FREQUENCY = dev->frequency;
  276. RGF_MOTOR_DUTY_CYCLE = dev->dutyCycle;
  277. RGF_MOTOR_SPEED = dev->speed;
  278. RGF_MOTOR_ANGLE_LOCK_TARGET = dev->targetAngle;
  279. }
  280. void MOTOR_STEP_C_1_Init(void){
  281. RGF_MOTOR_MODE = MOTOR_STEP_C_MODE_POST_MOTION;
  282. RGF_MOTOR_ENABLE = 0;
  283. RGF_MOTOR_DIRECTION = __ATY_PN_P;
  284. RGF_MOTOR_STEP_COUNT = 6;
  285. RGF_MOTOR_FREQUENCY = (1600.0 / 60.0);
  286. RGF_MOTOR_DUTY_CYCLE = 50.0;
  287. RGF_MOTOR_SPEED = 60.0;
  288. RGF_MOTOR_ANGLE_LOCK_TARGET = 0;
  289. // Prevent from getting into an interruption from the very beginning
  290. __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
  291. }
  292. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
  293. if(htim == &htim4){
  294. UserTimerLoop_Cycle1ms(&HW_TIMER_ATY_Dev_4);
  295. }
  296. if((uint8_t)RGF_MOTOR_MODE == 0 && htim == &htim2){
  297. // HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
  298. // HAL_TIM_Base_Stop_IT(&htim2);
  299. // RGF_MOTOR_STEP_COUNT = 0;
  300. // MOTOR_STEP_C_ATY_Dev_1.stepCount = 0;
  301. // MOTOR_STEP_C_ATY_Dev_1.dirSet(MOTOR_STEP_C_ATY_Dev_1.direction);
  302. }
  303. }
  304. */
  305. /* use
  306. MOTOR_STEP_C_1_Init();
  307. if(MSC_Cycle(&MOTOR_STEP_C_ATY_Dev_1,
  308. (uint8_t)RGF_MOTOR_MODE,
  309. (uint8_t)RGF_MOTOR_ENABLE,
  310. (uint8_t)RGF_MOTOR_DIRECTION,
  311. (uint16_t)RGF_MOTOR_STEP_COUNT,
  312. RGF_MOTOR_FREQUENCY,
  313. RGF_MOTOR_DUTY_CYCLE,
  314. RGF_MOTOR_SPEED,
  315. RGF_MOTOR_ANGLE,
  316. RGF_MOTOR_ANGLE_LOCK,
  317. RGF_MOTOR_ANGLE_LOCK_TARGET) != 0){
  318. MOTOR_STEP_C_1_ValueUpdateBack(&MOTOR_STEP_C_ATY_Dev_1);
  319. }
  320. */
  321. /******************************************************************************/
  322. /******************************** End Of File *********************************/