StepControlBase.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #pragma once
  2. #include "MotorControlBase.h"
  3. #include <algorithm>
  4. template <typename Accelerator, typename TimerField>
  5. class StepControlBase : public MotorControlBase<TimerField>
  6. {
  7. public:
  8. StepControlBase(unsigned pulseWidth = 5, unsigned accUpdatePeriod = 5000);
  9. // Non-blocking movements ----------------
  10. template <typename... Steppers>
  11. void moveAsync(Steppers &... steppers);
  12. template <size_t N>
  13. void moveAsync(Stepper *(&motors)[N]);
  14. void stopAsync();
  15. // Blocking movements --------------------
  16. template <typename... Steppers>
  17. void move(Steppers &... steppers);
  18. template <size_t N>
  19. void move(Stepper *(&motors)[N]);
  20. void stop();
  21. // Misc ----------------------------------
  22. void setCallback(void (*_callback)()) { this->callback = _callback; }
  23. protected:
  24. void accTimerISR();
  25. void doMove(int N, bool mode = true);
  26. Accelerator accelerator;
  27. StepControlBase(const StepControlBase &) = delete;
  28. StepControlBase &operator=(const StepControlBase &) = delete;
  29. };
  30. // Implementation *************************************************************************************************
  31. template <typename a, typename t>
  32. StepControlBase<a, t>::StepControlBase(unsigned pulseWidth, unsigned accUpdatePeriod)
  33. : MotorControlBase<t>(pulseWidth, accUpdatePeriod)
  34. {
  35. this->mode = MotorControlBase<t>::Mode::target;
  36. }
  37. template <typename a, typename t>
  38. void StepControlBase<a, t>::doMove(int N, bool move)
  39. {
  40. //Calculate Bresenham parameters ----------------------------------------------------------------
  41. std::sort(this->motorList, this->motorList + N, Stepper::cmpDelta); // The motor which does most steps leads the movement, move to top of list
  42. this->leadMotor = this->motorList[0];
  43. for (int i = 1; i < N; i++)
  44. {
  45. this->motorList[i]->B = 2 * this->motorList[i]->A - this->leadMotor->A;
  46. }
  47. // Calculate acceleration parameters --------------------------------------------------------------
  48. uint32_t targetSpeed = std::abs((*std::min_element(this->motorList, this->motorList + N, Stepper::cmpVmin))->vMax); // use the lowest max frequency for the move, scale by relSpeed
  49. uint32_t acceleration = (*std::min_element(this->motorList, this->motorList + N, Stepper::cmpAcc))->a; // use the lowest acceleration for the move
  50. if (this->leadMotor->A == 0 || targetSpeed == 0)
  51. return;
  52. // Start move---------------------------------------------------------------------------------------
  53. this->timerField.setStepFrequency(accelerator.prepareMovement(this->leadMotor->current, this->leadMotor->target, targetSpeed, acceleration));
  54. this->timerField.stepTimerStart();
  55. this->timerField.accTimerStart();
  56. }
  57. // ISR -----------------------------------------------------------------------------------------------------------
  58. template <typename a, typename t>
  59. void StepControlBase<a, t>::accTimerISR()
  60. {
  61. if (this->isRunning())
  62. {
  63. this->timerField.setStepFrequency(accelerator.updateSpeed(this->leadMotor->current));
  64. }
  65. }
  66. // MOVE ASYNC Commands -------------------------------------------------------------------------------------------------
  67. template <typename a, typename t>
  68. template <typename... Steppers>
  69. void StepControlBase<a, t>::moveAsync(Steppers &... steppers)
  70. {
  71. this->attachStepper(steppers...);
  72. doMove(sizeof...(steppers));
  73. }
  74. template <typename a, typename t>
  75. template <size_t N>
  76. void StepControlBase<a, t>::moveAsync(Stepper *(&motors)[N]) //move up to maxMotors motors synchronously
  77. {
  78. this->attachStepper(motors);
  79. doMove(N);
  80. }
  81. // MOVE Commands -------------------------------------------------------------------------------------------------
  82. template <typename a, typename t>
  83. template <typename... Steppers>
  84. void StepControlBase<a, t>::move(Steppers &... steppers)
  85. {
  86. moveAsync(steppers...);
  87. while (this->timerField.stepTimerIsRunning())
  88. {
  89. delay(1);
  90. }
  91. }
  92. template <typename a, typename t>
  93. template <size_t N>
  94. void StepControlBase<a, t>::move(Stepper *(&motors)[N])
  95. {
  96. moveAsync(motors);
  97. while (this->isRunning())
  98. {
  99. delay(1);
  100. }
  101. }
  102. template <typename a, typename t>
  103. void StepControlBase<a, t>::stopAsync()
  104. {
  105. uint32_t newTarget = accelerator.initiateStopping(this->leadMotor->current);
  106. this->leadMotor->target = this->leadMotor->current + this->leadMotor->dir * newTarget;
  107. }
  108. template <typename a, typename t>
  109. void StepControlBase<a, t>::stop()
  110. {
  111. stopAsync();
  112. while (this->isRunning())
  113. {
  114. delay(1);
  115. }
  116. }