Browse Source

Implement servo support for STM32F1 (#11580)

Implement servo support for STM32F1. Original code was incomplete and depended on Servo library from stm32duino which conflicts with `module/servo.h`.
jmz52 7 years ago
parent
commit
a77f8c6dd5

+ 74
- 8
Marlin/src/HAL/HAL_STM32F1/HAL_Servo_Stm32f1.cpp View File

27
 
27
 
28
 #if HAS_SERVOS
28
 #if HAS_SERVOS
29
 
29
 
30
+uint8_t ServoCount; //=0
31
+
30
 #include "HAL_Servo_Stm32f1.h"
32
 #include "HAL_Servo_Stm32f1.h"
31
 
33
 
32
-int8_t libServo::attach(const int pin) {
33
-  if (this->servoIndex >= MAX_SERVOS) return -1;
34
-  return Servo::attach(pin);
34
+//#include "Servo.h"
35
+
36
+#include <boards.h>
37
+#include <io.h>
38
+#include <pwm.h>
39
+#include <wirish_math.h>
40
+
41
+/**
42
+ * 20 millisecond period config. For a 1-based prescaler,
43
+ *
44
+ *    (prescaler * overflow / CYC_MSEC) msec = 1 timer cycle = 20 msec
45
+ * => prescaler * overflow = 20 * CYC_MSEC
46
+ *
47
+ * This uses the smallest prescaler that allows an overflow < 2^16.
48
+ */
49
+#define MAX_OVERFLOW    ((1 << 16) - 1)
50
+#define CYC_MSEC        (1000 * CYCLES_PER_MICROSECOND)
51
+#define TAU_MSEC        20
52
+#define TAU_USEC        (TAU_MSEC * 1000)
53
+#define TAU_CYC         (TAU_MSEC * CYC_MSEC)
54
+#define SERVO_PRESCALER (TAU_CYC / MAX_OVERFLOW + 1)
55
+#define SERVO_OVERFLOW  ((uint16)round((double)TAU_CYC / SERVO_PRESCALER))
56
+
57
+// Unit conversions
58
+#define US_TO_COMPARE(us) ((uint16)map((us), 0, TAU_USEC, 0, SERVO_OVERFLOW))
59
+#define COMPARE_TO_US(c)  ((uint32)map((c), 0, SERVO_OVERFLOW, 0, TAU_USEC))
60
+#define ANGLE_TO_US(a)    ((uint16)(map((a), this->minAngle, this->maxAngle, \
61
+                                        SERVO_DEFAULT_MIN_PW, SERVO_DEFAULT_MAX_PW)))
62
+#define US_TO_ANGLE(us)   ((int16)(map((us), SERVO_DEFAULT_MIN_PW, SERVO_DEFAULT_MAX_PW,  \
63
+                                       this->minAngle, this->maxAngle)))
64
+
65
+libServo::libServo() {
66
+  this->servoIndex = ServoCount < MAX_SERVOS ? ServoCount++ : INVALID_SERVO;
67
+}
68
+
69
+bool libServo::attach(const int32_t pin, const int32_t minAngle, const int32_t maxAngle) {
70
+  if (this->servoIndex >= MAX_SERVOS) return false;
71
+
72
+  this->pin = pin;
73
+  this->minAngle = minAngle;
74
+  this->maxAngle = maxAngle;
75
+
76
+  timer_dev *tdev = PIN_MAP[this->pin].timer_device;
77
+  uint8 tchan = PIN_MAP[this->pin].timer_channel;
78
+
79
+  pinMode(this->pin, PWM);
80
+  pwmWrite(this->pin, 0);
81
+
82
+  timer_pause(tdev);
83
+  timer_set_prescaler(tdev, SERVO_PRESCALER - 1); // prescaler is 1-based
84
+  timer_set_reload(tdev, SERVO_OVERFLOW);
85
+  timer_generate_update(tdev);
86
+  timer_resume(tdev);
87
+
88
+  return true;
35
 }
89
 }
36
 
90
 
37
-int8_t libServo::attach(const int pin, const int min, const int max) {
38
-  return Servo::attach(pin, min, max);
91
+bool libServo::detach() {
92
+  if (!this->attached()) return false;
93
+  pwmWrite(this->pin, 0);
94
+  return true;
39
 }
95
 }
40
 
96
 
41
-void libServo::move(const int value) {
97
+int32_t libServo::read() const {
98
+  if (this->attached()) {
99
+    timer_dev *tdev = PIN_MAP[this->pin].timer_device;
100
+    uint8 tchan = PIN_MAP[this->pin].timer_channel;
101
+    return US_TO_ANGLE(COMPARE_TO_US(timer_get_compare(tdev, tchan)));
102
+  }
103
+  return 0;
104
+}
105
+
106
+void libServo::move(const int32_t value) {
42
   constexpr uint16_t servo_delay[] = SERVO_DELAY;
107
   constexpr uint16_t servo_delay[] = SERVO_DELAY;
43
   static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
108
   static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
44
-  if (this->attach(0) >= 0) {
45
-    this->write(value);
109
+
110
+  if (this->attached()) {
111
+    pwmWrite(this->pin, US_TO_COMPARE(ANGLE_TO_US(constrain(value, this->minAngle, this->maxAngle))));
46
     safe_delay(servo_delay[this->servoIndex]);
112
     safe_delay(servo_delay[this->servoIndex]);
47
     #if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
113
     #if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
48
       this->detach();
114
       this->detach();

+ 26
- 11
Marlin/src/HAL/HAL_STM32F1/HAL_Servo_Stm32f1.h View File

24
 #ifndef HAL_SERVO_STM32F1_H
24
 #ifndef HAL_SERVO_STM32F1_H
25
 #define HAL_SERVO_STM32F1_H
25
 #define HAL_SERVO_STM32F1_H
26
 
26
 
27
-// Path needed, otherwise HAL version is used
28
-#include <../../libraries/Servo/src/Servo.h>
27
+// Pin number of unattached pins
28
+#define NOT_ATTACHED                    (-1)
29
+#define INVALID_SERVO                   255
29
 
30
 
30
-// Inherit and expand on the official library
31
-class libServo : public Servo {
32
-public:
33
-    int8_t attach(const int pin);
34
-    int8_t attach(const int pin, const int min, const int max);
35
-    void move(const int value);
36
-private:
37
-    uint16_t min_ticks;
38
-    uint16_t max_ticks;
31
+#ifndef MAX_SERVOS
32
+  #define MAX_SERVOS 3
33
+#endif
34
+
35
+#define SERVO_DEFAULT_MIN_PW            544
36
+#define SERVO_DEFAULT_MAX_PW            2400
37
+#define SERVO_DEFAULT_MIN_ANGLE         0
38
+#define SERVO_DEFAULT_MAX_ANGLE         180
39
+
40
+#define HAL_SERVO_LIB libServo
41
+
42
+class libServo {
43
+  public:
44
+    libServo();
45
+    bool attach(const int32_t pin, const int32_t minAngle=SERVO_DEFAULT_MIN_ANGLE, const int32_t maxAngle=SERVO_DEFAULT_MAX_ANGLE);
46
+    bool attached() const { return this->pin != NOT_ATTACHED; }
47
+    bool detach();
48
+    void move(const int32_t value);
49
+    int32_t read() const;
50
+  private:
39
     uint8_t servoIndex;               // index into the channel data for this servo
51
     uint8_t servoIndex;               // index into the channel data for this servo
52
+    int32_t pin = NOT_ATTACHED;
53
+    int32_t minAngle;
54
+    int32_t maxAngle;
40
 };
55
 };
41
 
56
 
42
 #endif // HAL_SERVO_STM32F1_H
57
 #endif // HAL_SERVO_STM32F1_H

+ 1
- 1
Marlin/src/HAL/shared/servo.cpp View File

53
 
53
 
54
 #include "../../inc/MarlinConfig.h"
54
 #include "../../inc/MarlinConfig.h"
55
 
55
 
56
-#if HAS_SERVOS && !(IS_32BIT_TEENSY || defined(TARGET_LPC1768) || defined(STM32F4) || defined(STM32F4xx))
56
+#if HAS_SERVOS && !(IS_32BIT_TEENSY || defined(TARGET_LPC1768) || defined(STM32F1) || defined(STM32F1xx) || defined(STM32F4) || defined(STM32F4xx))
57
 
57
 
58
 //#include <Arduino.h>
58
 //#include <Arduino.h>
59
 #include "servo.h"
59
 #include "servo.h"

+ 2
- 0
Marlin/src/HAL/shared/servo.h View File

74
 
74
 
75
 #elif defined(TARGET_LPC1768)
75
 #elif defined(TARGET_LPC1768)
76
   #include "../HAL_LPC1768/LPC1768_Servo.h"
76
   #include "../HAL_LPC1768/LPC1768_Servo.h"
77
+#elif defined(STM32F1) || defined(STM32F1xx)
78
+  #include "../HAL_STM32F1/HAL_Servo_STM32F1.h"
77
 #elif defined(STM32F4) || defined(STM32F4xx)
79
 #elif defined(STM32F4) || defined(STM32F4xx)
78
   #include "../HAL_STM32F4/HAL_Servo_STM32F4.h"
80
   #include "../HAL_STM32F4/HAL_Servo_STM32F4.h"
79
 #else
81
 #else

Loading…
Cancel
Save