Browse Source

Merge pull request #2339 from leptun/PFW-943

PFW-943: IR sensor gen. II - Updated PR
DRracer 4 years ago
parent
commit
35ce2896bb

+ 3 - 2
Firmware/adc.c

@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <avr/io.h>
 #include <avr/pgmspace.h>
+#include "pins.h"
 
 uint8_t adc_state;
 uint8_t adc_count;
@@ -24,8 +25,8 @@ void adc_init(void)
 	ADMUX |= (1 << REFS0);
 	ADCSRA |= (1 << ADEN);
 //	ADCSRA |= (1 << ADIF) | (1 << ADSC);
-	DIDR0 = (ADC_CHAN_MSK & 0xff);
-	DIDR2 = (ADC_CHAN_MSK >> 8);
+	DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff);
+	DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8);
 	adc_reset();
 //	adc_sim_mask = 0b0101;
 //	adc_sim_mask = 0b100101;

+ 13 - 4
Firmware/config.h

@@ -2,9 +2,21 @@
 #define _CONFIG_H
 
 
+#include "Configuration_prusa.h"
+#include "pins.h"
+
+#define IR_SENSOR_ANALOG (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
+
 //ADC configuration
+#if !IR_SENSOR_ANALOG
 #define ADC_CHAN_MSK      0b0000001001011111 //used AD channels bit mask (0,1,2,3,4,6,9)
+#define ADC_DIDR_MSK      0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input)
 #define ADC_CHAN_CNT      7         //number of used channels)
+#else //!IR_SENSOR_ANALOG
+#define ADC_CHAN_MSK      0b0000001101011111 //used AD channels bit mask (0,1,2,3,4,6,8,9)
+#define ADC_DIDR_MSK      0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input)
+#define ADC_CHAN_CNT      8         //number of used channels)
+#endif //!IR_SENSOR_ANALOG
 #define ADC_OVRSAMPL      16        //oversampling multiplier
 #define ADC_CALLBACK      adc_ready //callback function ()
 
@@ -42,11 +54,8 @@
 #define W25X20CL_SPCR          SPI_SPCR(W25X20CL_SPI_RATE, 1, 1, 1, 0)
 #define W25X20CL_SPSR          SPI_SPSR(W25X20CL_SPI_RATE)
 
-#include "boards.h"
-#include "Configuration_prusa.h"
-
 //LANG - Multi-language support
-//#define LANG_MODE              0 // primary language only
+//define LANG_MODE              0 // primary language only
 #define LANG_MODE              1 // sec. language support
 
 #define LANG_SIZE_RESERVED     0x3000 // reserved space for secondary language (12288 bytes)

+ 3 - 0
Firmware/eeprom.h

@@ -201,6 +201,9 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 #define EEPROM_SHEETS_BASE (EEPROM_CHECK_GCODE - EEPROM_SHEETS_SIZEOF) // Sheets
 static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
 
+#define EEPROM_FSENSOR_PCB (EEPROM_SHEETS_BASE-1) // uint8
+#define EEPROM_FSENSOR_ACTION_NA (EEPROM_FSENSOR_PCB-1) // uint8
+
 
 //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
 #define EEPROM_LAST_ITEM EEPROM_SHEETS_BASE

+ 120 - 18
Firmware/fsensor.cpp

@@ -15,6 +15,10 @@
 #include "mmu.h"
 #include "cardreader.h"
 
+#include "adc.h"
+#include "temperature.h"
+#include "config.h"
+
 //! @name Basic parameters
 //! @{
 #define FSENSOR_CHUNK_LEN    0.64F  //!< filament sensor chunk length 0.64mm
@@ -117,6 +121,13 @@ int16_t fsensor_oq_yd_max;
 uint16_t fsensor_oq_sh_sum;
 //! @}
 
+#if IR_SENSOR_ANALOG
+ClFsensorPCB oFsensorPCB;
+ClFsensorActionNA oFsensorActionNA;
+bool bIRsensorStateFlag=false;
+unsigned long nIRsensorLastTime;
+#endif //IR_SENSOR_ANALOG
+
 void fsensor_stop_and_save_print(void)
 {
     printf_P(PSTR("fsensor_stop_and_save_print\n"));
@@ -136,10 +147,11 @@ void fsensor_init(void)
 {
 #ifdef PAT9125
 	uint8_t pat9125 = pat9125_init();
-    printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
+     printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
 #endif //PAT9125
 	uint8_t fsensor = eeprom_read_byte((uint8_t*)EEPROM_FSENSOR);
 	fsensor_autoload_enabled=eeprom_read_byte((uint8_t*)EEPROM_FSENS_AUTOLOAD_ENABLED);
+     fsensor_not_responding = false;
 #ifdef PAT9125
 	uint8_t oq_meassure_enabled = eeprom_read_byte((uint8_t*)EEPROM_FSENS_OQ_MEASS_ENABLED);
 	fsensor_oq_meassure_enabled = (oq_meassure_enabled == 1)?true:false;
@@ -150,19 +162,27 @@ void fsensor_init(void)
 		fsensor = 0; //disable sensor
 		fsensor_not_responding = true;
 	}
-	else
-		fsensor_not_responding = false;
 #endif //PAT9125
+#if IR_SENSOR_ANALOG
+     bIRsensorStateFlag=false;
+     oFsensorPCB=(ClFsensorPCB)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_PCB);
+     oFsensorActionNA=(ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA);
+#endif //IR_SENSOR_ANALOG
 	if (fsensor)
-		fsensor_enable();
+		fsensor_enable(false);                  // (in this case) EEPROM update is not necessary
 	else
-		fsensor_disable();
-	printf_P(PSTR("FSensor %S\n"), (fsensor_enabled?PSTR("ENABLED"):PSTR("DISABLED\n")));
+		fsensor_disable(false);                 // (in this case) EEPROM update is not necessary
+	printf_P(PSTR("FSensor %S"), (fsensor_enabled?PSTR("ENABLED"):PSTR("DISABLED")));
+#if IR_SENSOR_ANALOG
+     printf_P(PSTR(" (sensor board revision: %S)\n"),(oFsensorPCB==ClFsensorPCB::_Rev03b)?PSTR("03b or newer"):PSTR("03 or older"));
+#else //IR_SENSOR_ANALOG
+     printf_P(PSTR("\n"));
+#endif //IR_SENSOR_ANALOG
 	if (check_for_ir_sensor()) ir_sensor_detected = true;
 
 }
 
-bool fsensor_enable(void)
+bool fsensor_enable(bool bUpdateEEPROM)
 {
 #ifdef PAT9125
 	if (mmu_enabled == false) { //filament sensor is pat9125, enable only if it is working
@@ -187,18 +207,34 @@ bool fsensor_enable(void)
 		FSensorStateMenu = 1;
 	}
 #else // PAT9125
-	fsensor_enabled = true;
-	eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, 0x01);
-	FSensorStateMenu = 1;
-#endif // PAT9125
+#if IR_SENSOR_ANALOG
+     if(!fsensor_IR_check())
+          {
+          bUpdateEEPROM=true;
+          fsensor_enabled=false;
+          fsensor_not_responding=true;
+          FSensorStateMenu=0;
+          }
+     else {
+#endif //IR_SENSOR_ANALOG
+     fsensor_enabled=true;
+     fsensor_not_responding=false;
+     FSensorStateMenu=1;
+#if IR_SENSOR_ANALOG
+          }
+#endif //IR_SENSOR_ANALOG
+     if(bUpdateEEPROM)
+          eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, FSensorStateMenu);
+#endif //PAT9125
 	return fsensor_enabled;
 }
 
-void fsensor_disable(void)
-{
+void fsensor_disable(bool bUpdateEEPROM)
+{ 
 	fsensor_enabled = false;
-	eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, 0x00); 
 	FSensorStateMenu = 0;
+     if(bUpdateEEPROM)
+          eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, 0x00); 
 }
 
 void fsensor_autoload_set(bool State)
@@ -589,10 +625,76 @@ void fsensor_update(void)
 			fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp;
 		}
 #else //PAT9125
-		if ((digitalRead(IR_SENSOR_PIN) == 1) && CHECK_FSENSOR && fsensor_enabled && ir_sensor_detected && ( ! fsensor_m600_enqueued) )
-		{
-			fsensor_stop_and_save_print();
-			fsensor_enque_M600();
+		if (CHECK_FSENSOR && fsensor_enabled && ir_sensor_detected && ( ! fsensor_m600_enqueued) )
+          {
+               if(digitalRead(IR_SENSOR_PIN))
+               {                                  // IR_SENSOR_PIN ~ H
+#if IR_SENSOR_ANALOG
+                    if(!bIRsensorStateFlag)
+                    {
+                         bIRsensorStateFlag=true;
+                         nIRsensorLastTime=_millis();
+                    }
+                    else
+                    {
+                         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 ...
+                              if((oFsensorPCB==ClFsensorPCB::_Rev03b)&&((nADC*OVERSAMPLENR)>((int)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(oFsensorActionNA==ClFsensorActionNA::_Pause)
+                                        lcd_pause_print();
+                              }
+                              else
+                              {
+#endif //IR_SENSOR_ANALOG
+                                   fsensor_stop_and_save_print();
+                                   fsensor_enque_M600();
+#if IR_SENSOR_ANALOG
+                              }
+                         }
+                    }
+               }
+               else
+               {                                  // IR_SENSOR_PIN ~ L
+                    bIRsensorStateFlag=false;
+#endif //IR_SENSOR_ANALOG
+               }
 		}
 #endif //PAT9125
 }
+
+#if IR_SENSOR_ANALOG
+bool fsensor_IR_check()
+{
+uint16_t volt_IR_int;
+bool bCheckResult;
+
+volt_IR_int=current_voltage_raw_IR;
+bCheckResult=(volt_IR_int<((int)IRsensor_Lmax_TRESHOLD))||(volt_IR_int>((int)IRsensor_Hmin_TRESHOLD));
+bCheckResult=bCheckResult&&(!((oFsensorPCB==ClFsensorPCB::_Rev03b)&&(volt_IR_int>((int)IRsensor_Hopen_TRESHOLD))));
+return(bCheckResult);
+}
+#endif //IR_SENSOR_ANALOG

+ 27 - 2
Firmware/fsensor.h

@@ -3,6 +3,7 @@
 #define FSENSOR_H
 
 #include <inttypes.h>
+#include "config.h"
 
 
 //! minimum meassured chunk length in steps
@@ -27,8 +28,8 @@ extern void fsensor_init(void);
 
 //! @name enable/disable
 //! @{
-extern bool fsensor_enable(void);
-extern void fsensor_disable(void);
+extern bool fsensor_enable(bool bUpdateEEPROM=true);
+extern void fsensor_disable(bool bUpdateEEPROM=true);
 //! @}
 
 //autoload feature enabled
@@ -65,4 +66,28 @@ extern void fsensor_st_block_begin(block_t* bl);
 extern void fsensor_st_block_chunk(block_t* bl, int cnt);
 //! @}
 
+
+#if IR_SENSOR_ANALOG
+#define IR_SENSOR_STEADY 10                       // [ms]
+
+enum class ClFsensorPCB:uint_least8_t
+{
+    _Old=0,
+    _Rev03b=1,
+    _Undef=EEPROM_EMPTY_VALUE
+};
+
+enum class ClFsensorActionNA:uint_least8_t
+{
+    _Continue=0,
+    _Pause=1,
+    _Undef=EEPROM_EMPTY_VALUE
+};
+
+extern ClFsensorPCB oFsensorPCB;
+extern ClFsensorActionNA oFsensorActionNA;
+
+extern bool fsensor_IR_check();
+#endif //IR_SENSOR_ANALOG
+
 #endif //FSENSOR_H

+ 3 - 0
Firmware/messages.c

@@ -128,6 +128,9 @@ const char MSG_SOUND_BLIND[] PROGMEM_I1 = ISTR("Assist"); ////
 const char MSG_MESH[] PROGMEM_I1 = ISTR("Mesh"); ////
 const char MSG_Z_PROBE_NR[] PROGMEM_I1 = ISTR("Z-probe nr."); ////
 const char MSG_MAGNETS_COMP[] PROGMEM_I1 = ISTR("Magnets comp."); ////
+const char MSG_FS_ACTION[] PROGMEM_I1 = ISTR("FS Action"); ////
+const char MSG_FS_CONTINUE[] PROGMEM_I1 = ISTR("Cont."); ////
+const char MSG_FS_PAUSE[] PROGMEM_I1 = ISTR("Pause"); ////
 
 //not internationalized messages
 const char MSG_SD_WORKDIR_FAIL[] PROGMEM_N1 = "workDir open failed"; ////

+ 3 - 0
Firmware/messages.h

@@ -128,6 +128,9 @@ extern const char MSG_SOUND_BLIND[];
 extern const char MSG_MESH[];
 extern const char MSG_Z_PROBE_NR[];
 extern const char MSG_MAGNETS_COMP[];
+extern const char MSG_FS_ACTION[];
+extern const char MSG_FS_CONTINUE[];
+extern const char MSG_FS_PAUSE[];
 
 //not internationalized messages
 extern const char MSG_BROWNOUT_RESET[];

+ 2 - 1
Firmware/pins_Einsy_1_0.h

@@ -71,12 +71,13 @@
 #define HEATER_2_PIN        -1
 #define TEMP_2_PIN          -1
 
-#define TEMP_AMBIENT_PIN     5 //A5
+#define TEMP_AMBIENT_PIN     6 //A6
 
 #define TEMP_PINDA_PIN       3 //A3
 
 #define VOLT_PWR_PIN         4 //A4
 #define VOLT_BED_PIN         9 //A9
+#define VOLT_IR_PIN          8 //A8
 
 
 #define E0_TMC2130_CS       66

+ 10 - 1
Firmware/temperature.cpp

@@ -44,6 +44,8 @@
 #include "Timer.h"
 #include "Configuration_prusa.h"
 
+#include "config.h"
+
 //===========================================================================
 //=============================public variables============================
 //===========================================================================
@@ -71,6 +73,10 @@ int current_voltage_raw_pwr = 0;
 int current_voltage_raw_bed = 0;
 #endif
 
+#if IR_SENSOR_ANALOG
+int current_voltage_raw_IR = 0;
+#endif //IR_SENSOR_ANALOG
+
 int current_temperature_bed_raw = 0;
 float current_temperature_bed = 0.0;
   
@@ -1576,11 +1582,14 @@ void adc_ready(void) //callback from adc when sampling finished
 	current_voltage_raw_pwr = adc_values[ADC_PIN_IDX(VOLT_PWR_PIN)];
 #endif
 #ifdef AMBIENT_THERMISTOR
-	current_temperature_raw_ambient = adc_values[ADC_PIN_IDX(TEMP_AMBIENT_PIN)];
+	current_temperature_raw_ambient = adc_values[ADC_PIN_IDX(TEMP_AMBIENT_PIN)]; // 5->6
 #endif //AMBIENT_THERMISTOR
 #ifdef VOLT_BED_PIN
 	current_voltage_raw_bed = adc_values[ADC_PIN_IDX(VOLT_BED_PIN)]; // 6->9
 #endif
+#if IR_SENSOR_ANALOG
+     current_voltage_raw_IR = adc_values[ADC_PIN_IDX(VOLT_IR_PIN)];
+#endif //IR_SENSOR_ANALOG
 	temp_meas_ready = true;
 }
 

+ 5 - 0
Firmware/temperature.h

@@ -27,6 +27,8 @@
   #include "stepper.h"
 #endif
 
+#include "config.h"
+
 
 #ifdef SYSTEM_TIMER_2
 
@@ -74,6 +76,9 @@ extern int current_voltage_raw_pwr;
 extern int current_voltage_raw_bed;
 #endif
 
+#if IR_SENSOR_ANALOG
+extern int current_voltage_raw_IR;
+#endif //IR_SENSOR_ANALOG
 
 #if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
   extern unsigned char soft_pwm_bed;

+ 134 - 16
Firmware/ultralcd.cpp

@@ -45,6 +45,10 @@
 #include "io_atmega2560.h"
 #include "first_lay_cal.h"
 
+#include "fsensor.h"
+#include "adc.h"
+#include "config.h"
+
 
 int scrollstuff = 0;
 char longFilenameOLD[LONG_FILENAME_LENGTH];
@@ -61,9 +65,6 @@ uint8_t SilentModeMenu_MMU = 1; //activate mmu unit stealth mode
 
 int8_t FSensorStateMenu = 1;
 
-extern bool fsensor_enable();
-extern void fsensor_disable();
-
 
 #ifdef SDCARD_SORT_ALPHA
 bool presort_flag = false;
@@ -197,6 +198,7 @@ enum class TestError : uint_least8_t
     SwappedFan,
     WiringFsensor,
     TriggeringFsensor,
+    FsensorLevel
 };
 
 static int  lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay);
@@ -228,6 +230,9 @@ static FanCheck lcd_selftest_fan_auto(int _fan);
 static bool lcd_selftest_fsensor();
 #endif //PAT9125
 static bool selftest_irsensor();
+#if IR_SENSOR_ANALOG
+static bool lcd_selftest_IRsensor();
+#endif //IR_SENSOR_ANALOG
 static void lcd_selftest_error(TestError error, const char *_error_1, const char *_error_2);
 static void lcd_colorprint_change();
 #ifdef SNMM
@@ -2018,11 +2023,11 @@ static void lcd_menu_temperatures()
     menu_back_if_clicked();
 }
 
-#if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN)
+#if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN) || IR_SENSOR_ANALOG
 #define VOLT_DIV_R1 10000
 #define VOLT_DIV_R2 2370
 #define VOLT_DIV_FAC ((float)VOLT_DIV_R2 / (VOLT_DIV_R2 + VOLT_DIV_R1))
-#define VOLT_DIV_REF 5
+
 //! @brief Show Voltages
 //!
 //! @code{.unparsed}
@@ -2040,10 +2045,17 @@ static void lcd_menu_voltages()
 	float volt_pwr = VOLT_DIV_REF * ((float)current_voltage_raw_pwr / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
 	float volt_bed = VOLT_DIV_REF * ((float)current_voltage_raw_bed / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
 	lcd_home();
-	lcd_printf_P(PSTR(" PWR:      %d.%01dV\n" " BED:      %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr)), (int)volt_bed, (int)(10*fabs(volt_bed - (int)volt_bed)));
-    menu_back_if_clicked();
+#if !IR_SENSOR_ANALOG
+	lcd_printf_P(PSTR("\n"));
+#endif //!IR_SENSOR_ANALOG
+     lcd_printf_P(PSTR(" PWR:      %4.1fV\n" " BED:      %4.1fV"), volt_pwr, volt_bed);
+#if IR_SENSOR_ANALOG
+     float volt_IR = VOLT_DIV_REF * ((float)current_voltage_raw_IR / (1023 * OVERSAMPLENR));
+     lcd_printf_P(PSTR("\n IR :       %3.1fV"),volt_IR);
+#endif //IR_SENSOR_ANALOG
+     menu_back_if_clicked();
 }
-#endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
+#endif //defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN) || IR_SENSOR_ANALOG
 
 #ifdef TMC2130
 //! @brief Show Belt Status
@@ -5691,6 +5703,41 @@ SETTINGS_VERSION;
 MENU_END();
 }
 
+#if IR_SENSOR_ANALOG
+static void lcd_fsensor_actionNA_set(void)
+{
+switch(oFsensorActionNA)
+     {
+     case ClFsensorActionNA::_Continue:
+          oFsensorActionNA=ClFsensorActionNA::_Pause;
+          break;
+     case ClFsensorActionNA::_Pause:
+          oFsensorActionNA=ClFsensorActionNA::_Continue;
+          break;
+     default:
+          oFsensorActionNA=ClFsensorActionNA::_Continue;
+     }
+eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA,(uint8_t)oFsensorActionNA);
+}
+
+#define FSENSOR_ACTION_NA \
+do\
+{\
+    switch(oFsensorActionNA)\
+         {\
+         case ClFsensorActionNA::_Continue:\
+              MENU_ITEM_TOGGLE_P(_T(MSG_FS_ACTION), _T(MSG_FS_CONTINUE), lcd_fsensor_actionNA_set);\
+              break;\
+         case ClFsensorActionNA::_Pause:\
+              MENU_ITEM_TOGGLE_P(_T(MSG_FS_ACTION), _T(MSG_FS_PAUSE), lcd_fsensor_actionNA_set);\
+              break;\
+         default:\
+              oFsensorActionNA=ClFsensorActionNA::_Continue;\
+         }\
+}\
+while (0)
+#endif //IR_SENSOR_ANALOG
+
 template <uint8_t number>
 static void select_sheet_menu()
 {
@@ -5722,6 +5769,9 @@ void lcd_hw_setup_menu(void)                      // can not be "static"
     SETTINGS_NOZZLE;
     MENU_ITEM_SUBMENU_P(_i("Checks"), lcd_checking_menu);
 
+#if IR_SENSOR_ANALOG
+    FSENSOR_ACTION_NA;
+#endif //IR_SENSOR_ANALOG
     MENU_END();
 }
 
@@ -7055,11 +7105,21 @@ static void lcd_tune_menu()
 
 #ifdef FILAMENT_SENSOR
 	if (FSensorStateMenu == 0) {
-		MENU_ITEM_TOGGLE_P(_T(MSG_FSENSOR), _T(MSG_OFF), lcd_fsensor_state_set);
+          if (fsensor_not_responding && (mmu_enabled == false)) {
+               /* Filament sensor not working*/
+               MENU_ITEM_TOGGLE_P(_T(MSG_FSENSOR), _T(MSG_NA), lcd_fsensor_state_set);
+          }
+          else {
+               /* Filament sensor turned off, working, no problems*/
+               MENU_ITEM_TOGGLE_P(_T(MSG_FSENSOR), _T(MSG_OFF), lcd_fsensor_state_set);
+          }
 	}
 	else {
 		MENU_ITEM_TOGGLE_P(_T(MSG_FSENSOR), _T(MSG_ON), lcd_fsensor_state_set);
 	}
+#if IR_SENSOR_ANALOG
+     FSENSOR_ACTION_NA;
+#endif //IR_SENSOR_ANALOG
 #endif //FILAMENT_SENSOR
 
 	SETTINGS_AUTO_DEPLETE;
@@ -7377,6 +7437,42 @@ void lcd_belttest()
 }
 #endif //TMC2130
 
+#if IR_SENSOR_ANALOG
+static bool lcd_selftest_IRsensor()
+{
+bool bAction;
+bool bPCBrev03b;
+uint16_t volt_IR_int;
+float volt_IR;
+
+volt_IR_int=current_voltage_raw_IR;
+bPCBrev03b=(volt_IR_int<((int)IRsensor_Hopen_TRESHOLD));
+volt_IR=VOLT_DIV_REF*((float)volt_IR_int/(1023*OVERSAMPLENR));
+printf_P(PSTR("Measured filament sensor high level: %4.2fV\n"),volt_IR);
+if(volt_IR_int<((int)IRsensor_Hmin_TRESHOLD))
+     {
+     lcd_selftest_error(TestError::FsensorLevel,"HIGH","");
+     return(false);
+     }
+lcd_show_fullscreen_message_and_wait_P(_i("Please insert filament (but not load them!) into extruder and then press the knob."));
+volt_IR_int=current_voltage_raw_IR;
+volt_IR=VOLT_DIV_REF*((float)volt_IR_int/(1023*OVERSAMPLENR));
+printf_P(PSTR("Measured filament sensor low level: %4.2fV\n"),volt_IR);
+if(volt_IR_int>((int)IRsensor_Lmax_TRESHOLD))
+     {
+     lcd_selftest_error(TestError::FsensorLevel,"LOW","");
+     return(false);
+     }
+if((bPCBrev03b?1:0)!=(uint8_t)oFsensorPCB)        // safer then "(uint8_t)bPCBrev03b"
+     {
+     printf_P(PSTR("Filament sensor board change detected: revision %S\n"),bPCBrev03b?PSTR("03b or newer"):PSTR("03 or older"));
+     oFsensorPCB=bPCBrev03b?ClFsensorPCB::_Rev03b:ClFsensorPCB::_Old;
+     eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
+     }
+return(true);
+}
+#endif //IR_SENSOR_ANALOG
+
 static void lcd_selftest_v()
 {
 	(void)lcd_selftest();
@@ -7393,8 +7489,16 @@ bool lcd_selftest()
 	#ifdef TMC2130
 	  FORCE_HIGH_POWER_START;
 	#endif // TMC2130
-	_delay(2000);
+#if !IR_SENSOR_ANALOG
+     _delay(2000);
+#endif //!IR_SENSOR_ANALOG
 	KEEPALIVE_STATE(IN_HANDLER);
+#if IR_SENSOR_ANALOG
+     bool bAction;
+     bAction=lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament unloaded?"),false,true);
+     if(!bAction)
+          return(false);
+#endif //IR_SENSOR_ANALOG
 
 	_progress = lcd_selftest_screen(TestScreen::ExtruderFan, _progress, 3, true, 2000);
 #if (defined(FANCHECK) && defined(TACH_0))
@@ -7580,12 +7684,20 @@ bool lcd_selftest()
         {
 #ifdef PAT9125
 			_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filaments sensor
-            _result = lcd_selftest_fsensor();
+               _result = lcd_selftest_fsensor();
 			if (_result)
 			{
 				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK
 			}
 #endif //PAT9125
+#if IR_SENSOR_ANALOG
+			_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filament sensor
+               _result = lcd_selftest_IRsensor();
+			if (_result)
+			{
+				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //filament sensor OK
+			}
+#endif //IR_SENSOR_ANALOG
         }
     }
 #endif //FILAMENT_SENSOR
@@ -8121,11 +8233,17 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
 		break;
 	case TestError::TriggeringFsensor:
-	    lcd_set_cursor(0, 2);
-        lcd_puts_P(_T(MSG_SELFTEST_FILAMENT_SENSOR));
-        lcd_set_cursor(0, 3);
-        lcd_puts_P(_i("False triggering"));////c=20
-        break;
+          lcd_set_cursor(0, 2);
+          lcd_puts_P(_T(MSG_SELFTEST_FILAMENT_SENSOR));
+          lcd_set_cursor(0, 3);
+          lcd_puts_P(_i("False triggering"));////c=20
+          break;
+	case TestError::FsensorLevel:
+          lcd_set_cursor(0, 2);
+          lcd_puts_P(_T(MSG_SELFTEST_FILAMENT_SENSOR));
+          lcd_set_cursor(0, 3);
+          lcd_printf_P(_i("%s level expected"),_error_1);////c=20
+          break;
 	}
 
 	_delay(1000);

+ 10 - 0
Firmware/ultralcd.h

@@ -7,6 +7,8 @@
 #include "menu.h"
 #include "mesh_bed_calibration.h"
 
+#include "config.h"
+
 extern void menu_lcd_longpress_func(void);
 extern void menu_lcd_charsetup_func(void);
 extern void menu_lcd_lcdupdate_func(void);
@@ -245,4 +247,12 @@ enum class WizState : uint8_t
 
 void lcd_wizard(WizState state);
 
+#define VOLT_DIV_REF 5
+#if IR_SENSOR_ANALOG
+#define IRsensor_Hmin_TRESHOLD (3.0*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~3.0V (0.6*Vcc)
+#define IRsensor_Lmax_TRESHOLD (1.5*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~1.5V (0.3*Vcc)
+#define IRsensor_Hopen_TRESHOLD (4.6*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k)
+#define IRsensor_Ldiode_TRESHOLD (0.3*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~0.3V
+#endif //IR_SENSOR_ANALOG
+
 #endif //ULTRALCD_H