Bladeren bron

Merge remote-tracking branch 'upstream/MK3' into #2472-#2356-belt-test-stealth-mode

vintagepc 5 jaren geleden
bovenliggende
commit
f1cba64e56

+ 2 - 2
Firmware/Configuration.h

@@ -16,8 +16,8 @@ extern uint16_t nPrinterType;
 extern PGM_P sPrinterName;
 
 // Firmware version
-#define FW_VERSION "3.9.0"
-#define FW_COMMIT_NR   3175
+#define FW_VERSION "3.9.0-RC1"
+#define FW_COMMIT_NR   3272
 // FW_VERSION_UNKNOWN means this is an unofficial build.
 // The firmware should only be checked into github with this symbol.
 #define FW_DEV_VERSION FW_VERSION_UNKNOWN

+ 0 - 1
Firmware/Configuration_adv.h

@@ -152,7 +152,6 @@
 #define Z_HOME_RETRACT_MM 2
 //#define QUICK_HOME  //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially.
 
-#define AXIS_RELATIVE_MODES {0, 0, 0, 0}
 #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step). Toshiba steppers are 4x slower, but Prusa3D does not use those.
 //By default pololu step drivers require an active high signal. However, some high power drivers require an active low signal as step.
 #define INVERT_X_STEP_PIN 0

+ 158 - 125
Firmware/Dcodes.cpp

@@ -1,5 +1,6 @@
 #include "Dcodes.h"
 //#include "Marlin.h"
+#include "Configuration.h"
 #include "language.h"
 #include "cmdqueue.h"
 #include <stdio.h>
@@ -100,16 +101,22 @@ void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperl
 #ifdef DEBUG_DCODE3
 #define EEPROM_SIZE 0x1000
     /*!
-    *
     ### D3 - Read/Write EEPROM <a href="https://reprap.org/wiki/G-code#D3:_Read.2FWrite_EEPROM">D3: Read/Write EEPROM</a>
     This command can be used without any additional parameters. It will read the entire eeprom.
-      
-          D3 [ A | C | X ]
-      
-      - `A` - Address (0x0000-0x0fff)
-      - `C` - Count (0x0001-0x1000)
-      - `X` - Data
-    *
+    #### Usage
+    
+        D3 [ A | C | X ]
+    
+    #### Parameters
+    - `A` - Address (x0000-x0fff)
+    - `C` - Count (1-4096)
+    - `X` - Data (hex)
+	
+	#### Notes
+	- The hex address needs to be lowercase without the 0 before the x
+	- Count is decimal 
+	- The hex data needs to be lowercase
+	
     */
 void dcode_3()
 {
@@ -179,7 +186,6 @@ void dcode_3()
 #define BOOT_APP_FLG_COPY  0x02
 #define BOOT_APP_FLG_FLASH 0x04
 
-extern uint8_t fsensor_log;
 extern float current_temperature_pinda;
 extern float axis_steps_per_unit[NUM_AXIS];
 
@@ -206,13 +212,13 @@ void dcode__1()
 #ifdef DEBUG_DCODES
 
     /*!
-    *
     ### D0 - Reset <a href="https://reprap.org/wiki/G-code#D0:_Reset">D0: Reset</a>
-      
-          D0 [ B ]
-      
-      - `B` - Bootloader
-    *
+    #### Usage
+    
+        D0 [ B ]
+    
+    #### Parameters
+    - `B` - Bootloader
     */
 void dcode_0()
 {
@@ -251,16 +257,22 @@ void dcode_1()
 }
 
     /*!
-    *
-    ### D2 - Read/Write RAM <a href="https://reprap.org/wiki/G-code#D2:_Read.2FWrite_RAM">D2: Read/Write RAM</a>
+    ### D2 - Read/Write RAM <a href="https://reprap.org/wiki/G-code#D2:_Read.2FWrite_RAM">D3: Read/Write RAM</a>
     This command can be used without any additional parameters. It will read the entire RAM.
-      
-          D2 [ A | C | X ]
-      
-      - `A` - Address (0x0000-0x1fff)
-      - `C` - Count (0x0001-0x2000)
-      - `X` - Data
-    *
+    #### Usage
+    
+        D2 [ A | C | X ]
+    
+    #### Parameters
+    - `A` - Address (x0000-x1fff)
+    - `C` - Count (1-8192)
+    - `X` - Data
+
+	#### Notes
+	- The hex address needs to be lowercase without the 0 before the x
+	- Count is decimal 
+	- The hex data needs to be lowercase
+	
     */
 void dcode_2()
 {
@@ -306,17 +318,17 @@ void dcode_2()
 }
 
     /*!
-    *
-    ### D4 - Read/Write PIN <a href="https://reprap.org/wiki/G-code#D4:_Read.2FWrite_PIN">D4: Read/Write PIN</a>
     
+    ### D4 - Read/Write PIN <a href="https://reprap.org/wiki/G-code#D4:_Read.2FWrite_PIN">D4: Read/Write PIN</a>
     To read the digital value of a pin you need only to define the pin number.
-      
-          D4 [ P | F | V ]
-      
-      - `P` - Pin (0-255)
-      - `F` - Function in/out (0/1)
-      - `V` - Value (0/1)
-    *
+    #### Usage
+    
+        D4 [ P | F | V ]
+    
+    #### Parameters
+    - `P` - Pin (0-255)
+    - `F` - Function in/out (0/1)
+    - `V` - Value (0/1)
     */
 void dcode_4()
 {
@@ -351,18 +363,24 @@ void dcode_4()
 #ifdef DEBUG_DCODE5
 
     /*!
-    *
     ### D5 - Read/Write FLASH <a href="https://reprap.org/wiki/G-code#D5:_Read.2FWrite_FLASH">D5: Read/Write Flash</a>
     This command can be used without any additional parameters. It will read the 1kb FLASH.
-      
-          D5 [ A | C | X | E ]
-      
-      - `A` - Address (0x00000-0x3ffff)
-      - `C` - Count (0x0001-0x2000)
-      - `X` - Data
-      - `E` - Erase
-    *
-    */
+    #### Usage
+    
+        D5 [ A | C | X | E ]
+    
+    #### Parameters
+    - `A` - Address (x00000-x3ffff)
+    - `C` - Count (1-8192)
+    - `X` - Data
+    - `E` - Erase
+ 	
+	#### Notes
+	- The hex address needs to be lowercase without the 0 before the x
+	- Count is decimal 
+	- The hex data needs to be lowercase
+	
+   */
 void dcode_5()
 {
 	printf_P(PSTR("D5 - Read/Write FLASH\n"));
@@ -427,24 +445,18 @@ void dcode_5()
 #ifdef DEBUG_DCODES
 
     /*!
-    *
     ### D6 - Read/Write external FLASH <a href="https://reprap.org/wiki/G-code#D6:_Read.2FWrite_external_FLASH">D6: Read/Write external Flash</a>
-    
     Reserved
-   *
-   */
+    */
 void dcode_6()
 {
 	LOG("D6 - Read/Write external FLASH\n");
 }
 
     /*!
-    *
     ### D7 - Read/Write Bootloader <a href="https://reprap.org/wiki/G-code#D7:_Read.2FWrite_Bootloader">D7: Read/Write Bootloader</a>
-    
     Reserved
-   *
-   */
+    */
 void dcode_7()
 {
 	LOG("D7 - Read/Write Bootloader\n");
@@ -461,16 +473,16 @@ void dcode_7()
 }
 
     /*!
-    *
     ### D8 - Read/Write PINDA <a href="https://reprap.org/wiki/G-code#D8:_Read.2FWrite_PINDA">D8: Read/Write PINDA</a>
-      
-          D8 [ ? | ! | P | Z ]
-      
-      - `?` - Read PINDA temperature shift values
-      - `!` - Reset PINDA temperature shift values to default
-      - `P` - Pinda temperature [C]
-      - `Z` - Z Offset [mm]
-    *
+    #### Usage
+    
+        D8 [ ? | ! | P | Z ]
+    
+    #### Parameters
+    - `?` - Read PINDA temperature shift values
+    - `!` - Reset PINDA temperature shift values to default
+    - `P` - Pinda temperature [C]
+    - `Z` - Z Offset [mm]
     */
 void dcode_8()
 {
@@ -514,21 +526,21 @@ void dcode_8()
 }
 
     /*!
-    *
     ### D9 - Read ADC <a href="https://reprap.org/wiki/G-code#D9:_Read.2FWrite_ADC">D9: Read ADC</a>
-      
-          D9 [ I | V ]
-      
-      - `I` - ADC channel index 
-         - `0` - Heater 0 temperature
-         - `1` - Heater 1 temperature
-         - `2` - Bed temperature
-         - `3` - PINDA temperature
-         - `4` - PWR voltage
-         - `5` - Ambient temperature
-         - `6` - BED voltage
-      - `V` Value to be written as simulated
-    *
+    #### Usage
+    
+        D9 [ I | V ]
+    
+    #### Parameters
+    - `I` - ADC channel index 
+        - `0` - Heater 0 temperature
+        - `1` - Heater 1 temperature
+        - `2` - Bed temperature
+        - `3` - PINDA temperature
+        - `4` - PWR voltage
+        - `5` - Ambient temperature
+        - `6` - BED voltage
+    - `V` Value to be written as simulated
     */
 const char* dcode_9_ADC_name(uint8_t i)
 {
@@ -604,11 +616,8 @@ void dcode_9()
 }
 
     /*!
-    *
     ### D10 - Set XYZ calibration = OK <a href="https://reprap.org/wiki/G-code#D10:_Set_XYZ_calibration_.3D_OK">D10: Set XYZ calibration = OK</a>
-    
-   *
-   */
+    */
 void dcode_10()
 {//Tell the printer that XYZ calibration went OK
 	LOG("D10 - XYZ calibration = OK\n");
@@ -616,11 +625,10 @@ void dcode_10()
 }
 
     /*!
-    *
     ### D12 - Time <a href="https://reprap.org/wiki/G-code#D12:_Time">D12: Time</a>
-    
-   *
-   */
+    Writes the current time in the log file.
+    */
+
 void dcode_12()
 {//Time
 	LOG("D12 - Time\n");
@@ -632,38 +640,61 @@ void dcode_12()
 #include "planner.h"
 #include "tmc2130.h"
 extern void st_synchronize();
-/**
- * @brief D2130 Trinamic stepper controller
- * D2130<axis><command>[subcommand][value]
- *  * Axis
- *  * * 'X'
- *  * * 'Y'
- *  * * 'Z'
- *  * * 'E'
- *  * command
- *  * * '0' current off
- *  * * '1' current on
- *  * * '+' single step
- *  * * * value sereval steps
- *  * * '-' dtto oposite direction
- *  * * '?' read register
- *  * * * "mres"
- *  * * * "step"
- *  * * * "mscnt"
- *  * * * "mscuract"
- *  * * * "wave"
- *  * * '!' set register
- *  * * * "mres"
- *  * * * "step"
- *  * * * "wave"
- *  * * * *0, 180..250 meaning: off, 0.9..1.25, recommended value is 1.1
- *  * * '@' home calibrate axis
- *
- *  Example:
- *  D2130E?wave //print extruder microstep linearity compensation curve
- *  D2130E!wave0 //disable extruder linearity compensation curve, (sine curve is used)
- *  D2130E!wave220 // (sin(x))^1.1 extruder microstep compensation curve used
- */
+    /*!
+    ### D2130 - Trinamic stepper controller <a href="https://reprap.org/wiki/G-code#D2130:_Trinamic_stepper_controller">D2130: Trinamic stepper controller</a>
+    @todo Please review by owner of the code. RepRap Wiki Gcode needs to be updated after review of owner as well.
+    
+    #### Usage
+    
+        D2130 [ Axis | Command | Subcommand | Value ]
+    
+    #### Parameters
+    - Axis
+      - `X` - X stepper driver
+      - `Y` - Y stepper driver
+      - `Z` - Z stepper driver
+      - `E` - Extruder stepper driver
+    - Commands
+      - `0`   - Current off
+      - `1`   - Current on
+      - `+`   - Single step
+      - `-`   - Single step oposite direction
+      - `NNN` - Value sereval steps
+      - `?`   - Read register
+      - Subcommands for read register
+        - `mres`     - Micro step resolution. More information in datasheet '5.5.2 CHOPCONF – Chopper Configuration'
+        - `step`     - Step
+        - `mscnt`    - Microstep counter. More information in datasheet '5.5 Motor Driver Registers'
+        - `mscuract` - Actual microstep current for motor. More information in datasheet '5.5 Motor Driver Registers'
+        - `wave`     - Microstep linearity compensation curve
+      - `!`   - Set register
+      - Subcommands for set register
+        - `mres`     - Micro step resolution
+        - `step`     - Step
+        - `wave`     - Microstep linearity compensation curve
+        - Values for set register
+          - `0, 180 --> 250` - Off
+          - `0.9 --> 1.25`   - Valid values (recommended is 1.1)
+      - `@`   - Home calibrate axis
+    
+    Examples:
+      
+          D2130E?wave
+      
+      Print extruder microstep linearity compensation curve
+      
+          D2130E!wave0
+      
+      Disable extruder linearity compensation curve, (sine curve is used)
+      
+          D2130E!wave220
+      
+      (sin(x))^1.1 extruder microstep compensation curve used
+    
+    Notes:
+      For more information see https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
+    *
+	*/
 void dcode_2130()
 {
 	printf_P(PSTR("D2130 - TMC2130\n"));
@@ -767,18 +798,18 @@ void dcode_2130()
 
 #ifdef PAT9125
     /*!
-    *
     ### D9125 - PAT9125 filament sensor <a href="https://reprap.org/wiki/G-code#D9:_Read.2FWrite_ADC">D9125: PAT9125 filament sensor</a>
-      
-          D9125 [ ? | ! | R | X | Y | L ]
-      
-      - `?` - Print values
-      - `!` - Print values
-      - `R` - Resolution. Not active in code
-      - `X` - X values
-      - `Y` - Y values
-      - `L` - Activate filament sensor log
-    *
+    #### Usage
+    
+        D9125 [ ? | ! | R | X | Y | L ]
+    
+    #### Parameters
+    - `?` - Print values
+    - `!` - Print values
+    - `R` - Resolution. Not active in code
+    - `X` - X values
+    - `Y` - Y values
+    - `L` - Activate filament sensor log
     */
 void dcode_9125()
 {
@@ -812,11 +843,13 @@ void dcode_9125()
 		pat9125_y = (int)code_value();
 		LOG("pat9125_y=%d\n", pat9125_y);
 	}
+#ifdef DEBUG_FSENSOR_LOG
 	if (code_seen('L'))
 	{
 		fsensor_log = (int)code_value();
 		LOG("fsensor_log=%d\n", fsensor_log);
 	}
+#endif //DEBUG_FSENSOR_LOG
 }
 #endif //PAT9125
 

+ 3 - 3
Firmware/Marlin.h

@@ -294,7 +294,7 @@ void setPwmFrequency(uint8_t pin, int val);
 
 extern bool fans_check_enabled;
 extern float homing_feedrate[];
-extern bool axis_relative_modes[];
+extern uint8_t axis_relative_modes;
 extern float feedrate;
 extern int feedmultiply;
 extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders
@@ -310,9 +310,9 @@ extern int8_t lcd_change_fil_state;
 extern float default_retraction;
 
 #ifdef TMC2130
-void homeaxis(int axis, uint8_t cnt = 1, uint8_t* pstep = 0);
+bool homeaxis(int axis, bool doError = true, uint8_t cnt = 1, uint8_t* pstep = 0);
 #else
-void homeaxis(int axis, uint8_t cnt = 1);
+bool homeaxis(int axis, bool doError = true, uint8_t cnt = 1);
 #endif //TMC2130
 
 

+ 116 - 44
Firmware/Marlin_main.cpp

@@ -46,6 +46,7 @@
 //-//
 #include "Configuration.h"
 #include "Marlin.h"
+#include "config.h"
   
 #ifdef ENABLE_AUTO_BED_LEVELING
 #include "vector_3.h"
@@ -178,9 +179,13 @@ float default_retraction = DEFAULT_RETRACTION;
 
 
 float homing_feedrate[] = HOMING_FEEDRATE;
-// Currently only the extruder axis may be switched to a relative mode.
-// Other axes are always absolute or relative based on the common relative_mode flag.
-bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
+
+//Although this flag and many others like this could be represented with a struct/bitfield for each axis (more readable and efficient code), the implementation
+//would not be standard across all platforms. That being said, the code will continue to use bitmasks for independent axis.
+//Moreover, according to C/C++ standard, the ordering of bits is platform/compiler dependent and the compiler is allowed to align the bits arbitrarily,
+//thus bit operations like shifting and masking may stop working and will be very hard to fix.
+uint8_t axis_relative_modes = 0;
+
 int feedmultiply=100; //100->1 200->2
 int extrudemultiply=100; //100->1 200->2
 int extruder_multiply[EXTRUDERS] = {100
@@ -640,6 +645,9 @@ void failstats_reset_print()
 	eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
 	eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
 	eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
+    fsensor_softfail = 0;
+#endif
 }
 
 
@@ -707,6 +715,12 @@ static void factory_reset(char level)
 
             eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
             eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
+
+			eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_X, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_Y, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_FERROR_COUNT, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
+
             eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_X_TOT, 0);
             eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_Y_TOT, 0);
             eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
@@ -1310,10 +1324,17 @@ void setup()
 	setup_photpin();
 
 	servo_init();
+
 	// Reset the machine correction matrix.
 	// It does not make sense to load the correction matrix until the machine is homed.
 	world2machine_reset();
-    
+
+    // Initialize current_position accounting for software endstops to
+    // avoid unexpected initial shifts on the first move
+    clamp_to_software_endstops(current_position);
+    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS],
+                      current_position[Z_AXIS], current_position[E_AXIS]);
+
 #ifdef FILAMENT_SENSOR
 	fsensor_init();
 #endif //FILAMENT_SENSOR
@@ -1881,10 +1902,6 @@ static void axis_is_at_home(int axis) {
   max_pos[axis] =          base_max_pos(axis) + cs.add_homing[axis];
 }
 
-
-inline void set_current_to_destination() { memcpy(current_position, destination, sizeof(current_position)); }
-inline void set_destination_to_current() { memcpy(destination, current_position, sizeof(destination)); }
-
 //! @return original feedmultiply
 static int setup_for_endstop_move(bool enable_endstops_now = true) {
     saved_feedrate = feedrate;
@@ -2180,9 +2197,9 @@ bool calibrate_z_auto()
 #endif //TMC2130
 
 #ifdef TMC2130
-void homeaxis(int axis, uint8_t cnt, uint8_t* pstep)
+bool homeaxis(int axis, bool doError, uint8_t cnt, uint8_t* pstep)
 #else
-void homeaxis(int axis, uint8_t cnt)
+bool homeaxis(int axis, bool doError, uint8_t cnt)
 #endif //TMC2130
 {
 	bool endstops_enabled  = enable_endstops(true); //RP: endstops should be allways enabled durring homing
@@ -2297,8 +2314,10 @@ void homeaxis(int axis, uint8_t cnt)
 #ifdef TMC2130
 		if (READ(Z_TMC2130_DIAG) != 0) { //Z crash
 			FORCE_HIGH_POWER_END;
-			kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
-			return; 
+			if (doError) kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
+            current_position[axis] = -5; //assume that nozzle crashed into bed
+            plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+			return 0; 
 		}
 #endif //TMC2130
         current_position[axis] = 0;
@@ -2313,8 +2332,10 @@ void homeaxis(int axis, uint8_t cnt)
 #ifdef TMC2130
 		if (READ(Z_TMC2130_DIAG) != 0) { //Z crash
 			FORCE_HIGH_POWER_END;
-			kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
-			return; 
+			if (doError) kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
+            current_position[axis] = -5; //assume that nozzle crashed into bed
+            plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+			return 0; 
 		}
 #endif //TMC2130
         axis_is_at_home(axis);
@@ -2327,6 +2348,7 @@ void homeaxis(int axis, uint8_t cnt)
 #endif	
     }
     enable_endstops(endstops_enabled);
+    return 1;
 }
 
 /**/
@@ -4996,7 +5018,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
 			
 			#ifdef SUPPORT_VERBOSITY
 			if (verbosity_level >= 1) {
-				clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
+				bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
 				SERIAL_PROTOCOL(mesh_point);
 				clamped ? SERIAL_PROTOCOLPGM(": xy clamped.\n") : SERIAL_PROTOCOLPGM(": no xy clamping\n");
 			}
@@ -5364,21 +5386,19 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
 
     /*!
 	### G90 - Switch off relative mode <a href="https://reprap.org/wiki/G-code#G90:_Set_to_Absolute_Positioning">G90: Set to Absolute Positioning</a>
-	All coordinates from now on are absolute relative to the origin of the machine. E axis is also switched to absolute mode.
+	All coordinates from now on are absolute relative to the origin of the machine. E axis is left intact.
     */
     case 90: {
-        for(uint8_t i = 0; i != NUM_AXIS; ++i)
-            axis_relative_modes[i] = false;
+		axis_relative_modes &= ~(X_AXIS_MASK | Y_AXIS_MASK | Z_AXIS_MASK);
     }
     break;
 
     /*!
 	### G91 - Switch on relative mode <a href="https://reprap.org/wiki/G-code#G91:_Set_to_Relative_Positioning">G91: Set to Relative Positioning</a>
-    All coordinates from now on are relative to the last position. E axis is also switched to relative mode.
+    All coordinates from now on are relative to the last position. E axis is left intact.
 	*/
     case 91: {
-        for(uint8_t i = 0; i != NUM_AXIS; ++i)
-            axis_relative_modes[i] = true;
+		axis_relative_modes |= X_AXIS_MASK | Y_AXIS_MASK | Z_AXIS_MASK;
     }
     break;
 
@@ -6555,7 +6575,7 @@ Sigma_Exit:
 	Makes the extruder interpret extrusion as absolute positions.
     */
     case 82:
-      axis_relative_modes[E_AXIS] = false;
+      axis_relative_modes &= ~E_AXIS_MASK;
       break;
 
     /*!
@@ -6563,7 +6583,7 @@ Sigma_Exit:
 	Makes the extruder interpret extrusion values as relative positions.
     */
     case 83:
-      axis_relative_modes[E_AXIS] = true;
+      axis_relative_modes |= E_AXIS_MASK;
       break;
 
     /*!
@@ -6672,7 +6692,7 @@ Sigma_Exit:
       {
         if(code_seen(axis_codes[i]))
         {
-          if(i == 3) { // E
+          if(i == E_AXIS) { // E
             float value = code_value();
             if(value < 20.0) {
               float factor = cs.axis_steps_per_unit[i] / value; // increase e constants if M92 E14 is given for netfab.
@@ -6681,6 +6701,9 @@ Sigma_Exit:
               axis_steps_per_sqr_second[i] *= factor;
             }
             cs.axis_steps_per_unit[i] = value;
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
+            fsensor_set_axis_steps_per_unit(value);
+#endif
           }
           else {
             cs.axis_steps_per_unit[i] = code_value();
@@ -8428,7 +8451,6 @@ Sigma_Exit:
 				res_valid |= (i == E_AXIS) && ((res_new == 64) || (res_new == 128)); // resolutions valid for E only
 				if (res_valid)
 				{
-					
 					st_synchronize();
 					uint16_t res = tmc2130_get_res(i);
 					tmc2130_set_res(i, res_new);
@@ -8445,6 +8467,10 @@ Sigma_Exit:
 						cs.axis_steps_per_unit[i] /= fac;
 						position[i] /= fac;
 					}
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
+                    if (i == E_AXIS)
+                        fsensor_set_axis_steps_per_unit(cs.axis_steps_per_unit[i]);
+#endif
 				}
 			}
 		}
@@ -8793,12 +8819,18 @@ Sigma_Exit:
     This command can be used without any additional parameters. It will read the entire RAM.
     #### Usage
     
-        D3 [ A | C | X ]
+        D2 [ A | C | X ]
     
     #### Parameters
-    - `A` - Address (0x0000-0x1fff)
-    - `C` - Count (0x0001-0x2000)
+    - `A` - Address (x0000-x1fff)
+    - `C` - Count (1-8192)
     - `X` - Data
+
+	#### Notes
+	- The hex address needs to be lowercase without the 0 before the x
+	- Count is decimal 
+	- The hex data needs to be lowercase
+	
     */
 	case 2:
 		dcode_2(); break;
@@ -8813,9 +8845,15 @@ Sigma_Exit:
         D3 [ A | C | X ]
     
     #### Parameters
-    - `A` - Address (0x0000-0x0fff)
-    - `C` - Count (0x0001-0x1000)
-    - `X` - Data
+    - `A` - Address (x0000-x0fff)
+    - `C` - Count (1-4096)
+    - `X` - Data (hex)
+	
+	#### Notes
+	- The hex address needs to be lowercase without the 0 before the x
+	- Count is decimal 
+	- The hex data needs to be lowercase
+	
     */
 	case 3:
 		dcode_3(); break;
@@ -8845,14 +8883,20 @@ Sigma_Exit:
     This command can be used without any additional parameters. It will read the 1kb FLASH.
     #### Usage
     
-        D3 [ A | C | X | E ]
+        D5 [ A | C | X | E ]
     
     #### Parameters
-    - `A` - Address (0x00000-0x3ffff)
-    - `C` - Count (0x0001-0x2000)
+    - `A` - Address (x00000-x3ffff)
+    - `C` - Count (1-8192)
     - `X` - Data
     - `E` - Erase
-    */
+ 	
+	#### Notes
+	- The hex address needs to be lowercase without the 0 before the x
+	- Count is decimal 
+	- The hex data needs to be lowercase
+	
+   */
 	case 5:
 		dcode_5(); break;
 		break;
@@ -8916,7 +8960,7 @@ Sigma_Exit:
 
     /*!
     ### D12 - Time <a href="https://reprap.org/wiki/G-code#D12:_Time">D12: Time</a>
-    Writes the actual time in the log file.
+    Writes the current time in the log file.
     */
 
 #endif //DEBUG_DCODES
@@ -9071,7 +9115,6 @@ Sigma_Exit:
       For more information see https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
     *
 	*/
-
 	case 2130:
 		dcode_2130(); break;
 #endif //TMC2130
@@ -9115,8 +9158,8 @@ Sigma_Exit:
 #### End of D-Codes
 */
 
-  /** @defgroup GCodes G-Code List 
-  */
+/** @defgroup GCodes G-Code List 
+*/
 
 // ---------------------------------------------------
 
@@ -9181,7 +9224,7 @@ void get_coordinates()
   for(int8_t i=0; i < NUM_AXIS; i++) {
     if(code_seen(axis_codes[i]))
     {
-      bool relative = axis_relative_modes[i];
+      bool relative = axis_relative_modes & (1 << i);
       destination[i] = (float)code_value();
       if (i == E_AXIS) {
         float emult = extruder_multiplier[active_extruder];
@@ -9451,10 +9494,15 @@ static void handleSafetyTimer()
 }
 #endif //SAFETYTIMER
 
+#define FS_CHECK_COUNT 15
 void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h
 {
-bool bInhibitFlag;
 #ifdef FILAMENT_SENSOR
+bool bInhibitFlag;
+#ifdef IR_SENSOR_ANALOG
+static uint8_t nFSCheckCount=0;
+#endif // IR_SENSOR_ANALOG
+
 	if (mmu_enabled == false)
 	{
 //-//		if (mcode_in_progress != 600) //M600 not in progress
@@ -9463,11 +9511,35 @@ bool bInhibitFlag;
 #endif // PAT9125
 #ifdef IR_SENSOR
           bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active
+#ifdef IR_SENSOR_ANALOG
+          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 (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && ! eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))
 			{
+#ifdef IR_SENSOR_ANALOG
+                    bool bTemp=current_voltage_raw_IR>IRsensor_Hmin_TRESHOLD;
+                    bTemp=bTemp&&current_voltage_raw_IR<IRsensor_Hopen_TRESHOLD;
+                    bTemp=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::_Rev03b;
+                              eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
+                              printf_IRSensorAnalogBoardChange(true);
+                              lcd_setstatuspgm(_i("FS rev. 03b or newer"));
+                         }
+                    }
+                    else nFSCheckCount=0;
+#endif // IR_SENSOR_ANALOG
 				if (fsensor_check_autoload())
 				{
 #ifdef PAT9125
@@ -10580,7 +10652,7 @@ void uvlo_()
 
     // Store the print E position before we lose track
 	eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION_E), current_position[E_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_UVLO_E_ABS, axis_relative_modes[3]?0:1);
+	eeprom_update_byte((uint8_t*)EEPROM_UVLO_E_ABS, (axis_relative_modes & E_AXIS_MASK)?0:1);
 
     // Clean the input command queue, inhibit serial processing using saved_printing
     cmdqueue_reset();
@@ -11169,7 +11241,7 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
     saved_feedmultiply2 = feedmultiply; //save feedmultiply
 	saved_active_extruder = active_extruder; //save active_extruder
 	saved_extruder_temperature = degTargetHotend(active_extruder);
-	saved_extruder_relative_mode = axis_relative_modes[E_AXIS];
+	saved_extruder_relative_mode = axis_relative_modes & E_AXIS_MASK;
 	saved_fanSpeed = fanSpeed;
 	cmdqueue_reset(); //empty cmdqueue
 	card.sdprinting = false;
@@ -11251,7 +11323,7 @@ void restore_print_from_ram_and_continue(float e_move)
 		wait_for_heater(_millis(), saved_active_extruder);
 		heating_status = 2;
 	}
-	axis_relative_modes[E_AXIS] = saved_extruder_relative_mode;
+	axis_relative_modes ^= (-saved_extruder_relative_mode ^ axis_relative_modes) & E_AXIS_MASK;
 	float e = saved_pos[E_AXIS] - e_move;
 	plan_set_e_position(e);
   

+ 19 - 10
Firmware/cardreader.cpp

@@ -136,8 +136,17 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
 						SERIAL_ECHOPGM("Access date: ");
 						MYSERIAL.println(p.lastAccessDate);
 						SERIAL_ECHOLNPGM("");*/
-						modificationDate = p.lastWriteDate;
-						modificationTime = p.lastWriteTime;
+						crmodDate = p.lastWriteDate;
+						crmodTime = p.lastWriteTime;
+						// There are scenarios when simple modification time is not enough (on MS Windows)
+						// For example - extract an old g-code from an archive onto the SD card.
+						// In such case the creation time is current time (which is correct), but the modification time
+						// stays the same - i.e. old.
+						// Therefore let's pick the most recent timestamp from both creation and modification timestamps
+						if( crmodDate < p.creationDate || ( crmodDate == p.creationDate && crmodTime < p.creationTime ) ){
+							crmodDate = p.creationDate;
+							crmodTime = p.creationTime;
+						}
 						//writeDate = p.lastAccessDate;
 						if (match != NULL) {
 							if (strcasecmp(match, filename) == 0) return;
@@ -773,8 +782,8 @@ void CardReader::presort() {
 		// retaining only two filenames at a time. This is very
 		// slow but is safest and uses minimal RAM.
 		char name1[LONG_FILENAME_LENGTH + 1];
-		uint16_t modification_time_bckp;
-		uint16_t modification_date_bckp;
+		uint16_t crmod_time_bckp;
+		uint16_t crmod_date_bckp;
 
 		#endif
 		position = 0;
@@ -800,8 +809,8 @@ void CardReader::presort() {
 				#else
 				// Copy filenames into the static array
 				strcpy(sortnames[i], LONGEST_FILENAME);
-				modification_time[i] = modificationTime;
-				modification_date[i] = modificationDate;
+				modification_time[i] = crmodTime;
+				modification_date[i] = crmodDate;
 				#if SDSORT_CACHE_NAMES
 				strcpy(sortshort[i], filename);
 				#endif
@@ -830,8 +839,8 @@ void CardReader::presort() {
 																	(modification_date[o1] < modification_date [o2]))
 			#else
 			#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0) //true if lowercase(name1) > lowercase(name2)
-			#define _SORT_CMP_TIME_NODIR() (((modification_date_bckp == modificationDate) && (modification_time_bckp > modificationTime)) || \
-																	(modification_date_bckp > modificationDate))
+			#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp > crmodTime)) || \
+																	(crmod_date_bckp > crmodDate))
 
 			#endif
 
@@ -882,8 +891,8 @@ void CardReader::presort() {
 					counter++;
 					getfilename_simple(positions[o1]);
 					strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
-					modification_date_bckp = modificationDate;
-					modification_time_bckp = modificationTime;
+					crmod_date_bckp = crmodDate;
+					crmod_time_bckp = crmodTime;
 					#if HAS_FOLDER_SORTING
 					bool dir1 = filenameIsDir;
 					#endif

+ 3 - 1
Firmware/cardreader.h

@@ -75,7 +75,9 @@ public:
   bool sdprinting ;  
   bool cardOK ;
   char filename[13];
-  uint16_t modificationTime, modificationDate;
+  // There are scenarios when simple modification time is not enough (on MS Windows)
+  // Therefore these timestamps hold the most recent one of creation/modification date/times
+  uint16_t crmodTime, crmodDate;
   uint32_t cluster, position;
   char longFilename[LONG_FILENAME_LENGTH];
   bool filenameIsDir;

+ 7 - 4
Firmware/config.h

@@ -5,10 +5,12 @@
 #include "Configuration_prusa.h"
 #include "pins.h"
 
-#define IR_SENSOR_ANALOG (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
+#if (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
+# define IR_SENSOR_ANALOG
+#endif
 
 //ADC configuration
-#if !IR_SENSOR_ANALOG
+#ifndef 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)
@@ -34,7 +36,8 @@
 //#define PAT9125_I2C_ADDR  0x79  //ID=HI
 //#define PAT9125_I2C_ADDR  0x73  //ID=NC
 #define PAT9125_XRES      0
-#define PAT9125_YRES      240
+#define PAT9125_YRES      240                   // maximum resolution (5*X cpi)
+#define PAT9124_YRES_MM   (5*PAT9125_YRES/25.4) // counts per mm
 
 //SM4 configuration
 #define SM4_DEFDELAY      500       //default step delay [us]
@@ -55,7 +58,7 @@
 #define W25X20CL_SPSR          SPI_SPSR(W25X20CL_SPI_RATE)
 
 //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)

+ 349 - 2
Firmware/eeprom.h

@@ -1,3 +1,13 @@
+
+/**
+ * @file
+ * @author 3d-gussner
+ */
+ /** \ingroup eeprom_table */
+ 
+ //! _This is a EEPROM table of currently implemented in Prusa firmware (dynamically generated from doxygen)._
+
+
 #ifndef EEPROM_H
 #define EEPROM_H
 
@@ -26,6 +36,338 @@ typedef struct
 #ifdef __cplusplus
 static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEPROM_SHEETS_SIZEOF.");
 #endif
+/** @defgroup eeprom_table EEPROM Table
+ *  
+ 
+  ---------------------------------------------------------------------------------
+  EEPROM 8-bit Empty value = 0xFFh 255
+  
+  EEPROM 16-bit Empty value = 0xFFFFh 65535
+  
+  _Italic = unused or default_
+  
+  __Bold = Status__
+  
+  In Default/FactoryReset column the 
+  
+   - __L__		Language
+   - __S__ 		Statistics
+   - __P__ 		Shipping prep
+   - __S/P__	Statistics and Shipping prep
+   
+  will overwrite existing values to 0 or default.
+  A FactoryReset All Data will overwrite the whole EEPROM with ffh and some values will be initialized automatically,
+  others need a reset / reboot.
+  
+  ---------------------------------------------------------------------------------
+  How can you use the debug codes?
+  - Serial terminal like Putty.
+  - Octoprint does support D-codes
+  - _Pronterface_ does __not__ support D-codes
+
+  ### !!! D-codes are case sensitive so please don't use upper case A,C or X in the address you want to read !!!
+   
+  #### Useful tools/links:
+  To convert hex to ascii 		https://www.rapidtables.com/convert/number/hex-to-ascii.html
+  
+  To convert hex to dec 		https://www.rapidtables.com/convert/number/hex-to-decimal.html
+  
+  Version: 1.0.1
+  
+  ---------------------------------------------------------------------------------
+  
+  
+| Address begin		| Bit/Type 	| Name 									| Valid values	| Default/FactoryReset	| Description 										| Gcode/Function| Debug code
+| :--				| :-- 		| :-- 									| :--:			| :--:					| :--												| :--:			| :--:
+| 0x0FFFh 4095		| uchar    	| EEPROM_SILENT 						| 00h 0			| ffh 255				| TMC Stealth mode: __off__ / miniRambo Power mode	| LCD menu		| D3 Ax0fff C1
+| ^ 				| ^ 		| ^										| 01h 1			| ^						| TMC Stealth mode: __on__ / miniRambo Silent mode	| ^				| ^ 
+| 0x0FFEh 4094		| uchar    	| EEPROM_LANG 							| 00h 0			| ffh 255		__L__	| English / LANG_ID_PRI								| LCD menu		| D3 Ax0ffe C1 
+| ^ 				| ^ 		| ^										| 01h 1			| ^						| Other language LANG_ID_SEC						| ^ 			| ^
+| 0x0FFCh 4092		| uint16	| EEPROM_BABYSTEP_X						| ???			| ff ffh 65535			| Babystep for X axis _unsued_						| ??? 			| D3 Ax0ffc C2
+| 0x0FFAh 4090		| uint16	| EEPROM_BABYSTEP_Y						| ???			| ff ffh 65535			| Babystep for Y axis _unsued_						| ^ 			| D3 Ax0ffa C2
+| 0x0FF8h 4088		| uint16	| EEPROM_BABYSTEP_Z						| ???			| ff ffh 65535			| Babystep for Z axis _lagacy_						| ^ 			| D3 Ax0ff8 C2
+| ^ 				| ^ 		| ^										| ^				| ^						| multiple values stored now in EEPROM_Sheets_base	| ^ 			| ^
+| 0x0FF7h 4087		| uint8		| EEPROM_CALIBRATION_STATUS				| ffh 255		| ffh 255				| Assembled _default_								| ??? 			| D3 Ax0ff7 C1
+| ^ 				| ^ 		| ^										| 01h 1			| ^						| Calibrated										| ^ 			| ^
+| ^ 				| ^ 		| ^										| e6h 230		| ^						| needs Live Z adjustment							| ^ 			| ^
+| ^ 				| ^ 		| ^										| f0h 240		| ^				__P__	| needs Z calibration								| ^ 			| ^
+| ^ 				| ^ 		| ^										| fah 250		| ^						| needs XYZ calibration								| ^ 			| ^ 
+| ^ 				| ^ 		| ^										| 00h 0			| ^						| Unknown											| ^ 			| ^
+| 0x0FF5h 4085		| uint16	| EEPROM_BABYSTEP_Z0					| ???			| ff ffh 65535			| Babystep for Z ???								| ??? 			| D3 Ax0ff5 C2
+| 0x0FF1h 4081		| uint32	| EEPROM_FILAMENTUSED					| ???			| 00 00 00 00h 0 __S/P__| Filament used in meters							| ??? 			| D3 Ax0ff1 C4
+| 0x0FEDh 4077		| uint32	| EEPROM_TOTALTIME						| ???			| 00 00 00 00h 0 __S/P__| Total print time									| ??? 			| D3 Ax0fed C4
+| 0x0FE5h 4069		| float		| EEPROM_BED_CALIBRATION_CENTER			| ???			| ff ff ff ffh			| ???											 	| ??? 			| D3 Ax0fe5 C8
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0FDDh 4061		| float		| EEPROM_BED_CALIBRATION_VEC_X			| ???			| ff ff ff ffh			| ???											 	| ??? 			| D3 Ax0fdd C8
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^	
+| 0x0FD5h 4053		| float		| EEPROM_BED_CALIBRATION_VEC_Y			| ???			| ff ff ff ffh			| ???											 	| ??? 			| D3 Ax0fd5 C8
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0FC5h 4037		| int16		| EEPROM_BED_CALIBRATION_Z_JITTER		| ???			| ff ffh 65535			| ???											 	| ??? 			| D3 Ax0fc5 C16
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^	
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0FC4h 4036		| bool		| EEPROM_FARM_MODE						| 00h 0			| ffh 255 		__P__	| Prusa farm mode: __off__							| G99 			| D3 Ax0fc4 C1
+| ^					| ^			| ^										| 01h 1			| ^						| Prusa farm mode: __on__							| G98			| ^
+| 0x0FC3h 4035		| free		| _EEPROM_FREE_NR1_						| ???			| ffh 255				| _Free EEPROM space_								| _free space_	| D3 Ax0fc3 C1
+| 0x0FC1h 4033		| ???		| EEPROM_FARM_NUMBER					| 000-999		| ff ffh / 000	__P__	| Prusa farm number	_only 0-9 are allowed: 000-999_	| LCD menu		| D3 Ax0fc1 C2
+| 0x0FC0h 4032		| bool		| EEPROM_BED_CORRECTION_VALID			| 00h 0			| 00h 0					| Bed correction invalid							| ??? 			| D3 Ax0fc0 C1
+| ^					| ^			| ^										| ffh 255		| 						| Bed correction valid								| ??? 			| ^
+| 0x0FBFh 4031		| char		| EEPROM_BED_CORRECTION_LEFT			| 00h ffh		| 00h 0					| Bed manual correction left						| LCD menu 		| D3 Ax0fbf C1
+| ^					| ^			| ^										| ^				| ^						| At this moment limited to +-100um					| G80 Lxxx 			| ^
+| 0x0FBEh 4030		| char		| EEPROM_BED_CORRECTION_RIGHT			| 00h ffh		| 00h 0					| Bed manual correction right						| LCD menu 		| D3 Ax0fbe C1
+| ^					| ^			| ^										| ^				| ^						| At this moment limited to +-100um					| G80 Rxxx 			| ^
+| 0x0FBDh 4029		| char		| EEPROM_BED_CORRECTION_FRONT			| 00h ffh		| 00h 0					| Bed manual correction front						| LCD menu 		| D3 Ax0fbd C1
+| ^					| ^			| ^										| ^				| ^						| At this moment limited to +-100um					| G80 Fxxx 			| ^
+| 0x0FBCh 4028		| char		| EEPROM_BED_CORRECTION_BACK			| 00h ffh		| 00h 0					| Bed manual correction back						| LCD menu 		| D3 Ax0fbc C1
+| ^					| ^			| ^										| ^				| ^						| At this moment limited to +-100um					| G80 Bxxx 			| ^
+| 0x0FBBh 4027		| bool		| EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY	| 00h 0			| ffh 255				| Toshiba Air: __off__								| LCD menu 		| D3 Ax0fbb C1
+| ^					| ^			| ^										| 01h 1			| ^						| Toshiba Air: __on__								| ^ 			| ^	
+| 0x0FBAh 4026		| uchar		| EEPROM_PRINT_FLAG						| ???			| ???					| _unsued_											| ??? 			| D3 Ax0fba C1
+| 0x0FB0h 4016		| int16		| EEPROM_PROBE_TEMP_SHIFT				| ???			| ???					| ???												| ??? 			| D3 Ax0fb0 C10
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0FAFh 4015		| bool		| EEPROM_TEMP_CAL_ACTIVE				| 00h 0			| 00h 0					| PINDA Temp cal.: __inactive__						| LCD menu		| D3 Ax0faf C1
+| ^					| ^			| ^										| ffh 255		| ^						| PINDA Temp cal.: __active__						| ^ 			| ^
+| 0x0FA7h 4007		| uint32	| EEPROM_BOWDEN_LENGTH					| ???			| ff 00 00 00h			| Bowden length										| ??? 			| D3 Ax0fae C8
+| ^					| ^			| ^										| ^				| 00 00 00 00h			| ^													| ^ 			| ^
+| 0x0FA6h 4006		| uint8		| EEPROM_CALIBRATION_STATUS_PINDA		| 00h 0			| ffh 255				| PINDA Temp: __not calibrated__					| ??? 			| D3 Ax0fa6 C1
+| ^					| ^			| ^										| 01h 1			| ^						| PINDA Temp: __calibrated__						| ^ 			| ^
+| 0x0FA5h 4005		| uint8		| EEPROM_UVLO							| 00h 0			| ffh 255				| Power Panic flag: __inactive__					| ??? 			| D3 Ax0fa5 C1
+| ^					| ^			| ^										| 01h 1			| ^						| Power Panic flag: __active__						| ^ 			| ^
+| ^					| ^			| ^										| 02h 2			| ^						| Power Panic flag: __???__							| ^ 			| ^
+| 0x0F9Dh 3997		| float		| EEPROM_UVLO_CURRENT_POSITION			| ???			| ffh 255				| Power Panic position 								| ??? 			| D3 Ax0f9d C8
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0F95h 3989		| char		| EEPROM_FILENAME						| ???			| ffh 255				| Power Panic Filename 								| ??? 			| D3 Ax0f95 C8
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0F91h 39851		| uint32	| EEPROM_FILE_POSITION					| ???			| ff ff ff ffh			| Power Panic File Position							| ??? 			| D3 Ax0f91 C4
+| 0x0F8Dh 3981		| float		| EEPROM_UVLO_CURRENT_POSITION_Z		| ???			| ff ff ff ffh			| Power Panic Z Position	 						| ^ 			| D3 Ax0f8d C4
+| 0x0F8Ch 3980		| ???		| EEPROM_UVLO_UNUSED_001				| ??? 			| ffh 255				| Power Panic _unused_								| ^ 			| D3 Ax0f8c C1
+| 0x0F8Bh 3979		| uint8		| EEPROM_UVLO_TARGET_BED				| ???			| ffh 255				| Power Panic Bed temperature						| ^ 			| D3 Ax0f8b C1
+| 0x0F89h 3977		| uint16	| EEPROM_UVLO_FEEDRATE					| ???			| ff ffh 65535			| Power Panic Feedrate								| ^ 			| D3 Ax0f89 C2
+| 0x0F88h 3976		| uint8		| EEPROM_UVLO_FAN_SPEED					| ???			| ffh 255				| Power Panic Fan speed								| ^ 			| D3 Ax0f88 C1
+| 0x0F87h 3975		| uint8		| EEPROM_FAN_CHECK_ENABLED				| 00h 0			| ???					| Fan Check __disabled__							| LCD menu		| D3 Ax0f87 C1
+| ^					| ^			| ^										| 01h 1			| ffh 255				| Fan Check __enabled__ 							| ^ 			| ^
+| 0x0F75h 3957		| uint16	| EEPROM_UVLO_MESH_BED_LEVELING			| ???			| ff ffh 65535			| Power Panic Mesh Bed Leveling						| ???			| D3 Ax0f75 C18 
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
+| 0x0F73h 3955		| uint16	| EEPROM_UVLO_Z_MICROSTEPS				| ???			| ff ffh 65535			| Power Panic Z microsteps							| ???			| D3 Ax0f73 C2 
+| 0x0F72h 3954		| uint8		| EEPROM_UVLO_E_ABS						| ???			| ffh 255				| Power Panic ??? position							| ???			| D3 Ax0f72 C1
+| 0x0F6Eh 3950		| foat		| EEPROM_UVLO_CURRENT_POSITION_E		| ???			| ff ff ff ffh			| Power Panic E position							| ???			| D3 Ax0f6e C4
+| 0x0F6Dh 3949		| ???		| _EEPROM_FREE_NR2_						| ???			| ffh 255				| _Free EEPROM space_								| _free space_	| D3 Ax0f6d C1
+| 0x0F6Ch 3948		| ???		| _EEPROM_FREE_NR3_						| ???			| ffh 255				| _Free EEPROM space_								| _free space_	| D3 Ax0f6c C1
+| 0x0F6Bh 3947		| ???		| _EEPROM_FREE_NR4_						| ???			| ffh 255				| _Free EEPROM space_								| _free space_	| D3 Ax0f6b C1
+| 0x0F6Ah 3946		| ???		| _EEPROM_FREE_NR5_						| ???			| ffh 255				| _Free EEPROM space_								| _free space_	| D3 Ax0f6a C1
+| 0x0F69h 3945		| uint8		| EEPROM_CRASH_DET						| ffh 255		| ffh 255				| Crash detection: __enabled__						| LCD menu		| D3 Ax0f69 C1
+| ^					| ^			| ^										| 00h 0			| ^						| Crash detection: __disabled__						| LCD menu		| ^
+| 0x0F68h 3944		| uint8		| EEPROM_CRASH_COUNT_Y					| 00h-ffh 0-255	| ffh 255		__S/P__	| Crashes detected on y axis						| ???			| D3 Ax0f68 C1
+| 0x0F67h 3943		| uint8		| EEPROM_FSENSOR						| 01h 1			| ffh 255		__P__	| Filament sensor: __enabled__						| LCD menu		| D3 Ax0f67 C1
+| ^					| ^			| ^										| 00h 0			| ^						| Filament sensor: __disabled__						| LCD menu		| ^
+| 0x0F65h 3942		| uint8		| EEPROM_CRASH_COUNT_X					| 00h-ffh 0-255	| ffh 255		__S/P__	| Crashes detected on x axis						| ???			| D3 Ax0f66 C1
+| 0x0F65h 3941		| uint8		| EEPROM_FERROR_COUNT					| 00h-ffh 0-255	| ffh 255		__S/P__	| Filament sensor error counter						| ???			| D3 Ax0f65 C1
+| 0x0F64h 3940		| uint8		| EEPROM_POWER_COUNT					| 00h-ffh 0-255	| ffh 255		__S/P__	| Power failure counter								| ???			| D3 Ax0f64 C1
+| 0x0F60h 3936		| float		| EEPROM_XYZ_CAL_SKEW					| ???			| ff ff ff ffh			| XYZ skew value									| ???			| D3 Ax0f60 C4
+| 0x0F5Fh 3935		| uint8		| EEPROM_WIZARD_ACTIVE					| 01h 1			| 01h 1			__P__	| Wizard __active__									| ???			| D3 Ax0f5f C1
+| ^					| ^			| ^										| 00h 0			| ^						| Wizard __inactive__								| ^ 			| ^
+| 0x0F5Dh 3933		| uint16	| EEPROM_BELTSTATUS_X					| ???			| ff ffh				| X Beltstatus 										| ???			| D3 Ax0f5d C2
+| 0x0F5Bh 3931		| uint16	| EEPROM_BELTSTATUS_Y					| ???			| ff ffh				| Y Beltstatus 										| ???			| D3 Ax0f5b C2
+| 0x0F5Ah 3930		| uint8		| EEPROM_DIR_DEPTH						| 00h-ffh 0-255	| ffh 255				| Directory depth									| ???			| D3 Ax0f5a C1
+| 0x0F0Ah 3850		| uint8		| EEPROM_DIRS							| ???			| ffh 255				| Directories ???									| ???			| D3 Ax0f0a C80
+| 0x0F09h 3849		| uint8		| EEPROM_SD_SORT						| 00h 0			| ffh 255				| SD card sort by: 	__time__						| LCD menu		| D3 Ax0f09 C1
+| ^					| ^			| ^										| 01h 1			| ^						| SD card sort by: 	__alphabet__					| LCD menu		| ^
+| ^					| ^			| ^										| 02h 1			| ^						| SD card:			__not sorted__					| LCD menu		| ^
+| 0x0F08h 3848		| uint8		| EEPROM_SECOND_SERIAL_ACTIVE			| 00h 0			| ffh 255				| RPi Port: __disabled__							| LCD menu		| D3 Ax0f08 C1
+| ^					| ^			| ^										| 01h 1			| ^						| RPi Port: __enabled__								| LCD menu		| ^
+| 0x0F07h 3847		| uint8		| EEPROM_FSENS_AUTOLOAD_ENABLED			| 01h 1			| ffh 255		__P__	| Filament autoload: __enabled__					| LCD menu		| D3 Ax0f07 C1
+| ^					| ^			| ^										| 00h 0			| ^						| Filament autoload: __disabled__					| LCD menu		| ^
+| 0x0F05h 3845		| uint16	| EEPROM_CRASH_COUNT_X_TOT				| 0000-fffe		| ff ffh		__S/P__	| Total crashes on x axis	  						| ???			| D3 Ax0f05 C2
+| 0x0F03h 3843		| uint16	| EEPROM_CRASH_COUNT_Y_TOT				| 0000-fffe		| ff ffh		__S/P__	| Total crashes on y axis  							| ???			| D3 Ax0f03 C2
+| 0x0F01h 3841		| uint16	| EEPROM_FERROR_COUNT_TOT				| 0000-fffe		| ff ffh		__S/P__	| Total filament sensor errors 						| ???			| D3 Ax0f01 C2
+| 0x0EFFh 3839		| uint16	| EEPROM_POWER_COUNT_TOT				| 0000-fffe		| ff ffh		__S/P__	| Total power failures		  						| ???			| D3 Ax0eff C2
+| 0x0EFEh 3838		| uint8		| EEPROM_TMC2130_HOME_X_ORIGIN			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efe C1
+| 0x0EFDh 3837		| uint8		| EEPROM	MC2130_HOME_X_BSTEPS			| ???			| ffh 255			| ???						  						| ???			| D3 Ax0efd C1
+| 0x0EFCh 3836		| uint8		| EEPROM_TMC2130_HOME_X_FSTEPS			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efc C1
+| 0x0EFBh 3835		| uint8		| EEPROM_TMC2130_HOME_Y_ORIGIN			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efb C1
+| 0x0EFAh 3834		| uint8		| EEPROM_TMC2130_HOME_Y_BSTEPS			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efa C1
+| 0x0EF9h 3833		| uint8		| EEPROM_TMC2130_HOME_Y_FSTEPS			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef9 C1
+| 0x0EF8h 3832		| uint8		| EEPROM_TMC2130_HOME_ENABLED			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef8 C1
+| 0x0EF7h 3831		| uint8		| EEPROM_TMC2130_WAVE_X_FAC				| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef7 C1
+| 0x0EF6h 3830		| uint8		| EEPROM_TMC2130_WAVE_Y_FAC				| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef6 C1
+| 0x0EF5h 3829		| uint8		| EEPROM_TMC2130_WAVE_Z_FAC				| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef5 C1
+| 0x0EF4h 3828		| uint8		| EEPROM_TMC2130_WAVE_E_FAC				| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef4 C1
+| 0x0EF3h 3827		| uint8		| EEPROM_TMC2130_X_MRES					| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef3 C1
+| 0x0EF2h 3826		| uint8		| EEPROM_TMC2130_Y_MRES					| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef2 C1
+| 0x0EF1h 3825		| uint8		| EEPROM_TMC2130_Z_MRES					| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef1 C1
+| 0x0EF0h 3824		| uint8		| EEPROM_TMC2130_E_MRES					| ???			| ffh 255				| ???						  						| ???			| D3 Ax0ef0 C1
+| 0x0EEE 3822		| uint16 	| EEPROM_PRINTER_TYPE					| ???			| ff ffh 65535			| Printer Type										| ???			| D3 Ax0eee C2
+| ^					| ^			| ^										| 64 00h 100	| ^						| PRINTER_MK1										| ???			| ^
+| ^					| ^			| ^										| c8 00h 200	| ^						| PRINTER_MK2										| ???			| ^
+| ^					| ^			| ^										| c9 00h 201	| ^						| PRINTER_MK2 with MMU1								| ???			| ^
+| ^					| ^			| ^										| ca 00h 202	| ^						| PRINTER_MK2S										| ???			| ^
+| ^					| ^			| ^										| cb 00h 203	| ^						| PRINTER_MK2S with MMU1							| ???			| ^
+| ^					| ^			| ^										| fa 00h 250	| ^						| PRINTER_MK2.5										| ???			| ^
+| ^					| ^			| ^										| 1a 4fh 20250	| ^						| PRINTER_MK2.5 with MMU2							| ???			| ^
+| ^					| ^			| ^										| fc 00h 252	| ^						| PRINTER_MK2.5S									| ???			| ^
+| ^					| ^			| ^										| 1c 4fh 20252	| ^						| PRINTER_MK2.5S with MMU2S							| ???			| ^
+| ^					| ^			| ^										| 2c 01h 300	| ^						| PRINTER_MK3										| ???			| ^
+| ^					| ^			| ^										| 4c 4fh 20300	| ^						| PRINTER_MK3 with MMU2								| ???			| ^
+| ^					| ^			| ^										| 2e 01h 302	| ^						| PRINTER_MK3S										| ???			| ^
+| ^					| ^			| ^										| 4e 4fh 20302	| ^						| PRINTER_MK3S with MMU2S							| ???			| ^
+| 0x0EEC 3820		| uint16	| EEPROM_BOARD_TYPE						| ???			| ff ffh 65535			| Board Type										| ???			| D3 Ax0eec C2
+| ^					| ^			| ^										| c8 00h 200	| ^						| BOARD_RAMBO_MINI_1_0								| ???			| ^
+| ^					| ^			| ^										| cb 00h 203	| ^						| BOARD_RAMBO_MINI_1_3								| ???			| ^
+| ^					| ^			| ^										| 36 01h 310	| ^						| BOARD_EINSY_1_0a									| ???			| ^
+| 0x0EE8 3816		| float		| EEPROM_EXTRUDER_MULTIPLIER_0			| ???			| ff ff ff ffh			| Power panic Extruder 0 multiplier					| ???			| D3 Ax0ee8 C4
+| 0x0EE4 3812		| float		| EEPROM_EXTRUDER_MULTIPLIER_1			| ???			| ff ff ff ffh			| Power panic Extruder 1 multiplier					| ???			| D3 Ax0ee4 C4
+| 0x0EE0 3808		| float		| EEPROM_EXTRUDER_MULTIPLIER_2			| ???			| ff ff ff ffh			| Power panic Extruder 2 multiplier					| ???			| D3 Ax0ee0 C4
+| 0x0EDE 3806		| uint16	| EEPROM_EXTRUDEMULTIPLY				| ???			| ff ffh 65535			| Power panic Extruder multiplier					| ???			| D3 Ax0ede C2
+| 0x0EDA 3802		| float		| EEPROM_UVLO_TINY_CURRENT_POSITION_Z	| ???			| ff ff ff ffh			| Power panic Z position							| ???			| D3 Ax0eda C4
+| 0x0ED8 3800		| uint16	| EEPROM_UVLO_TARGET_HOTEND				| ???			| ff ffh 65535			| Power panic target Hotend temperature				| ???			| D3 Ax0ed8 C2
+| 0x0ED7 3799		| uint8		| EEPROM_SOUND_MODE						| 00h 0			| ffh 255				| Sound mode: __loud__								| ???			| D3 Ax0ed7 C1
+| ^					| ^			| ^										| 01h 1			| ^						| Sound mode: __once__								| ^				| ^
+| ^					| ^			| ^										| 02h 1			| ^						| Sound mode: __silent__							| ^				| ^
+| ^					| ^			| ^										| 03h 1			| ^						| Sound mode: __assist__							| ^				| ^
+| 0x0ED6 3798		| bool		| EEPROM_AUTO_DEPLETE					| 01h 1			| ffh 255				| MMU2/s autodeplete: __on__						| ???			| D3 Ax0ed6 C1
+| ^					| ^			| ^										| 00h 0			| ^						| MMU2/s autodeplete: __off__						| ^				| ^
+| 0x0ED5 3797		| bool		| EEPROM_FSENS_OQ_MEASS_ENABLED			| ???			| ffh 255				| PAT1925 ???										| ???			| D3 Ax0ed5 C1
+| ^					| ^			| ^										| ???			| ^						| PAT1925 ???										| ^				| ^
+| 0x0ED3 3795		| uint16	| EEPROM_MMU_FAIL_TOT					| ???			| ff ffh 65535	__S/P__	| MMU2/s total failures								| ???			| D3 Ax0ed3 C2
+| 0x0ED2 3794		| uint8		| EEPROM_MMU_FAIL						| ???			| ffh 255		__S/P__	| MMU2/s fails during print							| ???			| D3 Ax0ed2 C1
+| 0x0ED0 3792		| uint16	| EEPROM_MMU_LOAD_FAIL_TOT				| ???			| ff ffh 65535	__S/P__	| MMU2/s total load failures						| ???			| D3 Ax0ed0 C2
+| 0x0ECF 3791		| uint8		| EEPROM_MMU_LOAD_FAIL					| ???			| ffh 255		__S/P__	| MMU2/s load failures during print					| ???			| D3 Ax0ecf C1
+| 0x0ECE 3790		| uint8		| EEPROM_MMU_CUTTER_ENABLED				| 00h 0			| ffh 255				| MMU2/s cutter: __disabled__						| LCD menu		| D3 Ax0ece C1
+| ^					| ^			| ^										| 01h 1			| ^						| MMU2/s cutter: __enabled__						| ^				| ^
+| ^					| ^			| ^										| 02h 2			| ^						| MMU2/s cutter: __always__							| ^				| ^
+| 0x0DAE 3502		| uint16	| EEPROM_UVLO_MESH_BED_LEVELING_FULL	| ???			| ff ffh 65535			| Power panic Mesh bed leveling points 				| ???			| D3 Ax0dae C288
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
+| 0x0DAD 3501		| uint8		| EEPROM_MBL_TYPE						| ???			| ffh 255				| Mesh bed leveling precision 		_unused atm_	| ???			| D3 Ax0dad C1
+| 0x0DAC 3500		| bool		| EEPROM_MBL_MAGNET_ELIMINATION			| 01h 1			| ffh 255				| Mesh bed leveling does: __ignores__ magnets		| LCD menu		| D3 Ax0dac C1
+| ^					| ^			| ^										| 00h 0			| ^						| Mesh bed leveling does: __NOT ignores__ magnets	| ^				| ^
+| 0x0DAB 3499		| uint8		| EEPROM_MBL_POINTS_NR					| 03h 3			| ffh 255				| Mesh bed leveling points: __3x3__					| LCD menu		| D3 Ax0dab C1
+| ^					| ^			| ^										| 07h 7			| ^						| Mesh bed leveling points: __7x7__					| ^				| ^
+| 0x0DAA 3498		| uint8		| EEPROM_MBL_PROBE_NR					| 03h 3			| ffh 255				| MBL times measurements for each point: __3__ 		| LCD menu		| D3 Ax0daa C1
+| ^					| ^			| ^										| 05h 5			| ^						| MBL times measurements for each point: __5__		| ^				| ^
+| ^					| ^			| ^										| 01h 1			| ^						| MBL times measurements for each point: __1__		| ^				| ^
+| 0x0DA9 3497		| uint8		| EEPROM_MMU_STEALTH					| 01h 1			| ffh 255				| MMU2/s Silent mode: __on__						| ???			| D3 Ax0da9 C1
+| ^					| ^			| ^										| 00h 0			| ^						| MMU2/s Silent mode: __off__						| ^				| ^
+| 0x0DA8 3496		| uint8		| EEPROM_CHECK_MODE						| 01h 1			| ffh 255				| Check mode for nozzle is: __warn__				| LCD menu		| D3 Ax0da8 C1
+| ^					| ^			| ^										| 02h 0			| ^						| Check mode for nozzle is: __strict__				| ^				| ^
+| ^					| ^			| ^										| 00h 0			| ^						| Check mode for nozzle is: __none__				| ^				| ^
+| 0x0DA7 3495		| uint8		| EEPROM_NOZZLE_DIAMETER				| 28h 40		| ffh 255				| Nozzle diameter is: __40 or 0.40mm__				| LCD menu		| D3 Ax0da7 C1
+| ^					| ^			| ^										| 3ch 60		| ^						| Nozzle diameter is: __60 or 0.60mm__				| ^				| ^
+| ^					| ^			| ^										| 19h 25		| ^						| Nozzle diameter is: __25 or 0.25mm__				| ^				| ^
+| 0x0DA5 3493		| uint16	| EEPROM_NOZZLE_DIAMETER_uM				| 9001h			| ff ffh 65535			| Nozzle diameter is: __400um__						| LCD menu		| D3 Ax0da5 C2
+| ^					| ^			| ^										| 5802h			| ^						| Nozzle diameter is: __600um__						| ^				| ^
+| ^					| ^			| ^										| fa00h			| ^						| Nozzle diameter is: __250um__						| ^				| ^
+| 0x0DA4 3492		| uint8		| EEPROM_CHECK_MODEL					| 01h 1			| ffh 255				| Check mode for printer model is: __warn__			| LCD menu		| D3 Ax0da4 C1
+| ^					| ^			| ^										| 02h 0			| ^						| Check mode for printer model is: __strict__		| ^				| ^
+| ^					| ^			| ^										| 00h 0			| ^						| Check mode for printer model is: __none__			| ^				| ^
+| 0x0DA3 3491		| uint8		| EEPROM_CHECK_VERSION					| 01h 1			| ffh 255				| Check mode for firmware is: __warn__				| LCD menu		| D3 Ax0da3 C1
+| ^					| ^			| ^										| 02h 0			| ^						| Check mode for firmware is: __strict__			| ^				| ^
+| ^					| ^			| ^										| 00h 0			| ^						| Check mode for firmware is: __none__				| ^				| ^
+| 0x0DA2 3490		| uint8		| EEPROM_CHECK_GCODE					| 01h 1			| ffh 255				| Check mode for gcode is: __warn__ _unused atm_	| LCD menu		| D3 Ax0da2 C1
+| ^					| ^			| ^										| 02h 0			| ^						| Check mode for gcode is: __strict__ _unused atm_	| ^				| ^
+| ^					| ^			| ^										| 00h 0			| ^						| Check mode for gcode is: __none__ _unused atm_	| ^				| ^
+| 0x0D49 3401		| uint16	| EEPROM_SHEETS_BASE					| ???			| ffh 255				| ???												| LCD menu		| D3 Ax0d49 C89
+| 0x0D49 3401		| char		| _1st Sheet block_						| 536d6f6f746831| ffffffffffffff		| 1st sheet - Name: 	_Smooth1_					| ^				| D3 Ax0d49 C7
+| 0x0D50 3408		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 1st sheet - Z offset 								| ^				| D3 Ax0d50 C2	
+| 0x0D52 3410		| uint8		| ^										| 00h 0			| ffh 255				| 1st sheet - bed temp 								| ^				| D3 Ax0d52 C1	
+| 0x0D53 3411		| uint8		| ^										| 00h 0			| ffh 255				| 1st sheet - PINDA temp 							| ^				| D3 Ax0d53 C1	
+| 0x0D54 3412		| char		| _2nd Sheet block_						| 536d6f6f746832| ffffffffffffff		| 2nd sheet - Name: 	_Smooth2_					| ^				| D3 Ax0d54 C7
+| 0x0D5B 3419		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 2nd sheet - Z offset 								| ^				| D3 Ax0d5b C2	
+| 0x0D5D 3421		| uint8		| ^										| 00h 0			| ffh 255				| 2nd sheet - bed temp 								| ^				| D3 Ax0d5d C1	
+| 0x0D5E 3422		| uint8		| ^										| 00h 0			| ffh 255				| 2nd sheet - PINDA temp 							| ^				| D3 Ax0d5e C1	
+| 0x0D5F 3423		| char		| _3rd Sheet block_						| 54657874757231| ffffffffffffff		| 3rd sheet - Name: 	_Textur1_					| ^				| D3 Ax0d5f C7
+| 0x0D66 3430		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 3rd sheet - Z offset 								| ^				| D3 Ax0d66 C2	
+| 0x0D68 3432		| uint8		| ^										| 00h 0			| ffh 255				| 3rd sheet - bed temp 								| ^				| D3 Ax0d68 C1	
+| 0x0D69 3433		| uint8		| ^										| 00h 0			| ffh 255				| 3rd sheet - PINDA temp 							| ^				| D3 Ax0d69 C1	
+| 0x0D6A 3434		| char		| _4th Sheet block_						| 54657874757232| ffffffffffffff		| 4th sheet - Name: 	_Textur2_					| ^				| D3 Ax0d6a C7
+| 0x0D71 3441		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 4th sheet - Z offset 								| ^				| D3 Ax0d71 C2	
+| 0x0D73 3443		| uint8		| ^										| 00h 0			| ffh 255				| 4th sheet - bed temp 								| ^				| D3 Ax0d73 C1	
+| 0x0D74 3444		| uint8		| ^										| 00h 0			| ffh 255				| 4th sheet - PINDA temp 							| ^				| D3 Ax0d74 C1	
+| 0x0D75 3445		| char		| _5th Sheet block_						| 437573746f6d31| ffffffffffffff		| 5th sheet - Name: 	_Custom1_					| ^				| D3 Ax0d75 C7
+| 0x0D7C 3452		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 5th sheet - Z offset 								| ^				| D3 Ax0d7c C2	
+| 0x0D7E 3454		| uint8		| ^										| 00h 0			| ffh 255				| 5th sheet - bed temp 								| ^				| D3 Ax0d7e C1	
+| 0x0D7F 3455		| uint8		| ^										| 00h 0			| ffh 255				| 5th sheet - PINDA temp 							| ^				| D3 Ax0d7f C1	
+| 0x0D80 3456		| char		| _6th Sheet block_						| 437573746f6d32| ffffffffffffff		| 6th sheet - Name: 	_Custom2_					| ^				| D3 Ax0d80 C7
+| 0x0D87 3463		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 6th sheet - Z offset 								| ^				| D3 Ax0d87 C2	
+| 0x0D89 3465		| uint8		| ^										| 00h 0			| ffh 255				| 6th sheet - bed temp 								| ^				| D3 Ax0d89 C1	
+| 0x0D8A 3466		| uint8		| ^										| 00h 0			| ffh 255				| 6th sheet - PINDA temp 							| ^				| D3 Ax0d8a C1	
+| 0x0D8B 3467		| char		| _7th Sheet block_						| 437573746f6d33| ffffffffffffff		| 7th sheet - Name: 	_Custom3_					| ^				| D3 Ax0d8b C7
+| 0x0D92 3474		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 7th sheet - Z offset 								| ^				| D3 Ax0d92 C2	
+| 0x0D94 3476		| uint8		| ^										| 00h 0			| ffh 255				| 7th sheet - bed temp 								| ^				| D3 Ax0d94 C1	
+| 0x0D95 3477		| uint8		| ^										| 00h 0			| ffh 255				| 7th sheet - PINDA temp 							| ^				| D3 Ax0d95 C1	
+| 0x0D96 3478		| char		| _8th Sheet block_						| 437573746f6d34| ffffffffffffff		| 8th sheet - Name: 	_Custom4_					| ^				| D3 Ax0d96 C7
+| 0x0D9D 3485		| uint16	| ^										| 00 00h 0		| ff ffh 65535			| 8th sheet - Z offset 								| ^				| D3 Ax0d9d C2	
+| 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 ???							| ^				| ^
+| 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
+| ^					| ^			| ^										| ???			| ^						| Power panic saved target e-axis					| ^				| D3 Ax0d43 C4
+| ^					| ^			| ^										| ???			| ^						| Power panic saved target z-axis					| ^				| D3 Ax0d3f C4
+| ^					| ^			| ^										| ???			| ^						| Power panic saved target y-axis					| ^				| D3 Ax0d3b C4
+| ^					| ^			| ^										| ???			| ^						| Power panic saved target x-axis					| ^				| D3 Ax0d37 C4
+| 0x0D35 3381		| uint16	| EEPROM_UVLO_FEEDMULTIPLY				| ???			| ff ffh 65355			| Power panic saved feed multiplier					| ???			| D3 Ax0d35 C2
+| 0x0D34 3380		| uint8		| EEPROM_BACKLIGHT_LEVEL_HIGH			| 00h - ffh 	| 82h 130				| LCD backlight bright:	__128__	Dim value to 255	| LCD menu		| D3 Ax0d34 C1
+| 0x0D33 3379		| uint8		| EEPROM_BACKLIGHT_LEVEL_LOW			| 00h - ffh		| 32h 50				| LCD backlight dim:	__50__ 	0 to Bright value	| LCD menu		| D3 Ax0d33 C1
+| 0x0D32 3378		| uint8		| EEPROM_BACKLIGHT_MODE					| 02h 2			| ffh 255				| LCD backlight mode: __Auto__						| LCD menu		| D3 Ax0d32 C1
+| ^					| ^			| ^										| 01h 1			| ^						| LCD backlight mode: __Bright__					| ^				| ^
+| ^					| ^			| ^										| 00h 0			| ^						| LCD backlight mode: __Dim__						| ^				| ^
+| 0x0D30 3376		| uint16	| EEPROM_BACKLIGHT_TIMEOUT				| 01 00 - ff ff | 0a 00h 65535			| LCD backlight timeout: __10__ seconds				| LCD menu		| D3 Ax0d30 C2
+| 0x0D2C 3372		| float		| EEPROM_UVLO_LA_K						| ???			| ff ff ff ffh			| Power panic saved Linear Advanced K value			| ???			| D3 Ax0d2c C4
+
+  
+| Address begin		| Bit/Type 	| Name 									| Valid values	| Default/FactoryReset	| Description 										| Gcode/Function| Debug code
+| :--:				| :--: 		| :--: 									| :--:			| :--:					| :--:												| :--:			| :--:
+| 0x0012 18			| uint16	| EEPROM_FIRMWARE_VERSION_END			| ???			| ff ffh 65535			| ???												| ???			| D3 Ax0012 C2
+| 0x0010 16			| uint16	| EEPROM_FIRMWARE_VERSION_FLAVOR		| ???			| ff ffh 65535			| ???												| ???			| D3 Ax0010 C2
+| 0x000E 14			| uint16	| EEPROM_FIRMWARE_VERSION_REVISION		| ???			| ff ffh 65535			| Firmware version revision number DEV/ALPHA/BETA/RC| ???			| D3 Ax000e C2
+| 0x000C 12			| uint16	| EEPROM_FIRMWARE_VERSION_MINOR			| ???			| ff ffh 65535			| Firmware version minor number						| ???			| D3 Ax000c C2
+| 0x000A 10			| uint16	| EEPROM_FIRMWARE_VERSION_MAJOR			| ???			| ff ffh 65535			| Firmware version major number 					| ???			| D3 Ax000a C2
+| 0x0000 0			| char		| FW_PRUSA3D_MAGIC						| ???			| ffffffffffffffffffff	| __`PRUSA3DFW`__				 					| ???			| D3 Ax0000 C10
+*/
 
 #define EEPROM_EMPTY_VALUE 0xFF
 #define EEPROM_EMPTY_VALUE16 0xFFFF
@@ -51,7 +393,8 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 // The offsets are saved as 16bit signed int, scaled to tenths of microns.
 #define EEPROM_BED_CALIBRATION_Z_JITTER   (EEPROM_BED_CALIBRATION_VEC_Y-2*8)
 #define EEPROM_FARM_MODE (EEPROM_BED_CALIBRATION_Z_JITTER-1)
-#define EEPROM_FARM_NUMBER (EEPROM_FARM_MODE-3)
+#define EEPROM_FREE_NR1 (EEPROM_FARM_MODE-1)
+#define EEPROM_FARM_NUMBER (EEPROM_FREE_NR1-2)
 
 // Correction of the bed leveling, in micrometers.
 // Maximum 50 micrometers allowed.
@@ -83,8 +426,12 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 #define EEPROM_UVLO_E_ABS            (EEPROM_UVLO_Z_MICROSTEPS - 1)
 #define EEPROM_UVLO_CURRENT_POSITION_E	(EEPROM_UVLO_E_ABS - 4)                 //float for current position in E
 
+#define EEPROM_FREE_NR2         (EEPROM_UVLO_CURRENT_POSITION_E - 1)			// FREE EEPROM SPACE
+#define EEPROM_FREE_NR3         (EEPROM_FREE_NR2 - 1)							// FREE EEPROM SPACE
+#define EEPROM_FREE_NR4         (EEPROM_FREE_NR3 - 1)							// FREE EEPROM SPACE
+#define EEPROM_FREE_NR5         (EEPROM_FREE_NR4 - 1)							// FREE EEPROM SPACE
 // Crash detection mode EEPROM setting 
-#define EEPROM_CRASH_DET         (EEPROM_UVLO_CURRENT_POSITION_E - 5)           // float (orig EEPROM_UVLO_MESH_BED_LEVELING-12) 
+#define EEPROM_CRASH_DET         (EEPROM_FREE_NR5 - 1)       				    // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-12) 
 // Crash detection counter Y (last print)
 #define EEPROM_CRASH_COUNT_Y       (EEPROM_CRASH_DET - 1)                       // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-15)
 // Filament sensor on/off EEPROM setting 

+ 160 - 108
Firmware/fsensor.cpp

@@ -18,19 +18,19 @@
 
 //! @name Basic parameters
 //! @{
-#define FSENSOR_CHUNK_LEN    0.64F  //!< filament sensor chunk length 0.64mm
-#define FSENSOR_ERR_MAX         17  //!< filament sensor maximum error count for runout detection
+#define FSENSOR_CHUNK_LEN      1.25 //!< filament sensor chunk length (mm)
+#define FSENSOR_ERR_MAX           4 //!< filament sensor maximum error/chunk count for runout detection
+
+#define FSENSOR_SOFTERR_CMAX      3 //!< number of contiguous soft failures before a triggering a runout
+#define FSENSOR_SOFTERR_DELTA 30000 //!< maximum interval (ms) to consider soft failures contiguous
 //! @}
 
 //! @name Optical quality measurement parameters
 //! @{
-#define FSENSOR_OQ_MAX_ES      6    //!< maximum error sum while loading (length ~64mm = 100chunks)
-#define FSENSOR_OQ_MAX_EM      2    //!< maximum error counter value while loading
-#define FSENSOR_OQ_MIN_YD      2    //!< minimum yd per chunk (applied to avg value)
-#define FSENSOR_OQ_MAX_YD      200  //!< maximum yd per chunk (applied to avg value)
-#define FSENSOR_OQ_MAX_PD      4    //!< maximum positive deviation (= yd_max/yd_avg)
-#define FSENSOR_OQ_MAX_ND      5    //!< maximum negative deviation (= yd_avg/yd_min)
-#define FSENSOR_OQ_MAX_SH      13   //!< maximum shutter value
+#define FSENSOR_OQ_MAX_ES      2    //!< maximum sum of error blocks during filament recheck
+#define FSENSOR_OQ_MIN_YD      2    //!< minimum yd sum during filament check (counts per inch)
+#define FSENSOR_OQ_MIN_BR      80   //!< minimum brightness value
+#define FSENSOR_OQ_MAX_SH      10   //!< maximum shutter value
 //! @}
 
 const char ERRMSG_PAT9125_NOT_RESP[] PROGMEM = "PAT9125 not responding (%d)!\n";
@@ -44,28 +44,35 @@ const char ERRMSG_PAT9125_NOT_RESP[] PROGMEM = "PAT9125 not responding (%d)!\n";
 #define FSENSOR_INT_PIN_PCMSK_BIT PCINT13         // PinChange Interrupt / PinChange Enable Mask @ PJ4
 #define FSENSOR_INT_PIN_PCICR_BIT PCIE1           // PinChange Interrupt Enable / Flag @ PJ4
 
-//uint8_t fsensor_int_pin = FSENSOR_INT_PIN;
-uint8_t fsensor_int_pin_old = 0;
-int16_t fsensor_chunk_len = 0;
-
 //! enabled = initialized and sampled every chunk event
 bool fsensor_enabled = true;
 //! runout watching is done in fsensor_update (called from main loop)
 bool fsensor_watch_runout = true;
 //! not responding - is set if any communication error occurred during initialization or readout
 bool fsensor_not_responding = false;
+
+#ifdef PAT9125
+uint8_t fsensor_int_pin_old = 0;
+//! optical checking "chunk lenght" (already in steps)
+int16_t fsensor_chunk_len = 0;
 //! enable/disable quality meassurement
 bool fsensor_oq_meassure_enabled = false;
-
 //! number of errors, updated in ISR
 uint8_t fsensor_err_cnt = 0;
 //! variable for accumulating step count (updated callbacks from stepper and ISR)
 int16_t fsensor_st_cnt = 0;
-//! last dy value from pat9125 sensor (used in ISR)
-int16_t fsensor_dy_old = 0;
+//! count of total sensor "soft" failures (filament status checks)
+uint8_t fsensor_softfail = 0;
+//! timestamp of last soft failure
+unsigned long fsensor_softfail_last = 0;
+//! count of soft failures within the configured time
+uint8_t fsensor_softfail_ccnt = 0;
+#endif
 
+#ifdef DEBUG_FSENSOR_LOG
 //! log flag: 0=log disabled, 1=log enabled
 uint8_t fsensor_log = 1;
+#endif //DEBUG_FSENSOR_LOG
 
 
 //! @name filament autoload variables
@@ -75,6 +82,8 @@ uint8_t fsensor_log = 1;
 bool fsensor_autoload_enabled = true;
 //! autoload watching enable/disable flag
 bool fsensor_watch_autoload = false;
+
+#ifdef PAT9125
 //
 uint16_t fsensor_autoload_y;
 //
@@ -84,6 +93,7 @@ uint32_t fsensor_autoload_last_millis;
 //
 uint8_t fsensor_autoload_sum;
 //! @}
+#endif
 
 
 //! @name filament optical quality measurement variables
@@ -111,7 +121,7 @@ int16_t fsensor_oq_yd_max;
 uint16_t fsensor_oq_sh_sum;
 //! @}
 
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
 ClFsensorPCB oFsensorPCB;
 ClFsensorActionNA oFsensorActionNA;
 bool bIRsensorStateFlag=false;
@@ -125,11 +135,29 @@ void fsensor_stop_and_save_print(void)
     fsensor_watch_runout = false;
 }
 
+#ifdef PAT9125
+// Reset all internal counters to zero, including stepper callbacks
+void fsensor_reset_err_cnt()
+{
+    fsensor_err_cnt = 0;
+    pat9125_y = 0;
+    st_reset_fsensor();
+}
+
+void fsensor_set_axis_steps_per_unit(float u)
+{
+    fsensor_chunk_len = (int16_t)(FSENSOR_CHUNK_LEN * u);
+}
+#endif
+
+
 void fsensor_restore_print_and_continue(void)
 {
     printf_P(PSTR("fsensor_restore_print_and_continue\n"));
     fsensor_watch_runout = true;
-	fsensor_err_cnt = 0;
+#ifdef PAT9125
+    fsensor_reset_err_cnt();
+#endif
     restore_print_from_ram_and_continue(0);
 }
 
@@ -154,7 +182,7 @@ void fsensor_init(void)
 #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;
-	fsensor_chunk_len = (int16_t)(FSENSOR_CHUNK_LEN * cs.axis_steps_per_unit[E_AXIS]);
+    fsensor_set_axis_steps_per_unit(cs.axis_steps_per_unit[E_AXIS]);
 
 	if (!pat9125)
 	{
@@ -162,7 +190,7 @@ void fsensor_init(void)
 		fsensor_not_responding = true;
 	}
 #endif //PAT9125
-#if IR_SENSOR_ANALOG
+#ifdef 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);
@@ -172,7 +200,7 @@ void fsensor_init(void)
 	else
 		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
+#ifdef 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"));
@@ -194,8 +222,7 @@ bool fsensor_enable(bool bUpdateEEPROM)
 		fsensor_enabled = pat9125 ? true : false;
 		fsensor_watch_runout = true;
 		fsensor_oq_meassure = false;
-		fsensor_err_cnt = 0;
-		fsensor_dy_old = 0;
+        fsensor_reset_err_cnt();
 		eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, fsensor_enabled ? 0x01 : 0x00);
 		FSensorStateMenu = fsensor_enabled ? 1 : 0;
 	}
@@ -206,7 +233,7 @@ bool fsensor_enable(bool bUpdateEEPROM)
 		FSensorStateMenu = 1;
 	}
 #else // PAT9125
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
      if(!fsensor_IR_check())
           {
           bUpdateEEPROM=true;
@@ -219,7 +246,7 @@ bool fsensor_enable(bool bUpdateEEPROM)
      fsensor_enabled=true;
      fsensor_not_responding=false;
      FSensorStateMenu=1;
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
           }
 #endif //IR_SENSOR_ANALOG
      if(bUpdateEEPROM)
@@ -275,12 +302,11 @@ void fsensor_autoload_check_start(void)
 	fsensor_autoload_last_millis = _millis();
 	fsensor_watch_runout = false;
 	fsensor_watch_autoload = true;
-	fsensor_err_cnt = 0;
 }
 
+
 void fsensor_autoload_check_stop(void)
 {
-
 //	puts_P(_N("fsensor_autoload_check_stop\n"));
 	if (!fsensor_enabled) return;
 //	puts_P(_N("fsensor_autoload_check_stop 1\n"));
@@ -291,7 +317,7 @@ void fsensor_autoload_check_stop(void)
 	fsensor_autoload_sum = 0;
 	fsensor_watch_autoload = false;
 	fsensor_watch_runout = true;
-	fsensor_err_cnt = 0;
+    fsensor_reset_err_cnt();
 }
 #endif //PAT9125
 
@@ -356,6 +382,7 @@ bool fsensor_check_autoload(void)
 	return false;
 }
 
+#ifdef PAT9125
 void fsensor_oq_meassure_set(bool State)
 {
 	fsensor_oq_meassure_enabled = State;
@@ -373,7 +400,7 @@ void fsensor_oq_meassure_start(uint8_t skip)
 	fsensor_oq_yd_sum = 0;
 	fsensor_oq_er_sum = 0;
 	fsensor_oq_er_max = 0;
-	fsensor_oq_yd_min = FSENSOR_OQ_MAX_YD;
+	fsensor_oq_yd_min = INT16_MAX;
 	fsensor_oq_yd_max = 0;
 	fsensor_oq_sh_sum = 0;
 	pat9125_update();
@@ -389,9 +416,9 @@ void fsensor_oq_meassure_stop(void)
 	printf_P(_N(" st_sum=%u yd_sum=%u er_sum=%u er_max=%hhu\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max);
 	printf_P(_N(" yd_min=%u yd_max=%u yd_avg=%u sh_avg=%u\n"), fsensor_oq_yd_min, fsensor_oq_yd_max, (uint16_t)((uint32_t)fsensor_oq_yd_sum * fsensor_chunk_len / fsensor_oq_st_sum), (uint16_t)(fsensor_oq_sh_sum / fsensor_oq_samples));
 	fsensor_oq_meassure = false;
-	fsensor_err_cnt = 0;
 }
 
+#ifdef FSENSOR_QUALITY
 const char _OK[] PROGMEM = "OK";
 const char _NG[] PROGMEM = "NG!";
 
@@ -427,18 +454,24 @@ bool fsensor_oq_result(void)
 	printf_P(_N("fsensor_oq_result %S\n"), (res?_OK:_NG));
 	return res;
 }
-#ifdef PAT9125
+#endif //FSENSOR_QUALITY
+
 ISR(FSENSOR_INT_PIN_VECT)
 {
 	if (mmu_enabled || ir_sensor_detected) return;
 	if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
 	fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
+
+    // prevent isr re-entry
 	static bool _lock = false;
 	if (_lock) return;
 	_lock = true;
+
+    // fetch fsensor_st_cnt atomically
 	int st_cnt = fsensor_st_cnt;
 	fsensor_st_cnt = 0;
 	sei();
+
 	uint8_t old_err_cnt = fsensor_err_cnt;
 	uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
 	if (!pat9125_res)
@@ -447,56 +480,71 @@ ISR(FSENSOR_INT_PIN_VECT)
 		fsensor_not_responding = true;
 		printf_P(ERRMSG_PAT9125_NOT_RESP, 1);
 	}
+
 	if (st_cnt != 0)
-	{ //movement
-		if (st_cnt > 0) //positive movement
-		{
-			if (pat9125_y < 0)
-			{
-				if (fsensor_err_cnt)
-					fsensor_err_cnt += 2;
-				else
-					fsensor_err_cnt++;
-			}
-			else if (pat9125_y > 0)
-			{
-				if (fsensor_err_cnt)
-					fsensor_err_cnt--;
-			}
-			else //(pat9125_y == 0)
-				if (((fsensor_dy_old <= 0) || (fsensor_err_cnt)) && (st_cnt > (fsensor_chunk_len >> 1)))
-					fsensor_err_cnt++;
-			if (fsensor_oq_meassure)
-			{
-				if (fsensor_oq_skipchunk)
-				{
-					fsensor_oq_skipchunk--;
-					fsensor_err_cnt = 0;
-				}
-				else
-				{
-					if (st_cnt == fsensor_chunk_len)
-					{
-						if (pat9125_y > 0) if (fsensor_oq_yd_min > pat9125_y) fsensor_oq_yd_min = (fsensor_oq_yd_min + pat9125_y) / 2;
-						if (pat9125_y >= 0) if (fsensor_oq_yd_max < pat9125_y) fsensor_oq_yd_max = (fsensor_oq_yd_max + pat9125_y) / 2;
-					}
-					fsensor_oq_samples++;
-					fsensor_oq_st_sum += st_cnt;
-					if (pat9125_y > 0) fsensor_oq_yd_sum += pat9125_y;
-					if (fsensor_err_cnt > old_err_cnt)
-						fsensor_oq_er_sum += (fsensor_err_cnt - old_err_cnt);
-					if (fsensor_oq_er_max < fsensor_err_cnt)
-						fsensor_oq_er_max = fsensor_err_cnt;
-					fsensor_oq_sh_sum += pat9125_s;
-				}
-			}
-		}
-		else //negative movement
-		{
-		}
-	}
-	else
-	{ //no movement
+	{
+        // movement was planned, check for sensor movement
+        int8_t st_dir = st_cnt >= 0;
+        int8_t pat9125_dir = pat9125_y >= 0;
+
+        if (pat9125_y == 0)
+        {
+            if (st_dir)
+            {
+                // no movement detected: we might be within a blind sensor range,
+                // update the frame and shutter parameters we didn't earlier
+                if (!fsensor_oq_meassure)
+                    pat9125_update_bs();
+
+                // increment the error count only if underexposed: filament likely missing
+                if ((pat9125_b < FSENSOR_OQ_MIN_BR) && (pat9125_s > FSENSOR_OQ_MAX_SH))
+                {
+                    // check for a dark frame (<30% avg brightness) with long exposure
+                    ++fsensor_err_cnt;
+                }
+                else
+                {
+                    // good frame, filament likely present
+                    if(fsensor_err_cnt) --fsensor_err_cnt;
+                }
+            }
+        }
+        else if (pat9125_dir != st_dir)
+        {
+            // detected direction opposite of motor movement
+            if (st_dir) ++fsensor_err_cnt;
+        }
+        else if (pat9125_dir == st_dir)
+        {
+            // direction agreeing with planned movement
+            if (fsensor_err_cnt) --fsensor_err_cnt;
+        }
+
+        if (st_dir && fsensor_oq_meassure)
+        {
+            // extruding with quality assessment
+            if (fsensor_oq_skipchunk)
+            {
+                fsensor_oq_skipchunk--;
+                fsensor_err_cnt = 0;
+            }
+            else
+            {
+                if (st_cnt == fsensor_chunk_len)
+                {
+                    if (pat9125_y > 0) if (fsensor_oq_yd_min > pat9125_y) fsensor_oq_yd_min = (fsensor_oq_yd_min + pat9125_y) / 2;
+                    if (pat9125_y >= 0) if (fsensor_oq_yd_max < pat9125_y) fsensor_oq_yd_max = (fsensor_oq_yd_max + pat9125_y) / 2;
+                }
+                fsensor_oq_samples++;
+                fsensor_oq_st_sum += st_cnt;
+                if (pat9125_y > 0) fsensor_oq_yd_sum += pat9125_y;
+                if (fsensor_err_cnt > old_err_cnt)
+                    fsensor_oq_er_sum += (fsensor_err_cnt - old_err_cnt);
+                if (fsensor_oq_er_max < fsensor_err_cnt)
+                    fsensor_oq_er_max = fsensor_err_cnt;
+                fsensor_oq_sh_sum += pat9125_s;
+            }
+        }
 	}
 
 #ifdef DEBUG_FSENSOR_LOG
@@ -507,9 +555,7 @@ ISR(FSENSOR_INT_PIN_VECT)
 	}
 #endif //DEBUG_FSENSOR_LOG
 
-	fsensor_dy_old = pat9125_y;
 	pat9125_y = 0;
-
 	_lock = false;
 	return;
 }
@@ -529,19 +575,16 @@ void fsensor_setup_interrupt(void)
      PCICR |= bit(FSENSOR_INT_PIN_PCICR_BIT);     // enable corresponding PinChangeInterrupt (set of pins)
 }
 
-#endif //PAT9125
-
 void fsensor_st_block_chunk(int cnt)
 {
 	if (!fsensor_enabled) return;
 	fsensor_st_cnt += cnt;
-	if (abs(fsensor_st_cnt) >= fsensor_chunk_len)
-	{
-// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
-		if (PIN_GET(FSENSOR_INT_PIN)) {PIN_VAL(FSENSOR_INT_PIN, LOW);}
-		else {PIN_VAL(FSENSOR_INT_PIN, HIGH);}
-	}
+
+    // !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
+    if (PIN_GET(FSENSOR_INT_PIN)) {PIN_VAL(FSENSOR_INT_PIN, LOW);}
+    else {PIN_VAL(FSENSOR_INT_PIN, HIGH);}
 }
+#endif //PAT9125
 
 
 //! Common code for enqueing M600 and supplemental codes into the command queue.
@@ -578,39 +621,48 @@ void fsensor_update(void)
             st_synchronize();
 
             // check the filament in isolation
-			fsensor_err_cnt = 0;
+            fsensor_reset_err_cnt();
 			fsensor_oq_meassure_start(0);
             float e_tmp = current_position[E_AXIS];
             current_position[E_AXIS] -= 3;
-            plan_buffer_line_curposXYZE(200/60, active_extruder);
+            plan_buffer_line_curposXYZE(250/60, active_extruder);
             current_position[E_AXIS] = e_tmp;
             plan_buffer_line_curposXYZE(200/60, active_extruder);
             st_synchronize();
-
-			uint8_t err_cnt = fsensor_err_cnt;
 			fsensor_oq_meassure_stop();
 
 			bool err = false;
-			err |= (err_cnt > 1);
-
-			err |= (fsensor_oq_er_sum > 2);
-			err |= (fsensor_oq_yd_sum < (4 * FSENSOR_OQ_MIN_YD));
+			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;
-
-			if (!err)
-				printf_P(PSTR("fsensor_err_cnt = 0\n"));
-			else
-				fsensor_enque_M600();
+            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;
+            if (!err && fsensor_softfail_ccnt <= FSENSOR_SOFTERR_CMAX)
+            {
+                printf_P(PSTR("fsensor_err_cnt = 0\n"));
+                ++fsensor_softfail;
+                ++fsensor_softfail_ccnt;
+                fsensor_softfail_last = now;
+            }
+            else
+            {
+                fsensor_softfail_ccnt = 0;
+                fsensor_softfail_last = 0;
+                fsensor_enque_M600();
+            }
 		}
 #else //PAT9125
 		if (CHECK_FSENSOR && ir_sensor_detected)
         {
                if(digitalRead(IR_SENSOR_PIN))
                {                                  // IR_SENSOR_PIN ~ H
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
                     if(!bIRsensorStateFlag)
                     {
                          bIRsensorStateFlag=true;
@@ -653,7 +705,7 @@ void fsensor_update(void)
 #endif //IR_SENSOR_ANALOG
                                   fsensor_checkpoint_print();
                                   fsensor_enque_M600();
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
                               }
                          }
                     }
@@ -667,7 +719,7 @@ void fsensor_update(void)
 #endif //PAT9125
 }
 
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
 bool fsensor_IR_check()
 {
 uint16_t volt_IR_int;

+ 18 - 6
Firmware/fsensor.h

@@ -6,15 +6,16 @@
 #include "config.h"
 
 
-//! minimum meassured chunk length in steps
-extern int16_t fsensor_chunk_len;
 // enable/disable flag
 extern bool fsensor_enabled;
 // not responding flag
 extern bool fsensor_not_responding;
-//enable/disable quality meassurement
-extern bool fsensor_oq_meassure_enabled;
-
+#ifdef PAT9125
+// optical checking "chunk lenght" (already in steps)
+extern int16_t fsensor_chunk_len;
+// count of soft failures
+extern uint8_t fsensor_softfail;
+#endif
 
 //! @name save restore printing
 //! @{
@@ -28,6 +29,11 @@ extern void fsensor_checkpoint_print(void);
 //! initialize
 extern void fsensor_init(void);
 
+#ifdef PAT9125
+//! update axis resolution
+extern void fsensor_set_axis_steps_per_unit(float u);
+#endif
+
 //! @name enable/disable
 //! @{
 extern bool fsensor_enable(bool bUpdateEEPROM=true);
@@ -52,8 +58,10 @@ extern void fsensor_autoload_check_stop(void);
 extern bool fsensor_check_autoload(void);
 //! @}
 
+#ifdef PAT9125
 //! @name optical quality measurement support
 //! @{
+extern bool fsensor_oq_meassure_enabled;
 extern void fsensor_oq_meassure_set(bool State);
 extern void fsensor_oq_meassure_start(uint8_t skip);
 extern void fsensor_oq_meassure_stop(void);
@@ -64,15 +72,19 @@ extern bool fsensor_oq_result(void);
 //! @{
 extern void fsensor_st_block_chunk(int cnt);
 
+// debugging
+extern uint8_t fsensor_log;
+
 // There's really nothing to do in block_begin: the stepper ISR likely has
 // called us already at the end of the last block, making this integration
 // redundant. LA1.5 might not always do that during a coasting move, so attempt
 // to drain fsensor_st_cnt anyway at the beginning of the new block.
 #define fsensor_st_block_begin(rev) fsensor_st_block_chunk(0)
 //! @}
+#endif //PAT9125
 
 
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
 #define IR_SENSOR_STEADY 10                       // [ms]
 
 enum class ClFsensorPCB:uint_least8_t

+ 3 - 1
Firmware/language.h

@@ -6,7 +6,9 @@
 
 #include "config.h"
 #include <inttypes.h>
-//#include <stdio.h>
+#ifdef DEBUG_SEC_LANG
+    #include <stdio.h>
+#endif //DEBUG_SEC_LANG
 
 #define PROTOCOL_VERSION "1.0"
 

+ 6 - 5
Firmware/mmu.cpp

@@ -383,8 +383,9 @@ void mmu_loop(void)
 			//printf_P(PSTR("Eact: %d\n"), int(e_active()));
 			if (!mmu_finda && CHECK_FSENSOR && fsensor_enabled) {
 				fsensor_checkpoint_print();
-				ad_markDepleted(mmu_extruder);
-				if (lcd_autoDepleteEnabled() && !ad_allDepleted())
+				if (mmu_extruder != MMU_FILAMENT_UNKNOWN) // Can't deplete unknown extruder.
+                    ad_markDepleted(mmu_extruder);
+				if (lcd_autoDepleteEnabled() && !ad_allDepleted() && mmu_extruder != MMU_FILAMENT_UNKNOWN) // Can't auto if F=?
 				{
 				    enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
 				}
@@ -795,8 +796,8 @@ void mmu_load_to_nozzle()
 {
 	st_synchronize();
 	
-	bool saved_e_relative_mode = axis_relative_modes[E_AXIS];
-	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = true;
+	const bool saved_e_relative_mode = axis_relative_modes & E_AXIS_MASK;
+	if (!saved_e_relative_mode) axis_relative_modes |= E_AXIS_MASK;
 	if (ir_sensor_detected)
 	{
 		current_position[E_AXIS] += 3.0f;
@@ -820,7 +821,7 @@ void mmu_load_to_nozzle()
 	feedrate = 871;
 	plan_buffer_line_curposXYZE(feedrate / 60, active_extruder);
     st_synchronize();
-	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = false;
+	if (!saved_e_relative_mode) axis_relative_modes &= ~E_AXIS_MASK;
 }
 
 void mmu_M600_wait_and_beep() {

+ 9 - 14
Firmware/pat9125.c

@@ -183,9 +183,9 @@ uint8_t pat9125_update(void)
 		if (pat9125_PID1 == 0xff) return 0;
 		if (ucMotion & 0x80)
 		{
-			uint8_t ucXL = pat9125_rd_reg(PAT9125_DELTA_XL);
-			uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
-			uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
+			uint16_t ucXL = pat9125_rd_reg(PAT9125_DELTA_XL);
+			uint16_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
+			uint16_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
 			if (pat9125_PID1 == 0xff) return 0;
 			int16_t iDX = ucXL | ((ucXYH << 4) & 0xf00);
 			int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
@@ -207,8 +207,8 @@ uint8_t pat9125_update_y(void)
 		if (pat9125_PID1 == 0xff) return 0;
 		if (ucMotion & 0x80)
 		{
-			uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
-			uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
+			uint16_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
+			uint16_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
 			if (pat9125_PID1 == 0xff) return 0;
 			int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
 			if (iDY & 0x800) iDY -= 4096;
@@ -219,18 +219,13 @@ uint8_t pat9125_update_y(void)
 	return 0;
 }
 
-uint8_t pat9125_update_y2(void)
+uint8_t pat9125_update_bs(void)
 {
 	if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
 	{
-		uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
-		if (pat9125_PID1 == 0xff) return 0; //NOACK error
-		if (ucMotion & 0x80)
-		{
-			int8_t dy = pat9125_rd_reg(PAT9125_DELTA_YL);
-			if (pat9125_PID1 == 0xff) return 0; //NOACK error
-			pat9125_y -= dy; //negative number, because direction switching does not work
-		}
+		pat9125_b = pat9125_rd_reg(PAT9125_FRAME);
+		pat9125_s = pat9125_rd_reg(PAT9125_SHUTTER);
+		if (pat9125_PID1 == 0xff) return 0;
 		return 1;
 	}
 	return 0;

+ 3 - 3
Firmware/pat9125.h

@@ -19,9 +19,9 @@ extern uint8_t pat9125_b;
 extern uint8_t pat9125_s;
 
 extern uint8_t pat9125_init(void);
-extern uint8_t pat9125_update(void);
-extern uint8_t pat9125_update_y(void);
-extern uint8_t pat9125_update_y2(void);
+extern uint8_t pat9125_update(void);    // update all sensor data
+extern uint8_t pat9125_update_y(void);  // update _y only
+extern uint8_t pat9125_update_bs(void); // update _b/_s only
 
 
 #if defined(__cplusplus)

+ 3 - 0
Firmware/planner.h

@@ -173,6 +173,9 @@ void plan_set_e_position(const float &e);
 // Reset the E position to zero at the start of the next segment
 void plan_reset_next_e();
 
+inline void set_current_to_destination() { memcpy(current_position, destination, sizeof(current_position)); }
+inline void set_destination_to_current() { memcpy(destination, current_position, sizeof(destination)); }
+
 extern bool e_active();
 
 void check_axes_activity();

+ 16 - 9
Firmware/stepper.cpp

@@ -36,9 +36,9 @@
 #include "tmc2130.h"
 #endif //TMC2130
 
-#ifdef FILAMENT_SENSOR
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
 #include "fsensor.h"
-int fsensor_counter = 0; //counter for e-steps
+int fsensor_counter; //counter for e-steps
 #endif //FILAMENT_SENSOR
 
 #include "mmu.h"
@@ -421,9 +421,8 @@ FORCE_INLINE void stepper_next_block()
 #endif /* LIN_ADVANCE */
       count_direction[E_AXIS] = 1;
     }
-#ifdef FILAMENT_SENSOR
-	fsensor_counter = 0;
-	fsensor_st_block_begin(count_direction[E_AXIS] < 0);
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
+    fsensor_st_block_begin(count_direction[E_AXIS] < 0);
 #endif //FILAMENT_SENSOR
   }
   else {
@@ -973,13 +972,13 @@ FORCE_INLINE void advance_isr_scheduler() {
             WRITE_NC(E0_STEP_PIN, !INVERT_E_STEP_PIN);
             e_steps += (rev? 1: -1);
             WRITE_NC(E0_STEP_PIN, INVERT_E_STEP_PIN);
-#ifdef FILAMENT_SENSOR
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
             fsensor_counter += (rev? -1: 1);
 #endif
         }
         while(--max_ticks);
 
-#ifdef FILAMENT_SENSOR
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
         if (abs(fsensor_counter) >= fsensor_chunk_len)
         {
             fsensor_st_block_chunk(fsensor_counter);
@@ -1357,8 +1356,6 @@ void quickStop()
 }
 
 #ifdef BABYSTEPPING
-
-
 void babystep(const uint8_t axis,const bool direction)
 {
   //MUST ONLY BE CALLED BY A ISR, it depends on that no other ISR interrupts this
@@ -1594,3 +1591,13 @@ void microstep_readings()
       #endif
 }
 #endif //TMC2130
+
+
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
+void st_reset_fsensor()
+{
+    CRITICAL_SECTION_START;
+    fsensor_counter = 0;
+    CRITICAL_SECTION_END;
+}
+#endif //FILAMENT_SENSOR

+ 4 - 1
Firmware/stepper.h

@@ -92,7 +92,10 @@ void microstep_readings();
 #ifdef BABYSTEPPING
   void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention
 #endif
-     
 
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
+// reset the internal filament sensor state
+void st_reset_fsensor();
+#endif
 
 #endif

+ 10 - 2
Firmware/temperature.cpp

@@ -73,7 +73,7 @@ int current_voltage_raw_pwr = 0;
 int current_voltage_raw_bed = 0;
 #endif
 
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
 int current_voltage_raw_IR = 0;
 #endif //IR_SENSOR_ANALOG
 
@@ -210,6 +210,14 @@ static void temp_runaway_check(int _heater_id, float _target_temperature, float
 static void temp_runaway_stop(bool isPreheat, bool isBed);
 #endif
 
+// return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on')
+bool checkAllHotends(void)
+{
+    bool result=false;
+    for(int i=0;i<EXTRUDERS;i++) result=(result||(target_temperature[i]!=0));
+    return(result);
+}
+
   void PID_autotune(float temp, int extruder, int ncycles)
   {
   pid_number_of_cycles = ncycles;
@@ -1588,7 +1596,7 @@ void adc_ready(void) //callback from adc when sampling finished
 #ifdef VOLT_BED_PIN
 	current_voltage_raw_bed = adc_values[ADC_PIN_IDX(VOLT_BED_PIN)]; // 6->9
 #endif
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
      current_voltage_raw_IR = adc_values[ADC_PIN_IDX(VOLT_IR_PIN)];
 #endif //IR_SENSOR_ANALOG
 	temp_meas_ready = true;

+ 6 - 1
Firmware/temperature.h

@@ -47,6 +47,8 @@
 void tp_init();  //initialize the heating
 void manage_heater(); //it is critical that this is called periodically.
 
+extern bool checkAllHotends(void);
+
 // low level conversion routines
 // do not use these routines and variables outside of temperature.cpp
 extern int target_temperature[EXTRUDERS];  
@@ -76,7 +78,7 @@ extern int current_voltage_raw_pwr;
 extern int current_voltage_raw_bed;
 #endif
 
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
 extern int current_voltage_raw_IR;
 #endif //IR_SENSOR_ANALOG
 
@@ -222,6 +224,9 @@ FORCE_INLINE bool isCoolingBed() {
 #error Invalid number of extruders
 #endif
 
+// return "false", if all heaters are 'off' (ie. "true", if any heater is 'on')
+#define CHECK_ALL_HEATERS (checkAllHotends()||(target_temperature_bed!=0))
+
 int getHeaterPower(int heater);
 void disable_heater();
 void updatePID();

+ 1 - 1
Firmware/tmc2130.cpp

@@ -994,7 +994,7 @@ bool tmc2130_home_calibrate(uint8_t axis)
 	uint8_t step[16];
 	uint8_t cnt[16];
 	uint8_t val[16];
-	homeaxis(axis, 16, step);
+	homeaxis(axis, true, 16, step);
 	bubblesort_uint8(step, 16, 0);
 	printf_P(PSTR("sorted samples:\n"));
 	for (uint8_t i = 0; i < 16; i++)

+ 135 - 76
Firmware/ultralcd.cpp

@@ -68,6 +68,10 @@ uint8_t SilentModeMenu_MMU = 1; //activate mmu unit stealth mode
 
 int8_t FSensorStateMenu = 1;
 
+#ifdef IR_SENSOR_ANALOG
+bool bMenuFSDetect=false;
+#endif //IR_SENSOR_ANALOG
+
 
 #ifdef SDCARD_SORT_ALPHA
 bool presort_flag = false;
@@ -114,7 +118,7 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
 // void copy_and_scalePID_d();
 
 /* Different menus */
-static void lcd_status_screen();
+//static void lcd_status_screen();                // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
 #if (LANG_MODE != 0)
 static void lcd_language_menu();
 #endif
@@ -235,8 +239,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();
+#ifdef IR_SENSOR_ANALOG
+static bool lcd_selftest_IRsensor(bool bStandalone=false);
+static void lcd_detect_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();
@@ -975,7 +980,7 @@ void lcdui_print_status_screen(void)
 }
 
 // Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent
-static void lcd_status_screen()
+void lcd_status_screen()                          // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
 {
 	if (firstrun == 1) 
 	{
@@ -1796,11 +1801,23 @@ static void lcd_menu_fails_stats_print()
     uint8_t crashX = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X);
     uint8_t crashY = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y);
     lcd_home();
+#ifndef PAT9125
     lcd_printf_P(failStatsFmt,
         _i("Last print failures"),  ////c=20 r=1
         _i("Power failures"), power,  ////c=14 r=1
         _i("Filam. runouts"), filam,  ////c=14 r=1
         _i("Crash"), crashX, crashY);  ////c=7 r=1
+#else
+    // On the MK3 include detailed PAT9125 statistics about soft failures
+    lcd_printf_P(PSTR("%S\n"
+                      " %-16.16S%-3d\n"
+                      " %-7.7S H %-3d S %-3d\n"
+                      " %-7.7S X %-3d Y %-3d"),
+                 _i("Last print failures"), ////c=20 r=1
+                 _i("Power failures"), power, ////c=14 r=1
+                 _i("Runouts"), filam, fsensor_softfail, //c=7 r=1
+                 _i("Crash"), crashX, crashY);  ////c=7 r=1
+#endif
     menu_back_if_clicked_fb();
 }
 
@@ -1940,7 +1957,7 @@ static void lcd_menu_temperatures()
     menu_back_if_clicked();
 }
 
-#if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN) || IR_SENSOR_ANALOG
+#if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN) || defined(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))
@@ -1952,27 +1969,24 @@ static void lcd_menu_temperatures()
 //! |                    |
 //! | PWR:         00.0V |	c=12 r=1
 //! | Bed:         00.0V |	c=12 r=1
-//! |                    |
+//! | IR :         00.0V |  c=12 r=1 optional
 //! ----------------------
 //! @endcode
 //! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations.
 static void lcd_menu_voltages()
 {
-	lcd_timeoutToStatus.stop(); //infinite timeout
-	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();
-#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);
+    lcd_timeoutToStatus.stop(); //infinite timeout
+    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:      %4.1fV\n" " BED:      %4.1fV"), volt_pwr, volt_bed);
+#ifdef 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();
+    menu_back_if_clicked();
 }
-#endif //defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN) || IR_SENSOR_ANALOG
+#endif //defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN) || defined(IR_SENSOR_ANALOG)
 
 #ifdef TMC2130
 //! @brief Show Belt Status
@@ -2146,6 +2160,23 @@ static void lcd_support_menu()
   MENU_ITEM_BACK_P(_i("Date:"));////MSG_DATE c=17 r=1
   MENU_ITEM_BACK_P(PSTR(__DATE__));
 
+#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(PSTR(" 03 or older"));
+            break;
+       case ClFsensorPCB::_Rev03b:
+            MENU_ITEM_BACK_P(PSTR(" 03b or newer"));
+            break;
+       case ClFsensorPCB::_Undef:
+       default:
+            MENU_ITEM_BACK_P(PSTR(" state unknown"));
+       }
+#endif // IR_SENSOR_ANALOG
+
 	MENU_ITEM_BACK_P(STR_SEPARATOR);
 	if (mmu_enabled)
 	{
@@ -2231,10 +2262,12 @@ void lcd_set_filament_autoload() {
      fsensor_autoload_set(!fsensor_autoload_enabled);
 }
 
+#if defined(FILAMENT_SENSOR) && defined(PAT9125)
 void lcd_set_filament_oq_meass()
 {
      fsensor_oq_meassure_set(!fsensor_oq_meassure_enabled);
 }
+#endif
 
 
 FilamentAction eFilamentAction=FilamentAction::None; // must be initialized as 'non-autoLoad'
@@ -5621,7 +5654,7 @@ SETTINGS_VERSION;
 MENU_END();
 }
 
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
 static void lcd_fsensor_actionNA_set(void)
 {
 switch(oFsensorActionNA)
@@ -5687,8 +5720,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
+#ifdef IR_SENSOR_ANALOG
     FSENSOR_ACTION_NA;
+    MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
 #endif //IR_SENSOR_ANALOG
     MENU_END();
 }
@@ -7107,7 +7141,7 @@ static void lcd_tune_menu()
 	else {
 		MENU_ITEM_TOGGLE_P(_T(MSG_FSENSOR), _T(MSG_ON), lcd_fsensor_state_set);
 	}
-#if IR_SENSOR_ANALOG
+#ifdef IR_SENSOR_ANALOG
      FSENSOR_ACTION_NA;
 #endif //IR_SENSOR_ANALOG
 #endif //FILAMENT_SENSOR
@@ -7335,10 +7369,7 @@ void lcd_print_stop()
 
     planner_abort_hard(); //needs to be done since plan_buffer_line resets waiting_inside_plan_buffer_line_print_aborted to false. Also copies current to destination.
     
-    axis_relative_modes[X_AXIS] = false;
-    axis_relative_modes[Y_AXIS] = false;
-    axis_relative_modes[Z_AXIS] = false;
-    axis_relative_modes[E_AXIS] = true;
+    axis_relative_modes = E_AXIS_MASK; //XYZ absolute, E relative
     
     isPrintPaused = false; //clear isPrintPaused flag to allow starting next print after pause->stop scenario.
 }
@@ -7471,39 +7502,60 @@ void lcd_belttest()
 }
 #endif //TMC2130
 
-#if IR_SENSOR_ANALOG
-static bool lcd_selftest_IRsensor()
+#ifdef IR_SENSOR_ANALOG
+// called also from marlin_main.cpp
+void printf_IRSensorAnalogBoardChange(bool bPCBrev03b){
+    printf_P(PSTR("Filament sensor board change detected: revision %S\n"), bPCBrev03b ? PSTR("03b or newer") : PSTR("03 or older"));
+}
+
+static bool lcd_selftest_IRsensor(bool bStandalone)
 {
-bool bAction;
-bool bPCBrev03b;
-uint16_t volt_IR_int;
-float volt_IR;
+    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);
+    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)){
+        if(!bStandalone)
+            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)){
+        if(!bStandalone)
+            lcd_selftest_error(TestError::FsensorLevel,"LOW","");
+        return(false);
+    }
+    if((bPCBrev03b?1:0)!=(uint8_t)oFsensorPCB){        // safer then "(uint8_t)bPCBrev03b"
+        printf_IRSensorAnalogBoardChange(bPCBrev03b);
+        oFsensorPCB=bPCBrev03b?ClFsensorPCB::_Rev03b:ClFsensorPCB::_Old;
+        eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
+    }
+    return(true);
+}
+
+static void lcd_detect_IRsensor(){
+    bool bAction;
+
+    bMenuFSDetect = true;                               // inhibits some code inside "manage_inactivity()"
+    bAction = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is the filament loaded?"), false, false);
+    if(!bAction){
+        lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action."));
+        return;
+    }
+    bAction = lcd_selftest_IRsensor(true);
+    if(bAction)
+        lcd_show_fullscreen_message_and_wait_P(_i("Sensor verified, remove the filament now."));
+    else
+        lcd_show_fullscreen_message_and_wait_P(_i("Verification failed, remove the filament and try again."));
+    bMenuFSDetect=false;                              // de-inhibits some code inside "manage_inactivity()"
 }
 #endif //IR_SENSOR_ANALOG
 
@@ -7517,7 +7569,8 @@ bool lcd_selftest()
 	int _progress = 0;
 	bool _result = true;
 	bool _swapped_fan = false;
-#if IR_SENSOR_ANALOG
+//#ifdef IR_SENSOR_ANALOG
+#if (0)
      bool bAction;
      bAction=lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is the filament unloaded?"),false,true);
      if(!bAction)
@@ -7529,10 +7582,7 @@ bool lcd_selftest()
 	#ifdef TMC2130
 	  FORCE_HIGH_POWER_START;
 	#endif // TMC2130
-     _delay(2000);
-    
-    FORCE_BL_ON_START;
-    
+	FORCE_BL_ON_START;
 	_delay(2000);
 	KEEPALIVE_STATE(IN_HANDLER);
 
@@ -7655,21 +7705,31 @@ bool lcd_selftest()
 #ifdef TMC2130
 		tmc2130_home_exit();
 		enable_endstops(false);
-		current_position[X_AXIS] = current_position[X_AXIS] + 14;
-		current_position[Y_AXIS] = current_position[Y_AXIS] + 12;
 #endif
 
 		//homeaxis(X_AXIS);
 		//homeaxis(Y_AXIS);
+        current_position[X_AXIS] += pgm_read_float(bed_ref_points_4);
+		current_position[Y_AXIS] += pgm_read_float(bed_ref_points_4+1);
+#ifdef TMC2130
+		//current_position[X_AXIS] += 0;
+		current_position[Y_AXIS] += 4;
+#endif //TMC2130
 		current_position[Z_AXIS] = current_position[Z_AXIS] + 10;
 		plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
 		st_synchronize();
+        set_destination_to_current();
 		_progress = lcd_selftest_screen(TestScreen::AxisZ, _progress, 3, true, 1500);
-		_result = lcd_selfcheck_axis(2, Z_MAX_POS);
-		if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) != 1) {
-			enquecommand_P(PSTR("G28 W"));
-			enquecommand_P(PSTR("G1 Z15 F1000"));
-		}
+#ifdef TMC2130
+		_result = homeaxis(Z_AXIS, false);
+#else
+        _result = lcd_selfcheck_axis(Z_AXIS, Z_MAX_POS);
+#endif //TMC2130
+
+		//raise Z to not damage the bed during and hotend testing
+		current_position[Z_AXIS] += 20;
+		plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
+		st_synchronize();
 	}
 
 #ifdef TMC2130
@@ -7726,7 +7786,8 @@ bool lcd_selftest()
 				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK
 			}
 #endif //PAT9125
-#if IR_SENSOR_ANALOG
+//#ifdef IR_SENSOR_ANALOG
+#if (0)
 			_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filament sensor
                _result = lcd_selftest_IRsensor();
 			if (_result)
@@ -7890,7 +7951,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
 }
 #endif //TMC2130
 
-//#ifndef TMC2130
+#ifndef TMC2130
 
 static bool lcd_selfcheck_axis(int _axis, int _travel)
 {
@@ -7989,12 +8050,13 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
 		{
 			lcd_selftest_error(TestError::Motor, _error_1, _error_2);
 		}
-	}
+	}    
+	current_position[_axis] = 0; //simulate axis home to avoid negative numbers for axis position, especially Z.
+	plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
 
 	return _stepresult;
 }
 
-#ifndef TMC2130
 static bool lcd_selfcheck_pulleys(int axis)
 {
 	float tmp_motor_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
@@ -8039,9 +8101,6 @@ static bool lcd_selfcheck_pulleys(int axis)
 			((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING) == 1)) {
 			endstop_triggered = true;
 			if (current_position_init - 1 <= current_position[axis] && current_position_init + 1 >= current_position[axis]) {
-				current_position[axis] += (axis == X_AXIS) ? 13 : 9;
-				plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
-				st_synchronize();
 				return(true);
 			}
 			else {

+ 8 - 1
Firmware/ultralcd.h

@@ -55,8 +55,10 @@ extern bool lcd_selftest();
 
 void lcd_menu_statistics(); 
 
+void lcd_status_screen();                         // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
 void lcd_menu_extruder_info();                    // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
 void lcd_menu_show_sensors_state();               // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
+
 #ifdef TMC2130
 bool lcd_crash_detect_enabled();
 void lcd_crash_detect_enable();
@@ -138,6 +140,11 @@ extern uint8_t farm_status;
 #define SILENT_MODE_OFF SILENT_MODE_POWER
 #endif
 
+#ifdef IR_SENSOR_ANALOG
+extern bool bMenuFSDetect;
+void printf_IRSensorAnalogBoardChange(bool bPCBrev03b);
+#endif //IR_SENSOR_ANALOG
+
 extern int8_t SilentModeMenu;
 extern uint8_t SilentModeMenu_MMU;
 
@@ -251,7 +258,7 @@ enum class WizState : uint8_t
 void lcd_wizard(WizState state);
 
 #define VOLT_DIV_REF 5
-#if IR_SENSOR_ANALOG
+#ifdef 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)

+ 4 - 4
Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h

@@ -151,8 +151,8 @@
 // this value is litlebit higher that real limit, because ambient termistor is on the board and is temperated from it,
 // temperature inside the case is around 31C for ambient temperature 25C, when the printer is powered on long time and idle
 // the real limit is 15C (same as MINTEMP limit), this is because 15C is end of scale for both used thermistors (bed, heater)
-#define MINTEMP_MINAMBIENT      25
-#define MINTEMP_MINAMBIENT_RAW  978
+#define MINTEMP_MINAMBIENT      10
+#define MINTEMP_MINAMBIENT_RAW  1002
 
 #define DEBUG_DCODE3
 
@@ -282,14 +282,14 @@
  *------------------------------------*/
 
 // Mintemps
-#define HEATER_0_MINTEMP 15
+#define HEATER_0_MINTEMP 10
 #define HEATER_1_MINTEMP 5
 #define HEATER_2_MINTEMP 5
 #define HEATER_MINTEMP_DELAY 15000                // [ms] ! if changed, check maximal allowed value @ ShortTimer
 #if HEATER_MINTEMP_DELAY>USHRT_MAX
 #error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
 #endif
-#define BED_MINTEMP 15
+#define BED_MINTEMP 10
 #define BED_MINTEMP_DELAY 50000                   // [ms] ! if changed, check maximal allowed value @ ShortTimer
 #if BED_MINTEMP_DELAY>USHRT_MAX
 #error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"

+ 4 - 4
Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h

@@ -153,8 +153,8 @@
 // this value is litlebit higher that real limit, because ambient termistor is on the board and is temperated from it,
 // temperature inside the case is around 31C for ambient temperature 25C, when the printer is powered on long time and idle
 // the real limit is 15C (same as MINTEMP limit), this is because 15C is end of scale for both used thermistors (bed, heater)
-#define MINTEMP_MINAMBIENT      25
-#define MINTEMP_MINAMBIENT_RAW  978
+#define MINTEMP_MINAMBIENT      10
+#define MINTEMP_MINAMBIENT_RAW  1002
 
 #define DEBUG_DCODE3
 
@@ -284,14 +284,14 @@
  *------------------------------------*/
 
 // Mintemps
-#define HEATER_0_MINTEMP 15
+#define HEATER_0_MINTEMP 10
 #define HEATER_1_MINTEMP 5
 #define HEATER_2_MINTEMP 5
 #define HEATER_MINTEMP_DELAY 15000                // [ms] ! if changed, check maximal allowed value @ ShortTimer
 #if HEATER_MINTEMP_DELAY>USHRT_MAX
 #error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
 #endif
-#define BED_MINTEMP 15
+#define BED_MINTEMP 10
 #define BED_MINTEMP_DELAY 50000                   // [ms] ! if changed, check maximal allowed value @ ShortTimer
 #if BED_MINTEMP_DELAY>USHRT_MAX
 #error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"