MOTOR_STEP_O_ATY.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /**
  2. * @file MOTOR_STEP_O_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 open 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. * @version
  66. * - 1_00_260109 > ATY
  67. * -# Preliminary version
  68. ********************************************************************************
  69. */
  70. #ifndef __MOTOR_STEP_O_ATY_C
  71. #define __MOTOR_STEP_O_ATY_C
  72. #include "MOTOR_STEP_O_ATY.h"
  73. #define MOTOR_STEP_O_ATY_TAG "\r\n[MOTOR_STEP_O_ATY] "
  74. /******************************* For user *************************************/
  75. /******************************************************************************/
  76. /**
  77. * @brief open loop stepper motor control
  78. *
  79. * @param dev
  80. * @param mode
  81. * @param enable
  82. * @param direction
  83. * @param stepCount
  84. * @param frequency
  85. * @param dutyCycle
  86. * @param speed
  87. * @return uint8_t 0: no update, 1: update, only for register update, en and dir is hardware
  88. * @note - Frequency and speed are mutually exclusive set, when set one, another
  89. * is auto calculate and update, speed has higher priority.
  90. * - When use speed, dutyCycle will set to 50% automatically.
  91. * - This function based on diff input and dev registers, so do not forget
  92. * update input registers back after update, like MSO_1_ValueUpdateBack().
  93. */
  94. uint8_t MSO_Cycle(struct MOTOR_STEP_O_ATY_Dev* dev,
  95. uint8_t mode, uint8_t enable, uint8_t direction,
  96. uint16_t stepCount,
  97. float frequency, float dutyCycle, float speed){
  98. uint8_t regUpdateFlag = 0;
  99. if(mode != dev->mode){
  100. dev->mode = mode;
  101. regUpdateFlag = 1;
  102. }
  103. if(enable != dev->enable){
  104. dev->enable = enable;
  105. dev->enSet(dev->enable);
  106. if(regUpdateFlag == 0) regUpdateFlag = 2;
  107. }
  108. if(direction != dev->direction){
  109. dev->direction = direction;
  110. dev->dirSet(dev->direction);
  111. if(regUpdateFlag == 0) regUpdateFlag = 2;
  112. }
  113. if(stepCount != dev->stepCount){
  114. dev->stepCount = stepCount;
  115. if(regUpdateFlag == 0) regUpdateFlag = 2;
  116. if(dev->mode == MOTOR_OPEN_MODE_COUNT)
  117. regUpdateFlag = 1;
  118. }
  119. if(speed != dev->speed){
  120. dev->speed = speed;
  121. dev->frequency = (dev->speed * (dev->fullSteps
  122. * dev->microstepping) / 60.0);
  123. dev->dutyCycle = 50.0;
  124. if(regUpdateFlag == 0) regUpdateFlag = 2;
  125. if(dev->mode == MOTOR_OPEN_MODE_NOCOUNT
  126. || (dev->mode == MOTOR_OPEN_MODE_COUNT && dev->stepCount == 1))
  127. regUpdateFlag = 1;
  128. }
  129. else if(frequency != dev->frequency
  130. || dutyCycle != dev->dutyCycle){
  131. dev->frequency = frequency;
  132. dev->dutyCycle = dutyCycle;
  133. if(dev->dutyCycle < 0) dev->dutyCycle = 0;
  134. else if(dev->dutyCycle > 100) dev->dutyCycle = 100;
  135. dev->speed = (dev->frequency * 60.0
  136. / (dev->fullSteps * dev->microstepping));
  137. if(regUpdateFlag == 0) regUpdateFlag = 2;
  138. if(dev->mode == MOTOR_OPEN_MODE_NOCOUNT
  139. || (dev->mode == MOTOR_OPEN_MODE_COUNT && dev->stepCount == 1))
  140. regUpdateFlag = 1;
  141. }
  142. if(regUpdateFlag == 1 && dev->mode == MOTOR_OPEN_MODE_COUNT){
  143. dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
  144. }
  145. else if(regUpdateFlag == 1 && dev->mode == MOTOR_OPEN_MODE_NOCOUNT){
  146. dev->pwmSet(dev->frequency, dev->dutyCycle);
  147. }
  148. return regUpdateFlag;
  149. }
  150. #endif /* __MOTOR_STEP_O_ATY_C */
  151. /************************************ etc *************************************/
  152. /* init
  153. #define MS_1_TIM htim1
  154. #define MS_1_TIM_CHANNEL TIM_CHANNEL_2
  155. #define MS_1_TIM_IT_CC TIM_IT_CC2
  156. #define MS_1_COUNT_TIM htim2
  157. // MOTOR Open ------------------------------------------------------------------
  158. #include "MOTOR_STEP_O_ATY.h"
  159. uint8_t MSO_1_EnSet(uint8_t en){
  160. HAL_GPIO_WritePin(MS_EN_GPIO_Port, MS_EN_Pin,
  161. (en == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  162. return __ATY_OK;
  163. }
  164. uint8_t MSO_1_DirSet(uint8_t dir){
  165. HAL_GPIO_WritePin(MS_DIRO_GPIO_Port, MS_DIRO_Pin,
  166. (dir == __ATY_PN_P) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  167. return __ATY_OK;
  168. }
  169. void MSO_1_PWM_NoCount(float freq, float dutycycle){
  170. uint32_t ticksPeriod = 1000000U / freq;
  171. uint32_t ticksPulse = ticksPeriod * (100.0 - dutycycle) / 100.0;
  172. HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
  173. __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
  174. __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
  175. __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
  176. HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
  177. }
  178. void MSO_1_PWM_Count(float freq, float dutycycle, uint16_t step){
  179. uint32_t ticksPeriod = 1000000U / freq;
  180. uint32_t ticksPulse = ticksPeriod * (100.0 - dutycycle) / 100.0;
  181. HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
  182. HAL_TIM_Base_Stop_IT(&MS_1_COUNT_TIM);
  183. __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
  184. // Set 1 to make sure the system can generate one pulse
  185. __HAL_TIM_SET_COUNTER(&MS_1_COUNT_TIM, 1);
  186. if(step != 0){
  187. // init counter 1, then do not need -1
  188. __HAL_TIM_SET_AUTORELOAD(&MS_1_COUNT_TIM, step);
  189. __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
  190. __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
  191. HAL_TIM_Base_Start_IT(&MS_1_COUNT_TIM);
  192. HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
  193. }
  194. }
  195. struct MOTOR_STEP_O_ATY_Dev MOTOR_STEP_O_ATY_Dev_1 = {
  196. .enSet = MSO_1_EnSet,
  197. .dirSet = MSO_1_DirSet,
  198. .pwmSet = MSO_1_PWM_NoCount,
  199. .pwmSetCount = MSO_1_PWM_Count,
  200. .mode = 0xFF,
  201. .enable = 0xFF,
  202. .direction = 0xFF,
  203. .stepCount = 0xFFFF,
  204. .frequency = -1.0,
  205. .dutyCycle = -1.0,
  206. .speed = -1.0,
  207. .fullSteps = 200,
  208. .microstepping = 8,
  209. .lock = __ATY_UNLOCKED
  210. };
  211. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
  212. if(htim == &htim4){
  213. UserTimerLoop_Cycle1ms(&HW_TIMER_ATY_Dev_4);
  214. }
  215. if((uint8_t)RGF_MOTOR_MODE == 0 && htim == &MS_1_COUNT_TIM){
  216. HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
  217. HAL_TIM_Base_Stop_IT(&MS_1_COUNT_TIM);
  218. RGF_MOTOR_STEP_COUNT = 0;
  219. MOTOR_STEP_O_ATY_Dev_1.stepCount = 0;
  220. }
  221. }
  222. void MSO_1_ValueUpdateBack(struct MOTOR_STEP_O_ATY_Dev* dev){
  223. RGF_MOTOR_MODE = dev->mode;
  224. RGF_MOTOR_ENABLE = dev->enable;
  225. RGF_MOTOR_DIRECTION = dev->direction;
  226. // RGF_MOTOR_STEP_COUNT = dev->stepCount;
  227. RGF_MOTOR_FREQUENCY = dev->frequency;
  228. RGF_MOTOR_DUTY_CYCLE = dev->dutyCycle;
  229. RGF_MOTOR_SPEED = dev->speed;
  230. }
  231. void MSO_1_Init(void){
  232. RGF_MOTOR_MODE = MOTOR_OPEN_MODE_COUNT;
  233. RGF_MOTOR_ENABLE = 1;
  234. RGF_MOTOR_DIRECTION = __ATY_PN_P;
  235. RGF_MOTOR_STEP_COUNT = 10000;
  236. RGF_MOTOR_FREQUENCY = (1600.0 / 60.0);
  237. RGF_MOTOR_DUTY_CYCLE = 50.0;
  238. RGF_MOTOR_SPEED = 200.0;
  239. // Prevent from getting into an interruption from the very beginning
  240. __HAL_TIM_CLEAR_FLAG(&MS_1_COUNT_TIM, TIM_FLAG_UPDATE);
  241. }
  242. */
  243. /* use
  244. MSO_1_Init();
  245. // 100ms cycle
  246. if(MSO_Cycle(&MOTOR_STEP_O_ATY_Dev_1,
  247. (uint8_t)RGF_MOTOR_MODE,
  248. (uint8_t)RGF_MOTOR_ENABLE,
  249. (uint8_t)RGF_MOTOR_DIRECTION,
  250. (uint16_t)RGF_MOTOR_STEP_COUNT,
  251. RGF_MOTOR_FREQUENCY,
  252. RGF_MOTOR_DUTY_CYCLE,
  253. RGF_MOTOR_SPEED) != 0){
  254. MSO_1_ValueUpdateBack(&MOTOR_STEP_O_ATY_Dev_1);
  255. }
  256. */
  257. /******************************************************************************/
  258. /******************************** End Of File *********************************/