Browse Source

⚡️ Controller Fan software PWM (etc.) (#23102)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
Mike La Spina 3 years ago
parent
commit
8ee368b718
No account linked to committer's email address

+ 8
- 34
Marlin/src/HAL/AVR/fast_pwm.cpp View File

@@ -54,8 +54,8 @@ Timer get_pwm_timer(const pin_t pin) {
54 54
       case TIMER1A: case TIMER1B:
55 55
     #endif
56 56
                                         break;
57
-    #if defined(TCCR2) || defined(TCCR2A)
58
-      #ifdef TCCR2
57
+    #if HAS_TCCR2 || defined(TCCR2A)
58
+      #if HAS_TCCR2
59 59
         case TIMER2: {
60 60
           Timer timer = {
61 61
             /*TCCRnQ*/  { &TCCR2, nullptr, nullptr },
@@ -200,16 +200,7 @@ void set_pwm_frequency(const pin_t pin, int f_desired) {
200 200
         res = res_temp_fast;
201 201
         j = i;
202 202
         // Set the Wave Generation Mode to FAST PWM
203
-        if (timer.n == 2) {
204
-          wgm = (
205
-            #if ENABLED(USE_OCR2A_AS_TOP)
206
-              WGM2_FAST_PWM_OCR2A
207
-            #else
208
-              WGM2_FAST_PWM
209
-            #endif
210
-          );
211
-        }
212
-        else wgm = WGM_FAST_PWM_ICRn;
203
+        wgm = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM) : WGM_FAST_PWM_ICRn;
213 204
       }
214 205
       // If PHASE CORRECT values are closes to desired f
215 206
       else if (f_phase_diff < f_diff) {
@@ -217,16 +208,7 @@ void set_pwm_frequency(const pin_t pin, int f_desired) {
217 208
         res = res_temp_phase_correct;
218 209
         j = i;
219 210
         // Set the Wave Generation Mode to PWM PHASE CORRECT
220
-        if (timer.n == 2) {
221
-          wgm = (
222
-            #if ENABLED(USE_OCR2A_AS_TOP)
223
-              WGM2_PWM_PC_OCR2A
224
-            #else
225
-              WGM2_PWM_PC
226
-            #endif
227
-          );
228
-        }
229
-        else wgm = WGM_PWM_PC_ICRn;
211
+        wgm = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC) : WGM_PWM_PC_ICRn;
230 212
       }
231 213
     }
232 214
   }
@@ -234,9 +216,7 @@ void set_pwm_frequency(const pin_t pin, int f_desired) {
234 216
   _SET_CSn(timer.TCCRnQ, j);
235 217
 
236 218
   if (timer.n == 2) {
237
-    #if ENABLED(USE_OCR2A_AS_TOP)
238
-      _SET_OCRnQ(timer.OCRnQ, 0, res);  // Set OCR2A value (TOP) = res
239
-    #endif
219
+    TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer.OCRnQ, 0, res));  // Set OCR2A value (TOP) = res
240 220
   }
241 221
   else
242 222
     _SET_ICRn(timer.ICRn, res);         // Set ICRn value (TOP) = res
@@ -257,15 +237,9 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
257 237
       Timer timer = get_pwm_timer(pin);
258 238
       if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
259 239
       // Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
260
-      _SET_COMnQ(timer.TCCRnQ, (timer.q
261
-          #ifdef TCCR2
262
-            + (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro
263
-          #endif
264
-        ), COM_CLEAR_SET + invert
265
-      );
266
-
267
-      uint16_t top = (timer.n == 2) ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
268
-      _SET_OCRnQ(timer.OCRnQ, timer.q, (v * top + v_size / 2) / v_size); // Scale 8/16-bit v to top value
240
+      _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
241
+      const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
242
+      _SET_OCRnQ(timer.OCRnQ, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
269 243
     }
270 244
 
271 245
   #else

+ 12
- 18
Marlin/src/HAL/AVR/fastio.h View File

@@ -211,32 +211,32 @@ enum ClockSource2 : char {
211 211
 
212 212
 // Set Clock Select bits
213 213
 // Ex: SET_CS3(PRESCALER_64);
214
+#ifdef TCCR2
215
+  #define HAS_TCCR2 1
216
+#endif
214 217
 #define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
215 218
 #define _SET_CS0(V) _SET_CS(0,V)
216 219
 #define _SET_CS1(V) _SET_CS(1,V)
217
-#ifdef TCCR2
218
-  #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
219
-#else
220
-  #define _SET_CS2(V) _SET_CS(2,V)
221
-#endif
222 220
 #define _SET_CS3(V) _SET_CS(3,V)
223 221
 #define _SET_CS4(V) _SET_CS(4,V)
224 222
 #define _SET_CS5(V) _SET_CS(5,V)
225 223
 #define SET_CS0(V) _SET_CS0(CS_##V)
226 224
 #define SET_CS1(V) _SET_CS1(CS_##V)
227
-#ifdef TCCR2
225
+
226
+#if HAS_TCCR2
227
+  #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
228 228
   #define SET_CS2(V) _SET_CS2(CS2_##V)
229 229
 #else
230
+  #define _SET_CS2(V) _SET_CS(2,V)
230 231
   #define SET_CS2(V) _SET_CS2(CS_##V)
231 232
 #endif
233
+
232 234
 #define SET_CS3(V) _SET_CS3(CS_##V)
233 235
 #define SET_CS4(V) _SET_CS4(CS_##V)
234 236
 #define SET_CS5(V) _SET_CS5(CS_##V)
235 237
 #define SET_CS(T,V) SET_CS##T(V)
236 238
 // Runtime (see set_pwm_frequency)
237
-#define _SET_CSn(TCCRnQ, V) do{ \
238
-    (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \
239
-  }while(0)
239
+#define _SET_CSn(TCCRnQ, V) (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
240 240
 
241 241
 // Set Compare Mode bits
242 242
 // Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
@@ -247,21 +247,15 @@ enum ClockSource2 : char {
247 247
 #define SET_COMC(T,V) SET_COM(T,C,V)
248 248
 #define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
249 249
 // Runtime (see set_pwm_duty)
250
-#define _SET_COMnQ(TCCRnQ, Q, V) do{ \
251
-    (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \
252
-  }while(0)
250
+#define _SET_COMnQ(TCCRnQ, Q, V) (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
253 251
 
254 252
 // Set OCRnQ register
255 253
 // Runtime (see set_pwm_duty):
256
-#define _SET_OCRnQ(OCRnQ, Q, V) do{ \
257
-    (*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \
258
-  }while(0)
254
+#define _SET_OCRnQ(OCRnQ, Q, V) (*(OCRnQ)[Q] = int(V) & 0xFFFF)
259 255
 
260 256
 // Set ICRn register (one per timer)
261 257
 // Runtime (see set_pwm_frequency)
262
-#define _SET_ICRn(ICRn, V) do{ \
263
-    (*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \
264
-  }while(0)
258
+#define _SET_ICRn(ICRn, V) (*(ICRn) = int(V) & 0xFFFF)
265 259
 
266 260
 // Set Noise Canceler bit
267 261
 // Ex: SET_ICNC(2,1)

+ 1
- 1
Marlin/src/HAL/AVR/inc/SanityCheck.h View File

@@ -28,7 +28,7 @@
28 28
 /**
29 29
  * Checks for FAST PWM
30 30
  */
31
-#if ENABLED(FAST_PWM_FAN) && (ENABLED(USE_OCR2A_AS_TOP) && defined(TCCR2))
31
+#if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2)
32 32
   #error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2"
33 33
 #endif
34 34
 

+ 22
- 21
Marlin/src/HAL/AVR/pinsDebug.h View File

@@ -102,7 +102,7 @@ void PRINT_ARRAY_NAME(uint8_t x) {
102 102
       return true;                                              \
103 103
     } else return false
104 104
 
105
-
105
+#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1)
106 106
 
107 107
 /**
108 108
  * Print a pin's PWM status.
@@ -113,7 +113,7 @@ static bool pwm_status(uint8_t pin) {
113 113
 
114 114
   switch (digitalPinToTimer_DEBUG(pin)) {
115 115
 
116
-    #if defined(TCCR0A) && defined(COM0A1)
116
+    #if ABTEST(0)
117 117
       #ifdef TIMER0A
118 118
         #if !AVR_AT90USB1286_FAMILY  // not available in Teensyduino type IDEs
119 119
           PWM_CASE(0, A);
@@ -122,20 +122,20 @@ static bool pwm_status(uint8_t pin) {
122 122
       PWM_CASE(0, B);
123 123
     #endif
124 124
 
125
-    #if defined(TCCR1A) && defined(COM1A1)
125
+    #if ABTEST(1)
126 126
       PWM_CASE(1, A);
127 127
       PWM_CASE(1, B);
128
-     #if defined(COM1C1) && defined(TIMER1C)
129
-      PWM_CASE(1, C);
130
-     #endif
128
+      #if defined(COM1C1) && defined(TIMER1C)
129
+        PWM_CASE(1, C);
130
+      #endif
131 131
     #endif
132 132
 
133
-    #if defined(TCCR2A) && defined(COM2A1)
133
+    #if ABTEST(2)
134 134
       PWM_CASE(2, A);
135 135
       PWM_CASE(2, B);
136 136
     #endif
137 137
 
138
-    #if defined(TCCR3A) && defined(COM3A1)
138
+    #if ABTEST(3)
139 139
       PWM_CASE(3, A);
140 140
       PWM_CASE(3, B);
141 141
       #ifdef COM3C1
@@ -149,7 +149,7 @@ static bool pwm_status(uint8_t pin) {
149 149
       PWM_CASE(4, C);
150 150
     #endif
151 151
 
152
-    #if defined(TCCR5A) && defined(COM5A1)
152
+    #if ABTEST(5)
153 153
       PWM_CASE(5, A);
154 154
       PWM_CASE(5, B);
155 155
       PWM_CASE(5, C);
@@ -166,16 +166,16 @@ static bool pwm_status(uint8_t pin) {
166 166
 const volatile uint8_t* const PWM_other[][3] PROGMEM = {
167 167
     { &TCCR0A, &TCCR0B, &TIMSK0 },
168 168
     { &TCCR1A, &TCCR1B, &TIMSK1 },
169
-  #if defined(TCCR2A) && defined(COM2A1)
169
+  #if ABTEST(2)
170 170
     { &TCCR2A, &TCCR2B, &TIMSK2 },
171 171
   #endif
172
-  #if defined(TCCR3A) && defined(COM3A1)
172
+  #if ABTEST(3)
173 173
     { &TCCR3A, &TCCR3B, &TIMSK3 },
174 174
   #endif
175 175
   #ifdef TCCR4A
176 176
     { &TCCR4A, &TCCR4B, &TIMSK4 },
177 177
   #endif
178
-  #if defined(TCCR5A) && defined(COM5A1)
178
+  #if ABTEST(5)
179 179
     { &TCCR5A, &TCCR5B, &TIMSK5 },
180 180
   #endif
181 181
 };
@@ -195,11 +195,11 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
195 195
    { (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
196 196
   #endif
197 197
 
198
-  #if defined(TCCR2A) && defined(COM2A1)
198
+  #if ABTEST(2)
199 199
     { &OCR2A, &OCR2B, 0 },
200 200
   #endif
201 201
 
202
-  #if defined(TCCR3A) && defined(COM3A1)
202
+  #if ABTEST(3)
203 203
     #ifdef COM3C1
204 204
       { (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
205 205
     #else
@@ -211,7 +211,7 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
211 211
     { (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
212 212
   #endif
213 213
 
214
-  #if defined(TCCR5A) && defined(COM5A1)
214
+  #if ABTEST(5)
215 215
     { (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
216 216
   #endif
217 217
 };
@@ -281,7 +281,7 @@ void timer_prefix(uint8_t T, char L, uint8_t N) {  // T - timer    L - pwm  N -
281 281
 static void pwm_details(uint8_t pin) {
282 282
   switch (digitalPinToTimer_DEBUG(pin)) {
283 283
 
284
-    #if defined(TCCR0A) && defined(COM0A1)
284
+    #if ABTEST(0)
285 285
       #ifdef TIMER0A
286 286
         #if !AVR_AT90USB1286_FAMILY  // not available in Teensyduino type IDEs
287 287
           case TIMER0A: timer_prefix(0, 'A', 3); break;
@@ -290,7 +290,7 @@ static void pwm_details(uint8_t pin) {
290 290
       case TIMER0B: timer_prefix(0, 'B', 3); break;
291 291
     #endif
292 292
 
293
-    #if defined(TCCR1A) && defined(COM1A1)
293
+    #if ABTEST(1)
294 294
       case TIMER1A: timer_prefix(1, 'A', 4); break;
295 295
       case TIMER1B: timer_prefix(1, 'B', 4); break;
296 296
       #if defined(COM1C1) && defined(TIMER1C)
@@ -298,12 +298,12 @@ static void pwm_details(uint8_t pin) {
298 298
       #endif
299 299
     #endif
300 300
 
301
-    #if defined(TCCR2A) && defined(COM2A1)
301
+    #if ABTEST(2)
302 302
       case TIMER2A: timer_prefix(2, 'A', 3); break;
303 303
       case TIMER2B: timer_prefix(2, 'B', 3); break;
304 304
     #endif
305 305
 
306
-    #if defined(TCCR3A) && defined(COM3A1)
306
+    #if ABTEST(3)
307 307
       case TIMER3A: timer_prefix(3, 'A', 4); break;
308 308
       case TIMER3B: timer_prefix(3, 'B', 4); break;
309 309
       #ifdef COM3C1
@@ -317,7 +317,7 @@ static void pwm_details(uint8_t pin) {
317 317
       case TIMER4C: timer_prefix(4, 'C', 4); break;
318 318
     #endif
319 319
 
320
-    #if defined(TCCR5A) && defined(COM5A1)
320
+    #if ABTEST(5)
321 321
       case TIMER5A: timer_prefix(5, 'A', 4); break;
322 322
       case TIMER5B: timer_prefix(5, 'B', 4); break;
323 323
       case TIMER5C: timer_prefix(5, 'C', 4); break;
@@ -351,7 +351,6 @@ static void pwm_details(uint8_t pin) {
351 351
   #endif
352 352
 } // pwm_details
353 353
 
354
-
355 354
 #ifndef digitalRead_mod                   // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
356 355
   int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed
357 356
     const uint8_t port = digitalPinToPort_DEBUG(pin);
@@ -397,3 +396,5 @@ static void pwm_details(uint8_t pin) {
397 396
 
398 397
 #define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
399 398
 #define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d)  "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
399
+
400
+#undef ABTEST

+ 8
- 4
Marlin/src/feature/controllerfan.cpp View File

@@ -72,10 +72,14 @@ void ControllerFan::update() {
72 72
       ? settings.active_speed : settings.idle_speed
73 73
     );
74 74
 
75
-    if (PWM_PIN(CONTROLLER_FAN_PIN))
76
-      set_pwm_duty(pin_t(CONTROLLER_FAN_PIN), speed);
77
-    else
78
-      WRITE(CONTROLLER_FAN_PIN, speed);
75
+    #if ENABLED(FAN_SOFT_PWM)
76
+      thermalManager.soft_pwm_controller_speed = speed;
77
+    #else
78
+      if (PWM_PIN(CONTROLLER_FAN_PIN))
79
+        set_pwm_duty(pin_t(CONTROLLER_FAN_PIN), speed);
80
+      else
81
+        WRITE(CONTROLLER_FAN_PIN, speed > 0);
82
+    #endif
79 83
   }
80 84
 }
81 85
 

+ 2
- 2
Marlin/src/lcd/menu/menu_configuration.cpp View File

@@ -266,10 +266,10 @@ void menu_advanced_settings();
266 266
   void menu_controller_fan() {
267 267
     START_MENU();
268 268
     BACK_ITEM(MSG_CONFIGURATION);
269
-    EDIT_ITEM_FAST(percent, MSG_CONTROLLER_FAN_IDLE_SPEED, &controllerFan.settings.idle_speed, _MAX(1, CONTROLLERFAN_SPEED_MIN) - 1, 255);
269
+    EDIT_ITEM_FAST(percent, MSG_CONTROLLER_FAN_IDLE_SPEED, &controllerFan.settings.idle_speed, CONTROLLERFAN_SPEED_MIN, 255);
270 270
     EDIT_ITEM(bool, MSG_CONTROLLER_FAN_AUTO_ON, &controllerFan.settings.auto_mode);
271 271
     if (controllerFan.settings.auto_mode) {
272
-      EDIT_ITEM_FAST(percent, MSG_CONTROLLER_FAN_SPEED, &controllerFan.settings.active_speed, _MAX(1, CONTROLLERFAN_SPEED_MIN) - 1, 255);
272
+      EDIT_ITEM_FAST(percent, MSG_CONTROLLER_FAN_SPEED, &controllerFan.settings.active_speed, CONTROLLERFAN_SPEED_MIN, 255);
273 273
       EDIT_ITEM(uint16_4, MSG_CONTROLLER_FAN_DURATION, &controllerFan.settings.duration, 0, 4800);
274 274
     }
275 275
     END_MENU();

+ 19
- 0
Marlin/src/module/temperature.cpp View File

@@ -41,6 +41,10 @@
41 41
   #include "../feature/spindle_laser.h"
42 42
 #endif
43 43
 
44
+#if ENABLED(USE_CONTROLLER_FAN)
45
+  #include "../feature/controllerfan.h"
46
+#endif
47
+
44 48
 #if ENABLED(EMERGENCY_PARSER)
45 49
   #include "motion.h"
46 50
 #endif
@@ -302,6 +306,10 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED);
302 306
   uint8_t Temperature::coolerfan_speed; // = 0
303 307
 #endif
304 308
 
309
+#if BOTH(FAN_SOFT_PWM, USE_CONTROLLER_FAN)
310
+  uint8_t Temperature::soft_pwm_controller_speed;
311
+#endif
312
+
305 313
 // Init fans according to whether they're native PWM or Software PWM
306 314
 #ifdef BOARD_OPENDRAIN_MOSFETS
307 315
   #define _INIT_SOFT_FAN(P) OUT_WRITE_OD(P, FAN_INVERTING ? LOW : HIGH)
@@ -3021,6 +3029,10 @@ void Temperature::isr() {
3021 3029
     static SoftPWM soft_pwm_cooler;
3022 3030
   #endif
3023 3031
 
3032
+  #if BOTH(FAN_SOFT_PWM, USE_CONTROLLER_FAN)
3033
+    static SoftPWM soft_pwm_controller;
3034
+  #endif
3035
+
3024 3036
   #define WRITE_FAN(n, v) WRITE(FAN##n##_PIN, (v) ^ FAN_INVERTING)
3025 3037
 
3026 3038
   #if DISABLED(SLOW_PWM_HEATERS)
@@ -3056,6 +3068,10 @@ void Temperature::isr() {
3056 3068
         _PWM_MOD(COOLER, soft_pwm_cooler, temp_cooler);
3057 3069
       #endif
3058 3070
 
3071
+      #if BOTH(USE_CONTROLLER_FAN, FAN_SOFT_PWM)
3072
+        WRITE(CONTROLLER_FAN_PIN, soft_pwm_controller.add(pwm_mask, soft_pwm_controller_speed));
3073
+      #endif
3074
+
3059 3075
       #if ENABLED(FAN_SOFT_PWM)
3060 3076
         #define _FAN_PWM(N) do{                                     \
3061 3077
           uint8_t &spcf = soft_pwm_count_fan[N];                    \
@@ -3132,6 +3148,9 @@ void Temperature::isr() {
3132 3148
         #if HAS_FAN7
3133 3149
           if (soft_pwm_count_fan[7] <= pwm_count_tmp) WRITE_FAN(7, LOW);
3134 3150
         #endif
3151
+        #if ENABLED(USE_CONTROLLER_FAN)
3152
+          if (soft_pwm_controller.count <= pwm_count_tmp) WRITE(CONTROLLER_FAN_PIN, LOW);
3153
+        #endif
3135 3154
       #endif
3136 3155
     }
3137 3156
 

+ 4
- 0
Marlin/src/module/temperature.h View File

@@ -387,6 +387,10 @@ class Temperature {
387 387
                      soft_pwm_count_fan[FAN_COUNT];
388 388
     #endif
389 389
 
390
+    #if BOTH(FAN_SOFT_PWM, USE_CONTROLLER_FAN)
391
+      static uint8_t soft_pwm_controller_speed;
392
+    #endif
393
+
390 394
     #if ENABLED(PREVENT_COLD_EXTRUSION)
391 395
       static bool allow_cold_extrude;
392 396
       static celsius_t extrude_min_temp;

Loading…
Cancel
Save