Переглянути джерело

🐛 Fix, improve PWM on AVR (#23463)

Mike La Spina 2 роки тому
джерело
коміт
2cfde39eca
Аккаунт користувача з таким Email не знайдено

+ 2
- 0
Marlin/src/HAL/AVR/HAL.cpp Переглянути файл

@@ -75,6 +75,8 @@ void HAL_init() {
75 75
   #if HAS_SERVO_3
76 76
     INIT_SERVO(3);
77 77
   #endif
78
+
79
+  init_pwm_timers();   // Init user timers to default frequency - 1000HZ
78 80
 }
79 81
 
80 82
 void HAL_reboot() {

+ 7
- 0
Marlin/src/HAL/AVR/HAL.h Переглянути файл

@@ -207,6 +207,7 @@ inline void HAL_adc_init() {
207 207
 #define strtof strtod
208 208
 
209 209
 #define HAL_CAN_SET_PWM_FREQ   // This HAL supports PWM Frequency adjustment
210
+#define PWM_FREQUENCY 1000     // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
210 211
 
211 212
 /**
212 213
  *  set_pwm_frequency
@@ -226,3 +227,9 @@ void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
226 227
  *  Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
227 228
  */
228 229
 void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
230
+
231
+/*
232
+ * init_pwm_timers
233
+ * sets the default frequency for timers 2-5 to 1000HZ
234
+ */
235
+void init_pwm_timers();

+ 96
- 165
Marlin/src/HAL/AVR/fast_pwm.cpp Переглянути файл

@@ -21,10 +21,7 @@
21 21
  */
22 22
 #ifdef __AVR__
23 23
 
24
-#include "../../inc/MarlinConfigPre.h"
25
-#include "HAL.h"
26
-
27
-#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
24
+#include "../../inc/MarlinConfig.h"
28 25
 
29 26
 struct Timer {
30 27
   volatile uint8_t* TCCRnQ[3];  // max 3 TCCR registers per timer
@@ -32,6 +29,8 @@ struct Timer {
32 29
   volatile uint16_t* ICRn;      // max 1 ICR register per timer
33 30
   uint8_t n;                    // the timer number [0->5]
34 31
   uint8_t q;                    // the timer output [0->2] (A->C)
32
+  bool isPWM;                   // True if pin is a "hardware timer"
33
+  bool isProtected;             // True if timer is protected
35 34
 };
36 35
 
37 36
 // Macros for the Timer structure
@@ -53,16 +52,13 @@ struct Timer {
53 52
 #define _SET_ICRn(ICRn, V) (*(ICRn) = int(V) & 0xFFFF)
54 53
 
55 54
 /**
56
- * get_pwm_timer
57
- *  Get the timer information and register of the provided pin.
58
- *  Return a Timer struct containing this information.
59
- *  Used by set_pwm_frequency, set_pwm_duty
55
+ * Return a Timer struct describing a pin's timer.
60 56
  */
61 57
 Timer get_pwm_timer(const pin_t pin) {
58
+
62 59
   uint8_t q = 0;
63 60
 
64 61
   switch (digitalPinToTimer(pin)) {
65
-    // Protect reserved timers (TIMER0 & TIMER1)
66 62
     #ifdef TCCR0A
67 63
       IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:)
68 64
       case TIMER0B:
@@ -71,212 +67,147 @@ Timer get_pwm_timer(const pin_t pin) {
71 67
       case TIMER1A: case TIMER1B:
72 68
     #endif
73 69
 
74
-    break;
70
+    break;    // Protect reserved timers (TIMER0 & TIMER1)
75 71
 
76 72
     #if HAS_TCCR2
77
-      case TIMER2: {
78
-        Timer timer = {
79
-          { &TCCR2, nullptr, nullptr },
80
-          { (uint16_t*)&OCR2, nullptr, nullptr },
81
-            nullptr,
82
-            2, 0
83
-        };
84
-        return timer;
85
-      }
73
+      case TIMER2:
74
+        return Timer({ { &TCCR2, nullptr, nullptr }, { (uint16_t*)&OCR2, nullptr, nullptr }, nullptr, 2, 0, true, false });
75
+    #elif ENABLED(USE_OCR2A_AS_TOP)
76
+      case TIMER2A: break; // protect TIMER2A since its OCR is used by TIMER2B
77
+      case TIMER2B:
78
+        return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, 1, true, false });
86 79
     #elif defined(TCCR2A)
87
-      #if ENABLED(USE_OCR2A_AS_TOP)
88
-        case TIMER2A:   break; // protect TIMER2A
89
-        case TIMER2B: {
90
-          Timer timer = {
91
-            { &TCCR2A,  &TCCR2B,  nullptr },
92
-            { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
93
-              nullptr,
94
-              2, 1
95
-          };
96
-          return timer;
97
-        }
98
-      #else
99
-        case TIMER2B: ++q;
100
-        case TIMER2A: {
101
-          Timer timer = {
102
-            { &TCCR2A,  &TCCR2B,  nullptr },
103
-            { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
104
-              nullptr,
105
-              2, q
106
-          };
107
-          return timer;
108
-        }
109
-      #endif
80
+      case TIMER2B: ++q; case TIMER2A:
81
+        return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, q, true, false });
110 82
     #endif
111 83
 
112 84
     #ifdef OCR3C
113
-      case TIMER3C: ++q;
114
-      case TIMER3B: ++q;
115
-      case TIMER3A: {
116
-        Timer timer = {
117
-          { &TCCR3A,  &TCCR3B,  &TCCR3C },
118
-          { &OCR3A,   &OCR3B,   &OCR3C },
119
-            &ICR3,
120
-            3, q
121
-        };
122
-        return timer;
123
-      }
85
+      case TIMER3C: ++q; case TIMER3B: ++q; case TIMER3A:
86
+        return Timer({ { &TCCR3A, &TCCR3B, &TCCR3C }, { &OCR3A, &OCR3B, &OCR3C  }, &ICR3, 3, q, true, false });
124 87
     #elif defined(OCR3B)
125
-      case TIMER3B: ++q;
126
-      case TIMER3A: {
127
-        Timer timer = {
128
-          { &TCCR3A,  &TCCR3B,  nullptr },
129
-          { &OCR3A,   &OCR3B,  nullptr },
130
-            &ICR3,
131
-            3, q
132
-        };
133
-        return timer;
134
-      }
88
+      case TIMER3B: ++q; case TIMER3A:
89
+        return Timer({ { &TCCR3A, &TCCR3B, nullptr }, { &OCR3A, &OCR3B, nullptr }, &ICR3, 3, q, true, false });
135 90
     #endif
136 91
 
137 92
     #ifdef TCCR4A
138
-      case TIMER4C: ++q;
139
-      case TIMER4B: ++q;
140
-      case TIMER4A: {
141
-        Timer timer = {
142
-          { &TCCR4A,  &TCCR4B,  &TCCR4C },
143
-          { &OCR4A,   &OCR4B,   &OCR4C },
144
-            &ICR4,
145
-            4, q
146
-        };
147
-        return timer;
148
-      }
93
+      case TIMER4C: ++q; case TIMER4B: ++q; case TIMER4A:
94
+        return Timer({ { &TCCR4A, &TCCR4B, &TCCR4C }, { &OCR4A, &OCR4B, &OCR4C }, &ICR4, 4, q, true, false });
149 95
     #endif
150 96
 
151 97
     #ifdef TCCR5A
152
-      case TIMER5C: ++q;
153
-      case TIMER5B: ++q;
154
-      case TIMER5A: {
155
-        Timer timer = {
156
-          { &TCCR5A,  &TCCR5B,  &TCCR5C },
157
-          { &OCR5A,   &OCR5B,   &OCR5C },
158
-            &ICR5,
159
-            5, q
160
-        };
161
-        return timer;
162
-      }
98
+      case TIMER5C: ++q; case TIMER5B: ++q; case TIMER5A:
99
+        return Timer({ { &TCCR5A, &TCCR5B, &TCCR5C }, { &OCR5A, &OCR5B, &OCR5C }, &ICR5, 5, q, true, false });
163 100
     #endif
164 101
   }
165 102
 
166
-  Timer timer = {
167
-    { nullptr, nullptr, nullptr },
168
-    { nullptr, nullptr, nullptr },
169
-      nullptr,
170
-      0, 0
171
-  };
172
-  return timer;
103
+  return Timer();
173 104
 }
174 105
 
175 106
 void set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
176 107
   Timer timer = get_pwm_timer(pin);
177
-  if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
178
-  uint16_t size;
179
-  if (timer.n == 2) size = 255; else size = 65535;
108
+  if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized
109
+
110
+  const bool is_timer2 = timer.n == 2;
111
+  const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF;
180 112
 
181
-  uint16_t res = 255;   // resolution (TOP value)
182
-  uint8_t j = 0;        // prescaler index
183
-  uint8_t wgm = 1;      // waveform generation mode
113
+  uint16_t res = 0xFF;        // resolution (TOP value)
114
+  uint8_t j = CS_NONE;        // prescaler index
115
+  uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode
184 116
 
185 117
   // Calculating the prescaler and resolution to use to achieve closest frequency
186 118
   if (f_desired != 0) {
187
-    int f = (F_CPU) / (2 * 1024 * size) + 1; // Initialize frequency as lowest (non-zero) achievable
188
-    uint16_t prescaler[] = { 0, 1, 8, /*TIMER2 ONLY*/32, 64, /*TIMER2 ONLY*/128, 256, 1024 };
189
-
190
-    // loop over prescaler values
191
-    LOOP_S_L_N(i, 1, 8) {
192
-      uint16_t res_temp_fast = 255, res_temp_phase_correct = 255;
193
-      if (timer.n == 2) {
194
-        // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
195
-        #if ENABLED(USE_OCR2A_AS_TOP)
196
-          const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
197
-          res_temp_fast = rtf - 1;
198
-          res_temp_phase_correct = rtf / 2;
119
+    constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 };  // (*) are Timer 2 only
120
+    uint16_t f = (F_CPU) / (2 * 1024 * maxtop) + 1;           // Start with the lowest non-zero frequency achievable (1 or 31)
121
+
122
+    LOOP_L_N(i, COUNT(prescaler)) {                           // Loop through all prescaler values
123
+      const uint16_t p = prescaler[i];
124
+      uint16_t res_fast_temp, res_pc_temp;
125
+      if (is_timer2) {
126
+        #if ENABLED(USE_OCR2A_AS_TOP)                         // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
127
+          const uint16_t rft = (F_CPU) / (p * f_desired);
128
+          res_fast_temp = rft - 1;
129
+          res_pc_temp = rft / 2;
130
+        #else
131
+          res_fast_temp = res_pc_temp = maxtop;
199 132
         #endif
200 133
       }
201 134
       else {
202
-        // Skip TIMER2 specific prescalers when not TIMER2
203
-        if (i == 3 || i == 5) continue;
204
-        const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
205
-        res_temp_fast = rtf - 1;
206
-        res_temp_phase_correct = rtf / 2;
135
+        if (p == 32 || p == 128) continue;                    // Skip TIMER2 specific prescalers when not TIMER2
136
+        const uint16_t rft = (F_CPU) / (p * f_desired);
137
+        res_fast_temp = rft - 1;
138
+        res_pc_temp = rft / 2;
207 139
       }
208 140
 
209
-      LIMIT(res_temp_fast, 1U, size);
210
-      LIMIT(res_temp_phase_correct, 1U, size);
141
+      LIMIT(res_fast_temp, 1U, maxtop);
142
+      LIMIT(res_pc_temp, 1U, maxtop);
143
+
211 144
       // Calculate frequencies of test prescaler and resolution values
212
-      const int f_temp_fast = (F_CPU) / (prescaler[i] * (1 + res_temp_fast)),
213
-                f_temp_phase_correct = (F_CPU) / (2 * prescaler[i] * res_temp_phase_correct),
214
-                f_diff = ABS(f - f_desired),
215
-                f_fast_diff = ABS(f_temp_fast - f_desired),
216
-                f_phase_diff = ABS(f_temp_phase_correct - f_desired);
145
+      const uint32_t f_diff      = _MAX(f, f_desired) - _MIN(f, f_desired),
146
+                     f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
147
+                     f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired),
148
+                     f_pc_temp   = (F_CPU) / (2 * p * res_pc_temp),
149
+                     f_pc_diff   = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired);
217 150
 
218
-      // If FAST values are closest to desired f
219
-      if (f_fast_diff < f_diff && f_fast_diff <= f_phase_diff) {
220
-        // Remember this combination
221
-        f = f_temp_fast;
222
-        res = res_temp_fast;
223
-        j = i;
151
+      if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f
224 152
         // Set the Wave Generation Mode to FAST PWM
225
-        if (timer.n == 2)
226
-          wgm = TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM);
227
-        else
228
-          wgm = WGM_FAST_PWM_ICRn;
153
+        wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
154
+        // Remember this combination
155
+        f = f_fast_temp; res = res_fast_temp; j = i + 1;
229 156
       }
230
-      // If PHASE CORRECT values are closes to desired f
231
-      else if (f_phase_diff < f_diff) {
232
-        f = f_temp_phase_correct;
233
-        res = res_temp_phase_correct;
234
-        j = i;
157
+      else if (f_pc_diff < f_diff) {                          // PHASE CORRECT values are closes to desired f
235 158
         // Set the Wave Generation Mode to PWM PHASE CORRECT
236
-        if (timer.n == 2)
237
-          wgm = TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_FAST_PWM);
238
-        else
239
-          wgm = WGM_PWM_PC_ICRn;
159
+        wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC)) : uint8_t(WGM_PWM_PC_ICRn);
160
+        f = f_pc_temp; res = res_pc_temp; j = i + 1;
240 161
       }
241 162
     }
242 163
   }
164
+
243 165
   _SET_WGMnQ(timer.TCCRnQ, wgm);
244 166
   _SET_CSn(timer.TCCRnQ, j);
245 167
 
246
-  if (timer.n == 2) {
247
-    TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer.OCRnQ, 0, res));  // Set OCR2A value (TOP) = res
168
+  if (is_timer2) {
169
+    TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer.OCRnQ, 0, res)); // Set OCR2A value (TOP) = res
248 170
   }
249 171
   else
250
-    _SET_ICRn(timer.ICRn, res);         // Set ICRn value (TOP) = res
172
+    _SET_ICRn(timer.ICRn, res);                               // Set ICRn value (TOP) = res
251 173
 }
252 174
 
253
-#endif // NEEDS_HARDWARE_PWM
254
-
255 175
 void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
256
-  #if NEEDS_HARDWARE_PWM
257
-
258
-    // If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
259
-    // Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
260
-    if (v == 0)
261
-      digitalWrite(pin, invert);
262
-    else if (v == v_size)
263
-      digitalWrite(pin, !invert);
264
-    else {
265
-      Timer timer = get_pwm_timer(pin);
266
-      if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
267
-      // Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
268
-      _SET_COMnQ(timer.TCCRnQ, timer.q TERN_(HAS_TCCR2, + (timer.q == 2)), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2
176
+  // If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
177
+  // Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
178
+  if (v == 0)
179
+    digitalWrite(pin, invert);
180
+  else if (v == v_size)
181
+    digitalWrite(pin, !invert);
182
+  else {
183
+    Timer timer = get_pwm_timer(pin);
184
+    if (timer.isProtected) return;                            // Leave protected timer unchanged
185
+    if (timer.isPWM) {
186
+      _SET_COMnQ(timer.TCCRnQ, SUM_TERN(HAS_TCCR2, timer.q, timer.q == 2), COM_CLEAR_SET + invert);   // COM20 is on bit 4 of TCCR2, so +1 for q==2
269 187
       const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
270 188
       _SET_OCRnQ(timer.OCRnQ, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
271 189
     }
190
+    else
191
+      digitalWrite(pin, v < 128 ? LOW : HIGH);
192
+  }
193
+}
272 194
 
273
-  #else
274
-
275
-    analogWrite(pin, v);
276
-    UNUSED(v_size);
277
-    UNUSED(invert);
195
+void init_pwm_timers() {
196
+  // Init some timer frequencies to a default 1KHz
197
+  const pin_t pwm_pin[] = {
198
+    #ifdef __AVR_ATmega2560__
199
+      10, 5, 6, 46
200
+    #elif defined(__AVR_ATmega1280__)
201
+      12, 31
202
+    #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__)
203
+      15, 6
204
+    #elif defined(__AVR_AT90USB1286__) || defined(__AVR_mega64) || defined(__AVR_mega128)
205
+      16, 24
206
+    #endif
207
+  };
278 208
 
279
-  #endif
209
+  LOOP_L_N(i, COUNT(pwm_pin))
210
+    set_pwm_frequency(pwm_pin[i], 1000);
280 211
 }
281 212
 
282 213
 #endif // __AVR__

+ 1
- 1
Marlin/src/HAL/AVR/fastio.cpp Переглянути файл

@@ -257,7 +257,7 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
257 257
     const float pwm_top = round(count);   // Get the rounded count
258 258
 
259 259
     ICR5 = (uint16_t)pwm_top - 1;         // Subtract 1 for TOP
260
-    OCR5A = pwm_top * ABS(dca);          // Update and scale DCs
260
+    OCR5A = pwm_top * ABS(dca);           // Update and scale DCs
261 261
     OCR5B = pwm_top * ABS(dcb);
262 262
     OCR5C = pwm_top * ABS(dcc);
263 263
     _SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes

+ 0
- 5
Marlin/src/inc/Conditionals_adv.h Переглянути файл

@@ -677,11 +677,6 @@
677 677
   #define CUTTER_UNIT_IS(V)    (_CUTTER_POWER(CUTTER_POWER_UNIT) == _CUTTER_POWER(V))
678 678
 #endif
679 679
 
680
-// Add features that need hardware PWM here
681
-#if ANY(FAST_PWM_FAN, SPINDLE_LASER_USE_PWM)
682
-  #define NEEDS_HARDWARE_PWM 1
683
-#endif
684
-
685 680
 #if !defined(__AVR__) || !defined(USBCON)
686 681
   // Define constants and variables for buffering serial data.
687 682
   // Use only 0 or powers of 2 greater than 1

+ 22
- 19
Marlin/src/module/stepper.cpp Переглянути файл

@@ -3257,33 +3257,33 @@ void Stepper::report_positions() {
3257 3257
 
3258 3258
       #elif HAS_MOTOR_CURRENT_PWM
3259 3259
 
3260
-        #define _WRITE_CURRENT_PWM(P) set_pwm_duty(pin_t(MOTOR_CURRENT_PWM_## P ##_PIN), 255L * current / (MOTOR_CURRENT_PWM_RANGE))
3260
+        #define _WRITE_CURRENT_PWM_DUTY(P) set_pwm_duty(pin_t(MOTOR_CURRENT_PWM_## P ##_PIN), 255L * current / (MOTOR_CURRENT_PWM_RANGE))
3261 3261
         switch (driver) {
3262 3262
           case 0:
3263 3263
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
3264
-              _WRITE_CURRENT_PWM(X);
3264
+              _WRITE_CURRENT_PWM_DUTY(X);
3265 3265
             #endif
3266 3266
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_Y)
3267
-              _WRITE_CURRENT_PWM(Y);
3267
+              _WRITE_CURRENT_PWM_DUTY(Y);
3268 3268
             #endif
3269 3269
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
3270
-              _WRITE_CURRENT_PWM(XY);
3270
+              _WRITE_CURRENT_PWM_DUTY(XY);
3271 3271
             #endif
3272 3272
             break;
3273 3273
           case 1:
3274 3274
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
3275
-              _WRITE_CURRENT_PWM(Z);
3275
+              _WRITE_CURRENT_PWM_DUTY(Z);
3276 3276
             #endif
3277 3277
             break;
3278 3278
           case 2:
3279 3279
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
3280
-              _WRITE_CURRENT_PWM(E);
3280
+              _WRITE_CURRENT_PWM_DUTY(E);
3281 3281
             #endif
3282 3282
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_E0)
3283
-              _WRITE_CURRENT_PWM(E0);
3283
+              _WRITE_CURRENT_PWM_DUTY(E0);
3284 3284
             #endif
3285 3285
             #if PIN_EXISTS(MOTOR_CURRENT_PWM_E1)
3286
-              _WRITE_CURRENT_PWM(E1);
3286
+              _WRITE_CURRENT_PWM_DUTY(E1);
3287 3287
             #endif
3288 3288
             break;
3289 3289
         }
@@ -3302,34 +3302,37 @@ void Stepper::report_positions() {
3302 3302
 
3303 3303
       #elif HAS_MOTOR_CURRENT_PWM
3304 3304
 
3305
+        #ifdef __SAM3X8E__
3306
+          #define _RESET_CURRENT_PWM_FREQ(P) NOOP
3307
+        #else
3308
+          #define _RESET_CURRENT_PWM_FREQ(P) set_pwm_frequency(pin_t(P), MOTOR_CURRENT_PWM_FREQUENCY)
3309
+        #endif
3310
+        #define INIT_CURRENT_PWM(P) do{ SET_PWM(MOTOR_CURRENT_PWM_## P ##_PIN); _RESET_CURRENT_PWM_FREQ(MOTOR_CURRENT_PWM_## P ##_PIN); }while(0)
3311
+
3305 3312
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
3306
-          SET_PWM(MOTOR_CURRENT_PWM_X_PIN);
3313
+          INIT_CURRENT_PWM(X);
3307 3314
         #endif
3308 3315
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_Y)
3309
-          SET_PWM(MOTOR_CURRENT_PWM_Y_PIN);
3316
+          INIT_CURRENT_PWM(Y);
3310 3317
         #endif
3311 3318
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
3312
-          SET_PWM(MOTOR_CURRENT_PWM_XY_PIN);
3319
+          INIT_CURRENT_PWM(XY);
3313 3320
         #endif
3314 3321
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
3315
-          SET_PWM(MOTOR_CURRENT_PWM_Z_PIN);
3322
+          INIT_CURRENT_PWM(Z);
3316 3323
         #endif
3317 3324
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
3318
-          SET_PWM(MOTOR_CURRENT_PWM_E_PIN);
3325
+          INIT_CURRENT_PWM(E);
3319 3326
         #endif
3320 3327
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_E0)
3321
-          SET_PWM(MOTOR_CURRENT_PWM_E0_PIN);
3328
+          INIT_CURRENT_PWM(E0);
3322 3329
         #endif
3323 3330
         #if PIN_EXISTS(MOTOR_CURRENT_PWM_E1)
3324
-          SET_PWM(MOTOR_CURRENT_PWM_E1_PIN);
3331
+          INIT_CURRENT_PWM(E1);
3325 3332
         #endif
3326 3333
 
3327 3334
         refresh_motor_power();
3328 3335
 
3329
-        // Set Timer5 to 31khz so the PWM of the motor power is as constant as possible. (removes a buzzing noise)
3330
-        #ifdef __AVR__
3331
-          SET_CS5(PRESCALER_1);
3332
-        #endif
3333 3336
       #endif
3334 3337
     }
3335 3338
 

+ 4
- 0
Marlin/src/module/stepper.h Переглянути файл

@@ -317,6 +317,10 @@ class Stepper {
317 317
         #ifndef PWM_MOTOR_CURRENT
318 318
           #define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT
319 319
         #endif
320
+        #ifndef MOTOR_CURRENT_PWM_FREQUENCY
321
+          #define MOTOR_CURRENT_PWM_FREQUENCY 31400
322
+        #endif
323
+
320 324
         #define MOTOR_CURRENT_COUNT LINEAR_AXES
321 325
       #elif HAS_MOTOR_CURRENT_SPI
322 326
         static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;

Завантаження…
Відмінити
Зберегти