Browse Source

Merge pull request #8 from PavelSindler/MK3

recover print after blackout
XPila 7 years ago
parent
commit
f3379b57b1

+ 10 - 0
Firmware/Configuration.h

@@ -47,6 +47,16 @@
 #define EEPROM_TEMP_CAL_ACTIVE (EEPROM_PROBE_TEMP_SHIFT - 1)
 #define EEPROM_BOWDEN_LENGTH (EEPROM_TEMP_CAL_ACTIVE - 2*4) //4 x int for bowden lengths for multimaterial
 #define EEPROM_CALIBRATION_STATUS_PINDA (EEPROM_BOWDEN_LENGTH - 1) //0 - not calibrated; 1 - calibrated
+#define EEPROM_UVLO						(EEPROM_CALIBRATION_STATUS_PINDA - 1) //1 - uvlo during print
+#define EEPROM_UVLO_CURRENT_POSITION	(EEPROM_UVLO-2*4) // 2 x float for current_position in X and Y axes
+#define EEPROM_FILENAME (EEPROM_UVLO_CURRENT_POSITION - 8) //8chars to store filename without extension
+#define EEPROM_FILE_POSITION (EEPROM_FILENAME - 4) //32 bit for uint32_t file position 
+#define EEPROM_UVLO_CURRENT_POSITION_Z	(EEPROM_FILE_POSITION - 4) //float for current position in Z
+#define EEPROM_UVLO_TARGET_HOTEND		(EEPROM_UVLO_CURRENT_POSITION_Z - 1)
+#define EEPROM_UVLO_TARGET_BED			(EEPROM_UVLO_TARGET_HOTEND - 1)
+#define EEPROM_UVLO_FEEDRATE			(EEPROM_UVLO_TARGET_BED - 2)
+#define EEPROM_UVLO_FAN_SPEED			(EEPROM_UVLO_FEEDRATE - 1) 
+
 
 // Currently running firmware, each digit stored as uint16_t.
 // The flavor differentiates a dev, alpha, beta, release candidate or a release version.

+ 16 - 5
Firmware/Marlin.h

@@ -209,7 +209,7 @@ void ClearToSend();
 
 void get_coordinates();
 void prepare_move();
-void kill(const char *full_screen_message = NULL);
+void kill(const char *full_screen_message = NULL, unsigned char id = 0);
 void Stop();
 
 bool IsStopped();
@@ -302,9 +302,9 @@ extern unsigned int custom_message_state;
 extern char snmm_filaments_used;
 extern unsigned long PingTime;
 
-extern bool fan_state[2];
-extern int fan_edge_counter[2];
-extern int fan_speed[2];
+extern bool fan_state[2];
+extern int fan_edge_counter[2];
+extern int fan_speed[2];
 
 // Handling multiple extruders pins
 extern uint8_t active_extruder;
@@ -351,4 +351,15 @@ float temp_comp_interpolation(float temperature);
 void temp_compensation_apply();
 void temp_compensation_start();
 void wait_for_heater(long codenum);
-void serialecho_temperatures();
+void serialecho_temperatures();
+
+void uvlo_();
+void recover_print();
+void setup_uvlo_interrupt();
+
+extern void save_print_to_eeprom();
+extern void restore_print_from_eeprom();
+extern void position_menu();
+
+
+#define UVLO !(PINE & (1<<4))

+ 191 - 5
Firmware/Marlin_main.cpp

@@ -1210,9 +1210,13 @@ void setup()
 	if (eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA) == 255) {
 		eeprom_write_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0);
 	}
+	if (eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 255) {
+		eeprom_write_byte((uint8_t*)EEPROM_UVLO, 0);
+	}
 
 #ifndef DEBUG_SKIP_STARTMSGS
 	check_babystep(); //checking if Z babystep is in allowed range
+	setup_uvlo_interrupt();
 	
   if (calibration_status() == CALIBRATION_STATUS_ASSEMBLED ||
       calibration_status() == CALIBRATION_STATUS_UNKNOWN) {
@@ -1238,6 +1242,16 @@ void setup()
   // Store the currently running firmware into an eeprom,
   // so the next time the firmware gets updated, it will know from which version it has been updated.
   update_current_firmware_version_to_eeprom();
+  if (eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 1) { //previous print was terminated by UVLO
+	  if (lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_RECOVER_PRINT, false))	recover_print();
+	  else {
+		  eeprom_update_byte((uint8_t*)EEPROM_UVLO, 0);
+		  lcd_update_enable(true);
+		  lcd_update(2);
+		  lcd_setstatuspgm(WELCOME_MSG);
+	  }
+  }
+  
 }
 
 void trace();
@@ -1492,7 +1506,7 @@ void get_command()
 
         //If command was e-stop process now
         if(strcmp(cmdbuffer+bufindw+1, "M112") == 0)
-          kill();
+          kill("", 2);
         
         // Store the current line into buffer, move to the next line.
         cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_USB;
@@ -1608,7 +1622,11 @@ void get_command()
       }
       cmdbuffer[bufindw+serial_count+1] = 0; //terminate string
       cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD;
+	  SERIAL_ECHOPGM("cmdbuffer:");
+	  MYSERIAL.print(cmdbuffer);
       ++ buflen;
+	  SERIAL_ECHOPGM("buflen:");
+	  MYSERIAL.print(buflen);
       bufindw += strlen(cmdbuffer+bufindw+1) + 2;
       if (bufindw == sizeof(cmdbuffer))
           bufindw = 0;
@@ -2676,6 +2694,11 @@ void process_commands()
 
 	  homing_flag = false;
 
+	  SERIAL_ECHOLNPGM("Homing happened");
+	  SERIAL_ECHOPGM("Current position X AXIS:");
+	  MYSERIAL.println(current_position[X_AXIS]);
+	  SERIAL_ECHOPGM("Current position Y_AXIS:");
+	  MYSERIAL.println(current_position[Y_AXIS]);
       break;
 
 #ifdef ENABLE_AUTO_BED_LEVELING
@@ -4143,7 +4166,7 @@ Sigma_Exit:
       setWatch();
       break;
     case 112: //  M112 -Emergency Stop
-      kill();
+      kill("", 3);
       break;
     case 140: // M140 set bed temp
       if (code_seen('S')) setTargetBed(code_value());
@@ -6022,7 +6045,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument s
 
   if( (millis() - previous_millis_cmd) >  max_inactive_time )
     if(max_inactive_time)
-      kill();
+      kill("", 4);
   if(stepper_inactive_time)  {
     if( (millis() - previous_millis_cmd) >  stepper_inactive_time )
     {
@@ -6064,7 +6087,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument s
     // ----------------------------------------------------------------
     if ( killCount >= KILL_DELAY)
     {
-       kill();
+       kill("", 5);
     }
   #endif
     
@@ -6096,8 +6119,11 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument s
   check_axes_activity();
 }
 
-void kill(const char *full_screen_message)
+void kill(const char *full_screen_message, unsigned char id)
 {
+	SERIAL_ECHOPGM("KILL: ");
+	MYSERIAL.println(int(id));
+	//return;
   cli(); // Stop interrupts
   disable_heater();
 
@@ -6780,3 +6806,163 @@ void serialecho_temperatures() {
 	SERIAL_PROTOCOL_F(degBed(), 1);
 	SERIAL_PROTOCOLLN("");
 }
+
+
+
+void uvlo_() {
+		//SERIAL_ECHOLNPGM("UVLO");	
+		save_print_to_eeprom();
+		float current_position_bckp[2];
+		int feedrate_bckp = feedrate;
+		current_position_bckp[X_AXIS] = st_get_position_mm(X_AXIS);
+		current_position_bckp[Y_AXIS] = st_get_position_mm(Y_AXIS);
+
+		eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), current_position_bckp[X_AXIS]);
+		eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4), current_position_bckp[Y_AXIS]);
+		eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION_Z), current_position[Z_AXIS]);
+		EEPROM_save_B(EEPROM_UVLO_FEEDRATE, &feedrate_bckp);
+		eeprom_update_byte((uint8_t*)EEPROM_UVLO_TARGET_HOTEND, target_temperature[active_extruder]);
+		eeprom_update_byte((uint8_t*)EEPROM_UVLO_TARGET_BED, target_temperature_bed);
+		eeprom_update_byte((uint8_t*)EEPROM_UVLO_FAN_SPEED, fanSpeed);
+		disable_x();
+		disable_y();
+		planner_abort_hard();
+		// Because the planner_abort_hard() initialized current_position[Z] from the stepper,
+		// Z baystep is no more applied. Reset it.
+		babystep_reset();
+		// Clean the input command queue.
+		cmdqueue_reset();
+		card.sdprinting = false;
+		card.closefile();
+
+		current_position[E_AXIS] -= DEFAULT_RETRACTION;
+		sei(); //enable stepper driver interrupt to move Z axis
+		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 400, active_extruder);
+		st_synchronize();
+		current_position[Z_AXIS] += UVLO_Z_AXIS_SHIFT;
+		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 40, active_extruder);
+		st_synchronize();
+		eeprom_update_byte((uint8_t*)EEPROM_UVLO, 1);
+}
+
+void setup_uvlo_interrupt() {
+	DDRE &= ~(1 << 4); //input pin
+	PORTE &= ~(1 << 4); //no internal pull-up
+
+						//sensing falling edge
+	EICRB |= (1 << 0);
+	EICRB &= ~(1 << 1);
+
+	//enable INT4 interrupt
+	EIMSK |= (1 << 4);
+}
+
+ISR(INT4_vect) {
+	EIMSK &= ~(1 << 4); //disable INT4 interrupt to make sure that this code will be executed just once 
+	SERIAL_ECHOLNPGM("INT4");
+	if (IS_SD_PRINTING) uvlo_();
+}
+
+
+void save_print_to_eeprom() {
+	//eeprom_update_word((uint16_t*)(EPROM_UVLO_CMD_QUEUE), bufindw - bufindr );
+	//BLOCK_BUFFER_SIZE: max. 16 linear moves in planner buffer
+#define TYP_GCODE_LENGTH 30 //G1 X117.489 Y22.814 E1.46695 + cr lf
+	//card.get_sdpos() -> byte currently read from SD card
+	//bufindw -> position in circular buffer where to write
+	//bufindr -> position in circular buffer where to read
+	//bufflen -> number of lines in buffer -> for each line one special character??
+	//number_of_blocks() returns number of linear movements buffered in planner
+	long sd_position = card.get_sdpos() - ((bufindw > bufindr) ? (bufindw - bufindr) : sizeof(cmdbuffer) - bufindr + bufindw) - TYP_GCODE_LENGTH* number_of_blocks();
+	if (sd_position < 0) sd_position = 0;
+	/*SERIAL_ECHOPGM("sd position before correction:");
+	MYSERIAL.println(card.get_sdpos());
+	SERIAL_ECHOPGM("bufindw:");
+	MYSERIAL.println(bufindw);
+	SERIAL_ECHOPGM("bufindr:");
+	MYSERIAL.println(bufindr);
+	SERIAL_ECHOPGM("sizeof(cmd_buffer):");
+	MYSERIAL.println(sizeof(cmdbuffer));
+	SERIAL_ECHOPGM("sd position after correction:");
+	MYSERIAL.println(sd_position);*/
+	eeprom_update_dword((uint32_t*)(EEPROM_FILE_POSITION), sd_position);
+}
+
+void recover_print() {
+	char cmd[30];
+	lcd_update_enable(true);
+	lcd_update(2);
+	lcd_setstatuspgm(WELCOME_MSG);
+
+	target_temperature[active_extruder] = eeprom_read_byte((uint8_t*)EEPROM_UVLO_TARGET_HOTEND);
+	target_temperature_bed = eeprom_read_byte((uint8_t*)EEPROM_UVLO_TARGET_BED);
+	float z_pos = UVLO_Z_AXIS_SHIFT + eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_Z));
+
+	SERIAL_ECHOPGM("Target temperature:");
+	MYSERIAL.println(target_temperature[0]);
+	SERIAL_ECHOPGM("Target temp bed:");
+	MYSERIAL.println(target_temperature_bed);
+
+	enquecommand_P(PSTR("G28 X"));
+	enquecommand_P(PSTR("G28 Y"));
+	strcpy(cmd, "G92 Z");
+	strcat(cmd, ftostr43(z_pos));
+	enquecommand(cmd);
+
+	eeprom_update_byte((uint8_t*)EEPROM_UVLO, 0);
+	while ((abs(degHotend(0)- target_temperature[0])>5) || (abs(degBed() -target_temperature_bed)>3)) { //wait for heater and bed to reach target temp
+		delay_keep_alive(1000);
+	}
+	restore_print_from_eeprom();
+	SERIAL_ECHOPGM("current_position[Z_AXIS]:");
+	MYSERIAL.print(current_position[Z_AXIS]);
+}
+
+void restore_print_from_eeprom() {
+	float x_rec, y_rec;
+	int feedrate_rec;
+	uint8_t fan_speed_rec;
+	char cmd[30];
+	char* c;
+	char filename[13];
+	char str[5] = ".gco";
+	x_rec = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0));
+	y_rec = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4));
+	fan_speed_rec = eeprom_read_byte((uint8_t*)EEPROM_UVLO_FAN_SPEED);
+	EEPROM_read_B(EEPROM_UVLO_FEEDRATE, &feedrate_rec);
+	SERIAL_ECHOPGM("Feedrate:");
+	MYSERIAL.println(feedrate_rec);
+	for (int i = 0; i < 8; i++) {
+		filename[i] = eeprom_read_byte((uint8_t*)EEPROM_FILENAME + i);
+		
+	}
+	filename[8] = '\0';
+
+	MYSERIAL.print(filename);
+	strcat(filename, str);
+	sprintf_P(cmd, PSTR("M23 %s"), filename);
+	for (c = &cmd[4]; *c; c++)
+		 *c = tolower(*c);
+	enquecommand(cmd);
+	uint32_t position = eeprom_read_dword((uint32_t*)(EEPROM_FILE_POSITION));
+	SERIAL_ECHOPGM("Position read from eeprom:");
+	MYSERIAL.println(position);
+	enquecommand_P(PSTR("M24")); //M24 - Start SD print
+	sprintf_P(cmd, PSTR("M26 S%lu"), position);
+	enquecommand(cmd);	
+	enquecommand_P(PSTR("M83")); //E axis relative mode
+	strcpy(cmd, "G1 X");
+	strcat(cmd, ftostr32(x_rec));
+	strcat(cmd, " Y");
+	strcat(cmd, ftostr32(y_rec));
+	enquecommand(cmd);
+	enquecommand_P(PSTR("G1 Z"  STRINGIFY(-UVLO_Z_AXIS_SHIFT)));
+	enquecommand_P(PSTR("G1 E"  STRINGIFY(DEFAULT_RETRACTION)" F480"));
+	enquecommand_P(PSTR("G1 E0.5"));
+	sprintf_P(cmd, PSTR("G1 F%d"), feedrate_rec);
+	enquecommand(cmd);
+	strcpy(cmd, "M106 S");
+	strcat(cmd, itostr3(int(fan_speed_rec)));
+	enquecommand(cmd);
+	
+}

+ 1 - 1
Firmware/cardreader.cpp

@@ -262,7 +262,7 @@ void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
        SERIAL_ERROR_START;
        SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
        SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
-       kill();
+       kill("", 1);
        return;
      }
      

+ 1 - 0
Firmware/cardreader.h

@@ -47,6 +47,7 @@ public:
   FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);};
   FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;};
   FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;};
+  FORCE_INLINE uint32_t get_sdpos() { if (!isFileOpen()) return 0; else return(sdpos); };
 
   bool ToshibaFlashAir_isEnabled() const { return card.getFlashAirCompatible(); }
   void ToshibaFlashAir_enable(bool enable) { card.setFlashAirCompatible(enable); }

+ 5 - 0
Firmware/language_all.cpp

@@ -2203,6 +2203,11 @@ const char * const MSG_REBOOT_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_REBOOT_DE
 };
 
+const char MSG_RECOVER_PRINT_EN[] PROGMEM = "Blackout occured. Recover print?";
+const char * const MSG_RECOVER_PRINT_LANG_TABLE[1] PROGMEM = {
+	MSG_RECOVER_PRINT_EN
+};
+
 const char MSG_RECTRACT_EN[] PROGMEM = "Rectract";
 const char * const MSG_RECTRACT_LANG_TABLE[1] PROGMEM = {
 	MSG_RECTRACT_EN

+ 2 - 0
Firmware/language_all.h

@@ -414,6 +414,8 @@ extern const char* const MSG_PRUSA3D_HOWTO_LANG_TABLE[LANG_NUM];
 #define MSG_PRUSA3D_HOWTO LANG_TABLE_SELECT(MSG_PRUSA3D_HOWTO_LANG_TABLE)
 extern const char* const MSG_REBOOT_LANG_TABLE[LANG_NUM];
 #define MSG_REBOOT LANG_TABLE_SELECT(MSG_REBOOT_LANG_TABLE)
+extern const char* const MSG_RECOVER_PRINT_LANG_TABLE[1];
+#define MSG_RECOVER_PRINT LANG_TABLE_SELECT_EXPLICIT(MSG_RECOVER_PRINT_LANG_TABLE, 0)
 extern const char* const MSG_RECTRACT_LANG_TABLE[1];
 #define MSG_RECTRACT LANG_TABLE_SELECT_EXPLICIT(MSG_RECTRACT_LANG_TABLE, 0)
 extern const char* const MSG_REFRESH_LANG_TABLE[1];

+ 1 - 1
Firmware/language_en.h

@@ -302,4 +302,4 @@
 #define(length=17, lines=1) MSG_EXTRUDER_2						"Extruder 2"
 #define(length=17, lines=1) MSG_EXTRUDER_3						"Extruder 3"
 #define(length=17, lines=1) MSG_EXTRUDER_4						"Extruder 4"
-
+#define(length=20, lines=2) MSG_RECOVER_PRINT					"Blackout occured. Recover print?"

+ 4 - 3
Firmware/pins.h

@@ -507,16 +507,17 @@
 
 #ifdef ULTRA_LCD
 
-#define KILL_PIN          32
+//#define KILL_PIN          32
 
 #ifdef NEWPANEL
 
+
 #define BEEPER      84  // Beeper on AUX-4
 #define LCD_PINS_RS     82
 //#define LCD_PINS_ENABLE 18
 //#define LCD_PINS_D4     19
 #define LCD_PINS_ENABLE 61
-#define LCD_PINS_D4 59
+#define LCD_PINS_D4		59
 #define LCD_PINS_D5     70
 #define LCD_PINS_D6     85
 #define LCD_PINS_D7     71
@@ -529,7 +530,7 @@
 #define SDCARDDETECT   15
 
 #define TACH_0 79
-#define TACH_1 80
+#define TACH_1 80 
 
 #endif //NEWPANEL
 #endif //ULTRA_LCD

+ 3 - 1
Firmware/planner.cpp

@@ -1215,7 +1215,9 @@ void reset_acceleration_rates()
         axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
         }
 }
-
+unsigned char number_of_blocks() {
+	return (block_buffer_head + BLOCK_BUFFER_SIZE - block_buffer_tail) & (BLOCK_BUFFER_SIZE - 1);
+}
 #ifdef PLANNER_DIAGNOSTICS
 uint8_t planner_queue_min()
 {

+ 2 - 0
Firmware/planner.h

@@ -199,6 +199,8 @@ void set_extrude_min_temp(float temp);
 void reset_acceleration_rates();
 #endif
 
+unsigned char number_of_blocks();
+
 // #define PLANNER_DIAGNOSTICS
 #ifdef PLANNER_DIAGNOSTICS
 // Diagnostic functions to display planner buffer underflow on the display.

+ 1 - 0
Firmware/stepper.cpp

@@ -335,6 +335,7 @@ FORCE_INLINE void trapezoid_generator_reset() {
 // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
 ISR(TIMER1_COMPA_vect)
 {
+	//if (UVLO) uvlo();
   // If there is no current block, attempt to pop one from the buffer
   if (current_block == NULL) {
     // Anything in the buffer?

+ 53 - 52
Firmware/temperature.cpp

@@ -405,55 +405,55 @@ void setExtruderAutoFanState(int pin, bool state)
   analogWrite(pin, newFanSpeed);
 }
 
-void countFanSpeed()
-{
-	fan_speed[0] = (fan_edge_counter[0] * (float(250) / (millis() - extruder_autofan_last_check)));
-	fan_speed[1] = (fan_edge_counter[1] * (float(250) / (millis() - extruder_autofan_last_check)));
-
-	fan_edge_counter[0] = 0;
-	fan_edge_counter[1] = 0;
-}
-
-void checkFanSpeed()
-{
-	static unsigned char fan_speed_errors[2] = { 0,0 };
-
-	if (fan_speed[0] == 0 && current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE) fan_speed_errors[0]++;
-	else fan_speed_errors[0] = 0;
-
-	if (fan_speed[1] == 0 && fanSpeed > MIN_PRINT_FAN_SPEED) fan_speed_errors[1]++;
-	else fan_speed_errors[1] = 0;
-
-	if (fan_speed_errors[0] > 5) fanSpeedError(0);
-	if (fan_speed_errors[1] > 5) fanSpeedError(1);
-}
-
-void fanSpeedError(unsigned char _fan) {
-
-	if (card.sdprinting) {
-		card.pauseSDPrint();
-	}
-
-	setTargetHotend0(0);
-	/*lcd_update();
-	WRITE(BEEPER, HIGH);
-	delayMicroseconds(500);
-	WRITE(BEEPER, LOW);
-	delayMicroseconds(100);*/
-
-
-	SERIAL_ERROR_START;
-	switch (_fan) {
-	case 0:
-		SERIAL_ERRORLNPGM("ERROR: Extruder fan speed is lower then expected");
-		LCD_ALERTMESSAGEPGM("Err: EXTR. FAN ERROR");
-		break;
-	case 1:
-		SERIAL_ERRORLNPGM("ERROR: Print fan speed is lower then expected");
-		LCD_ALERTMESSAGEPGM("Err: PRINT FAN ERROR");
-		break;
-	}
-}
+void countFanSpeed()
+{	
+	fan_speed[0] = (fan_edge_counter[0] * (float(250) / (millis() - extruder_autofan_last_check)));
+	fan_speed[1] = (fan_edge_counter[1] * (float(250) / (millis() - extruder_autofan_last_check)));
+
+	fan_edge_counter[0] = 0;
+	fan_edge_counter[1] = 0;
+}
+
+void checkFanSpeed()
+{
+	static unsigned char fan_speed_errors[2] = { 0,0 };
+
+	if (fan_speed[0] == 0 && current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE) fan_speed_errors[0]++;
+	else fan_speed_errors[0] = 0;
+
+	if (fan_speed[1] == 0 && fanSpeed > MIN_PRINT_FAN_SPEED) fan_speed_errors[1]++;
+	else fan_speed_errors[1] = 0;
+
+	if (fan_speed_errors[0] > 5) fanSpeedError(0);
+	if (fan_speed_errors[1] > 15) fanSpeedError(1);
+}
+
+void fanSpeedError(unsigned char _fan) {
+
+	if (card.sdprinting) {
+		card.pauseSDPrint();
+	}
+
+	setTargetHotend0(0);
+	/*lcd_update();
+	WRITE(BEEPER, HIGH);
+	delayMicroseconds(500);
+	WRITE(BEEPER, LOW);
+	delayMicroseconds(100);*/
+
+
+	SERIAL_ERROR_START;
+	switch (_fan) {
+	case 0:
+		SERIAL_ERRORLNPGM("ERROR: Extruder fan speed is lower then expected");
+		LCD_ALERTMESSAGEPGM("Err: EXTR. FAN ERROR");
+		break;
+	case 1:
+		SERIAL_ERRORLNPGM("ERROR: Print fan speed is lower then expected");
+		LCD_ALERTMESSAGEPGM("Err: PRINT FAN ERROR");
+		break;
+	}
+}
 
 
 void checkExtruderAutoFans()
@@ -628,8 +628,8 @@ void manage_heater()
       (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
   if(millis() - extruder_autofan_last_check > 1000)  // only need to check fan state very infrequently
   {
-	countFanSpeed();
-	checkFanSpeed();
+	countFanSpeed();
+	checkFanSpeed();
     checkExtruderAutoFans();
     extruder_autofan_last_check = millis();
   }  
@@ -754,7 +754,7 @@ static float analog2temp(int raw, uint8_t e) {
       SERIAL_ERROR_START;
       SERIAL_ERROR((int)e);
       SERIAL_ERRORLNPGM(" - Invalid extruder number !");
-      kill();
+      kill("", 6);
       return 0.0;
   } 
   #ifdef HEATER_0_USES_MAX6675
@@ -1462,6 +1462,7 @@ int read_max6675()
 // Timer 0 is shared with millies
 ISR(TIMER0_COMPB_vect)
 {
+//	if (UVLO) uvlo();
   //these variables are only accesible from the ISR, but static, so they don't lose their value
   static unsigned char temp_count = 0;
   static unsigned long raw_temp_0_value = 0;

+ 4 - 0
Firmware/tmc2130.cpp

@@ -162,10 +162,13 @@ void tmc2130_check_overtemp()
 	//drivers_disabled[0] = 1; //TEST
 	if( millis() - checktime > 1000 )
 	{
+		//SERIAL_ECHOLNPGM("drv_status:");
 		for(int i=0;i<4;i++)
 		{
 			uint32_t drv_status = 0;
 			tmc2130_rd(cs[i], TMC2130_REG_DRV_STATUS, &drv_status);
+			//MYSERIAL.print(drv_status);
+			//SERIAL_ECHOPGM(" ");
 			if (drv_status & ((uint32_t)1<<26))
 			{ // BIT 26 - over temp prewarning ~120C (+-20C)
 				SERIAL_ERRORRPGM(TMC_OVERTEMP_MSG);
@@ -175,6 +178,7 @@ void tmc2130_check_overtemp()
 				kill(TMC_OVERTEMP_MSG);
 			}
 		}
+		//SERIAL_ECHOLNPGM("");
 		checktime = millis();
 	}
 }

+ 6 - 3
Firmware/ultralcd.cpp

@@ -3684,8 +3684,6 @@ void lcd_confirm_print()
 
 }
 
-
-
 static void lcd_main_menu()
 {
 
@@ -3696,7 +3694,9 @@ static void lcd_main_menu()
 
   
  MENU_ITEM(back, MSG_WATCH, lcd_status_screen);
-   /* if (farm_mode && !IS_SD_PRINTING )
+ MENU_ITEM(function, PSTR("recover print"), recover_print);
+
+ /* if (farm_mode && !IS_SD_PRINTING )
     {
     
         int tempScrool = 0;
@@ -4830,6 +4830,9 @@ static void menu_action_sdfile(const char* filename, char* longFilename)
   for (c = &cmd[4]; *c; c++)
     *c = tolower(*c);
   enquecommand(cmd);
+  for (int i = 0; i < 8; i++) {
+	  eeprom_write_byte((uint8_t*)EEPROM_FILENAME + i, filename[i]);
+  }
   enquecommand_P(PSTR("M24"));
   lcd_return_to_status();
 }