My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

HAL_Servo_STM32F1.cpp 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  7. * Copyright (C) 2017 Victor Perez
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. #ifdef __STM32F1__
  24. #include "../../inc/MarlinConfig.h"
  25. #if HAS_SERVOS
  26. uint8_t ServoCount = 0;
  27. #include "HAL_Servo_STM32F1.h"
  28. //#include "Servo.h"
  29. #include <boards.h>
  30. #include <io.h>
  31. #include <pwm.h>
  32. #include <wirish_math.h>
  33. /**
  34. * 20 millisecond period config. For a 1-based prescaler,
  35. *
  36. * (prescaler * overflow / CYC_MSEC) msec = 1 timer cycle = 20 msec
  37. * => prescaler * overflow = 20 * CYC_MSEC
  38. *
  39. * This uses the smallest prescaler that allows an overflow < 2^16.
  40. */
  41. #define MAX_OVERFLOW ((1 << 16) - 1)
  42. #define CYC_MSEC (1000 * CYCLES_PER_MICROSECOND)
  43. #define TAU_MSEC 20
  44. #define TAU_USEC (TAU_MSEC * 1000)
  45. #define TAU_CYC (TAU_MSEC * CYC_MSEC)
  46. #define SERVO_PRESCALER (TAU_CYC / MAX_OVERFLOW + 1)
  47. #define SERVO_OVERFLOW ((uint16_t)round((double)TAU_CYC / SERVO_PRESCALER))
  48. // Unit conversions
  49. #define US_TO_COMPARE(us) ((uint16_t)map((us), 0, TAU_USEC, 0, SERVO_OVERFLOW))
  50. #define COMPARE_TO_US(c) ((uint32_t)map((c), 0, SERVO_OVERFLOW, 0, TAU_USEC))
  51. #define ANGLE_TO_US(a) ((uint16_t)(map((a), this->minAngle, this->maxAngle, \
  52. SERVO_DEFAULT_MIN_PW, SERVO_DEFAULT_MAX_PW)))
  53. #define US_TO_ANGLE(us) ((int16_t)(map((us), SERVO_DEFAULT_MIN_PW, SERVO_DEFAULT_MAX_PW, \
  54. this->minAngle, this->maxAngle)))
  55. libServo::libServo() {
  56. this->servoIndex = ServoCount < MAX_SERVOS ? ServoCount++ : INVALID_SERVO;
  57. }
  58. bool libServo::attach(const int32_t pin, const int32_t minAngle, const int32_t maxAngle) {
  59. if (this->servoIndex >= MAX_SERVOS) return false;
  60. if (!PWM_PIN(pin)) return false;
  61. this->minAngle = minAngle;
  62. this->maxAngle = maxAngle;
  63. timer_dev *tdev = PIN_MAP[pin].timer_device;
  64. uint8_t tchan = PIN_MAP[pin].timer_channel;
  65. pinMode(pin, PWM);
  66. pwmWrite(pin, 0);
  67. timer_pause(tdev);
  68. timer_set_prescaler(tdev, SERVO_PRESCALER - 1); // prescaler is 1-based
  69. timer_set_reload(tdev, SERVO_OVERFLOW);
  70. timer_generate_update(tdev);
  71. timer_resume(tdev);
  72. this->pin = pin; // set attached()
  73. return true;
  74. }
  75. bool libServo::detach() {
  76. if (!this->attached()) return false;
  77. pwmWrite(this->pin, 0);
  78. return true;
  79. }
  80. int32_t libServo::read() const {
  81. if (this->attached()) {
  82. timer_dev *tdev = PIN_MAP[this->pin].timer_device;
  83. uint8_t tchan = PIN_MAP[this->pin].timer_channel;
  84. return US_TO_ANGLE(COMPARE_TO_US(timer_get_compare(tdev, tchan)));
  85. }
  86. return 0;
  87. }
  88. void libServo::move(const int32_t value) {
  89. constexpr uint16_t servo_delay[] = SERVO_DELAY;
  90. static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
  91. if (this->attached()) {
  92. pwmWrite(this->pin, US_TO_COMPARE(ANGLE_TO_US(constrain(value, this->minAngle, this->maxAngle))));
  93. safe_delay(servo_delay[this->servoIndex]);
  94. #if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
  95. this->detach();
  96. #endif
  97. }
  98. }
  99. #endif // HAS_SERVOS
  100. #endif // __STM32F1__