Browse Source

MK3s IR sensor improvement (#2698)

* Update EEPROM_FSENSOR_PCB documentation

* Update IR sensor check

* Rename IR messags and add UNKNOWN state

* Update code to use new messages

* To be continued

* Move fsensor related things from ultralcd.h to fsensor.h

* Use defined Thresholds

* IR sensor auto detection "0.3 or older" and "0.4 or newer" when trigger status changes.
Typo fixes
Doxygen documentation

* Cleanup spaces

* Revert PF-build.sh changes

* re-add space in messages

* revert doxygen snytax

* Remove double _Undef

* Fix indentation and doxygen syntax

* Fix indentation

* Better message handling

* Fix indentation

* Fix indentation

* More indentation fixwa

* Extract common code into manage_inactivity_IR_ANALOG_Check

Saves ~60B of code

* Revert indentation changes on fsensor.cpp

* Keep the selftest IR sensor part disabled

Everything shall happen at runtime

* Fix indentation fsensor_update

* Fix another misleading indentation in fsensor_update

Co-authored-by: Alex Voinea <voinea.dragos.alexandru@gmail.com>
Co-authored-by: D.R.racer <drracer@drracer.eu>
3d-gussner 3 years ago
parent
commit
d1865fc59a
8 changed files with 242 additions and 198 deletions
  1. 64 51
      Firmware/Marlin_main.cpp
  2. 3 2
      Firmware/eeprom.h
  3. 117 91
      Firmware/fsensor.cpp
  4. 14 0
      Firmware/fsensor.h
  5. 3 2
      Firmware/messages.c
  6. 3 2
      Firmware/messages.h
  7. 37 32
      Firmware/ultralcd.cpp
  8. 1 18
      Firmware/ultralcd.h

+ 64 - 51
Firmware/Marlin_main.cpp

@@ -9451,7 +9451,32 @@ static void handleSafetyTimer()
 }
 #endif //SAFETYTIMER
 
-#define FS_CHECK_COUNT 250
+#ifdef IR_SENSOR_ANALOG
+#define FS_CHECK_COUNT 16
+/// Switching mechanism of the fsensor type.
+/// Called from 2 spots which have a very similar behavior
+/// 1: ClFsensorPCB::_Old -> ClFsensorPCB::_Rev04 and print _i("FS v0.4 or newer")
+/// 2: ClFsensorPCB::_Rev04 -> oFsensorPCB=ClFsensorPCB::_Old and print _i("FS v0.3 or older")
+void manage_inactivity_IR_ANALOG_Check(uint16_t &nFSCheckCount, ClFsensorPCB isVersion, ClFsensorPCB switchTo, const char *statusLineTxt_P) {
+    bool bTemp = (!CHECK_ALL_HEATERS);
+    bTemp = bTemp && (menu_menu == lcd_status_screen);
+    bTemp = bTemp && ((oFsensorPCB == isVersion) || (oFsensorPCB == ClFsensorPCB::_Undef));
+    bTemp = bTemp && fsensor_enabled;
+    if (bTemp) {
+        nFSCheckCount++;
+        if (nFSCheckCount > FS_CHECK_COUNT) {
+            nFSCheckCount = 0; // not necessary
+            oFsensorPCB = switchTo;
+            eeprom_update_byte((uint8_t *)EEPROM_FSENSOR_PCB, (uint8_t)oFsensorPCB);
+            printf_IRSensorAnalogBoardChange();
+            lcd_setstatuspgm(statusLineTxt_P);
+        }
+    } else {
+        nFSCheckCount = 0;
+    }
+}
+#endif
+
 void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h
 {
 #ifdef FILAMENT_SENSOR
@@ -9464,15 +9489,15 @@ static uint16_t nFSCheckCount=0;
 	{
 //-//		if (mcode_in_progress != 600) //M600 not in progress
 #ifdef PAT9125
-          bInhibitFlag=(menu_menu==lcd_menu_extruder_info); // Support::ExtruderInfo menu active
+		bInhibitFlag=(menu_menu==lcd_menu_extruder_info); // Support::ExtruderInfo menu active
 #endif // PAT9125
 #ifdef IR_SENSOR
-          bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active
+		bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active
 #ifdef IR_SENSOR_ANALOG
-          bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Settings::HWsetup::FSdetect menu active
+		bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Settings::HWsetup::FSdetect menu active
 #endif // IR_SENSOR_ANALOG
 #endif // IR_SENSOR
-          if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
+		if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
 		{
 			if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && ! eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))
 			{
@@ -9483,7 +9508,7 @@ static uint16_t nFSCheckCount=0;
 				if( current_voltage_raw_IR > maxVolt )maxVolt = current_voltage_raw_IR;
 				if( current_voltage_raw_IR < minVolt )minVolt = current_voltage_raw_IR;
 				
-#if 0
+#if 0 // Start: IR Sensor debug info
 				{ // debug print
 					static uint16_t lastVolt = ~0U;
 					if( current_voltage_raw_IR != lastVolt ){
@@ -9491,38 +9516,29 @@ static uint16_t nFSCheckCount=0;
 						lastVolt = current_voltage_raw_IR;
 					}
 				}
-#endif
-				// the trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage
-				// to be detected as the new fsensor
-				// We can either fake it by extending the detection window to a looooong time
-				// or do some other countermeasures
-				
-				// what we want to detect:
-				// if minvolt gets below ~0.6V, it means there is an old fsensor
-				// if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor
-				// So I'm waiting for a situation, when minVolt gets to range <0, 0.7> and maxVolt gets into range <4.4, 5>
-				// If and only if minVolt is in range <0.6, 0.7> and maxVolt is in range <4.4, 4.5>, I'm considering a situation with the new fsensor
-				// otherwise, I don't care
+#endif // End: IR Sensor debug info
+				//! The trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage
+				//! to be detected as the new fsensor
+				//! We can either fake it by extending the detection window to a looooong time
+				//! or do some other countermeasures
 				
-				if( minVolt >= Voltage2Raw(0.3F) && minVolt <= Voltage2Raw(0.5F) 
-				 && maxVolt >= Voltage2Raw(4.2F) && maxVolt <= Voltage2Raw(4.6F)
+				//! what we want to detect:
+				//! if minvolt gets below ~0.3V, it means there is an old fsensor
+				//! if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor
+				//! So I'm waiting for a situation, when minVolt gets to range <0, 1.5> and maxVolt gets into range <3.0, 5>
+				//! If and only if minVolt is in range <0.3, 1.5> and maxVolt is in range <3.0, 4.6>, I'm considering a situation with the new fsensor
+				if( minVolt >= IRsensor_Ldiode_TRESHOLD && minVolt <= IRsensor_Lmax_TRESHOLD 
+				 && maxVolt >= IRsensor_Hmin_TRESHOLD && maxVolt <= IRsensor_Hopen_TRESHOLD
 				){
-                    bool bTemp = (!CHECK_ALL_HEATERS);
-                    bTemp = bTemp && (menu_menu==lcd_status_screen);
-                    bTemp = bTemp && ((oFsensorPCB==ClFsensorPCB::_Old)||(oFsensorPCB==ClFsensorPCB::_Undef));
-                    bTemp = bTemp && fsensor_enabled;
-                    if(bTemp){
-                         nFSCheckCount++;
-                         if(nFSCheckCount>FS_CHECK_COUNT){
-                              nFSCheckCount=0;    // not necessary
-                              oFsensorPCB=ClFsensorPCB::_Rev04;
-                              eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
-                              printf_IRSensorAnalogBoardChange(true);
-                              lcd_setstatuspgm(_i("FS v0.4 or newer"));////c=18
-                         }
-                    } else {
-						nFSCheckCount=0;
-					}
+					manage_inactivity_IR_ANALOG_Check(nFSCheckCount, ClFsensorPCB::_Old, ClFsensorPCB::_Rev04, _i("FS v0.4 or newer") ); ////c=18
+				} 
+				//! If and only if minVolt is in range <0.0, 0.3> and maxVolt is in range  <4.6, 5.0V>, I'm considering a situation with the old fsensor
+				//! Note, we are not relying on one voltage here - getting just +5V can mean an old fsensor or a broken new sensor - that's why
+				//! we need to have both voltages detected correctly to allow switching back to the old fsensor.
+				else if( minVolt < IRsensor_Ldiode_TRESHOLD 
+				 && maxVolt > IRsensor_Hopen_TRESHOLD && maxVolt <= IRsensor_VMax_TRESHOLD
+				){
+					manage_inactivity_IR_ANALOG_Check(nFSCheckCount, ClFsensorPCB::_Rev04, oFsensorPCB=ClFsensorPCB::_Old, _i("FS v0.3 or older")); ////c=18
 				}
 #endif // IR_SENSOR_ANALOG
 				if (fsensor_check_autoload())
@@ -9533,7 +9549,7 @@ static uint16_t nFSCheckCount=0;
 //-//					if (degHotend0() > EXTRUDE_MINTEMP)
 if(0)
 					{
-            Sound_MakeCustom(50,1000,false);
+						Sound_MakeCustom(50,1000,false);
 						loading_flag = true;
 						enquecommand_front_P((PSTR("M701")));
 					}
@@ -9544,20 +9560,17 @@ if(0)
 						show_preheat_nozzle_warning();
 						lcd_update_enable(true);
 */
-                              eFilamentAction=FilamentAction::AutoLoad;
-                              bFilamentFirstRun=false;
-                              if(target_temperature[0]>=EXTRUDE_MINTEMP)
-                              {
-                                   bFilamentPreheatState=true;
-//                                   mFilamentItem(target_temperature[0],target_temperature_bed);
-                                   menu_submenu(mFilamentItemForce);
-                              }
-                              else
-                              {
-                                   menu_submenu(lcd_generic_preheat_menu);
-                                   lcd_timeoutToStatus.start();
-                              }
-                         }
+						eFilamentAction=FilamentAction::AutoLoad;
+						bFilamentFirstRun=false;
+						if(target_temperature[0]>=EXTRUDE_MINTEMP){
+							bFilamentPreheatState=true;
+//							mFilamentItem(target_temperature[0],target_temperature_bed);
+							menu_submenu(mFilamentItemForce);
+						} else {
+							menu_submenu(lcd_generic_preheat_menu);
+							lcd_timeoutToStatus.start();
+						}
+					}
 				}
 			}
 			else

+ 3 - 2
Firmware/eeprom.h

@@ -341,8 +341,9 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | 0x0D9F 3487		| uint8		| ^										| 00h 0			| ffh 255				| 8th sheet - bed temp 								| ^				| D3 Ax0d9f C1	
 | 0x0DA0 3488		| uint8		| ^										| 00h 0			| ffh 255				| 8th sheet - PINDA temp 							| ^				| D3 Ax0da0 C1	
 | 0x0DA1 3489		| uint8		| ???									| 00h 0			| ffh 255				| ???												| ???			| D3 Ax0da1 C1
-| 0x0D48 3400		| uint8		| EEPROM_FSENSOR_PCB					| ???			| ffh 255				| Filament Sensor type old vs new					| ???			| D3 Ax0d48 C1
-| ^					| ^			| ^										| ???			| ^						| Filament Sensor type ???							| ^				| ^
+| 0x0D48 3400		| uint8		| EEPROM_FSENSOR_PCB					| ffh 255		| ffh 255				| Filament Sensor type IR unknown					| LCD Support	| D3 Ax0d48 C1
+| ^					| ^			| ^										| 00h 0			| ^						| Filament Sensor type IR 0.3 or older				| ^				| ^
+| ^					| ^			| ^										| 01h 1			| ^						| Filament Sensor type IR 0.4 or newer				| ^				| ^
 | 0x0D47 3399		| uint8		| EEPROM_FSENSOR_ACTION_NA				| 00h 0			| ffh 255				| Filament Sensor action: __Continue__				| LCD menu		| D3 Ax0d47 C1
 | ^					| ^			| ^										| 01h 1			| ^						| Filament Sensor action: __Pause__					| ^				| ^
 | 0x0D37 3383		| float		| EEPROM_UVLO_SAVED_TARGET				| ???			| ff ff ff ffh			| Power panic saved target all-axis					| ???			| D3 Ax0d37 C16

+ 117 - 91
Firmware/fsensor.cpp

@@ -170,6 +170,21 @@ void fsensor_checkpoint_print(void)
     restore_print_from_ram_and_continue(0);
 }
 
+#ifdef IR_SENSOR_ANALOG
+const char* FsensorIRVersionText()
+{
+	switch(oFsensorPCB)
+	{
+		case ClFsensorPCB::_Old:
+			return _T(MSG_IR_03_OR_OLDER);
+		case ClFsensorPCB::_Rev04:
+			return _T(MSG_IR_04_OR_NEWER);
+		default:
+			return _T(MSG_IR_UNKNOWN);
+	}
+}
+#endif //IR_SENSOR_ANALOG
+
 void fsensor_init(void)
 {
 #ifdef PAT9125
@@ -207,9 +222,9 @@ void fsensor_init(void)
 	}
 	printf_P(PSTR("FSensor %S"), (fsensor_enabled?PSTR("ENABLED"):PSTR("DISABLED")));
 #ifdef IR_SENSOR_ANALOG
-     printf_P(PSTR(" (sensor board revision:%S)\n"), (oFsensorPCB==ClFsensorPCB::_Rev04) ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER));
+	printf_P(PSTR(" (sensor board revision:%S)\n"), FsensorIRVersionText());
 #else //IR_SENSOR_ANALOG
-     printf_P(PSTR("\n"));
+	MYSERIAL.println();
 #endif //IR_SENSOR_ANALOG
 	if (check_for_ir_sensor()){
 		ir_sensor_detected = true;
@@ -611,15 +626,15 @@ void fsensor_enque_M600(){
 void fsensor_update(void)
 {
 #ifdef PAT9125
-		if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
-		{
-			fsensor_stop_and_save_print();
+    if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
+        {
+            fsensor_stop_and_save_print();
             KEEPALIVE_STATE(IN_HANDLER);
 
-			bool autoload_enabled_tmp = fsensor_autoload_enabled;
-			fsensor_autoload_enabled = false;
-			bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled;
-			fsensor_oq_meassure_enabled = true;
+            bool autoload_enabled_tmp = fsensor_autoload_enabled;
+            fsensor_autoload_enabled = false;
+            bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled;
+            fsensor_oq_meassure_enabled = true;
 
             // move the nozzle away while checking the filament
             current_position[Z_AXIS] += 0.8;
@@ -629,24 +644,23 @@ void fsensor_update(void)
 
             // check the filament in isolation
             fsensor_reset_err_cnt();
-			fsensor_oq_meassure_start(0);
+            fsensor_oq_meassure_start(0);
             float e_tmp = current_position[E_AXIS];
             current_position[E_AXIS] -= 3;
             plan_buffer_line_curposXYZE(250/60);
             current_position[E_AXIS] = e_tmp;
             plan_buffer_line_curposXYZE(200/60);
             st_synchronize();
-			fsensor_oq_meassure_stop();
+            fsensor_oq_meassure_stop();
 
-			bool err = false;
-			err |= (fsensor_err_cnt > 0);                   // final error count is non-zero
-			err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit
-			err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit
+            bool err = false;
+            err |= (fsensor_err_cnt > 0);                   // final error count is non-zero
+            err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit
+            err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit
 
             fsensor_restore_print_and_continue();
             fsensor_autoload_enabled = autoload_enabled_tmp;
             fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp;
-
             unsigned long now = _millis();
             if (!err && (now - fsensor_softfail_last) > FSENSOR_SOFTERR_DELTA)
                 fsensor_softfail_ccnt = 0;
@@ -663,70 +677,70 @@ void fsensor_update(void)
                 fsensor_softfail_last = 0;
                 fsensor_enque_M600();
             }
-		}
+        }
 #else //PAT9125
-		if (CHECK_FSENSOR && ir_sensor_detected)
+        if (CHECK_FSENSOR && ir_sensor_detected)
         {
-               if(digitalRead(IR_SENSOR_PIN))
-               {                                  // IR_SENSOR_PIN ~ H
+            if(digitalRead(IR_SENSOR_PIN))
+            {                                  // IR_SENSOR_PIN ~ H
 #ifdef IR_SENSOR_ANALOG
-                    if(!bIRsensorStateFlag)
-                    {
-                         bIRsensorStateFlag=true;
-                         nIRsensorLastTime=_millis();
-                    }
-                    else
+                if(!bIRsensorStateFlag)
+                {
+                    bIRsensorStateFlag=true;
+                    nIRsensorLastTime=_millis();
+                }
+                else
+                {
+                    if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY)
                     {
-                         if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY)
-                         {
-                              uint8_t nMUX1,nMUX2;
-                              uint16_t nADC;
-                              bIRsensorStateFlag=false;
-                              // sequence for direct data reading from AD converter
-                              DISABLE_TEMPERATURE_INTERRUPT();
-                              nMUX1=ADMUX;        // ADMUX saving
-                              nMUX2=ADCSRB;
-                              adc_setmux(VOLT_IR_PIN);
-                              ADCSRA|=(1<<ADSC);  // first conversion after ADMUX change discarded (preventively)
-                              while(ADCSRA&(1<<ADSC))
-                                   ;
-                              ADCSRA|=(1<<ADSC);  // second conversion used
-                              while(ADCSRA&(1<<ADSC))
-                                   ;
-                              nADC=ADC;
-                              ADMUX=nMUX1;        // ADMUX restoring
-                              ADCSRB=nMUX2;
-                              ENABLE_TEMPERATURE_INTERRUPT();
-                              // end of sequence for ...
-							  // Detection of correct function of fsensor v04 - it must NOT read >4.6V
-							  // If it does, it means a disconnected cables or faulty board
-                              if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) )
-                              {
-                                   fsensor_disable();
-                                   fsensor_not_responding = true;
-                                   printf_P(PSTR("IR sensor not responding (%d)!\n"),1);
-								   if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause)
-
-								   // if we are printing and FS action is set to "Pause", force pause the print
-                                   if(oFsensorActionNA==ClFsensorActionNA::_Pause)
-                                        lcd_pause_print();
-                              }
-                              else
-                              {
+                        uint8_t nMUX1,nMUX2;
+                        uint16_t nADC;
+                        bIRsensorStateFlag=false;
+                        // sequence for direct data reading from AD converter
+                        DISABLE_TEMPERATURE_INTERRUPT();
+                        nMUX1=ADMUX;        // ADMUX saving
+                        nMUX2=ADCSRB;
+                        adc_setmux(VOLT_IR_PIN);
+                        ADCSRA|=(1<<ADSC);  // first conversion after ADMUX change discarded (preventively)
+                        while(ADCSRA&(1<<ADSC))
+                            ;
+                        ADCSRA|=(1<<ADSC);  // second conversion used
+                        while(ADCSRA&(1<<ADSC))
+                            ;
+                        nADC=ADC;
+                        ADMUX=nMUX1;        // ADMUX restoring
+                        ADCSRB=nMUX2;
+                        ENABLE_TEMPERATURE_INTERRUPT();
+                        // end of sequence for ...
+                        // Detection of correct function of fsensor v04 - it must NOT read >4.6V
+                        // If it does, it means a disconnected cables or faulty board
+                        if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) )
+                        {
+                            fsensor_disable();
+                            fsensor_not_responding = true;
+                            printf_P(PSTR("IR sensor not responding (%d)!\n"),1);
+                            if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause)
+
+                            // if we are printing and FS action is set to "Pause", force pause the print
+                            if(oFsensorActionNA==ClFsensorActionNA::_Pause)
+                                lcd_pause_print();
+                        }
+                        else
+                        {
 #endif //IR_SENSOR_ANALOG
-                                  fsensor_checkpoint_print();
-                                  fsensor_enque_M600();
+                            fsensor_checkpoint_print();
+                            fsensor_enque_M600();
 #ifdef IR_SENSOR_ANALOG
-                              }
-                         }
+                        }
                     }
-               }
-               else
-               {                                  // IR_SENSOR_PIN ~ L
-                    bIRsensorStateFlag=false;
+                }
+                   }
+                   else
+                   {                                  // IR_SENSOR_PIN ~ L
+                        bIRsensorStateFlag=false;
 #endif //IR_SENSOR_ANALOG
-               }
-		}
+            }
+        }
 #endif //PAT9125
 }
 
@@ -734,24 +748,36 @@ void fsensor_update(void)
 /// This is called only upon start of the printer or when switching the fsensor ON in the menu
 /// We cannot do temporal window checks here (aka the voltage has been in some range for a period of time)
 bool fsensor_IR_check(){
-	if( IRsensor_Lmax_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_Hmin_TRESHOLD ){
-		// If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly.
-		// Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way,
-		// that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual
-		// and would have been considered more like a sabotage than normal printer operation
-		printf_P(PSTR("fsensor in forbidden range 1.5-3V - bad lever\n"));
-		return false; 
-	}
-	
-	if( oFsensorPCB == ClFsensorPCB::_Rev04 ){
-		// newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount
-		if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){
-			printf_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected\n"));
-			return false;
-		}
-	}
-
-	// otherwise the IR fsensor is considered working correctly
-	return true;
+    if( IRsensor_Lmax_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_Hmin_TRESHOLD ){
+        /// If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly.
+        /// Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way,
+        /// that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual
+        /// and would have been considered more like a sabotage than normal printer operation
+        printf_P(PSTR("fsensor in forbidden range 1.5-3V - check sensor\n"));
+        return false; 
+    }
+    if( oFsensorPCB == ClFsensorPCB::_Rev04 ){
+        /// newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount
+        if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){
+            printf_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected\n"));
+            return false;
+        }
+        /// newer IR sensor cannot normally produce 0-0.3V, this is considered a failure 
+#if 0	//Disabled as it has to be decided if we gonna use this or not.
+        if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){
+            printf_P(PSTR("fsensor v0.4 in fault range 0.0-0.3V - wrong IR sensor\n"));
+            return false;
+        }
+#endif
+    }
+    /// If IR sensor is "uknown state" and filament is not loaded > 1.5V return false
+#if 0
+    if( (oFsensorPCB == ClFsensorPCB::_Undef) && ( current_voltage_raw_IR > IRsensor_Lmax_TRESHOLD ) ){
+        printf_P(PSTR("Unknown IR sensor version and no filament loaded detected.\n"));
+        return false;
+    }
+#endif
+    // otherwise the IR fsensor is considered working correctly
+    return true;
 }
 #endif //IR_SENSOR_ANALOG

+ 14 - 0
Firmware/fsensor.h

@@ -83,6 +83,7 @@ extern uint8_t fsensor_log;
 //! @}
 #endif //PAT9125
 
+#define VOLT_DIV_REF 5
 
 #ifdef IR_SENSOR_ANALOG
 #define IR_SENSOR_STEADY 10                       // [ms]
@@ -103,8 +104,21 @@ enum class ClFsensorActionNA:uint_least8_t
 
 extern ClFsensorPCB oFsensorPCB;
 extern ClFsensorActionNA oFsensorActionNA;
+extern const char* FsensorIRVersionText();
 
 extern bool fsensor_IR_check();
+constexpr uint16_t Voltage2Raw(float V){
+	return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
+}
+constexpr float Raw2Voltage(uint16_t raw){
+	return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) );
+}
+constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
+constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
+constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
+constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059
+constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368
+
 #endif //IR_SENSOR_ANALOG
 
 #endif //FSENSOR_H

+ 3 - 2
Firmware/messages.c

@@ -140,8 +140,9 @@ const char MSG_DIM[] PROGMEM_I1 = ISTR("Dim"); ////c=6
 const char MSG_AUTO[] PROGMEM_I1 = ISTR("Auto"); ////c=6
 #ifdef IR_SENSOR_ANALOG
 // Beware - the space at the beginning is necessary since it is reused in LCD menu items which are to be with a space
-const char MSG_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////c=18
-const char MSG_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////c=18
+const char MSG_IR_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////c=18
+const char MSG_IR_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////c=18
+const char MSG_IR_UNKNOWN[] PROGMEM_I1 = ISTR("unknown state");////c=18
 #endif
 
 //not internationalized messages

+ 3 - 2
Firmware/messages.h

@@ -139,8 +139,9 @@ extern const char MSG_BRIGHT[];
 extern const char MSG_DIM[];
 extern const char MSG_AUTO[];
 #ifdef IR_SENSOR_ANALOG
-extern const char MSG_04_OR_NEWER[];
-extern const char MSG_03_OR_OLDER[];
+extern const char MSG_IR_04_OR_NEWER[];
+extern const char MSG_IR_03_OR_OLDER[];
+extern const char MSG_IR_UNKNOWN[];
 #endif
 
 //not internationalized messages

+ 37 - 32
Firmware/ultralcd.cpp

@@ -2166,18 +2166,7 @@ static void lcd_support_menu()
 #ifdef IR_SENSOR_ANALOG
   MENU_ITEM_BACK_P(STR_SEPARATOR);
   MENU_ITEM_BACK_P(PSTR("Fil. sensor v.:"));
-  switch(oFsensorPCB)
-       {
-       case ClFsensorPCB::_Old:
-            MENU_ITEM_BACK_P(_T(MSG_03_OR_OLDER));
-            break;
-       case ClFsensorPCB::_Rev04:
-            MENU_ITEM_BACK_P(_T(MSG_04_OR_NEWER));
-            break;
-       case ClFsensorPCB::_Undef:
-       default:
-            MENU_ITEM_BACK_P(PSTR(" unknown state"));
-       }
+  MENU_ITEM_BACK_P(FsensorIRVersionText());
 #endif // IR_SENSOR_ANALOG
 
 	MENU_ITEM_BACK_P(STR_SEPARATOR);
@@ -5725,7 +5714,9 @@ void lcd_hw_setup_menu(void)                      // can not be "static"
 
 #ifdef IR_SENSOR_ANALOG
     FSENSOR_ACTION_NA;
-    MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
+    //! Fsensor Detection isn't ready for mmu yet it is temporarily disabled.
+    //! @todo Don't forget to remove this as soon Fsensor Detection works with mmu
+    if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
 #endif //IR_SENSOR_ANALOG
     MENU_END();
 }
@@ -7508,8 +7499,8 @@ void lcd_belttest()
 
 #ifdef IR_SENSOR_ANALOG
 // called also from marlin_main.cpp
-void printf_IRSensorAnalogBoardChange(bool bPCBrev04){
-    printf_P(PSTR("Filament sensor board change detected: revision%S\n"), bPCBrev04 ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER));
+void printf_IRSensorAnalogBoardChange(){
+    printf_P(PSTR("Filament sensor board change detected: revision%S\n"), FsensorIRVersionText());
 }
 
 static bool lcd_selftest_IRsensor(bool bStandalone)
@@ -7534,8 +7525,8 @@ static bool lcd_selftest_IRsensor(bool bStandalone)
         return(false);
     }
     if((bPCBrev04 ? 1 : 0) != (uint8_t)oFsensorPCB){        // safer then "(uint8_t)bPCBrev04"
-        printf_IRSensorAnalogBoardChange(bPCBrev04);
         oFsensorPCB=bPCBrev04 ? ClFsensorPCB::_Rev04 : ClFsensorPCB::_Old;
+        printf_IRSensorAnalogBoardChange();
         eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
     }
     return(true);
@@ -7543,22 +7534,26 @@ static bool lcd_selftest_IRsensor(bool bStandalone)
 
 static void lcd_detect_IRsensor(){
     bool bAction;
-
+    bool loaded;
     bMenuFSDetect = true;                               // inhibits some code inside "manage_inactivity()"
-    bAction = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament loaded?"), false, false);
-    if(bAction){
-        lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action."));////c=20 r=4
+    /// Check if filament is loaded. If it is loaded stop detection.
+    /// @todo Add autodetection with MMU2s
+    loaded = ! READ(IR_SENSOR_PIN);
+    if(loaded ){
+        lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action."));
         return;
+    } else {
+        lcd_show_fullscreen_message_and_wait_P(_i("Please check the IR sensor connections and filament is unloaded."));
+        bAction = lcd_selftest_IRsensor(true);
     }
-    bAction = lcd_selftest_IRsensor(true);
-	if(bAction){
+    if(bAction){
         lcd_show_fullscreen_message_and_wait_P(_i("Sensor verified, remove the filament now."));////c=20 r=3
-		// the fsensor board has been successfully identified, any previous "not responding" may be cleared now
-		fsensor_not_responding = false;
+        // the fsensor board has been successfully identified, any previous "not responding" may be cleared now
+        fsensor_not_responding = false;
     } else {
         lcd_show_fullscreen_message_and_wait_P(_i("Verification failed, remove the filament and try again."));////c=20 r=5
-		// here it is unclear what to to with the fsensor_not_responding flag
-	}
+        // here it is unclear what to to with the fsensor_not_responding flag
+    }
     bMenuFSDetect=false;                              // de-inhibits some code inside "manage_inactivity()"
 }
 #endif //IR_SENSOR_ANALOG
@@ -7574,9 +7569,17 @@ bool lcd_selftest()
 	bool _result = true;
 	bool _swapped_fan = false;
 #ifdef IR_SENSOR_ANALOG
-	//!   Check if IR sensor is in unknown state, set it temporarily to 0.3 or older
-	//! @todo This has to be improved
-	if( oFsensorPCB == ClFsensorPCB::_Undef) eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,0);
+	//!   Check if IR sensor is in unknown state, if so run Fsensor Detection
+	//!   As the Fsensor Detection isn't yet ready for the mmu2s we set temporarily the IR sensor 0.3 or older for mmu2s
+	//! @todo Don't forget to remove this as soon Fsensor Detection works with mmu
+	if( oFsensorPCB == ClFsensorPCB::_Undef) {
+		if (!mmu_enabled) {
+			lcd_detect_IRsensor();
+		}
+		else {
+			eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,0);
+		}
+	}
 #endif //IR_SENSOR_ANALOG
 	lcd_wait_for_cool_down();
 	lcd_clear();
@@ -7784,10 +7787,12 @@ bool lcd_selftest()
 				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK
 			}
 #endif //PAT9125
-//#ifdef IR_SENSOR_ANALOG
-#if (0)
+#if 0
+	// Intentionally disabled - that's why we moved the detection to runtime by just checking the two voltages.
+	// The idea is not to force the user to remove and insert the filament on an assembled printer.
+//def IR_SENSOR_ANALOG
 			_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filament sensor
-               _result = lcd_selftest_IRsensor();
+			_result = lcd_selftest_IRsensor();
 			if (_result)
 			{
 				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //filament sensor OK

+ 1 - 18
Firmware/ultralcd.h

@@ -142,7 +142,7 @@ extern uint8_t farm_status;
 
 #ifdef IR_SENSOR_ANALOG
 extern bool bMenuFSDetect;
-void printf_IRSensorAnalogBoardChange(bool bPCBrev04);
+void printf_IRSensorAnalogBoardChange();
 #endif //IR_SENSOR_ANALOG
 
 extern int8_t SilentModeMenu;
@@ -257,21 +257,4 @@ enum class WizState : uint8_t
 
 void lcd_wizard(WizState state);
 
-#define VOLT_DIV_REF 5
-#ifdef IR_SENSOR_ANALOG
-constexpr uint16_t Voltage2Raw(float V){
-	return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
-}
-constexpr float Raw2Voltage(uint16_t raw){
-	return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) );
-}
-constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
-constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
-constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059
-constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
-constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368
-
-
-#endif //IR_SENSOR_ANALOG
-
 #endif //ULTRALCD_H