Browse Source

ALTFAN implementation (#2692)

* ALTFAN implementation

* Use CRITICAL_SECTION macros

* Use uint16_t instead of unsigned int

* Add forgotten CRITICAL_SECTION

* Documentation
Alex Voinea 3 years ago
parent
commit
751f810dd7

+ 7 - 0
Firmware/Marlin_main.cpp

@@ -1252,6 +1252,13 @@ void setup()
 	    w25x20cl_err_msg();
 	    printf_P(_n("W25X20CL not responding.\n"));
 	}
+#ifdef EXTRUDER_ALTFAN_DETECT
+	SERIAL_ECHORPGM(_n("Extruder fan type: "));
+	if (extruder_altfan_detect())
+		SERIAL_ECHOLNRPGM(PSTR("ALTFAN"));
+	else
+		SERIAL_ECHOLNRPGM(PSTR("NOCTUA"));
+#endif //EXTRUDER_ALTFAN_DETECT
 
 	plan_init();  // Initialize planner;
 

+ 3 - 2
Firmware/system_timer.h

@@ -8,11 +8,12 @@
 
 #ifdef SYSTEM_TIMER_2
 #include "timer02.h"
+#include "tone04.h"
 #define _millis millis2
 #define _micros micros2
 #define _delay delay2
-#define _tone tone
-#define _noTone noTone
+#define _tone tone4
+#define _noTone noTone4
 
 #define timer02_set_pwm0(pwm0)
 

+ 80 - 78
Firmware/temperature.cpp

@@ -143,14 +143,18 @@ static volatile bool temp_meas_ready = false;
 #ifdef FAN_SOFT_PWM
   static unsigned char soft_pwm_fan;
 #endif
-#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
-    (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
-    (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
+
+uint8_t fanSpeedBckp = 255;
+
+#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
   unsigned long extruder_autofan_last_check = _millis();
-  uint8_t fanSpeedBckp = 255;
+  
   bool fan_measuring = false;
-
-#endif  
+  uint8_t fanState = 0;
+#ifdef EXTRUDER_ALTFAN_DETECT
+  bool extruderFanIsAltfan = false; //set to Noctua
+#endif //EXTRUDER_ALTFAN_DETECT
+#endif
 
 
 #if EXTRUDERS > 3
@@ -210,6 +214,35 @@ static void temp_runaway_check(int _heater_id, float _target_temperature, float
 static void temp_runaway_stop(bool isPreheat, bool isBed);
 #endif
 
+#ifdef EXTRUDER_ALTFAN_DETECT
+ISR(INT6_vect) {
+	fan_edge_counter[0]++;
+}
+
+bool extruder_altfan_detect()
+{
+	setExtruderAutoFanState(3);
+
+	SET_INPUT(TACH_0);
+	CRITICAL_SECTION_START;
+	EICRB &= ~(1 << ISC61);
+	EICRB |= (1 << ISC60);
+	EIMSK |= (1 << INT6);
+	fan_edge_counter[0] = 0;
+	CRITICAL_SECTION_END;
+	extruder_autofan_last_check = _millis();
+
+	_delay(1000);
+
+	EIMSK &= ~(1 << INT6);
+
+	countFanSpeed();
+	extruderFanIsAltfan = fan_speed[0] > 100;
+	setExtruderAutoFanState(1);
+	return extruderFanIsAltfan;
+}
+#endif //EXTRUDER_ALTFAN_DETECT
+
 // return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on')
 bool checkAllHotends(void)
 {
@@ -239,9 +272,7 @@ bool checkAllHotends(void)
   const uint8_t safety_check_cycles_count = (extruder < 0) ? 45 : 10; //10 cycles / 20s delay for extruder and 45 cycles / 90s for heatbed
   float temp_ambient;
 
-#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
-    (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
-    (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
+#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
   unsigned long extruder_autofan_last_check = _millis();
 #endif
 
@@ -289,9 +320,7 @@ bool checkAllHotends(void)
       max=max(max,input);
       min=min(min,input);
 
-      #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
-          (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
-          (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
+      #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
       if(_millis() - extruder_autofan_last_check > 2500) {
         checkExtruderAutoFans();
         extruder_autofan_last_check = _millis();
@@ -447,29 +476,31 @@ int getHeaterPower(int heater) {
   return soft_pwm[heater];
 }
 
-#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
-    (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
-    (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
+#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
 
   #if defined(FAN_PIN) && FAN_PIN > -1
     #if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN 
        #error "You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN"
     #endif
-    #if EXTRUDER_1_AUTO_FAN_PIN == FAN_PIN 
-       #error "You cannot set EXTRUDER_1_AUTO_FAN_PIN equal to FAN_PIN"
-    #endif
-    #if EXTRUDER_2_AUTO_FAN_PIN == FAN_PIN 
-       #error "You cannot set EXTRUDER_2_AUTO_FAN_PIN equal to FAN_PIN"
-    #endif
-  #endif 
+  #endif
 
-void setExtruderAutoFanState(int pin, bool state)
+void setExtruderAutoFanState(uint8_t state)
 {
-  unsigned char newFanSpeed = (state != 0) ? EXTRUDER_AUTO_FAN_SPEED : 0;
-  // this idiom allows both digital and PWM fan outputs (see M42 handling).
-  pinMode(pin, OUTPUT);
-  digitalWrite(pin, newFanSpeed);
-  //analogWrite(pin, newFanSpeed);
+	//If bit 1 is set (0x02), then the extruder fan speed won't be adjusted according to temperature. Useful for forcing
+	//the fan to either On or Off during certain tests/errors.
+
+	fanState = state;
+	uint8_t newFanSpeed = 0;
+	if (fanState & 0x01)
+	{
+#ifdef EXTRUDER_ALTFAN_DETECT
+		if (extruderFanIsAltfan) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT;
+		else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
+#else //EXTRUDER_ALTFAN_DETECT
+		newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
+#endif //EXTRUDER_ALTFAN_DETECT
+	}
+	timer4_set_fan0(newFanSpeed);
 }
 
 #if (defined(FANCHECK) && (((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1)))))
@@ -503,7 +534,7 @@ void checkFanSpeed()
 	  fans_check_enabled = (eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED) > 0);
 	static unsigned char fan_speed_errors[2] = { 0,0 };
 #if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 >-1))
-	if ((fan_speed[0] == 0) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;}
+	if ((fan_speed[0] < 20) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;}
 	else{
     fan_speed_errors[0] = 0;
     host_keepalive();
@@ -577,47 +608,14 @@ void fanSpeedError(unsigned char _fan) {
 
 void checkExtruderAutoFans()
 {
-  uint8_t fanState = 0;
-
-  // which fan pins need to be turned on?      
-  #if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
-  if (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)
-	  fanState |= 1;
-  #endif
-  #if defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1
-    if (current_temperature[1] > EXTRUDER_AUTO_FAN_TEMPERATURE) 
-    {
-      if (EXTRUDER_1_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN) 
-        fanState |= 1;
-      else
-        fanState |= 2;
-    }
-  #endif
-  #if defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1
-    if (current_temperature[2] > EXTRUDER_AUTO_FAN_TEMPERATURE) 
-    {
-      if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN) 
-        fanState |= 1;
-      else if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN) 
-        fanState |= 2;
-      else
-        fanState |= 4;
-    }
-  #endif
-  
-  // update extruder auto fan states
-  #if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
-    setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, (fanState & 1) != 0);
-  #endif 
-  #if defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1
-    if (EXTRUDER_1_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN) 
-      setExtruderAutoFanState(EXTRUDER_1_AUTO_FAN_PIN, (fanState & 2) != 0);
-  #endif 
-  #if defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1
-    if (EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN 
-        && EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN)
-      setExtruderAutoFanState(EXTRUDER_2_AUTO_FAN_PIN, (fanState & 4) != 0);
-  #endif 
+#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
+	if (!(fanState & 0x02))
+	{
+		fanState &= ~1;
+		fanState |= current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE;
+	}
+	setExtruderAutoFanState(fanState);
+#endif 
 }
 
 #endif // any extruder auto fan pins set
@@ -737,9 +735,7 @@ void manage_heater()
 #define FAN_CHECK_DURATION 100 //100ms
 
 #ifndef DEBUG_DISABLE_FANCHECK
-  #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
-      (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
-      (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
+  #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
 
 #ifdef FAN_SOFT_PWM
 #ifdef FANCHECK
@@ -1098,7 +1094,9 @@ void tp_init()
 
   timer0_init();
   OCR2B = 128;
-  TIMSK2 |= (1<<OCIE2B);  
+  TIMSK2 |= (1<<OCIE2B);
+  
+  timer4_init(); //for tone and Extruder fan PWM
   
   // Wait for temperature measurement to settle
   _delay(250);
@@ -1357,9 +1355,11 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
 		isBed ? LCD_ALERTMESSAGEPGM("BED PREHEAT ERROR") : LCD_ALERTMESSAGEPGM("PREHEAT ERROR");
 		SERIAL_ERROR_START;
 		isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)");
-		SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
+#ifdef EXTRUDER_ALTFAN_DETECT
+		extruderFanIsAltfan = false; //full speed
+#endif //EXTRUDER_ALTFAN_DETECT
+		setExtruderAutoFanState(3);
 		SET_OUTPUT(FAN_PIN);
-		WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
 #ifdef FAN_SOFT_PWM
 		fanSpeedSoftPwm = 255;
 #else //FAN_SOFT_PWM
@@ -1441,12 +1441,14 @@ void max_temp_error(uint8_t e) {
 
     
   #endif
-    SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
     SET_OUTPUT(FAN_PIN);
     SET_OUTPUT(BEEPER);
     WRITE(FAN_PIN, 1);
-    WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
     WRITE(BEEPER, 1);
+#ifdef EXTRUDER_ALTFAN_DETECT
+    extruderFanIsAltfan = false; //full speed
+#endif //EXTRUDER_ALTFAN_DETECT
+    setExtruderAutoFanState(3);
     // fanSpeed will consumed by the check_axes_activity() routine.
     fanSpeed=255;
 	if (farm_mode) { prusa_statistics(93); }

+ 5 - 3
Firmware/temperature.h

@@ -245,7 +245,7 @@ FORCE_INLINE void autotempShutdown(){
 
 void PID_autotune(float temp, int extruder, int ncycles);
 
-void setExtruderAutoFanState(int pin, bool state);
+void setExtruderAutoFanState(uint8_t state);
 void checkExtruderAutoFans();
 
 
@@ -270,10 +270,12 @@ void check_fans();
 void check_min_temp();
 void check_max_temp();
 
-
-#endif
+#ifdef EXTRUDER_ALTFAN_DETECT
+  extern bool extruder_altfan_detect();
+#endif //EXTRUDER_ALTFAN_DETECT
 
 extern unsigned long extruder_autofan_last_check;
 extern uint8_t fanSpeedBckp;
 extern bool fan_measuring;
 
+#endif

+ 126 - 0
Firmware/tone04.c

@@ -0,0 +1,126 @@
+//tone04.c
+// use atmega timer4 as main tone timer instead of timer2
+// timer2 is used for System timer.
+
+#include "system_timer.h"
+#include "Configuration_prusa.h"
+
+#ifdef SYSTEM_TIMER_2
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "pins.h"
+
+#ifndef CRITICAL_SECTION_START
+	#define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
+	#define CRITICAL_SECTION_END    SREG = _sreg;
+#endif //CRITICAL_SECTION_START
+
+
+#include "fastio.h"
+
+void timer4_init(void)
+{
+	CRITICAL_SECTION_START;
+	
+	SET_OUTPUT(BEEPER);
+	WRITE(BEEPER, LOW);
+	
+	SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
+	
+	// Set timer mode 9 (PWM,Phase and Frequency Correct)
+	// Prescaler is CLK/1024
+	// Output compare is disabled on all timer pins
+	// Input capture is disabled
+	// All interrupts are disabled
+	TCCR4A = (1 << WGM40);
+	TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40);
+	OCR4A = 255;
+	OCR4B = 255;
+	OCR4C = 255;
+	TIMSK4 = 0;
+	
+	CRITICAL_SECTION_END;
+}
+
+#ifdef EXTRUDER_0_AUTO_FAN_PIN
+void timer4_set_fan0(uint8_t duty)
+{
+	if (duty == 0 || duty == 255)
+	{
+		// We use digital logic if the duty cycle is 0% or 100%
+		TCCR4A &= ~(1 << COM4C1);
+		OCR4C = 0;
+		WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty);
+	}
+	else
+	{
+		// Use the timer for fan speed. Enable the timer compare output and set the duty cycle.
+		// This function also handles the impossible scenario of a fan speed change during a Tone.
+		// Better be safe than sorry.
+		CRITICAL_SECTION_START;
+		// Enable the PWM output on the fan pin.
+		TCCR4A |= (1 << COM4C1);
+		OCR4C = (((uint32_t)duty) * ((uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255))) / ((uint32_t)255);
+		CRITICAL_SECTION_END;
+	}
+}
+#endif //EXTRUDER_0_AUTO_FAN_PIN
+
+// Because of the timer mode change, we need two interrupts. We could also try to assume that the frequency is x2
+// and use a TOGGLE(), but this seems to work well enough so I left it as it is now.
+ISR(TIMER4_COMPA_vect)
+{
+	WRITE(BEEPER, 1);
+}
+
+ISR(TIMER4_OVF_vect)
+{
+	WRITE(BEEPER, 0);
+}
+
+void tone4(__attribute__((unused)) uint8_t _pin, uint16_t frequency)
+{
+	//this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only
+	uint8_t prescalarbits = 0b001;
+	uint32_t ocr = F_CPU / frequency / 2 - 1;
+	
+	if (ocr > 0xffff)
+	{
+		ocr = F_CPU / frequency / 2 / 64 - 1;
+		prescalarbits = 0b011;
+	}
+	
+	CRITICAL_SECTION_START;
+	// Set calcualted prescaler
+	TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
+#ifdef EXTRUDER_0_AUTO_FAN_PIN
+	// Scale the fan PWM duty cycle so that it remains constant, but at the tone frequency
+	OCR4C = (((uint32_t)OCR4C) * ocr) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255);
+#endif //EXTRUDER_0_AUTO_FAN_PIN
+	// Set calcualted ocr
+	OCR4A = ocr;
+	// Enable Output compare A interrupt and timer overflow interrupt
+	TIMSK4 |= (1 << OCIE4A) | (1 << TOIE4);
+	CRITICAL_SECTION_END;
+}
+
+void noTone4(__attribute__((unused)) uint8_t _pin)
+{
+	CRITICAL_SECTION_START;
+	// Revert prescaler to CLK/1024
+	TCCR4B = (TCCR4B & 0b11111000) | (1 << CS42) | (1 << CS40);
+#ifdef EXTRUDER_0_AUTO_FAN_PIN
+	// Scale the fan OCR back to the original value.
+	OCR4C = (((uint32_t)OCR4C) * (uint32_t)255) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255);
+#endif //EXTRUDER_0_AUTO_FAN_PIN
+	OCR4A = 255;
+	// Disable Output compare A interrupt and timer overflow interrupt
+	TIMSK4 &= ~((1 << OCIE4A) | (1 << TOIE4));
+	CRITICAL_SECTION_END;
+	// Turn beeper off if it was on when noTone was called
+	WRITE(BEEPER, 0);
+}
+
+
+#endif //SYSTEM_TIMER_2

+ 25 - 0
Firmware/tone04.h

@@ -0,0 +1,25 @@
+//tone04.h
+// use atmega timer4 as main tone timer instead of timer2
+// timer2 is used for System timer.
+#ifndef TIMER04_H
+#define TIMER04_H
+
+#include <inttypes.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
+extern void timer4_init(void);
+
+extern void timer4_set_fan0(uint8_t duty);
+
+extern void tone4(uint8_t _pin, uint16_t frequency);
+
+extern void noTone4(uint8_t _pin);
+
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+
+#endif //TIMER02_H

+ 7 - 25
Firmware/ultralcd.cpp

@@ -6673,7 +6673,7 @@ static bool fan_error_selftest()
 	fanSpeedSoftPwm = 255;
 #endif //FAN_SOFT_PWM
     manage_heater(); //enables print fan
-    setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, 1); //force enables the extruder fan untill the first manage_heater() call.
+    setExtruderAutoFanState(3); //force enables the extruder fan
 #ifdef FAN_SOFT_PWM
     extruder_autofan_last_check = _millis();
     fan_measuring = true;
@@ -6681,6 +6681,7 @@ static bool fan_error_selftest()
     _delay(1000); //delay_keep_alive would turn off extruder fan, because temerature is too low (maybe)
     manage_heater();
     fanSpeed = 0;
+	setExtruderAutoFanState(1); //releases lock on the extruder fan
 #ifdef FAN_SOFT_PWM
     fanSpeedSoftPwm = 0;
 #endif //FAN_SOFT_PWM
@@ -8468,8 +8469,7 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
 		lcd_set_cursor(0, 1);
 		if(check_opposite == true) lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN)); 
 		else lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN));
-		SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
-		WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
+		setExtruderAutoFanState(3);
 		break;
 	case 1:
 		// object cooling fan
@@ -8498,23 +8498,6 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
 	lcd_button_pressed = false;
 	do
 	{
-		switch (_fan)
-		{
-		case 0:
-			// extruder cooling fan
-			SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
-			WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
-			break;
-		case 1:
-			// object cooling fan
-			SET_OUTPUT(FAN_PIN);
-#ifdef FAN_SOFT_PWM
-			fanSpeedSoftPwm = 255;
-#else //FAN_SOFT_PWM
-			analogWrite(FAN_PIN, 255);
-#endif //FAN_SOFT_PWM
-			break;
-		}
 		if (abs((enc_dif - lcd_encoder_diff)) > 2) {
 			if (enc_dif > lcd_encoder_diff) {
 				_result = !check_opposite;
@@ -8541,8 +8524,7 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
 
 	} while (!lcd_clicked());
 	KEEPALIVE_STATE(IN_HANDLER);
-	SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
-	WRITE(EXTRUDER_0_AUTO_FAN_PIN, 0);
+	setExtruderAutoFanState(0);
 	SET_OUTPUT(FAN_PIN);
 #ifdef FAN_SOFT_PWM
 	fanSpeedSoftPwm = 0;
@@ -8562,13 +8544,13 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
 	case 0:
 		fanSpeed = 0;
 		manage_heater();			//turn off fan
-		setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, 1); //extruder fan
+		setExtruderAutoFanState(3); //extruder fan
 #ifdef FAN_SOFT_PWM
 		extruder_autofan_last_check = _millis();
 		fan_measuring = true;
 #endif //FAN_SOFT_PWM
-		_delay(2000);				//delay_keep_alive would turn off extruder fan, because temerature is too low
-
+		_delay(2000);
+		setExtruderAutoFanState(0); //extruder fan
 		manage_heater();			//count average fan speed from 2s delay and turn off fans
 
 		printf_P(PSTR("Test 1:\n"));

+ 2 - 0
Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h

@@ -331,6 +331,8 @@
 #define EXTRUDER_2_AUTO_FAN_PIN   -1
 #define EXTRUDER_AUTO_FAN_TEMPERATURE 50
 #define EXTRUDER_AUTO_FAN_SPEED   255  // == full speed
+#define EXTRUDER_ALTFAN_DETECT
+#define EXTRUDER_ALTFAN_SPEED_SILENT 128