Browse Source

✨ Fan tachometer support (#23086)

Co-authored-by: Scott Lahteine <github@thinkyhead.com>
Giuliano Zaro 2 years ago
parent
commit
7110d11c9d
No account linked to committer's email address

+ 40
- 0
Marlin/Configuration_adv.h View File

@@ -604,6 +604,40 @@
604 604
 #define COOLER_AUTO_FAN_SPEED 255
605 605
 
606 606
 /**
607
+ * Hotend Cooling Fans tachometers
608
+ *
609
+ * Define one or more tachometer pins to enable fan speed
610
+ * monitoring, and reporting of fan speeds with M123.
611
+ *
612
+ * NOTE: Only works with fans up to 7000 RPM.
613
+ */
614
+//#define FOURWIRES_FANS      // Needed with AUTO_FAN when 4-wire PWM fans are installed
615
+//#define E0_FAN_TACHO_PIN -1
616
+//#define E0_FAN_TACHO_PULLUP
617
+//#define E0_FAN_TACHO_PULLDOWN
618
+//#define E1_FAN_TACHO_PIN -1
619
+//#define E1_FAN_TACHO_PULLUP
620
+//#define E1_FAN_TACHO_PULLDOWN
621
+//#define E2_FAN_TACHO_PIN -1
622
+//#define E2_FAN_TACHO_PULLUP
623
+//#define E2_FAN_TACHO_PULLDOWN
624
+//#define E3_FAN_TACHO_PIN -1
625
+//#define E3_FAN_TACHO_PULLUP
626
+//#define E3_FAN_TACHO_PULLDOWN
627
+//#define E4_FAN_TACHO_PIN -1
628
+//#define E4_FAN_TACHO_PULLUP
629
+//#define E4_FAN_TACHO_PULLDOWN
630
+//#define E5_FAN_TACHO_PIN -1
631
+//#define E5_FAN_TACHO_PULLUP
632
+//#define E5_FAN_TACHO_PULLDOWN
633
+//#define E6_FAN_TACHO_PIN -1
634
+//#define E6_FAN_TACHO_PULLUP
635
+//#define E6_FAN_TACHO_PULLDOWN
636
+//#define E7_FAN_TACHO_PIN -1
637
+//#define E7_FAN_TACHO_PULLUP
638
+//#define E7_FAN_TACHO_PULLDOWN
639
+
640
+/**
607 641
  * Part-Cooling Fan Multiplexer
608 642
  *
609 643
  * This feature allows you to digitally multiplex the fan output.
@@ -3608,6 +3642,12 @@
3608 3642
 //#define CNC_COORDINATE_SYSTEMS
3609 3643
 
3610 3644
 /**
3645
+ * Auto-report fan speed with M123 S<seconds>
3646
+ * Requires fans with tachometer pins
3647
+ */
3648
+//#define AUTO_REPORT_FANS
3649
+
3650
+/**
3611 3651
  * Auto-report temperatures with M155 S<seconds>
3612 3652
  */
3613 3653
 #define AUTO_REPORT_TEMPERATURES

+ 7
- 0
Marlin/src/MarlinCore.cpp View File

@@ -212,6 +212,10 @@
212 212
 
213 213
 #include "module/tool_change.h"
214 214
 
215
+#if HAS_FANCHECK
216
+  #include "feature/fancheck.h"
217
+#endif
218
+
215 219
 #if ENABLED(USE_CONTROLLER_FAN)
216 220
   #include "feature/controllerfan.h"
217 221
 #endif
@@ -829,6 +833,7 @@ void idle(bool no_stepper_sleep/*=false*/) {
829 833
   #if HAS_AUTO_REPORTING
830 834
     if (!gcode.autoreport_paused) {
831 835
       TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick());
836
+      TERN_(AUTO_REPORT_FANS, fan_check.auto_reporter.tick());
832 837
       TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick());
833 838
       TERN_(AUTO_REPORT_POSITION, position_auto_reporter.tick());
834 839
       TERN_(BUFFER_MONITORING, queue.auto_report_buffer_statistics());
@@ -1275,6 +1280,8 @@ void setup() {
1275 1280
     SETUP_RUN(controllerFan.setup());
1276 1281
   #endif
1277 1282
 
1283
+  TERN_(HAS_FANCHECK, fan_check.init());
1284
+
1278 1285
   // UI must be initialized before EEPROM
1279 1286
   // (because EEPROM code calls the UI).
1280 1287
 

+ 1
- 0
Marlin/src/core/language.h View File

@@ -140,6 +140,7 @@
140 140
 #define STR_RESEND                          "Resend: "
141 141
 #define STR_UNKNOWN_COMMAND                 "Unknown command: \""
142 142
 #define STR_ACTIVE_EXTRUDER                 "Active Extruder: "
143
+#define STR_ERR_FANSPEED                    "Fan speed E"
143 144
 
144 145
 #define STR_PROBE_OFFSET                    "Probe Offset"
145 146
 #define STR_SKEW_MIN                        "min_skew_factor: "

+ 207
- 0
Marlin/src/feature/fancheck.cpp View File

@@ -0,0 +1,207 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+/**
24
+ * fancheck.cpp - fan tachometer check
25
+ */
26
+
27
+#include "../inc/MarlinConfig.h"
28
+
29
+#if HAS_FANCHECK
30
+
31
+#include "fancheck.h"
32
+#include "../module/temperature.h"
33
+
34
+#if HAS_AUTO_FAN && EXTRUDER_AUTO_FAN_SPEED != 255 && DISABLED(FOURWIRES_FANS)
35
+  bool FanCheck::measuring = false;
36
+#endif
37
+bool FanCheck::tacho_state[TACHO_COUNT];
38
+uint16_t FanCheck::edge_counter[TACHO_COUNT];
39
+uint8_t FanCheck::rps[TACHO_COUNT];
40
+FanCheck::TachoError FanCheck::error = FanCheck::TachoError::NONE;
41
+bool FanCheck::enabled;
42
+
43
+void FanCheck::init() {
44
+  #define _TACHINIT(N) TERN(E##N##_FAN_TACHO_PULLUP, SET_INPUT_PULLUP, TERN(E##N##_FAN_TACHO_PULLDOWN, SET_INPUT_PULLDOWN, SET_INPUT))(E##N##_FAN_TACHO_PIN)
45
+  #if HAS_E0_FAN_TACHO
46
+    _TACHINIT(0);
47
+  #endif
48
+  #if HAS_E1_FAN_TACHO
49
+    _TACHINIT(1);
50
+  #endif
51
+  #if HAS_E2_FAN_TACHO
52
+    _TACHINIT(2);
53
+  #endif
54
+  #if HAS_E3_FAN_TACHO
55
+    _TACHINIT(3);
56
+  #endif
57
+  #if HAS_E4_FAN_TACHO
58
+    _TACHINIT(4);
59
+  #endif
60
+  #if HAS_E5_FAN_TACHO
61
+    _TACHINIT(5);
62
+  #endif
63
+  #if HAS_E6_FAN_TACHO
64
+    _TACHINIT(6);
65
+  #endif
66
+  #if HAS_E7_FAN_TACHO
67
+    _TACHINIT(7);
68
+  #endif
69
+}
70
+
71
+void FanCheck::update_tachometers() {
72
+  bool status;
73
+
74
+  #define _TACHO_CASE(N) case N: status = READ(E##N##_FAN_TACHO_PIN); break;
75
+  LOOP_L_N(f, TACHO_COUNT) {
76
+    switch (f) {
77
+      #if HAS_E0_FAN_TACHO
78
+        _TACHO_CASE(0)
79
+      #endif
80
+      #if HAS_E1_FAN_TACHO
81
+        _TACHO_CASE(1)
82
+      #endif
83
+      #if HAS_E2_FAN_TACHO
84
+        _TACHO_CASE(2)
85
+      #endif
86
+      #if HAS_E3_FAN_TACHO
87
+        _TACHO_CASE(3)
88
+      #endif
89
+      #if HAS_E4_FAN_TACHO
90
+        _TACHO_CASE(4)
91
+      #endif
92
+      #if HAS_E5_FAN_TACHO
93
+        _TACHO_CASE(5)
94
+      #endif
95
+      #if HAS_E6_FAN_TACHO
96
+        _TACHO_CASE(6)
97
+      #endif
98
+      #if HAS_E7_FAN_TACHO
99
+        _TACHO_CASE(7)
100
+      #endif
101
+      default: continue;
102
+    }
103
+
104
+    if (status != tacho_state[f]) {
105
+      if (measuring) ++edge_counter[f];
106
+      tacho_state[f] = status;
107
+    }
108
+  }
109
+}
110
+
111
+void FanCheck::compute_speed(uint16_t elapsedTime) {
112
+  static uint8_t errors_count[TACHO_COUNT];
113
+  static uint8_t fan_reported_errors_msk = 0;
114
+
115
+  uint8_t fan_error_msk = 0;
116
+  LOOP_L_N(f, TACHO_COUNT) {
117
+    switch (f) {
118
+      TERN_(HAS_E0_FAN_TACHO, case 0:)
119
+      TERN_(HAS_E1_FAN_TACHO, case 1:)
120
+      TERN_(HAS_E2_FAN_TACHO, case 2:)
121
+      TERN_(HAS_E3_FAN_TACHO, case 3:)
122
+      TERN_(HAS_E4_FAN_TACHO, case 4:)
123
+      TERN_(HAS_E5_FAN_TACHO, case 5:)
124
+      TERN_(HAS_E6_FAN_TACHO, case 6:)
125
+      TERN_(HAS_E7_FAN_TACHO, case 7:)
126
+        // Compute fan speed
127
+        rps[f] = edge_counter[f] * float(250) / elapsedTime;
128
+        edge_counter[f] = 0;
129
+
130
+        // Check fan speed
131
+        constexpr int8_t max_extruder_fan_errors = TERN(HAS_PWMFANCHECK, 10000, 5000) / Temperature::fan_update_interval_ms;
132
+
133
+        if (rps[f] >= 20 || TERN0(HAS_AUTO_FAN, thermalManager.autofan_speed[f] == 0))
134
+          errors_count[f] = 0;
135
+        else if (errors_count[f] < max_extruder_fan_errors)
136
+          ++errors_count[f];
137
+        else if (enabled)
138
+          SBI(fan_error_msk, f);
139
+        break;
140
+      }
141
+    }
142
+
143
+  // Drop the error when all fans are ok
144
+  if (!fan_error_msk && error == TachoError::REPORTED) error = TachoError::FIXED;
145
+
146
+  if (error == TachoError::FIXED && !printJobOngoing() && !printingIsPaused()) {
147
+    error = TachoError::NONE; // if the issue has been fixed while the printer is idle, reenable immediately
148
+    ui.reset_alert_level();
149
+  }
150
+
151
+  if (fan_error_msk & ~fan_reported_errors_msk) {
152
+    // Handle new faults only
153
+    LOOP_L_N(f, TACHO_COUNT) if (TEST(fan_error_msk, f)) report_speed_error(f);
154
+  }
155
+  fan_reported_errors_msk = fan_error_msk;
156
+}
157
+
158
+void FanCheck::report_speed_error(uint8_t fan) {
159
+  if (printJobOngoing()) {
160
+    if (error == TachoError::NONE) {
161
+      if (thermalManager.degTargetHotend(fan) != 0) {
162
+        kill(GET_TEXT_F(MSG_FAN_SPEED_FAULT));
163
+        error = TachoError::REPORTED;
164
+      }
165
+      else
166
+        error = TachoError::DETECTED;   // Plans error for next processed command
167
+    }
168
+  }
169
+  else if (!printingIsPaused()) {
170
+    thermalManager.setTargetHotend(0, fan); // Always disable heating
171
+    if (error == TachoError::NONE) error = TachoError::REPORTED;
172
+  }
173
+
174
+  SERIAL_ERROR_MSG(STR_ERR_FANSPEED, fan);
175
+  LCD_ALERTMESSAGE(MSG_FAN_SPEED_FAULT);
176
+}
177
+
178
+void FanCheck::print_fan_states() {
179
+  LOOP_L_N(s, 2) {
180
+    LOOP_L_N(f, TACHO_COUNT) {
181
+      switch (f) {
182
+        TERN_(HAS_E0_FAN_TACHO, case 0:)
183
+        TERN_(HAS_E1_FAN_TACHO, case 1:)
184
+        TERN_(HAS_E2_FAN_TACHO, case 2:)
185
+        TERN_(HAS_E3_FAN_TACHO, case 3:)
186
+        TERN_(HAS_E4_FAN_TACHO, case 4:)
187
+        TERN_(HAS_E5_FAN_TACHO, case 5:)
188
+        TERN_(HAS_E6_FAN_TACHO, case 6:)
189
+        TERN_(HAS_E7_FAN_TACHO, case 7:)
190
+          SERIAL_ECHOPGM("E", f);
191
+          if (s == 0)
192
+            SERIAL_ECHOPGM(":", 60 * rps[f], " RPM ");
193
+          else
194
+            SERIAL_ECHOPGM("@:", TERN(HAS_AUTO_FAN, thermalManager.autofan_speed[f], 255), " ");
195
+          break;
196
+      }
197
+    }
198
+  }
199
+  SERIAL_EOL();
200
+}
201
+
202
+#if ENABLED(AUTO_REPORT_FANS)
203
+  AutoReporter<FanCheck::AutoReportFan> FanCheck::auto_reporter;
204
+  void FanCheck::AutoReportFan::report() { print_fan_states(); }
205
+#endif
206
+
207
+#endif // HAS_FANCHECK

+ 89
- 0
Marlin/src/feature/fancheck.h View File

@@ -0,0 +1,89 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "../inc/MarlinConfig.h"
25
+
26
+#if HAS_FANCHECK
27
+
28
+#include "../MarlinCore.h"
29
+#include "../lcd/marlinui.h"
30
+
31
+#if ENABLED(AUTO_REPORT_FANS)
32
+  #include "../libs/autoreport.h"
33
+#endif
34
+
35
+#if ENABLED(PARK_HEAD_ON_PAUSE)
36
+  #include "../gcode/queue.h"
37
+#endif
38
+
39
+/**
40
+ * fancheck.h
41
+ */
42
+#define TACHO_COUNT TERN(HAS_E7_FAN_TACHO, 8, TERN(HAS_E6_FAN_TACHO, 7, TERN(HAS_E5_FAN_TACHO, 6, TERN(HAS_E4_FAN_TACHO, 5, TERN(HAS_E3_FAN_TACHO, 4, TERN(HAS_E2_FAN_TACHO, 3, TERN(HAS_E1_FAN_TACHO, 2, 1)))))))
43
+
44
+class FanCheck {
45
+  private:
46
+
47
+    enum class TachoError : uint8_t { NONE, DETECTED, REPORTED, FIXED };
48
+
49
+    #if HAS_PWMFANCHECK
50
+      static bool measuring;  // For future use (3 wires PWM controlled fans)
51
+    #else
52
+      static constexpr bool measuring = true;
53
+    #endif
54
+    static bool tacho_state[TACHO_COUNT];
55
+    static uint16_t edge_counter[TACHO_COUNT];
56
+    static uint8_t rps[TACHO_COUNT];
57
+    static TachoError error;
58
+
59
+    static inline void report_speed_error(uint8_t fan);
60
+
61
+  public:
62
+
63
+    static bool enabled;
64
+
65
+    static void init();
66
+    static void update_tachometers();
67
+    static void compute_speed(uint16_t elapsedTime);
68
+    static void print_fan_states();
69
+    #if HAS_PWMFANCHECK
70
+      static inline void toggle_measuring() { measuring = !measuring; }
71
+      static inline bool is_measuring() { return measuring; }
72
+    #endif
73
+
74
+    static inline void check_deferred_error() {
75
+      if (error == TachoError::DETECTED) {
76
+        error = TachoError::REPORTED;
77
+        TERN(PARK_HEAD_ON_PAUSE, queue.inject(F("M125")), kill(GET_TEXT_F(MSG_FAN_SPEED_FAULT)));
78
+      }
79
+    }
80
+
81
+    #if ENABLED(AUTO_REPORT_FANS)
82
+      struct AutoReportFan { static void report(); };
83
+      static AutoReporter<AutoReportFan> auto_reporter;
84
+    #endif
85
+};
86
+
87
+extern FanCheck fan_check;
88
+
89
+#endif // HAS_FANCHECK

+ 1
- 1
Marlin/src/gcode/control/M999.cpp View File

@@ -22,7 +22,7 @@
22 22
 
23 23
 #include "../gcode.h"
24 24
 
25
-#include "../../lcd/marlinui.h" // for lcd_reset_alert_level
25
+#include "../../lcd/marlinui.h" // for ui.reset_alert_level
26 26
 #include "../../MarlinCore.h"   // for marlin_state
27 27
 #include "../queue.h"           // for flush_and_request_resend
28 28
 

+ 10
- 0
Marlin/src/gcode/gcode.cpp View File

@@ -65,6 +65,10 @@ GcodeSuite gcode;
65 65
   #include "../feature/password/password.h"
66 66
 #endif
67 67
 
68
+#if HAS_FANCHECK
69
+  #include "../feature/fancheck.h"
70
+#endif
71
+
68 72
 #include "../MarlinCore.h" // for idle, kill
69 73
 
70 74
 // Inactivity shutdown
@@ -296,6 +300,8 @@ void GcodeSuite::dwell(millis_t time) {
296 300
  * Process the parsed command and dispatch it to its handler
297 301
  */
298 302
 void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
303
+  TERN_(HAS_FANCHECK, fan_check.check_deferred_error());
304
+
299 305
   KEEPALIVE_STATE(IN_HANDLER);
300 306
 
301 307
  /**
@@ -577,6 +583,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
577 583
         case 113: M113(); break;                                  // M113: Set Host Keepalive interval
578 584
       #endif
579 585
 
586
+      #if HAS_FANCHECK
587
+        case 123: M123(); break;                                  // M123: Report fan states or set fans auto-report interval
588
+      #endif
589
+
580 590
       #if HAS_HEATED_BED
581 591
         case 140: M140(); break;                                  // M140: Set bed temperature
582 592
         case 190: M190(); break;                                  // M190: Wait for bed temperature to reach target

+ 5
- 0
Marlin/src/gcode/gcode.h View File

@@ -156,6 +156,7 @@
156 156
  * M121 - Disable endstops detection.
157 157
  *
158 158
  * M122 - Debug stepper (Requires at least one _DRIVER_TYPE defined as TMC2130/2160/5130/5160/2208/2209/2660 or L6470)
159
+ * M123 - Report fan tachometers. (Requires En_FAN_TACHO_PIN) Optionally set auto-report interval. (Requires AUTO_REPORT_FANS)
159 160
  * M125 - Save current position and move to filament change position. (Requires PARK_HEAD_ON_PAUSE)
160 161
  *
161 162
  * M126 - Solenoid Air Valve Open. (Requires BARICUDA)
@@ -736,6 +737,10 @@ private:
736 737
   static void M120();
737 738
   static void M121();
738 739
 
740
+  #if HAS_FANCHECK
741
+    static void M123();
742
+  #endif
743
+
739 744
   #if ENABLED(PARK_HEAD_ON_PAUSE)
740 745
     static void M125();
741 746
   #endif

+ 48
- 0
Marlin/src/gcode/temp/M123.cpp View File

@@ -0,0 +1,48 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../inc/MarlinConfig.h"
24
+
25
+#if HAS_FANCHECK
26
+
27
+#include "../gcode.h"
28
+#include "../../feature/fancheck.h"
29
+
30
+/**
31
+ * M123: Report fan states -or- set interval for auto-report
32
+ *
33
+ *   S<seconds> : Set auto-report interval
34
+ */
35
+void GcodeSuite::M123() {
36
+
37
+  #if ENABLED(AUTO_REPORT_FANS)
38
+    if (parser.seenval('S')) {
39
+      fan_check.auto_reporter.set_interval(parser.value_byte());
40
+      return;
41
+    }
42
+  #endif
43
+
44
+  fan_check.print_fan_states();
45
+
46
+}
47
+
48
+#endif // HAS_FANCHECK

+ 33
- 1
Marlin/src/inc/Conditionals_post.h View File

@@ -2510,10 +2510,42 @@
2510 2510
   #define AUTO_CHAMBER_IS_E 1
2511 2511
 #endif
2512 2512
 
2513
+// Fans check
2514
+#if HAS_HOTEND && PIN_EXISTS(E0_FAN_TACHO)
2515
+  #define HAS_E0_FAN_TACHO 1
2516
+#endif
2517
+#if HOTENDS > 1 && PIN_EXISTS(E1_FAN_TACHO)
2518
+  #define HAS_E1_FAN_TACHO 1
2519
+#endif
2520
+#if HOTENDS > 2 && PIN_EXISTS(E2_FAN_TACHO)
2521
+  #define HAS_E2_FAN_TACHO 1
2522
+#endif
2523
+#if HOTENDS > 3 && PIN_EXISTS(E3_FAN_TACHO)
2524
+  #define HAS_E3_FAN_TACHO 1
2525
+#endif
2526
+#if HOTENDS > 4 && PIN_EXISTS(E4_FAN_TACHO)
2527
+  #define HAS_E4_FAN_TACHO 1
2528
+#endif
2529
+#if HOTENDS > 5 && PIN_EXISTS(E5_FAN_TACHO)
2530
+  #define HAS_E5_FAN_TACHO 1
2531
+#endif
2532
+#if HOTENDS > 6 && PIN_EXISTS(E6_FAN_TACHO)
2533
+  #define HAS_E6_FAN_TACHO 1
2534
+#endif
2535
+#if HOTENDS > 7 && PIN_EXISTS(E7_FAN_TACHO)
2536
+  #define HAS_E7_FAN_TACHO 1
2537
+#endif
2538
+#if ANY(HAS_E0_FAN_TACHO, HAS_E1_FAN_TACHO, HAS_E2_FAN_TACHO, HAS_E3_FAN_TACHO, HAS_E4_FAN_TACHO, HAS_E5_FAN_TACHO, HAS_E6_FAN_TACHO, HAS_E7_FAN_TACHO)
2539
+  #define HAS_FANCHECK 1
2540
+  #if HAS_AUTO_FAN && EXTRUDER_AUTO_FAN_SPEED != 255 && DISABLED(FOURWIRES_FANS)
2541
+    #define HAS_PWMFANCHECK 1
2542
+  #endif
2543
+#endif
2544
+
2513 2545
 #if !HAS_TEMP_SENSOR
2514 2546
   #undef AUTO_REPORT_TEMPERATURES
2515 2547
 #endif
2516
-#if ANY(AUTO_REPORT_TEMPERATURES, AUTO_REPORT_SD_STATUS, AUTO_REPORT_POSITION)
2548
+#if ANY(AUTO_REPORT_TEMPERATURES, AUTO_REPORT_SD_STATUS, AUTO_REPORT_POSITION, AUTO_REPORT_FANS)
2517 2549
   #define HAS_AUTO_REPORTING 1
2518 2550
 #endif
2519 2551
 

+ 25
- 0
Marlin/src/inc/SanityCheck.h View File

@@ -2584,6 +2584,31 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
2584 2584
 #endif
2585 2585
 
2586 2586
 /**
2587
+ * Fan check
2588
+ */
2589
+#if HAS_FANCHECK
2590
+  #if BOTH(E0_FAN_TACHO_PULLUP, E0_FAN_TACHO_PULLDOWN)
2591
+    #error "Enable only one of E0_FAN_TACHO_PULLUP or E0_FAN_TACHO_PULLDOWN."
2592
+  #elif BOTH(E1_FAN_TACHO_PULLUP, E1_FAN_TACHO_PULLDOWN)
2593
+    #error "Enable only one of E1_FAN_TACHO_PULLUP or E1_FAN_TACHO_PULLDOWN."
2594
+  #elif BOTH(E2_FAN_TACHO_PULLUP, E2_FAN_TACHO_PULLDOWN)
2595
+    #error "Enable only one of E2_FAN_TACHO_PULLUP or E2_FAN_TACHO_PULLDOWN."
2596
+  #elif BOTH(E3_FAN_TACHO_PULLUP, E3_FAN_TACHO_PULLDOWN)
2597
+    #error "Enable only one of E3_FAN_TACHO_PULLUP or E3_FAN_TACHO_PULLDOWN."
2598
+  #elif BOTH(E4_FAN_TACHO_PULLUP, E4_FAN_TACHO_PULLDOWN)
2599
+    #error "Enable only one of E4_FAN_TACHO_PULLUP or E4_FAN_TACHO_PULLDOWN."
2600
+  #elif BOTH(E5_FAN_TACHO_PULLUP, E5_FAN_TACHO_PULLDOWN)
2601
+    #error "Enable only one of E5_FAN_TACHO_PULLUP or E5_FAN_TACHO_PULLDOWN."
2602
+  #elif BOTH(E6_FAN_TACHO_PULLUP, E6_FAN_TACHO_PULLDOWN)
2603
+    #error "Enable only one of E6_FAN_TACHO_PULLUP or E6_FAN_TACHO_PULLDOWN."
2604
+  #elif BOTH(E7_FAN_TACHO_PULLUP, E7_FAN_TACHO_PULLDOWN)
2605
+    #error "Enable only one of E7_FAN_TACHO_PULLUP or E7_FAN_TACHO_PULLDOWN."
2606
+  #endif
2607
+#elif ENABLED(AUTO_REPORT_FANS)
2608
+  #error "AUTO_REPORT_FANS requires one or more fans with a tachometer pin."
2609
+#endif
2610
+
2611
+/**
2587 2612
  * Make sure only one EEPROM type is enabled
2588 2613
  */
2589 2614
 #if ENABLED(EEPROM_SETTINGS)

+ 2
- 0
Marlin/src/lcd/language/language_en.h View File

@@ -570,6 +570,7 @@ namespace Language_en {
570 570
   LSTR MSG_INFO_RUNAWAY_OFF               = _UxGT("Runaway Watch: OFF");
571 571
   LSTR MSG_INFO_RUNAWAY_ON                = _UxGT("Runaway Watch: ON");
572 572
   LSTR MSG_HOTEND_IDLE_TIMEOUT            = _UxGT("Hotend Idle Timeout");
573
+  LSTR MSG_FAN_SPEED_FAULT                = _UxGT("Fan speed fault");
573 574
 
574 575
   LSTR MSG_CASE_LIGHT                     = _UxGT("Case Light");
575 576
   LSTR MSG_CASE_LIGHT_BRIGHTNESS          = _UxGT("Light Brightness");
@@ -613,6 +614,7 @@ namespace Language_en {
613 614
   LSTR MSG_RUNOUT_SENSOR                  = _UxGT("Runout Sensor");
614 615
   LSTR MSG_RUNOUT_DISTANCE_MM             = _UxGT("Runout Dist mm");
615 616
   LSTR MSG_RUNOUT_ENABLE                  = _UxGT("Enable Runout");
617
+  LSTR MSG_FANCHECK                       = _UxGT("Fan Tacho Check");
616 618
   LSTR MSG_KILL_HOMING_FAILED             = _UxGT("Homing Failed");
617 619
   LSTR MSG_LCD_PROBING_FAILED             = _UxGT("Probing Failed");
618 620
 

+ 3
- 0
Marlin/src/lcd/language/language_it.h View File

@@ -556,6 +556,7 @@ namespace Language_it {
556 556
   LSTR MSG_INFO_RUNAWAY_OFF               = _UxGT("Controllo fuga: OFF");
557 557
   LSTR MSG_INFO_RUNAWAY_ON                = _UxGT("Controllo fuga: ON");
558 558
   LSTR MSG_HOTEND_IDLE_TIMEOUT            = _UxGT("Timeout inatt.ugello");
559
+  LSTR MSG_FAN_SPEED_FAULT                = _UxGT("Err.vel.della ventola");
559 560
 
560 561
   LSTR MSG_CASE_LIGHT                     = _UxGT("Luci Case");
561 562
   LSTR MSG_CASE_LIGHT_BRIGHTNESS          = _UxGT("Luminosità Luci");
@@ -597,6 +598,8 @@ namespace Language_it {
597 598
   LSTR MSG_FILAMENT_CHANGE_NOZZLE         = _UxGT("  Ugello: ");
598 599
   LSTR MSG_RUNOUT_SENSOR                  = _UxGT("Sens.filo termin.");  // Max 17 characters
599 600
   LSTR MSG_RUNOUT_DISTANCE_MM             = _UxGT("Dist mm filo term.");
601
+  LSTR MSG_RUNOUT_ENABLE                  = _UxGT("Abil.filo termin.");
602
+  LSTR MSG_FANCHECK                       = _UxGT("Verif.tacho vent.");  // Max 17 characters
600 603
   LSTR MSG_KILL_HOMING_FAILED             = _UxGT("Home fallito");
601 604
   LSTR MSG_LCD_PROBING_FAILED             = _UxGT("Sondaggio fallito");
602 605
 

+ 0
- 4
Marlin/src/lcd/marlinui.cpp View File

@@ -1566,10 +1566,6 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
1566 1566
     TERN_(HAS_LCD_MENU, return_to_status());
1567 1567
   }
1568 1568
 
1569
-  #if ANY(PARK_HEAD_ON_PAUSE, SDSUPPORT)
1570
-    #include "../gcode/queue.h"
1571
-  #endif
1572
-
1573 1569
   void MarlinUI::pause_print() {
1574 1570
     #if HAS_LCD_MENU
1575 1571
       synchronize(GET_TEXT(MSG_PAUSING));

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

@@ -34,6 +34,10 @@
34 34
   #include "../../feature/runout.h"
35 35
 #endif
36 36
 
37
+#if HAS_FANCHECK
38
+  #include "../../feature/fancheck.h"
39
+#endif
40
+
37 41
 #if ENABLED(POWER_LOSS_RECOVERY)
38 42
   #include "../../feature/powerloss.h"
39 43
 #endif
@@ -537,6 +541,10 @@ void menu_configuration() {
537 541
     EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled, runout.reset);
538 542
   #endif
539 543
 
544
+  #if HAS_FANCHECK
545
+    EDIT_ITEM(bool, MSG_FANCHECK, &fan_check.enabled);
546
+  #endif
547
+
540 548
   #if ENABLED(POWER_LOSS_RECOVERY)
541 549
     EDIT_ITEM(bool, MSG_OUTAGE_RECOVERY, &recovery.enabled, recovery.changed);
542 550
   #endif

+ 31
- 0
Marlin/src/module/settings.cpp View File

@@ -154,6 +154,10 @@
154 154
   #include "../libs/buzzer.h"
155 155
 #endif
156 156
 
157
+#if HAS_FANCHECK
158
+  #include "../feature/fancheck.h"
159
+#endif
160
+
157 161
 #if ENABLED(DGUS_LCD_UI_MKS)
158 162
   #include "../lcd/extui/dgus/DGUSScreenHandler.h"
159 163
   #include "../lcd/extui/dgus/DGUSDisplayDef.h"
@@ -492,6 +496,13 @@ typedef struct SettingsDataStruct {
492 496
   #endif
493 497
 
494 498
   //
499
+  // Fan tachometer check
500
+  //
501
+  #if HAS_FANCHECK
502
+    bool fan_check_enabled;
503
+  #endif
504
+
505
+  //
495 506
   // MKS UI controller
496 507
   //
497 508
   #if ENABLED(DGUS_LCD_UI_MKS)
@@ -1434,6 +1445,13 @@ void MarlinSettings::postprocess() {
1434 1445
     #endif
1435 1446
 
1436 1447
     //
1448
+    // Fan tachometer check
1449
+    //
1450
+    #if HAS_FANCHECK
1451
+      EEPROM_WRITE(fan_check.enabled);
1452
+    #endif
1453
+
1454
+    //
1437 1455
     // MKS UI controller
1438 1456
     //
1439 1457
     #if ENABLED(DGUS_LCD_UI_MKS)
@@ -2340,6 +2358,14 @@ void MarlinSettings::postprocess() {
2340 2358
       #endif
2341 2359
 
2342 2360
       //
2361
+      // Fan tachometer check
2362
+      //
2363
+      #if HAS_FANCHECK
2364
+        _FIELD_TEST(fan_check_enabled);
2365
+        EEPROM_READ(fan_check.enabled);
2366
+      #endif
2367
+
2368
+      //
2343 2369
       // MKS UI controller
2344 2370
       //
2345 2371
       #if ENABLED(DGUS_LCD_UI_MKS)
@@ -3037,6 +3063,11 @@ void MarlinSettings::reset() {
3037 3063
   #endif
3038 3064
 
3039 3065
   //
3066
+  // Fan tachometer check
3067
+  //
3068
+  TERN_(HAS_FANCHECK, fan_check.enabled = true);
3069
+
3070
+  //
3040 3071
   // MKS UI controller
3041 3072
   //
3042 3073
   TERN_(DGUS_LCD_UI_MKS, MKS_reset_settings());

+ 34
- 33
Marlin/src/module/temperature.cpp View File

@@ -294,7 +294,7 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED);
294 294
   redundant_info_t Temperature::temp_redundant;
295 295
 #endif
296 296
 
297
-#if ENABLED(AUTO_POWER_E_FANS)
297
+#if EITHER(AUTO_POWER_E_FANS, HAS_FANCHECK)
298 298
   uint8_t Temperature::autofan_speed[HOTENDS]; // = { 0 }
299 299
 #endif
300 300
 
@@ -526,8 +526,9 @@ volatile bool Temperature::raw_temps_ready = false;
526 526
   millis_t Temperature::preheat_end_time[HOTENDS] = { 0 };
527 527
 #endif
528 528
 
529
-#if HAS_AUTO_FAN
530
-  millis_t Temperature::next_auto_fan_check_ms = 0;
529
+#if HAS_FAN_LOGIC
530
+  constexpr millis_t Temperature::fan_update_interval_ms;
531
+  millis_t Temperature::fan_update_ms = 0;
531 532
 #endif
532 533
 
533 534
 #if ENABLED(FAN_SOFT_PWM)
@@ -614,7 +615,7 @@ volatile bool Temperature::raw_temps_ready = false;
614 615
       bool heated = false;
615 616
     #endif
616 617
 
617
-    TERN_(HAS_AUTO_FAN, next_auto_fan_check_ms = next_temp_ms + 2500UL);
618
+    TERN_(HAS_FAN_LOGIC, fan_update_ms = next_temp_ms + fan_update_interval_ms);
618 619
 
619 620
     TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_STARTED));
620 621
     TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(isbed ? PID_BED_START : PID_EXTR_START));
@@ -659,12 +660,7 @@ volatile bool Temperature::raw_temps_ready = false;
659 660
           ONHEATING(start_temp, current_temp, target);
660 661
         #endif
661 662
 
662
-        #if HAS_AUTO_FAN
663
-          if (ELAPSED(ms, next_auto_fan_check_ms)) {
664
-            checkExtruderAutoFans();
665
-            next_auto_fan_check_ms = ms + 2500UL;
666
-          }
667
-        #endif
663
+        TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms));
668 664
 
669 665
         if (heating && current_temp > target && ELAPSED(ms, t2 + 5000UL)) {
670 666
           heating = false;
@@ -853,6 +849,7 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {
853 849
 #define _EFANOVERLAP(A,B) _FANOVERLAP(E##A,B)
854 850
 
855 851
 #if HAS_AUTO_FAN
852
+
856 853
   #if EXTRUDER_AUTO_FAN_SPEED != 255
857 854
     #define INIT_E_AUTO_FAN_PIN(P) do{ if (P == FAN1_PIN || P == FAN2_PIN) { SET_PWM(P); SET_FAST_PWM_FREQ(P); } else SET_OUTPUT(P); }while(0)
858 855
   #else
@@ -866,7 +863,7 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {
866 863
 
867 864
   #define CHAMBER_FAN_INDEX HOTENDS
868 865
 
869
-  void Temperature::checkExtruderAutoFans() {
866
+  void Temperature::update_autofans() {
870 867
     #define _EFAN(B,A) _EFANOVERLAP(A,B) ? B :
871 868
     static const uint8_t fanBit[] PROGMEM = {
872 869
       0
@@ -914,36 +911,43 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {
914 911
             break;
915 912
         #endif
916 913
         default:
917
-          #if ENABLED(AUTO_POWER_E_FANS)
914
+          #if EITHER(AUTO_POWER_E_FANS, HAS_FANCHECK)
918 915
             autofan_speed[realFan] = fan_on ? EXTRUDER_AUTO_FAN_SPEED : 0;
919 916
           #endif
920 917
           break;
921 918
       }
922 919
 
920
+      #if BOTH(HAS_FANCHECK, HAS_PWMFANCHECK)
921
+        #define _AUTOFAN_SPEED() fan_check.is_measuring() ? 255 : EXTRUDER_AUTO_FAN_SPEED
922
+      #else
923
+        #define _AUTOFAN_SPEED() 255
924
+      #endif
925
+      #define _AUTOFAN_CASE(N) case N: _UPDATE_AUTO_FAN(E##N, fan_on, _AUTOFAN_SPEED()); break
926
+
923 927
       switch (f) {
924 928
         #if HAS_AUTO_FAN_0
925
-          case 0: _UPDATE_AUTO_FAN(E0, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
929
+          _AUTOFAN_CASE(0);
926 930
         #endif
927 931
         #if HAS_AUTO_FAN_1
928
-          case 1: _UPDATE_AUTO_FAN(E1, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
932
+          _AUTOFAN_CASE(1);
929 933
         #endif
930 934
         #if HAS_AUTO_FAN_2
931
-          case 2: _UPDATE_AUTO_FAN(E2, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
935
+          _AUTOFAN_CASE(2);
932 936
         #endif
933 937
         #if HAS_AUTO_FAN_3
934
-          case 3: _UPDATE_AUTO_FAN(E3, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
938
+          _AUTOFAN_CASE(3);
935 939
         #endif
936 940
         #if HAS_AUTO_FAN_4
937
-          case 4: _UPDATE_AUTO_FAN(E4, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
941
+          _AUTOFAN_CASE(4);
938 942
         #endif
939 943
         #if HAS_AUTO_FAN_5
940
-          case 5: _UPDATE_AUTO_FAN(E5, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
944
+          _AUTOFAN_CASE(5);
941 945
         #endif
942 946
         #if HAS_AUTO_FAN_6
943
-          case 6: _UPDATE_AUTO_FAN(E6, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
947
+          _AUTOFAN_CASE(6);
944 948
         #endif
945 949
         #if HAS_AUTO_FAN_7
946
-          case 7: _UPDATE_AUTO_FAN(E7, fan_on, EXTRUDER_AUTO_FAN_SPEED); break;
950
+          _AUTOFAN_CASE(7);
947 951
         #endif
948 952
         #if HAS_AUTO_CHAMBER_FAN && !AUTO_CHAMBER_IS_E
949 953
           case CHAMBER_FAN_INDEX: _UPDATE_AUTO_FAN(CHAMBER, fan_on, CHAMBER_AUTO_FAN_SPEED); break;
@@ -1367,20 +1371,14 @@ void Temperature::manage_heater() {
1367 1371
       _temp_error((heater_id_t)HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), GET_TEXT_F(MSG_ERR_REDUNDANT_TEMP));
1368 1372
   #endif
1369 1373
 
1370
-  #if HAS_AUTO_FAN
1371
-    if (ELAPSED(ms, next_auto_fan_check_ms)) { // only need to check fan state very infrequently
1372
-      checkExtruderAutoFans();
1373
-      next_auto_fan_check_ms = ms + 2500UL;
1374
-    }
1375
-  #endif
1374
+  // Manage extruder auto fans and/or read fan tachometers
1375
+  TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms));
1376 1376
 
1377
-  #if ENABLED(FILAMENT_WIDTH_SENSOR)
1378
-    /**
1379
-     * Dynamically set the volumetric multiplier based
1380
-     * on the delayed Filament Width measurement.
1381
-     */
1382
-    filwidth.update_volumetric();
1383
-  #endif
1377
+  /**
1378
+   * Dynamically set the volumetric multiplier based
1379
+   * on the delayed Filament Width measurement.
1380
+   */
1381
+  TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_volumetric());
1384 1382
 
1385 1383
   #if HAS_HEATED_BED
1386 1384
 
@@ -3501,6 +3499,9 @@ void Temperature::isr() {
3501 3499
     babystep.task();
3502 3500
   #endif
3503 3501
 
3502
+  // Check fan tachometers
3503
+  TERN_(HAS_FANCHECK, fan_check.update_tachometers());
3504
+
3504 3505
   // Poll endstops state, if required
3505 3506
   endstops.poll();
3506 3507
 

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

@@ -37,6 +37,10 @@
37 37
   #include "../libs/autoreport.h"
38 38
 #endif
39 39
 
40
+#if HAS_FANCHECK
41
+  #include "../feature/fancheck.h"
42
+#endif
43
+
40 44
 #ifndef SOFT_PWM_SCALE
41 45
   #define SOFT_PWM_SCALE 0
42 46
 #endif
@@ -344,6 +348,10 @@ typedef struct { int16_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_ra
344 348
 
345 349
 #endif
346 350
 
351
+#if HAS_AUTO_FAN || HAS_FANCHECK
352
+  #define HAS_FAN_LOGIC 1
353
+#endif
354
+
347 355
 class Temperature {
348 356
 
349 357
   public:
@@ -372,7 +380,7 @@ class Temperature {
372 380
       static redundant_info_t temp_redundant;
373 381
     #endif
374 382
 
375
-    #if ENABLED(AUTO_POWER_E_FANS)
383
+    #if EITHER(AUTO_POWER_E_FANS, HAS_FANCHECK)
376 384
       static uint8_t autofan_speed[HOTENDS];
377 385
     #endif
378 386
     #if ENABLED(AUTO_POWER_CHAMBER_FAN)
@@ -459,6 +467,10 @@ class Temperature {
459 467
       static int16_t lpq_len;
460 468
     #endif
461 469
 
470
+    #if HAS_FAN_LOGIC
471
+      static constexpr millis_t fan_update_interval_ms = TERN(HAS_PWMFANCHECK, 5000, TERN(HAS_FANCHECK, 1000, 2500));
472
+    #endif
473
+
462 474
   private:
463 475
 
464 476
     #if ENABLED(WATCH_HOTENDS)
@@ -510,8 +522,28 @@ class Temperature {
510 522
       static millis_t preheat_end_time[HOTENDS];
511 523
     #endif
512 524
 
513
-    #if HAS_AUTO_FAN
514
-      static millis_t next_auto_fan_check_ms;
525
+    #if HAS_FAN_LOGIC
526
+      static millis_t fan_update_ms;
527
+
528
+      static inline void manage_extruder_fans(millis_t ms) {
529
+        if (ELAPSED(ms, fan_update_ms)) { // only need to check fan state very infrequently
530
+          const millis_t next_ms = ms + fan_update_interval_ms;
531
+          #if HAS_PWMFANCHECK
532
+            #define FAN_CHECK_DURATION 100
533
+            if (fan_check.is_measuring()) {
534
+              fan_check.compute_speed(ms + FAN_CHECK_DURATION - fan_update_ms);
535
+              fan_update_ms = next_ms;
536
+            }
537
+            else
538
+              fan_update_ms = ms + FAN_CHECK_DURATION;
539
+            fan_check.toggle_measuring();
540
+          #else
541
+            TERN_(HAS_FANCHECK, fan_check.compute_speed(next_ms - fan_update_ms));
542
+            fan_update_ms = next_ms;
543
+          #endif
544
+          TERN_(HAS_AUTO_FAN, update_autofans()); // Needed as last when HAS_PWMFANCHECK to properly force fan speed
545
+        }
546
+      }
515 547
     #endif
516 548
 
517 549
     #if ENABLED(PROBING_HEATERS_OFF)
@@ -961,7 +993,7 @@ class Temperature {
961 993
       static int16_t read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex=0));
962 994
     #endif
963 995
 
964
-    static void checkExtruderAutoFans();
996
+    static void update_autofans();
965 997
 
966 998
     #if HAS_HOTEND
967 999
       static float get_pid_output_hotend(const uint8_t e);

+ 8
- 0
Marlin/src/pins/stm32f4/pins_BTT_BTT002_V1_0.h View File

@@ -188,6 +188,14 @@
188 188
   #endif
189 189
 #endif
190 190
 
191
+#ifndef E0_FAN_TACHO_PIN
192
+  #ifdef MK3_FAN_PINS
193
+    #define E0_FAN_TACHO_PIN                PE0   // Fan1
194
+  #else
195
+    #define E0_FAN_TACHO_PIN                PE1   // Fan0
196
+  #endif
197
+#endif
198
+
191 199
 /**
192 200
  * -----------------------------------BTT002 V1.0----------------------------------------
193 201
  *               ------                                          ------                  |

+ 2
- 1
ini/features.ini View File

@@ -107,6 +107,7 @@ CANCEL_OBJECTS                         = src_filter=+<src/feature/cancel_object.
107 107
 CASE_LIGHT_ENABLE                      = src_filter=+<src/feature/caselight.cpp> +<src/gcode/feature/caselight>
108 108
 EXTERNAL_CLOSED_LOOP_CONTROLLER        = src_filter=+<src/feature/closedloop.cpp> +<src/gcode/calibrate/M12.cpp>
109 109
 USE_CONTROLLER_FAN                     = src_filter=+<src/feature/controllerfan.cpp>
110
+HAS_COOLER|LASER_COOLANT_FLOW_METER    = src_filter=+<src/feature/cooler.cpp>
110 111
 HAS_MOTOR_CURRENT_DAC                  = src_filter=+<src/feature/dac>
111 112
 DIRECT_STEPPING                        = src_filter=+<src/feature/direct_stepping.cpp> +<src/gcode/motion/G6.cpp>
112 113
 EMERGENCY_PARSER                       = src_filter=+<src/feature/e_parser.cpp> -<src/gcode/control/M108_*.cpp>
@@ -114,6 +115,7 @@ I2C_POSITION_ENCODERS                  = src_filter=+<src/feature/encoder_i2c.cp
114 115
 IIC_BL24CXX_EEPROM                     = src_filter=+<src/libs/BL24CXX.cpp>
115 116
 HAS_SPI_FLASH                          = src_filter=+<src/libs/W25Qxx.cpp>
116 117
 HAS_ETHERNET                           = src_filter=+<src/feature/ethernet.cpp> +<src/gcode/feature/network/M552-M554.cpp>
118
+HAS_FANCHECK                           = src_filter=+<src/feature/fancheck.cpp> +<src/gcode/temp/M123.cpp>
117 119
 HAS_FANMUX                             = src_filter=+<src/feature/fanmux.cpp>
118 120
 FILAMENT_WIDTH_SENSOR                  = src_filter=+<src/feature/filwidth.cpp> +<src/gcode/feature/filwidth>
119 121
 FWRETRACT                              = src_filter=+<src/feature/fwretract.cpp> +<src/gcode/feature/fwretract>
@@ -211,7 +213,6 @@ GCODE_REPEAT_MARKERS                   = src_filter=+<src/feature/repeat.cpp> +<
211 213
 HAS_EXTRUDERS                          = src_filter=+<src/gcode/units/M82_M83.cpp> +<src/gcode/temp/M104_M109.cpp> +<src/gcode/config/M221.cpp>
212 214
 HAS_TEMP_PROBE                         = src_filter=+<src/gcode/temp/M192.cpp>
213 215
 HAS_COOLER                             = src_filter=+<src/gcode/temp/M143_M193.cpp>
214
-HAS_COOLER|LASER_COOLANT_FLOW_METER    = src_filter=+<src/feature/cooler.cpp>
215 216
 AUTO_REPORT_TEMPERATURES               = src_filter=+<src/gcode/temp/M155.cpp>
216 217
 INCH_MODE_SUPPORT                      = src_filter=+<src/gcode/units/G20_G21.cpp>
217 218
 TEMPERATURE_UNITS_SUPPORT              = src_filter=+<src/gcode/units/M149.cpp>

+ 2
- 0
platformio.ini View File

@@ -111,6 +111,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
111 111
   -<src/feature/e_parser.cpp>
112 112
   -<src/feature/encoder_i2c.cpp>
113 113
   -<src/feature/ethernet.cpp> -<src/gcode/feature/network/M552-M554.cpp>
114
+  -<src/feature/fancheck.cpp>
114 115
   -<src/feature/fanmux.cpp>
115 116
   -<src/feature/filwidth.cpp> -<src/gcode/feature/filwidth>
116 117
   -<src/feature/fwretract.cpp> -<src/gcode/feature/fwretract>
@@ -228,6 +229,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
228 229
   -<src/gcode/sd/M32.cpp>
229 230
   -<src/gcode/sd/M808.cpp>
230 231
   -<src/gcode/temp/M104_M109.cpp>
232
+  -<src/gcode/temp/M123.cpp>
231 233
   -<src/gcode/temp/M155.cpp>
232 234
   -<src/gcode/temp/M192.cpp>
233 235
   -<src/gcode/units/G20_G21.cpp>

Loading…
Cancel
Save