RotateControlBase.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #pragma once
  2. #include "MotorControlBase.h"
  3. #include <algorithm>
  4. #include "core_pins.h"
  5. template <typename Accelerator, typename TimerField>
  6. class RotateControlBase : public MotorControlBase<TimerField>
  7. {
  8. public:
  9. RotateControlBase(unsigned pulseWidth = 5, unsigned accUpdatePeriod = 5000);
  10. // Non-blocking movements ----------------
  11. template <typename... Steppers>
  12. void rotateAsync(Steppers &... steppers);
  13. template <size_t N>
  14. void rotateAsync(Stepper *(&motors)[N]);
  15. void stopAsync();
  16. void emergencyStop() {
  17. accelerator.eStop();
  18. this->timerField.stepTimerStop();
  19. }
  20. // Blocking movements --------------------
  21. void stop();
  22. void overrideSpeed(float speedFac);
  23. void overrideAcceleration(float accFac);
  24. protected:
  25. void doRotate(int N, float speedFactor = 1.0);
  26. void accTimerISR();
  27. Accelerator accelerator;
  28. RotateControlBase(const RotateControlBase &) = delete;
  29. RotateControlBase &operator=(const RotateControlBase &) = delete;
  30. };
  31. // Implementation *************************************************************************************************
  32. template <typename a, typename t>
  33. RotateControlBase<a, t>::RotateControlBase(unsigned pulseWidth, unsigned accUpdatePeriod)
  34. : MotorControlBase<t>(pulseWidth, accUpdatePeriod)
  35. {
  36. this->mode = MotorControlBase<t>::Mode::notarget;
  37. }
  38. template <typename a, typename t>
  39. void RotateControlBase<a, t>::doRotate(int N, float speedFactor)
  40. {
  41. //Calculate Bresenham parameters ----------------------------------------------------------------
  42. std::sort(this->motorList, this->motorList + N, Stepper::cmpVmax);
  43. this->leadMotor = this->motorList[0];
  44. if (this->leadMotor->vMax == 0)
  45. return;
  46. this->leadMotor->currentSpeed = 0;
  47. this->leadMotor->A = std::abs(this->leadMotor->vMax);
  48. for (int i = 1; i < N; i++)
  49. {
  50. this->motorList[i]->A = std::abs(this->motorList[i]->vMax);
  51. this->motorList[i]->B = 2 * this->motorList[i]->A - this->leadMotor->A;
  52. }
  53. uint32_t acceleration = (*std::min_element(this->motorList, this->motorList + N, Stepper::cmpAcc))->a; // use the lowest acceleration for the move
  54. // Start moving---------------------------------------------------------------------------------------
  55. accelerator.prepareRotation(this->leadMotor->current, this->leadMotor->vMax, acceleration, this->accUpdatePeriod, speedFactor);
  56. this->timerField.setStepFrequency(0);
  57. this->timerField.accTimerStart();
  58. }
  59. // ISR -----------------------------------------------------------------------------------------------------------
  60. template <typename a, typename t>
  61. void RotateControlBase<a, t>::accTimerISR()
  62. {
  63. int32_t newSpeed = accelerator.updateSpeed(this->leadMotor->current); // get new speed for the leading motor
  64. //Serial.printf("rc,curSpeed: %i newspd:%i\n",this->leadMotor->currentSpeed, newSpeed);
  65. if (this->leadMotor->currentSpeed == newSpeed)
  66. {
  67. return; // nothing changed, just keep running
  68. }
  69. int dir = newSpeed >= 0 ? 1 : -1; // direction changed? -> toggle direction of all motors
  70. if (dir != this->leadMotor->dir)
  71. {
  72. Stepper **motor = this->motorList;
  73. while ((*motor) != nullptr)
  74. {
  75. (*motor++)->toggleDir();
  76. }
  77. delayMicroseconds(this->pulseWidth);
  78. }
  79. this->timerField.setStepFrequency(std::abs(newSpeed)); // speed changed, update timer
  80. this->leadMotor->currentSpeed = newSpeed;
  81. }
  82. // ROTATE Commands -------------------------------------------------------------------------------
  83. template <typename a, typename t>
  84. template <typename... Steppers>
  85. void RotateControlBase<a, t>::rotateAsync(Steppers &... steppers)
  86. {
  87. this->attachStepper(steppers...);
  88. doRotate(sizeof...(steppers));
  89. }
  90. template <typename a, typename t>
  91. template <size_t N>
  92. void RotateControlBase<a, t>::rotateAsync(Stepper *(&steppers)[N])
  93. {
  94. this->attachStepper(steppers);
  95. doRotate(N);
  96. }
  97. template <typename a, typename t>
  98. void RotateControlBase<a, t>::overrideSpeed(float factor)
  99. {
  100. accelerator.overrideSpeed(factor);
  101. }
  102. template <typename a, typename t>
  103. void RotateControlBase<a, t>::overrideAcceleration(float factor)
  104. {
  105. accelerator.overrideAcceleration(factor);
  106. }
  107. template <typename a, typename t>
  108. void RotateControlBase<a, t>::stopAsync()
  109. {
  110. accelerator.initiateStopping(this->leadMotor->current);
  111. }
  112. template <typename a, typename t>
  113. void RotateControlBase<a, t>::stop()
  114. {
  115. stopAsync();
  116. while (this->isRunning())
  117. {
  118. delay(1);
  119. }
  120. }