diff --git a/.gitignore b/.gitignore index 321c24319..bf77e0f0a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ Firmware/Doc /Firmware/Firmware - Shortcut.lnk /Firmware/variants/1_75mm_MK3-MMU-EINSy10a-E3Dv6full.h.bak /Firmware/Marlin_main.cpp~RF12cfae7.TMP +/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h.bak diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index 6e08fe287..7c6d95cfa 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -7,8 +7,8 @@ #define STR(x) STR_HELPER(x) // Firmware version -#define FW_VERSION "3.4.0-RC1" -#define FW_COMMIT_NR 1170 +#define FW_VERSION "3.4.0-RC2" +#define FW_COMMIT_NR 1267 // 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 diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index c098b216d..8512de1e4 100644 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -348,6 +348,7 @@ extern bool sortAlpha; extern char dir_names[3][9]; +extern int8_t lcd_change_fil_state; // save/restore printing extern bool saved_printing; @@ -359,6 +360,9 @@ extern uint8_t print_percent_done_normal; extern uint32_t print_time_remaining_normal; extern uint8_t print_percent_done_silent; extern uint32_t print_time_remaining_silent; +extern uint16_t mcode_in_progress; +extern uint16_t gcode_in_progress; + #define PRINT_TIME_REMAINING_INIT 0xffffffff #define PRINT_PERCENT_DONE_INIT 0xff #define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == CUSTOM_MSG_TYPE_TEMCAL) || saved_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL) || card.paused || mmu_print_saved) @@ -391,7 +395,6 @@ uint8_t check_printer_version(); float temp_compensation_pinda_thermistor_offset(float temperature_pinda); #endif //PINDA_THERMISTOR -void wait_for_heater(long codenum); void serialecho_temperatures(); bool check_commands(); @@ -468,4 +471,4 @@ void proc_commands(); void M600_load_filament(); void M600_load_filament_movements(); void M600_wait_for_user(); -void M600_check_state(); \ No newline at end of file +void M600_check_state(); diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 4966caa11..cc836df60 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -543,8 +543,9 @@ static bool saved_extruder_relative_mode = false; //=========================================================================== static void get_arc_coordinates(); -static bool setTargetedHotend(int code); +static bool setTargetedHotend(int code, uint8_t &extruder); static void print_time_remaining_init(); +static void wait_for_heater(long codenum, uint8_t extruder); uint16_t gcode_in_progress = 0; uint16_t mcode_in_progress = 0; @@ -1355,6 +1356,7 @@ void setup() plan_init(); // Initialize planner; factory_reset(); + lcd_encoder_diff=0; #ifdef TMC2130 uint8_t silentMode = eeprom_read_byte((uint8_t*)EEPROM_SILENT); @@ -1962,8 +1964,8 @@ void loop() checkHitEndstops(); lcd_update(0); #ifdef FILAMENT_SENSOR - if (mcode_in_progress != 600) //M600 not in progress - fsensor_update(); + if (mcode_in_progress != 600 && !mmu_enabled) //M600 not in progress + fsensor_update(); #endif //FILAMENT_SENSOR #ifdef TMC2130 tmc2130_check_overtemp(); @@ -3097,7 +3099,7 @@ void gcode_M600(bool automatic, float x_position, float y_position, float z_shif st_synchronize(); //Beep, manage nozzle heater and wait for user to start unload filament - if(!automatic) M600_wait_for_user(); + if(!mmu_enabled) M600_wait_for_user(); lcd_change_fil_state = 0; @@ -3118,12 +3120,29 @@ void gcode_M600(bool automatic, float x_position, float y_position, float z_shif } if (mmu_enabled) + { + if (!automatic) { + if (saved_printing) mmu_eject_filament(mmu_extruder, false); //if M600 was invoked by filament senzor (FINDA) eject filament so user can easily remove it + mmu_M600_wait_and_beep(); + if (saved_printing) { + + lcd_clear(); + lcd_set_cursor(0, 2); + lcd_puts_P(_T(MSG_PLEASE_WAIT)); + + mmu_command(MMU_CMD_R0); + manage_response(false, false); + } + } mmu_M600_load_filament(automatic); + } else M600_load_filament(); if(!automatic) M600_check_state(); + lcd_update_enable(true); + //Not let's go back to print fanSpeed = fanSpeedBckp; @@ -3139,7 +3158,7 @@ void gcode_M600(bool automatic, float x_position, float y_position, float z_shif //Move Z back plan_buffer_line(lastpos[X_AXIS], lastpos[Y_AXIS], lastpos[Z_AXIS], current_position[E_AXIS], FILAMENTCHANGE_ZFEED, active_extruder); st_synchronize(); - + //Set E position to original plan_set_e_position(lastpos[E_AXIS]); @@ -3162,8 +3181,11 @@ void gcode_M701() { printf_P(PSTR("gcode_M701 begin\n")); - if (mmu_enabled) - extr_adj(mmu_extruder);//loads current extruder + if (mmu_enabled) + { + extr_adj(tmp_extruder);//loads current extruder + mmu_extruder = tmp_extruder; + } else { enable_z(); @@ -3212,15 +3234,18 @@ void gcode_M701() custom_message_type = CUSTOM_MSG_TYPE_STATUS; #ifdef FILAMENT_SENSOR - fsensor_oq_meassure_stop(); - - if (!fsensor_oq_result()) + if (mmu_enabled == false) { - bool disable = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Fil. sensor response is poor, disable it?"), false, true); - lcd_update_enable(true); - lcd_update(2); - if (disable) - fsensor_disable(); + fsensor_oq_meassure_stop(); + + if (!fsensor_oq_result()) + { + bool disable = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Fil. sensor response is poor, disable it?"), false, true); + lcd_update_enable(true); + lcd_update(2); + if (disable) + fsensor_disable(); + } } #endif //FILAMENT_SENSOR } @@ -3408,7 +3433,9 @@ void process_commands() } #endif //BACKLASH_Y #endif //TMC2130 - + else if (code_seen("FSENSOR_RECOVER")) { + fsensor_restore_print_and_continue(); + } else if(code_seen("PRUSA")){ if (code_seen("Ping")) { //PRUSA Ping if (farm_mode) { @@ -5340,15 +5367,18 @@ Sigma_Exit: break; case 104: // M104 - if(setTargetedHotend(104)){ - break; - } - if (code_seen('S')) - { - setTargetHotendSafe(code_value(), tmp_extruder); - } - setWatch(); - break; + { + uint8_t extruder; + if(setTargetedHotend(104,extruder)){ + break; + } + if (code_seen('S')) + { + setTargetHotendSafe(code_value(), extruder); + } + setWatch(); + break; + } case 112: // M112 -Emergency Stop kill(_n(""), 3); break; @@ -5356,14 +5386,16 @@ Sigma_Exit: if (code_seen('S')) setTargetBed(code_value()); break; case 105 : // M105 - if(setTargetedHotend(105)){ + { + uint8_t extruder; + if(setTargetedHotend(105, extruder)){ break; } #if defined(TEMP_0_PIN) && TEMP_0_PIN > -1 SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); + SERIAL_PROTOCOL_F(degHotend(extruder),1); SERIAL_PROTOCOLPGM(" /"); - SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1); + SERIAL_PROTOCOL_F(degTargetHotend(extruder),1); #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1 SERIAL_PROTOCOLPGM(" B:"); SERIAL_PROTOCOL_F(degBed(),1); @@ -5388,7 +5420,7 @@ Sigma_Exit: SERIAL_PROTOCOL((EXTRUDER_WATTS * getHeaterPower(tmp_extruder))/127); SERIAL_PROTOCOLPGM("W"); #else - SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); + SERIAL_PROTOCOL(getHeaterPower(extruder)); #endif SERIAL_PROTOCOLPGM(" B@:"); @@ -5446,9 +5478,11 @@ Sigma_Exit: KEEPALIVE_STATE(NOT_BUSY); return; break; + } case 109: {// M109 - Wait for extruder heater to reach target. - if(setTargetedHotend(109)){ + uint8_t extruder; + if(setTargetedHotend(109, extruder)){ break; } LCD_MESSAGERPGM(_T(MSG_HEATING)); @@ -5459,10 +5493,10 @@ Sigma_Exit: autotemp_enabled=false; #endif if (code_seen('S')) { - setTargetHotendSafe(code_value(), tmp_extruder); + setTargetHotendSafe(code_value(), extruder); CooldownNoWait = true; } else if (code_seen('R')) { - setTargetHotendSafe(code_value(), tmp_extruder); + setTargetHotendSafe(code_value(), extruder); CooldownNoWait = false; } #ifdef AUTOTEMP @@ -5479,13 +5513,13 @@ Sigma_Exit: codenum = millis(); /* See if we are heating up or cooling down */ - target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling + target_direction = isHeatingHotend(extruder); // true if heating, false if cooling KEEPALIVE_STATE(NOT_BUSY); cancel_heatup = false; - wait_for_heater(codenum); //loops until target temperature is reached + wait_for_heater(codenum, extruder); //loops until target temperature is reached LCD_MESSAGERPGM(_T(MSG_HEATING_COMPLETE)); KEEPALIVE_STATE(IN_HANDLER); @@ -5806,10 +5840,10 @@ Sigma_Exit: case 200: // M200 D set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters). { - tmp_extruder = active_extruder; + uint8_t extruder = active_extruder; if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { + extruder = code_value(); + if(extruder >= EXTRUDERS) { SERIAL_ECHO_START; SERIAL_ECHO(_i("M200 Invalid extruder "));////MSG_M200_INVALID_EXTRUDER c=0 r=0 break; @@ -5823,7 +5857,7 @@ Sigma_Exit: // for all extruders volumetric_enabled = false; } else { - filament_size[tmp_extruder] = (float)code_value(); + filament_size[extruder] = (float)code_value(); // make sure all extruders have some sane value for the filament size filament_size[0] = (filament_size[0] == 0.0 ? DEFAULT_NOMINAL_FILAMENT_DIA : filament_size[0]); #if EXTRUDERS > 1 @@ -6011,25 +6045,26 @@ Sigma_Exit: #if EXTRUDERS > 1 case 218: // M218 - set hotend offset (in mm), T X Y { - if(setTargetedHotend(218)){ + uint8_t extruder; + if(setTargetedHotend(218, extruder)){ break; } if(code_seen('X')) { - extruder_offset[X_AXIS][tmp_extruder] = code_value(); + extruder_offset[X_AXIS][extruder] = code_value(); } if(code_seen('Y')) { - extruder_offset[Y_AXIS][tmp_extruder] = code_value(); + extruder_offset[Y_AXIS][extruder] = code_value(); } SERIAL_ECHO_START; SERIAL_ECHORPGM(MSG_HOTEND_OFFSET); - for(tmp_extruder = 0; tmp_extruder < EXTRUDERS; tmp_extruder++) + for(extruder = 0; extruder < EXTRUDERS; extruder++) { SERIAL_ECHO(" "); - SERIAL_ECHO(extruder_offset[X_AXIS][tmp_extruder]); + SERIAL_ECHO(extruder_offset[X_AXIS][extruder]); SERIAL_ECHO(","); - SERIAL_ECHO(extruder_offset[Y_AXIS][tmp_extruder]); + SERIAL_ECHO(extruder_offset[Y_AXIS][extruder]); } SERIAL_ECHOLN(""); }break; @@ -6049,10 +6084,11 @@ Sigma_Exit: int tmp_code = code_value(); if (code_seen('T')) { - if(setTargetedHotend(221)){ + uint8_t extruder; + if(setTargetedHotend(221, extruder)){ break; } - extruder_multiply[tmp_extruder] = tmp_code; + extruder_multiply[extruder] = tmp_code; } else { @@ -6744,7 +6780,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)) case 701: //M701: load filament { if (mmu_enabled && code_seen('E')) - mmu_extruder = code_value(); + tmp_extruder = code_value(); gcode_M701(); } break; @@ -6780,132 +6816,132 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)) else if(code_seen('T')) { - int index; - st_synchronize(); - for (index = 1; *(strchr_pointer + index) == ' ' || *(strchr_pointer + index) == '\t'; index++); - - if ((*(strchr_pointer + index) < '0' || *(strchr_pointer + index) > '9') && *(strchr_pointer + index) != '?') { - SERIAL_ECHOLNPGM("Invalid T code."); - } - else { - if (*(strchr_pointer + index) == '?') { - tmp_extruder = choose_extruder_menu(); - } - else { - tmp_extruder = code_value(); - } - snmm_filaments_used |= (1 << tmp_extruder); //for stop print + int index; + st_synchronize(); + for (index = 1; *(strchr_pointer + index) == ' ' || *(strchr_pointer + index) == '\t'; index++); -if (mmu_enabled) -{ - //printf_P(PSTR("T code: %d \n"), tmp_extruder); - //mmu_printf_P(PSTR("T%d\n"), tmp_extruder); - mmu_command(MMU_CMD_T0 + tmp_extruder); + if ((*(strchr_pointer + index) < '0' || *(strchr_pointer + index) > '4') && *(strchr_pointer + index) != '?') { + SERIAL_ECHOLNPGM("Invalid T code."); + } + else { + if (*(strchr_pointer + index) == '?') { + tmp_extruder = choose_extruder_menu(); + } + else { + tmp_extruder = code_value(); + } + snmm_filaments_used |= (1 << tmp_extruder); //for stop print - manage_response(true, true); + if (mmu_enabled) + { + mmu_command(MMU_CMD_T0 + tmp_extruder); - mmu_extruder = tmp_extruder; //filament change is finished + manage_response(true, true); + mmu_command(MMU_CMD_C0); + mmu_extruder = tmp_extruder; //filament change is finished - if (*(strchr_pointer + index) == '?')// for single material usage with mmu - mmu_load_to_nozzle(); -} -else -{ + if (*(strchr_pointer + index) == '?')// for single material usage with mmu + { + mmu_load_to_nozzle(); + } + } + else + { #ifdef SNMM - #ifdef LIN_ADVANCE - if (mmu_extruder != tmp_extruder) - clear_current_adv_vars(); //Check if the selected extruder is not the active one and reset LIN_ADVANCE variables if so. - #endif - - mmu_extruder = tmp_extruder; +#ifdef LIN_ADVANCE + if (mmu_extruder != tmp_extruder) + clear_current_adv_vars(); //Check if the selected extruder is not the active one and reset LIN_ADVANCE variables if so. +#endif - - delay(100); + mmu_extruder = tmp_extruder; - disable_e0(); - disable_e1(); - disable_e2(); - pinMode(E_MUX0_PIN, OUTPUT); - pinMode(E_MUX1_PIN, OUTPUT); + delay(100); - delay(100); - SERIAL_ECHO_START; - SERIAL_ECHO("T:"); - SERIAL_ECHOLN((int)tmp_extruder); - switch (tmp_extruder) { - case 1: - WRITE(E_MUX0_PIN, HIGH); - WRITE(E_MUX1_PIN, LOW); + disable_e0(); + disable_e1(); + disable_e2(); - break; - case 2: - WRITE(E_MUX0_PIN, LOW); - WRITE(E_MUX1_PIN, HIGH); + pinMode(E_MUX0_PIN, OUTPUT); + pinMode(E_MUX1_PIN, OUTPUT); - break; - case 3: - WRITE(E_MUX0_PIN, HIGH); - WRITE(E_MUX1_PIN, HIGH); + delay(100); + SERIAL_ECHO_START; + SERIAL_ECHO("T:"); + SERIAL_ECHOLN((int)tmp_extruder); + switch (tmp_extruder) { + case 1: + WRITE(E_MUX0_PIN, HIGH); + WRITE(E_MUX1_PIN, LOW); - break; - default: - WRITE(E_MUX0_PIN, LOW); - WRITE(E_MUX1_PIN, LOW); + break; + case 2: + WRITE(E_MUX0_PIN, LOW); + WRITE(E_MUX1_PIN, HIGH); - break; - } - delay(100); + break; + case 3: + WRITE(E_MUX0_PIN, HIGH); + WRITE(E_MUX1_PIN, HIGH); + + break; + default: + WRITE(E_MUX0_PIN, LOW); + WRITE(E_MUX1_PIN, LOW); + + break; + } + delay(100); #else //SNMM - if (tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHOPGM("T"); - SERIAL_PROTOCOLLN((int)tmp_extruder); - SERIAL_ECHOLNRPGM(_n("Invalid extruder"));////MSG_INVALID_EXTRUDER c=0 r=0 - } - else { - #if EXTRUDERS > 1 - boolean make_move = false; - #endif - if (code_seen('F')) { - #if EXTRUDERS > 1 - make_move = true; - #endif - next_feedrate = code_value(); - if (next_feedrate > 0.0) { - feedrate = next_feedrate; - } - } - #if EXTRUDERS > 1 - if (tmp_extruder != active_extruder) { - // Save current position to return to after applying extruder offset - memcpy(destination, current_position, sizeof(destination)); - // Offset extruder (only by XY) - int i; - for (i = 0; i < 2; i++) { - current_position[i] = current_position[i] - - extruder_offset[i][active_extruder] + - extruder_offset[i][tmp_extruder]; - } - // Set the new active extruder and position - active_extruder = tmp_extruder; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - // Move to the old position if 'F' was in the parameters - if (make_move && Stopped == false) { - prepare_move(); - } - } - #endif - SERIAL_ECHO_START; - SERIAL_ECHORPGM(_n("Active Extruder: "));////MSG_ACTIVE_EXTRUDER c=0 r=0 - SERIAL_PROTOCOLLN((int)active_extruder); - } + if (tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHOPGM("T"); + SERIAL_PROTOCOLLN((int)tmp_extruder); + SERIAL_ECHOLNRPGM(_n("Invalid extruder"));////MSG_INVALID_EXTRUDER c=0 r=0 + } + else { +#if EXTRUDERS > 1 + boolean make_move = false; +#endif + if (code_seen('F')) { +#if EXTRUDERS > 1 + make_move = true; +#endif + next_feedrate = code_value(); + if (next_feedrate > 0.0) { + feedrate = next_feedrate; + } + } +#if EXTRUDERS > 1 + if (tmp_extruder != active_extruder) { + // Save current position to return to after applying extruder offset + memcpy(destination, current_position, sizeof(destination)); + // Offset extruder (only by XY) + int i; + for (i = 0; i < 2; i++) { + current_position[i] = current_position[i] - + extruder_offset[i][active_extruder] + + extruder_offset[i][tmp_extruder]; + } + // Set the new active extruder and position + active_extruder = tmp_extruder; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + // Move to the old position if 'F' was in the parameters + if (make_move && Stopped == false) { + prepare_move(); + } + } +#endif + SERIAL_ECHO_START; + SERIAL_ECHORPGM(_n("Active Extruder: "));////MSG_ACTIVE_EXTRUDER c=0 r=0 + SERIAL_PROTOCOLLN((int)active_extruder); + } #endif //SNMM -} - } + } + } } // end if(code_seen('T')) (end of T codes) else if (code_seen('D')) // D codes (debug) @@ -7301,38 +7337,41 @@ static void handleSafetyTimer() void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h { #ifdef FILAMENT_SENSOR - if (mcode_in_progress != 600) //M600 not in progress + if (mmu_enabled == false) { - if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL)) + if (mcode_in_progress != 600) //M600 not in progress { - if (fsensor_check_autoload()) + if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL)) { - fsensor_autoload_check_stop(); - if (degHotend0() > EXTRUDE_MINTEMP) + if (fsensor_check_autoload()) { -if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)) - tone(BEEPER, 1000); - delay_keep_alive(50); - noTone(BEEPER); - loading_flag = true; - enquecommand_front_P((PSTR("M701"))); - } - else - { - lcd_update_enable(false); - lcd_clear(); - lcd_set_cursor(0, 0); - lcd_puts_P(_T(MSG_ERROR)); - lcd_set_cursor(0, 2); - lcd_puts_P(_T(MSG_PREHEAT_NOZZLE)); - delay(2000); - lcd_clear(); - lcd_update_enable(true); + fsensor_autoload_check_stop(); + if (degHotend0() > EXTRUDE_MINTEMP) + { + if ((eSoundMode == e_SOUND_MODE_LOUD) || (eSoundMode == e_SOUND_MODE_ONCE)) + tone(BEEPER, 1000); + delay_keep_alive(50); + noTone(BEEPER); + loading_flag = true; + enquecommand_front_P((PSTR("M701"))); + } + else + { + lcd_update_enable(false); + lcd_clear(); + lcd_set_cursor(0, 0); + lcd_puts_P(_T(MSG_ERROR)); + lcd_set_cursor(0, 2); + lcd_puts_P(_T(MSG_PREHEAT_NOZZLE)); + delay(2000); + lcd_clear(); + lcd_update_enable(true); + } } } + else + fsensor_autoload_check_stop(); } - else - fsensor_autoload_check_stop(); } #endif //FILAMENT_SENSOR @@ -7555,11 +7594,21 @@ void setPwmFrequency(uint8_t pin, int val) } #endif //FAST_PWM_FAN -bool setTargetedHotend(int code){ - tmp_extruder = active_extruder; +//! @brief Get and validate extruder number +//! +//! If it is not specified, active_extruder is returned in parameter extruder. +//! @param [in] code M code number +//! @param [out] extruder +//! @return error +//! @retval true Invalid extruder specified in T code +//! @retval false Valid extruder specified in T code, or not specifiead + +bool setTargetedHotend(int code, uint8_t &extruder) +{ + extruder = active_extruder; if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { + extruder = code_value(); + if(extruder >= EXTRUDERS) { SERIAL_ECHO_START; switch(code){ case 104: @@ -7578,7 +7627,7 @@ bool setTargetedHotend(int code){ SERIAL_ECHO(_i("M221 Invalid extruder "));////MSG_M221_INVALID_EXTRUDER c=0 r=0 break; } - SERIAL_PROTOCOLLN((int)tmp_extruder); + SERIAL_PROTOCOLLN((int)extruder); return true; } } @@ -7643,7 +7692,7 @@ void delay_keep_alive(unsigned int ms) } } -void wait_for_heater(long codenum) { +static void wait_for_heater(long codenum, uint8_t extruder) { #ifdef TEMP_RESIDENCY_TIME long residencyStart; @@ -7659,9 +7708,9 @@ void wait_for_heater(long codenum) { { //Print Temp Reading and remaining time every 1 second while heating up/cooling down if (!farm_mode) { SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOL_F(degHotend(tmp_extruder), 1); + SERIAL_PROTOCOL_F(degHotend(extruder), 1); SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOL((int)tmp_extruder); + SERIAL_PROTOCOL((int)extruder); #ifdef TEMP_RESIDENCY_TIME SERIAL_PROTOCOLPGM(" W:"); @@ -7686,9 +7735,9 @@ void wait_for_heater(long codenum) { #ifdef TEMP_RESIDENCY_TIME /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time or when current temp falls outside the hysteresis after target temp was reached */ - if ((residencyStart == -1 && target_direction && (degHotend(tmp_extruder) >= (degTargetHotend(tmp_extruder) - TEMP_WINDOW))) || - (residencyStart == -1 && !target_direction && (degHotend(tmp_extruder) <= (degTargetHotend(tmp_extruder) + TEMP_WINDOW))) || - (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS)) + if ((residencyStart == -1 && target_direction && (degHotend(extruder) >= (degTargetHotend(extruder) - TEMP_WINDOW))) || + (residencyStart == -1 && !target_direction && (degHotend(extruder) <= (degTargetHotend(extruder) + TEMP_WINDOW))) || + (residencyStart > -1 && labs(degHotend(extruder) - degTargetHotend(extruder)) > TEMP_HYSTERESIS)) { residencyStart = millis(); } @@ -8843,8 +8892,7 @@ void M600_check_state() { //Wait for user to check the state lcd_change_fil_state = 0; - - while ((lcd_change_fil_state == 0)||(lcd_change_fil_state != 1)){ + while (lcd_change_fil_state != 1){ lcd_change_fil_state = 0; KEEPALIVE_STATE(PAUSED_FOR_USER); lcd_alright(); @@ -8868,10 +8916,9 @@ void M600_check_state() // Everything good default: lcd_change_success(); - lcd_update_enable(true); break; } - } + } } void M600_wait_for_user() { @@ -9036,7 +9083,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)) fsensor_disable(); } #endif //FILAMENT_SENSOR - + lcd_update_enable(false); } #define FIL_LOAD_LENGTH 60 diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 28498f139..54a216488 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -144,6 +144,7 @@ // Sound Mode //#define EEPROM_SOUND_MODE (EEPROM_EXTRUDEMULTIPLY-1) // uint8 #define EEPROM_SOUND_MODE (EEPROM_UVLO_TINY_Z_MICROSTEPS-1) // uint8 +#define EEPROM_AUTO_DEPLETE (EEPROM_SOUND_MODE-1) //bool // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! diff --git a/Firmware/menu.cpp b/Firmware/menu.cpp index b63629edf..bd5238269 100644 --- a/Firmware/menu.cpp +++ b/Firmware/menu.cpp @@ -9,15 +9,20 @@ #include "Configuration.h" #include "Marlin.h" #include "ultralcd.h" +#include "language.h" extern int32_t lcd_encoder; +#define MENU_DEPTH_MAX 4 -menu_record_t menu_stack[MENU_DEPTH_MAX]; +static menu_record_t menu_stack[MENU_DEPTH_MAX]; uint8_t menu_data[MENU_DATA_SIZE]; +#ifndef __AVR__ +#error "menu_data is non-portable to non 8bit processor" +#endif uint8_t menu_depth = 0; @@ -33,6 +38,8 @@ uint8_t menu_leaving = 0; menu_func_t menu_menu = 0; +static_assert(sizeof(menu_data)>= sizeof(menu_data_edit_t),"menu_data_edit_t doesn't fit into menu_data"); + void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state) { @@ -86,7 +93,7 @@ void menu_back(void) } } -void menu_back_no_reset(void) +static void menu_back_no_reset(void) { if (menu_depth > 0) { @@ -120,7 +127,7 @@ void menu_submenu(menu_func_t submenu) } } -void menu_submenu_no_reset(menu_func_t submenu) +static void menu_submenu_no_reset(menu_func_t submenu) { if (menu_depth <= MENU_DEPTH_MAX) { @@ -158,7 +165,7 @@ int menu_draw_item_printf_P(char type_char, const char* format, ...) } */ -int menu_draw_item_puts_P(char type_char, const char* str) +static int menu_draw_item_puts_P(char type_char, const char* str) { lcd_set_cursor(0, menu_row); int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char); @@ -263,8 +270,13 @@ const char menu_fmt_float31[] PROGMEM = "%c%.12S:%s%+06.1f"; const char menu_fmt_float13[] PROGMEM = "%c%.12S:%s%+06.3f"; +const char menu_fmt_float13off[] PROGMEM = "%c%.12S:%s%"; -void menu_draw_int3(char chr, const char* str, int16_t val) +template +static void menu_draw_P(char chr, const char* str, int16_t val); + +template<> +void menu_draw_P(char chr, const char* str, int16_t val) { int text_len = strlen_P(str); if (text_len > 15) text_len = 15; @@ -274,6 +286,27 @@ void menu_draw_int3(char chr, const char* str, int16_t val) lcd_printf_P(menu_fmt_int3, chr, str, spaces, val); } +template<> +void menu_draw_P(char chr, const char* str, int16_t val) +{ + menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]); + int text_len = strlen_P(str); + if (text_len > 15) text_len = 15; + char spaces[21]; + strcpy_P(spaces, menu_20x_space); + spaces[12 - text_len] = 0; + float factor = 1.0 + static_cast(val) / 1000.0; + if (val <= _md->minEditValue) + { + lcd_printf_P(menu_fmt_float13off, chr, str, spaces); + lcd_puts_P(_i(" [off]")); + } + else + { + lcd_printf_P(menu_fmt_float13, chr, str, spaces, factor); + } +} + //draw up to 12 chars of text, ':' and float number in format +123.0 void menu_draw_float31(char chr, const char* str, float val) { @@ -296,16 +329,8 @@ void menu_draw_float13(char chr, const char* str, float val) lcd_printf_P(menu_fmt_float13, chr, str, spaces, val); } -typedef struct -{ - //Variables used when editing values. - const char* editLabel; - void* editValue; - int32_t minEditValue; - int32_t maxEditValue; -} menu_data_edit_t; - -void _menu_edit_int3(void) +template +static void _menu_edit_P(void) { menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]); if (lcd_draw_update) @@ -313,16 +338,17 @@ void _menu_edit_int3(void) if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue; if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue; lcd_set_cursor(0, 1); - menu_draw_int3(' ', _md->editLabel, (int)lcd_encoder); + menu_draw_P(' ', _md->editLabel, (int)lcd_encoder); } if (LCD_CLICKED) { - *((int*)(_md->editValue)) = (int)lcd_encoder; + *((T)(_md->editValue)) = lcd_encoder; menu_back_no_reset(); } } -uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int16_t max_val) +template +uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val) { menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]); if (menu_item == menu_line) @@ -330,11 +356,11 @@ uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int if (lcd_draw_update) { lcd_set_cursor(0, menu_row); - menu_draw_int3((lcd_encoder == menu_item)?'>':' ', str, *pval); + menu_draw_P((lcd_encoder == menu_item)?'>':' ', str, *pval); } if (menu_clicked && (lcd_encoder == menu_item)) { - menu_submenu_no_reset(_menu_edit_int3); + menu_submenu_no_reset(_menu_edit_P); _md->editLabel = str; _md->editValue = pval; _md->minEditValue = min_val; @@ -347,6 +373,9 @@ uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int return 0; } +template uint8_t menu_item_edit_P(const char* str, int16_t *pval, int16_t min_val, int16_t max_val); +template uint8_t menu_item_edit_P(const char* str, uint8_t *pval, int16_t min_val, int16_t max_val); + #undef _menu_data diff --git a/Firmware/menu.h b/Firmware/menu.h index 06c901035..73e4925a6 100644 --- a/Firmware/menu.h +++ b/Firmware/menu.h @@ -4,9 +4,7 @@ #include -#define MENU_DEPTH_MAX 4 #define MENU_DATA_SIZE 32 -#define MENU_DATA_EDIT_SIZE 12 //Function pointer to menu functions. typedef void (*menu_func_t)(void); @@ -17,7 +15,14 @@ typedef struct int8_t position; } menu_record_t; -extern menu_record_t menu_stack[MENU_DEPTH_MAX]; +typedef struct +{ + //Variables used when editing values. + const char* editLabel; + void* editValue; + int32_t minEditValue; + int32_t maxEditValue; +} menu_data_edit_t; extern uint8_t menu_data[MENU_DATA_SIZE]; @@ -50,21 +55,16 @@ extern void menu_end(void); extern void menu_back(void); -extern void menu_back_no_reset(void); - extern void menu_back_if_clicked(void); extern void menu_back_if_clicked_fb(void); extern void menu_submenu(menu_func_t submenu); -extern void menu_submenu_no_reset(menu_func_t submenu); - extern uint8_t menu_item_ret(void); //extern int menu_draw_item_printf_P(char type_char, const char* format, ...); -extern int menu_draw_item_puts_P(char type_char, const char* str); //int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, ); @@ -91,17 +91,16 @@ extern const char menu_fmt_int3[]; extern const char menu_fmt_float31[]; -extern void menu_draw_int3(char chr, const char* str, int16_t val); extern void menu_draw_float31(char chr, const char* str, float val); extern void menu_draw_float13(char chr, const char* str, float val); -extern void _menu_edit_int3(void); -#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { if (menu_item_edit_int3(str, pval, minval, maxval)) return; } while (0) +#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { if (menu_item_edit_P(str, pval, minval, maxval)) return; } while (0) //#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) MENU_ITEM_EDIT(int3, str, pval, minval, maxval) -extern uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int16_t max_val); +template +extern uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val); #endif //_MENU_H diff --git a/Firmware/mmu.cpp b/Firmware/mmu.cpp index 57da1e80f..7ceb53e96 100644 --- a/Firmware/mmu.cpp +++ b/Firmware/mmu.cpp @@ -7,22 +7,22 @@ #include "uart2.h" #include "temperature.h" #include "Configuration_prusa.h" +#include "fsensor.h" +#include "cardreader.h" +#include "ultralcd.h" +#include "sound.h" - -extern const char* lcd_display_message_fullscreen_P(const char *msg); -extern void lcd_show_fullscreen_message_and_wait_P(const char *msg); -extern int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting = true, bool default_yes = false); -extern void lcd_return_to_status(); -extern void lcd_wait_for_heater(); -extern char choose_extruder_menu(); - +#define CHECK_FINDA ((IS_SD_PRINTING || is_usb_printing) && (mcode_in_progress != 600) && !saved_printing && e_active()) #define MMU_TODELAY 100 #define MMU_TIMEOUT 10 +#define MMU_CMD_TIMEOUT 300000ul //5min timeout for mmu commands (except P0) +#define MMU_P0_TIMEOUT 3000ul //timeout for P0 command: 3seconds #define MMU_HWRESET #define MMU_RST_PIN 76 +#define MMU_REQUIRED_FW_BUILDNR 83 bool mmu_enabled = false; @@ -103,6 +103,7 @@ void mmu_init(void) //mmu main loop - state machine processing void mmu_loop(void) { + int filament = 0; // printf_P(PSTR("MMU loop, state=%d\n"), mmu_state); switch (mmu_state) { @@ -137,6 +138,9 @@ void mmu_loop(void) { fscanf_P(uart2io, PSTR("%u"), &mmu_buildnr); //scan buildnr from buffer printf_P(PSTR("MMU => '%dok'\n"), mmu_buildnr); + bool version_valid = mmu_check_version(); + if (!version_valid) mmu_show_warning(); + else puts_P(PSTR("MMU version valid")); puts_P(PSTR("MMU <= 'P0'")); mmu_puts_P(PSTR("P0\n")); //send 'read finda' request mmu_state = -4; @@ -157,14 +161,46 @@ void mmu_loop(void) { if ((mmu_cmd >= MMU_CMD_T0) && (mmu_cmd <= MMU_CMD_T4)) { - int extruder = mmu_cmd - MMU_CMD_T0; - printf_P(PSTR("MMU <= 'T%d'\n"), extruder); - mmu_printf_P(PSTR("T%d\n"), extruder); + filament = mmu_cmd - MMU_CMD_T0; + printf_P(PSTR("MMU <= 'T%d'\n"), filament); + mmu_printf_P(PSTR("T%d\n"), filament); + mmu_state = 3; // wait for response + } + else if ((mmu_cmd >= MMU_CMD_L0) && (mmu_cmd <= MMU_CMD_L4)) + { + filament = mmu_cmd - MMU_CMD_L0; + printf_P(PSTR("MMU <= 'L%d'\n"), filament); + mmu_printf_P(PSTR("L%d\n"), filament); + mmu_state = 3; // wait for response + } + else if (mmu_cmd == MMU_CMD_C0) + { + printf_P(PSTR("MMU <= 'C0'\n")); + mmu_puts_P(PSTR("C0\n")); //send 'continue loading' + mmu_state = 3; + } + else if (mmu_cmd == MMU_CMD_U0) + { + printf_P(PSTR("MMU <= 'U0'\n")); + mmu_puts_P(PSTR("U0\n")); //send 'unload current filament' + mmu_state = 3; + } + else if ((mmu_cmd >= MMU_CMD_E0) && (mmu_cmd <= MMU_CMD_E4)) + { + int filament = mmu_cmd - MMU_CMD_E0; + printf_P(PSTR("MMU <= 'E%d'\n"), filament); + mmu_printf_P(PSTR("E%d\n"), filament); //send eject filament + mmu_state = 3; // wait for response + } + else if (mmu_cmd == MMU_CMD_R0) + { + printf_P(PSTR("MMU <= 'R0'\n")); + mmu_puts_P(PSTR("R0\n")); //send recover after eject mmu_state = 3; // wait for response } mmu_cmd = 0; } - else if ((mmu_last_response + 1000) < millis()) //request every 1s + else if ((mmu_last_response + 300) < millis()) //request every 300ms { puts_P(PSTR("MMU <= 'P0'")); mmu_puts_P(PSTR("P0\n")); //send 'read finda' request @@ -176,24 +212,31 @@ void mmu_loop(void) { fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer printf_P(PSTR("MMU => '%dok'\n"), mmu_finda); + //printf_P(PSTR("Eact: %d\n"), int(e_active())); + if (!mmu_finda && CHECK_FINDA && fsensor_enabled) { + fsensor_stop_and_save_print(); + enquecommand_front_P(PSTR("FSENSOR_RECOVER")); //then recover + if (lcd_autoDeplete) enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command + else enquecommand_front_P(PSTR("M600")); //save print and run M600 command + } mmu_state = 1; if (mmu_cmd == 0) mmu_ready = true; } - else if ((mmu_last_request + 30000) < millis()) + else if ((mmu_last_request + MMU_P0_TIMEOUT) < millis()) { //resend request after timeout (30s) mmu_state = 1; } return; - case 3: //response to commands T0-T4 + case 3: //response to mmu commands if (mmu_rx_ok() > 0) { - printf_P(PSTR("MMU => 'ok'\n"), mmu_finda); + printf_P(PSTR("MMU => 'ok'\n")); mmu_ready = true; mmu_state = 1; } - else if ((mmu_last_request + 30000) < millis()) - { //resend request after timeout (30s) + else if ((mmu_last_request + MMU_CMD_TIMEOUT) < millis()) + { //resend request after timeout (5 min) mmu_state = 1; } return; @@ -289,7 +332,7 @@ void manage_response(bool move_axes, bool turn_off_nozzle) } st_synchronize(); mmu_print_saved = true; - + printf_P(PSTR("MMU not responding\n")); hotend_temp_bckp = degTargetHotend(active_extruder); if (move_axes) { z_position_bckp = current_position[Z_AXIS]; @@ -311,23 +354,28 @@ void manage_response(bool move_axes, bool turn_off_nozzle) if (turn_off_nozzle) { //set nozzle target temperature to 0 setAllTargetHotends(0); - printf_P(PSTR("MMU not responding\n")); - lcd_show_fullscreen_message_and_wait_P(_i("MMU needs user attention. Please press knob to resume nozzle target temperature.")); - setTargetHotend(hotend_temp_bckp, active_extruder); - while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5) { - delay_keep_alive(1000); - lcd_wait_for_heater(); - } } } - lcd_display_message_fullscreen_P(_i("Check MMU. Fix the issue and then press button on MMU unit.")); + lcd_display_message_fullscreen_P(_i("MMU needs user attention. Fix the issue and then press button on MMU unit.")); delay_keep_alive(1000); } else if (mmu_print_saved) { - printf_P(PSTR("MMU start responding\n")); - lcd_clear(); - lcd_display_message_fullscreen_P(_i("MMU OK. Resuming...")); + printf_P(PSTR("MMU starts responding\n")); + if (turn_off_nozzle) + { + lcd_clear(); + setTargetHotend(hotend_temp_bckp, active_extruder); + lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature...")); + delay_keep_alive(3000); + while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5) + { + delay_keep_alive(1000); + lcd_wait_for_heater(); + } + } if (move_axes) { + lcd_clear(); + lcd_display_message_fullscreen_P(_i("MMU OK. Resuming position...")); current_position[X_AXIS] = x_position_bckp; current_position[Y_AXIS] = y_position_bckp; plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder); @@ -337,6 +385,8 @@ void manage_response(bool move_axes, bool turn_off_nozzle) st_synchronize(); } else { + lcd_clear(); + lcd_display_message_fullscreen_P(_i("MMU OK. Resuming...")); delay_keep_alive(1000); //delay just for showing MMU OK message for a while in case that there are no xyz movements } } @@ -344,6 +394,12 @@ void manage_response(bool move_axes, bool turn_off_nozzle) if (lcd_update_was_enabled) lcd_update_enable(true); } +//! @brief load filament to nozzle of multimaterial printer +//! +//! This function is used only only after T? (user select filament) and M600 (change filament). +//! It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading +//! filament to nozzle. +//! void mmu_load_to_nozzle() { st_synchronize(); @@ -369,17 +425,56 @@ void mmu_load_to_nozzle() if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = false; } +void mmu_M600_wait_and_beep() { + //Beep and wait for user to remove old filament and prepare new filament for load + + KEEPALIVE_STATE(PAUSED_FOR_USER); + + int counterBeep = 0; + lcd_display_message_fullscreen_P(_i("Remove old filament and press the knob to start loading new filament.")); + bool bFirst=true; + + while (!lcd_clicked()){ + manage_heater(); + manage_inactivity(true); + + #if BEEPER > 0 + if (counterBeep == 500) { + counterBeep = 0; + } + SET_OUTPUT(BEEPER); + if (counterBeep == 0) { + if((eSoundMode==e_SOUND_MODE_LOUD)||((eSoundMode==e_SOUND_MODE_ONCE)&&bFirst)) + { + bFirst=false; + WRITE(BEEPER, HIGH); + } + } + if (counterBeep == 20) { + WRITE(BEEPER, LOW); + } + + counterBeep++; + #endif //BEEPER > 0 + + delay_keep_alive(4); + } + WRITE(BEEPER, LOW); +} + void mmu_M600_load_filament(bool automatic) { //load filament for mmu v2 bool response = false; bool yes = false; + tmp_extruder = mmu_extruder; if (!automatic) { +#ifdef MMU_M600_SWITCH_EXTRUDER yes = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Do you want to switch extruder?"), false); if(yes) tmp_extruder = choose_extruder_menu(); else tmp_extruder = mmu_extruder; - +#endif //MMU_M600_SWITCH_EXTRUDER } else { tmp_extruder = (tmp_extruder+1)%5; @@ -396,10 +491,12 @@ void mmu_M600_load_filament(bool automatic) mmu_command(MMU_CMD_T0 + tmp_extruder); manage_response(false, true); + mmu_command(MMU_CMD_C0); mmu_extruder = tmp_extruder; //filament change is finished mmu_load_to_nozzle(); + st_synchronize(); current_position[E_AXIS]+= FILAMENTCHANGE_FINALFEED ; plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2, active_extruder); @@ -479,8 +576,13 @@ void display_loading() void extr_adj(int extruder) //loading filament for SNMM { #ifndef SNMM - printf_P(PSTR("L%d \n"),extruder); - fprintf_P(uart2io, PSTR("L%d\n"), extruder); + uint8_t cmd = MMU_CMD_L0 + extruder; + if (cmd > MMU_CMD_L4) + { + printf_P(PSTR("Filament out of range %d \n"),extruder); + return; + } + mmu_command(cmd); //show which filament is currently loaded @@ -490,7 +592,7 @@ void extr_adj(int extruder) //loading filament for SNMM //if(strlen(_T(MSG_LOADING_FILAMENT))>18) lcd.setCursor(0, 1); //else lcd.print(" "); lcd_print(" "); - lcd_print(mmu_extruder + 1); + lcd_print(extruder + 1); // get response manage_response(false, false); @@ -564,9 +666,8 @@ void extr_unload() current_position[E_AXIS] -= 80; plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2500 / 60, active_extruder); st_synchronize(); - printf_P(PSTR("U0\n")); - fprintf_P(uart2io, PSTR("U0\n")); + mmu_command(MMU_CMD_U0); // get response manage_response(false, true); @@ -688,6 +789,31 @@ void extr_adj_4() #endif } +void mmu_eject_fil_0() +{ + mmu_eject_filament(0, true); +} + +void mmu_eject_fil_1() +{ + mmu_eject_filament(1, true); +} + +void mmu_eject_fil_2() +{ + mmu_eject_filament(2, true); +} + +void mmu_eject_fil_3() +{ + mmu_eject_filament(3, true); +} + +void mmu_eject_fil_4() +{ + mmu_eject_filament(4, true); +} + void load_all() { #ifndef SNMM @@ -807,3 +933,57 @@ void extr_unload_4() change_extr(4); extr_unload(); } + +bool mmu_check_version() +{ + return (mmu_buildnr >= MMU_REQUIRED_FW_BUILDNR); +} + +void mmu_show_warning() +{ + printf_P(PSTR("MMU2 firmware version invalid. Required version: build number %d or higher."), MMU_REQUIRED_FW_BUILDNR); + kill(_i("Please update firmware in your MMU2. Waiting for reset.")); +} + +void mmu_eject_filament(uint8_t filament, bool recover) +{ + if (filament < 5) + { + + if (degHotend0() > EXTRUDE_MINTEMP) + { + st_synchronize(); + lcd_update_enable(false); + lcd_clear(); + lcd_set_cursor(0, 1); lcd_puts_P(_i("Ejecting filament")); + current_position[E_AXIS] -= 80; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2500 / 60, active_extruder); + st_synchronize(); + + lcd_update_enable(true); + + mmu_command(MMU_CMD_E0 + filament); + manage_response(false, false); + if (recover) + { + lcd_show_fullscreen_message_and_wait_P(_i("Please remove filament and then press the knob.")); + mmu_command(MMU_CMD_R0); + manage_response(false, false); + } + } + else + { + lcd_clear(); + lcd_set_cursor(0, 0); + lcd_puts_P(_T(MSG_ERROR)); + lcd_set_cursor(0, 2); + lcd_puts_P(_T(MSG_PREHEAT_NOZZLE)); + delay(2000); + lcd_clear(); + } + } + else + { + puts_P(PSTR("Filament nr out of range!")); + } +} \ No newline at end of file diff --git a/Firmware/mmu.h b/Firmware/mmu.h index 763c15ea8..35c1e18c6 100644 --- a/Firmware/mmu.h +++ b/Firmware/mmu.h @@ -23,6 +23,20 @@ extern int16_t mmu_buildnr; #define MMU_CMD_T2 0x12 #define MMU_CMD_T3 0x13 #define MMU_CMD_T4 0x14 +#define MMU_CMD_L0 0x20 +#define MMU_CMD_L1 0x21 +#define MMU_CMD_L2 0x22 +#define MMU_CMD_L3 0x23 +#define MMU_CMD_L4 0x24 +#define MMU_CMD_C0 0x30 +#define MMU_CMD_U0 0x40 +#define MMU_CMD_E0 0x50 +#define MMU_CMD_E1 0x51 +#define MMU_CMD_E2 0x52 +#define MMU_CMD_E3 0x53 +#define MMU_CMD_E4 0x54 +#define MMU_CMD_R0 0x60 + extern int mmu_puts_P(const char* str); @@ -49,7 +63,7 @@ extern void manage_response(bool move_axes, bool turn_off_nozzle); extern void mmu_load_to_nozzle(); extern void mmu_M600_load_filament(bool automatic); - +extern void mmu_M600_wait_and_beep(); extern void extr_mov(float shift, float feed_rate); extern void change_extr(int extr); @@ -74,3 +88,12 @@ extern void extr_unload_1(); extern void extr_unload_2(); extern void extr_unload_3(); extern void extr_unload_4(); + +extern bool mmu_check_version(); +extern void mmu_show_warning(); +extern void mmu_eject_filament(uint8_t filament, bool recover); +extern void mmu_eject_fil_0(); +extern void mmu_eject_fil_1(); +extern void mmu_eject_fil_2(); +extern void mmu_eject_fil_3(); +extern void mmu_eject_fil_4(); diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index e89cbef8d..058fd2a9d 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -494,6 +494,23 @@ void getHighESpeed() } #endif +bool e_active() +{ + unsigned char e_active = 0; + block_t *block; + if(block_buffer_tail != block_buffer_head) + { + uint8_t block_index = block_buffer_tail; + while(block_index != block_buffer_head) + { + block = &block_buffer[block_index]; + if(block->steps_e.wide != 0) e_active++; + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + } + return (e_active > 0) ? true : false ; +} + void check_axes_activity() { unsigned char x_active = 0; diff --git a/Firmware/planner.h b/Firmware/planner.h index 8d648c8e8..998a3595b 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -154,7 +154,7 @@ void plan_set_position(float x, float y, float z, const float &e); void plan_set_z_position(const float &z); void plan_set_e_position(const float &e); - +extern bool e_active(); void check_axes_activity(); diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index e1eaf67e5..45175c028 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -41,6 +41,8 @@ int fsensor_counter = 0; //counter for e-steps #endif //FILAMENT_SENSOR +#include "mmu.h" + #ifdef DEBUG_STACK_MONITOR uint16_t SP_min = 0x21FF; #endif //DEBUG_STACK_MONITOR @@ -470,8 +472,11 @@ FORCE_INLINE void stepper_next_block() #endif #ifdef FILAMENT_SENSOR - fsensor_counter = 0; - fsensor_st_block_begin(current_block); + if (mmu_enabled == false) + { + fsensor_counter = 0; + fsensor_st_block_begin(current_block); + } #endif //FILAMENT_SENSOR // The busy flag is set by the plan_get_current_block() call. // current_block->busy = true; @@ -901,7 +906,10 @@ FORCE_INLINE void isr() { if (step_loops < estep_loops) estep_loops = step_loops; #ifdef FILAMENT_SENSOR - fsensor_counter += estep_loops; + if (mmu_enabled == false) + { + fsensor_counter += estep_loops; + } #endif //FILAMENT_SENSOR do { WRITE_NC(E0_STEP_PIN, !INVERT_E_STEP_PIN); @@ -1027,7 +1035,9 @@ FORCE_INLINE void isr() { // There is not enough time to fit even a single additional tick. // Tick all the extruder ticks now. #ifdef FILAMENT_SENSOR - fsensor_counter += e_steps; + if (mmu_enabled == false) { + fsensor_counter += e_steps; + } #endif //FILAMENT_SENSOR MSerial.checkRx(); // Check for serial chars. do { @@ -1049,15 +1059,17 @@ FORCE_INLINE void isr() { // If current block is finished, reset pointer if (step_events_completed.wide >= current_block->step_event_count.wide) { #ifdef FILAMENT_SENSOR - fsensor_st_block_chunk(current_block, fsensor_counter); - fsensor_counter = 0; + if (mmu_enabled == false) { + fsensor_st_block_chunk(current_block, fsensor_counter); + fsensor_counter = 0; + } #endif //FILAMENT_SENSOR current_block = NULL; plan_discard_current_block(); } #ifdef FILAMENT_SENSOR - else if (fsensor_counter >= fsensor_chunk_len) + else if ((fsensor_counter >= fsensor_chunk_len) && (mmu_enabled == false)) { fsensor_st_block_chunk(current_block, fsensor_counter); fsensor_counter = 0; diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index ee81f5a6b..46ac9d665 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -35,7 +35,6 @@ #include "mmu.h" -extern int lcd_change_fil_state; extern bool fans_check_enabled; @@ -88,6 +87,7 @@ unsigned long display_time; //just timer for showing pid finished message on lcd float pid_temp = DEFAULT_PID_TEMP; static bool forceMenuExpire = false; +bool lcd_autoDeplete; static float manual_feedrate[] = MANUAL_FEEDRATE; @@ -123,7 +123,7 @@ static void lcd_control_temperature_preheat_pla_settings_menu(); static void lcd_control_temperature_preheat_abs_settings_menu(); static void lcd_control_motion_menu(); static void lcd_control_volumetric_menu(); -//static void lcd_settings_menu_back(); +static void lcd_settings_linearity_correction_menu_save(); static void prusa_stat_printerstatus(int _status); static void prusa_stat_farm_number(); @@ -530,9 +530,9 @@ void lcdui_print_extruder(void) { int chars = 0; if (mmu_extruder == tmp_extruder) - chars = lcd_printf_P(_N(" T%u"), mmu_extruder); + chars = lcd_printf_P(_N(" T%u"), mmu_extruder+1); else - chars = lcd_printf_P(_N(" %u>%u"), mmu_extruder, tmp_extruder); + chars = lcd_printf_P(_N(" %u>%u"), mmu_extruder+1, tmp_extruder+1); lcd_space(5 - chars); } @@ -597,8 +597,15 @@ void lcdui_print_time(void) int chars = 0; if ((PRINTER_ACTIVE) && ((print_time_remaining_normal != PRINT_TIME_REMAINING_INIT) || (starttime != 0))) { - char suff = (print_time_remaining_normal == PRINT_TIME_REMAINING_INIT)?' ':'R'; - chars = lcd_printf_P(_N("%c%02u:%02u%c"), LCD_STR_CLOCK[0], print_t / 60, print_t % 60, suff); + char suff = ' '; + char suff_doubt = ' '; + if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT) + { + suff = 'R'; + if (feedmultiply != 100) + suff_doubt = '?'; + } + chars = lcd_printf_P(_N("%c%02u:%02u%c%c"), LCD_STR_CLOCK[0], print_t / 60, print_t % 60, suff, suff_doubt); } else chars = lcd_printf_P(_N("%c--:-- "), LCD_STR_CLOCK[0]); @@ -1882,20 +1889,22 @@ static void lcd_menu_extruder_info() // Shutter register is an index of LASER shutter time. It is automatically controlled by the chip's internal // auto-exposure algorithm. When the chip is tracking on a good reflection surface, the Shutter is small. // When the chip is tracking on a poor reflection surface, the Shutter is large. Value ranges from 0 to 46. - - if (!fsensor_enabled) - lcd_puts_P(_N("Filament sensor\n" "is disabled.")); - else + if (mmu_enabled == false) { - if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL)) - pat9125_update(); - lcd_printf_P(_N( - "Fil. Xd:%3d Yd:%3d\n" - "Int: %3d Shut: %3d" - ), - pat9125_x, pat9125_y, - pat9125_b, pat9125_s - ); + if (!fsensor_enabled) + lcd_puts_P(_N("Filament sensor\n" "is disabled.")); + else + { + if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL)) + pat9125_update(); + lcd_printf_P(_N( + "Fil. Xd:%3d Yd:%3d\n" + "Int: %3d Shut: %3d" + ), + pat9125_x, pat9125_y, + pat9125_b, pat9125_s + ); + } } #endif //FILAMENT_SENSOR @@ -2090,9 +2099,7 @@ static void lcd_support_menu() uint8_t ip[4]; // 4bytes char ip_str[3*4+3+1]; // 16bytes } _menu_data_t; -#if (22 > MENU_DATA_SIZE) -#error "check MENU_DATA_SIZE definition!" -#endif + static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); if (_md->status == 0 || lcd_draw_update == 2) { @@ -2421,6 +2428,7 @@ static void lcd_menu_AutoLoadFilament() } else { + static_assert(sizeof(menu_data)>=sizeof(ShortTimer), "ShortTimer doesn't fit into menu_data"); ShortTimer* ptimer = (ShortTimer*)&(menu_data[0]); if (!ptimer->running()) ptimer->start(); lcd_set_cursor(0, 0); @@ -2537,9 +2545,7 @@ static void _lcd_move(const char *name, int axis, int min, int max) bool initialized; // 1byte bool endstopsEnabledPrevious; // 1byte } _menu_data_t; -#if (2 > MENU_DATA_SIZE) -#error "check MENU_DATA_SIZE definition!" -#endif + static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); if (!_md->initialized) { @@ -2743,9 +2749,7 @@ static void _lcd_babystep(int axis, const char *msg) int babystepMem[3]; // 6bytes float babystepMemMM[3]; // 12bytes } _menu_data_t; -#if (19 > MENU_DATA_SIZE) -#error "check MENU_DATA_SIZE definition!" -#endif + static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); if (_md->status == 0) { @@ -2826,16 +2830,14 @@ static void lcd_babystep_z() typedef struct { // 12bytes + 9bytes = 21bytes total - uint8_t reserved[MENU_DATA_EDIT_SIZE]; //12 bytes reserved for number editing functions + menu_data_edit_t reserved; //12 bytes reserved for number editing functions int8_t status; // 1byte int16_t left; // 2byte int16_t right; // 2byte int16_t front; // 2byte int16_t rear; // 2byte } _menu_data_adjust_bed_t; -#if (21 > MENU_DATA_SIZE) -#error "check MENU_DATA_SIZE definition!" -#endif +static_assert(sizeof(menu_data)>= sizeof(_menu_data_adjust_bed_t),"_menu_data_adjust_bed_t doesn't fit into menu_data"); void lcd_adjust_bed_reset(void) { @@ -3559,6 +3561,27 @@ void lcd_diag_show_end_stops() lcd_return_to_status(); } +#ifdef TMC2130 +static void lcd_show_pinda_state() +{ +lcd_set_cursor(0, 0); +lcd_puts_P((PSTR("P.I.N.D.A. state"))); +lcd_set_cursor(0, 2); +lcd_puts_P(READ(Z_MIN_PIN)?(PSTR("Z1 (LED off)")):(PSTR("Z0 (LED on) "))); // !!! both strings must have same length (due to dynamic refreshing) +} + +static void menu_show_pinda_state() +{ +lcd_timeoutToStatus.stop(); +lcd_show_pinda_state(); +if(LCD_CLICKED) + { + lcd_timeoutToStatus.start(); + menu_back(); + } +} +#endif // defined TMC2130 + void prusa_statistics(int _message, uint8_t _fil_nr) { @@ -4047,15 +4070,16 @@ static void lcd_crash_mode_set() static void lcd_fsensor_state_set() { FSensorStateMenu = !FSensorStateMenu; //set also from fsensor_enable() and fsensor_disable() - if (!FSensorStateMenu) { - fsensor_disable(); - if (fsensor_autoload_enabled) - menu_submenu(lcd_filament_autoload_info); - }else{ - fsensor_enable(); - if (fsensor_not_responding) - menu_submenu(lcd_fsensor_fail); - } + if (!FSensorStateMenu) { + fsensor_disable(); + if (fsensor_autoload_enabled && !mmu_enabled) + menu_submenu(lcd_filament_autoload_info); + } + else { + fsensor_enable(); + if (fsensor_not_responding && !mmu_enabled) + menu_submenu(lcd_fsensor_fail); + } } #endif //FILAMENT_SENSOR @@ -4386,6 +4410,7 @@ void lcd_wizard(int state) { break; case 5: //is filament loaded? //start to preheat nozzle and bed to save some time later + lcd_commands_type = LCD_COMMAND_V2_CAL; setTargetHotend(PLA_PREHEAT_HOTEND_TEMP, 0); setTargetBed(PLA_PREHEAT_HPB_TEMP); wizard_event = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament loaded?"), false);////MSG_WIZARD_FILAMENT_LOADED c=20 r=2 @@ -4423,6 +4448,7 @@ void lcd_wizard(int state) { #ifdef SNMM change_extr(0); #endif + loading_flag = true; gcode_M701(); state = 9; break; @@ -4495,28 +4521,181 @@ void lcd_wizard(int state) { lcd_return_to_status(); lcd_update(2); } -/* + +#ifdef TMC2130 void lcd_settings_linearity_correction_menu(void) { MENU_BEGIN(); - if (menu_item_back_P(_T(MSG_MAIN))) - { - lcd_settings_menu_back(); - return; - } -// MENU_ITEM_BACK_P(_T(MSG_SETTINGS)); + MENU_ITEM_BACK_P(_T(MSG_SETTINGS)); #ifdef TMC2130_LINEARITY_CORRECTION_XYZ //tmc2130_wave_fac[X_AXIS] - int corr[4] = {tmc2130_wave_fac[X_AXIS], tmc2130_wave_fac[Y_AXIS], tmc2130_wave_fac[Z_AXIS], tmc2130_wave_fac[E_AXIS]}; - MENU_ITEM_EDIT_int3_P(_i("X-correct"), &corr[X_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 - MENU_ITEM_EDIT_int3_P(_i("Y-correct"), &corr[Y_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 - MENU_ITEM_EDIT_int3_P(_i("Z-correct"), &corr[Z_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 + MENU_ITEM_EDIT_int3_P(_i("X-correct"), &tmc2130_wave_fac[X_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 + MENU_ITEM_EDIT_int3_P(_i("Y-correct"), &tmc2130_wave_fac[Y_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 + MENU_ITEM_EDIT_int3_P(_i("Z-correct"), &tmc2130_wave_fac[Z_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 #endif //TMC2130_LINEARITY_CORRECTION_XYZ - MENU_ITEM_EDIT_int3_P(_i("E-correct"), &corr[E_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 + MENU_ITEM_EDIT_int3_P(_i("E-correct"), &tmc2130_wave_fac[E_AXIS], TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0 MENU_END(); + if(menu_leaving) + { + lcd_settings_linearity_correction_menu_save(); + } +} +#endif // TMC2130 + +#ifdef FILAMENT_SENSOR +#define SETTINGS_FILAMENT_SENSOR \ +do\ +{\ + if (FSensorStateMenu == 0)\ + {\ + if (fsensor_not_responding)\ + {\ + /* Filament sensor not working*/\ + MENU_ITEM_FUNCTION_P(_i("Fil. sensor [N/A]"), lcd_fsensor_state_set);/*////MSG_FSENSOR_NA c=0 r=0*/\ + MENU_ITEM_SUBMENU_P(_T(MSG_FSENS_AUTOLOAD_NA), lcd_fsensor_fail);\ + }\ + else\ + {\ + /* Filament sensor turned off, working, no problems*/\ + MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_OFF), lcd_fsensor_state_set);\ + if (mmu_enabled == false)if (mmu_enabled == false)\ + {\ + MENU_ITEM_SUBMENU_P(_T(MSG_FSENS_AUTOLOAD_NA), lcd_filament_autoload_info);\ + }\ + }\ + }\ + else\ + {\ + /* Filament sensor turned on, working, no problems*/\ + MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_ON), lcd_fsensor_state_set);\ + if (mmu_enabled == false)\ + {\ + if (fsensor_autoload_enabled)\ + MENU_ITEM_FUNCTION_P(_i("F. autoload [on]"), lcd_set_filament_autoload);/*////MSG_FSENS_AUTOLOAD_ON c=17 r=1*/\ + else\ + MENU_ITEM_FUNCTION_P(_i("F. autoload [off]"), lcd_set_filament_autoload);/*////MSG_FSENS_AUTOLOAD_OFF c=17 r=1*/\ + }\ + }\ +}\ +while(0) + +#else //FILAMENT_SENSOR +#define SETTINGS_FILAMENT_SENSOR do{}while(0) +#endif //FILAMENT_SENSOR + +#ifdef TMC2130 +#define SETTINGS_SILENT_MODE \ +do\ +{\ + if(!farm_mode)\ + {\ + if (SilentModeMenu == SILENT_MODE_NORMAL)\ + {\ + MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_OFF), lcd_silent_mode_set);\ + }\ + else MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_ON), lcd_silent_mode_set);\ + if (SilentModeMenu == SILENT_MODE_NORMAL)\ + {\ + if (CrashDetectMenu == 0)\ + {\ + MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_OFF), lcd_crash_mode_set);\ + }\ + else MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_ON), lcd_crash_mode_set);\ + }\ + else MENU_ITEM_SUBMENU_P(_T(MSG_CRASHDETECT_NA), lcd_crash_mode_info);\ + }\ +}\ +while (0) + +#else //TMC2130 +#define SETTINGS_SILENT_MODE \ +do\ +{\ + if(!farm_mode)\ + {\ + switch (SilentModeMenu)\ + {\ + case SILENT_MODE_POWER:\ + MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set);\ + break;\ + case SILENT_MODE_SILENT:\ + MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_ON), lcd_silent_mode_set);\ + break;\ + case SILENT_MODE_AUTO:\ + MENU_ITEM_FUNCTION_P(_T(MSG_AUTO_MODE_ON), lcd_silent_mode_set);\ + break;\ + default:\ + MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set);\ + break; /* (probably) not needed*/\ + }\ + }\ +}\ +while (0) +#endif //TMC2130 + +#ifdef SDCARD_SORT_ALPHA +#define SETTINGS_SD \ +do\ +{\ + if (card.ToshibaFlashAir_isEnabled())\ + MENU_ITEM_FUNCTION_P(_i("SD card [flshAir]"), lcd_toshiba_flash_air_compatibility_toggle);/*////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1*/\ + else\ + MENU_ITEM_FUNCTION_P(_i("SD card [normal]"), lcd_toshiba_flash_air_compatibility_toggle);/*////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1*/\ +\ + if (!farm_mode)\ + {\ + uint8_t sdSort;\ + EEPROM_read(EEPROM_SD_SORT, (uint8_t*)&sdSort, sizeof(sdSort));\ + switch (sdSort)\ + {\ + case SD_SORT_TIME: MENU_ITEM_FUNCTION_P(_i("Sort: [time]"), lcd_sort_type_set); break;/*////MSG_SORT_TIME c=17 r=1*/\ + case SD_SORT_ALPHA: MENU_ITEM_FUNCTION_P(_i("Sort: [alphabet]"), lcd_sort_type_set); break;/*////MSG_SORT_ALPHA c=17 r=1*/\ + default: MENU_ITEM_FUNCTION_P(_i("Sort: [none]"), lcd_sort_type_set);/*////MSG_SORT_NONE c=17 r=1*/\ + }\ + }\ +}\ +while (0) +#else // SDCARD_SORT_ALPHA +#define SETTINGS_SD \ +do\ +{\ + if (card.ToshibaFlashAir_isEnabled())\ + MENU_ITEM_FUNCTION_P(_i("SD card [flshAir]"), lcd_toshiba_flash_air_compatibility_toggle);/*////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1*/\ + else\ + MENU_ITEM_FUNCTION_P(_i("SD card [normal]"), lcd_toshiba_flash_air_compatibility_toggle);/*////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1*/\ +}\ +while (0) +#endif // SDCARD_SORT_ALPHA + +#define SETTINGS_SOUND \ +do\ +{\ + switch(eSoundMode)\ + {\ + case e_SOUND_MODE_LOUD:\ + MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_LOUD),lcd_sound_state_set);\ + break;\ + case e_SOUND_MODE_ONCE:\ + MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_ONCE),lcd_sound_state_set);\ + break;\ + case e_SOUND_MODE_SILENT:\ + MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_SILENT),lcd_sound_state_set);\ + break;\ + case e_SOUND_MODE_MUTE:\ + MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_MUTE),lcd_sound_state_set);\ + break;\ + default:\ + MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_LOUD),lcd_sound_state_set);\ + }\ +}\ +while (0) + +static void auto_deplete_switch() +{ + lcd_autoDeplete = !lcd_autoDeplete; + eeprom_update_byte((unsigned char *)EEPROM_AUTO_DEPLETE, lcd_autoDeplete); } -*/ static void lcd_settings_menu() { EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu)); @@ -4525,70 +4704,28 @@ static void lcd_settings_menu() MENU_ITEM_SUBMENU_P(_i("Temperature"), lcd_control_temperature_menu);////MSG_TEMPERATURE c=0 r=0 if (!homing_flag) - MENU_ITEM_SUBMENU_P(_i("Move axis"), lcd_move_menu_1mm);////MSG_MOVE_AXIS c=0 r=0 + MENU_ITEM_SUBMENU_P(_i("Move axis"), lcd_move_menu_1mm);////MSG_MOVE_AXIS c=0 r=0 if (!isPrintPaused) - MENU_ITEM_GCODE_P(_i("Disable steppers"), PSTR("M84"));////MSG_DISABLE_STEPPERS c=0 r=0 + MENU_ITEM_GCODE_P(_i("Disable steppers"), PSTR("M84"));////MSG_DISABLE_STEPPERS c=0 r=0 -#ifndef TMC2130 - if (!farm_mode) - { //dont show in menu if we are in farm mode - switch (SilentModeMenu) - { - case SILENT_MODE_POWER: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break; - case SILENT_MODE_SILENT: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_ON), lcd_silent_mode_set); break; - case SILENT_MODE_AUTO: MENU_ITEM_FUNCTION_P(_T(MSG_AUTO_MODE_ON), lcd_silent_mode_set); break; - default: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break; // (probably) not needed - } - } -#endif //TMC2130 + SETTINGS_FILAMENT_SENSOR; -#ifdef FILAMENT_SENSOR - if (FSensorStateMenu == 0) + if (mmu_enabled) { - if (fsensor_not_responding) - { - // Filament sensor not working - MENU_ITEM_FUNCTION_P(_i("Fil. sensor [N/A]"), lcd_fsensor_state_set);////MSG_FSENSOR_NA c=0 r=0 - MENU_ITEM_SUBMENU_P(_T(MSG_FSENS_AUTOLOAD_NA), lcd_fsensor_fail); - } - else - { - // Filament sensor turned off, working, no problems - MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_OFF), lcd_fsensor_state_set); - MENU_ITEM_SUBMENU_P(_T(MSG_FSENS_AUTOLOAD_NA), lcd_filament_autoload_info); - } + if (lcd_autoDeplete) MENU_ITEM_FUNCTION_P(_i("Auto deplete [on]"), auto_deplete_switch); + else MENU_ITEM_FUNCTION_P(_i("Auto deplete[off]"), auto_deplete_switch); } - else - { - // Filament sensor turned on, working, no problems - MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_ON), lcd_fsensor_state_set); - if (fsensor_autoload_enabled) - MENU_ITEM_FUNCTION_P(_i("F. autoload [on]"), lcd_set_filament_autoload);////MSG_FSENS_AUTOLOAD_ON c=17 r=1 - else - MENU_ITEM_FUNCTION_P(_i("F. autoload [off]"), lcd_set_filament_autoload);////MSG_FSENS_AUTOLOAD_OFF c=17 r=1 - } -#endif //FILAMENT_SENSOR if (fans_check_enabled == true) MENU_ITEM_FUNCTION_P(_i("Fans check [on]"), lcd_set_fan_check);////MSG_FANS_CHECK_ON c=17 r=1 else MENU_ITEM_FUNCTION_P(_i("Fans check [off]"), lcd_set_fan_check);////MSG_FANS_CHECK_OFF c=17 r=1 -#ifdef TMC2130 - if(!farm_mode) - { - if (SilentModeMenu == SILENT_MODE_NORMAL) { MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_OFF), lcd_silent_mode_set); } - else MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_ON), lcd_silent_mode_set); - if (SilentModeMenu == SILENT_MODE_NORMAL) - { - if (CrashDetectMenu == 0) { MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_OFF), lcd_crash_mode_set); } - else MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_ON), lcd_crash_mode_set); - } - else MENU_ITEM_SUBMENU_P(_T(MSG_CRASHDETECT_NA), lcd_crash_mode_info); - } + SETTINGS_SILENT_MODE; -// MENU_ITEM_SUBMENU_P(_i("Lin. correction"), lcd_settings_linearity_correction_menu); -#endif //TMC2130 +#if defined (TMC2130) && defined (LINEARITY_CORRECTION) + MENU_ITEM_SUBMENU_P(_i("Lin. correction"), lcd_settings_linearity_correction_menu); +#endif //LINEARITY_CORRECTION && TMC2130 if (temp_cal_active == false) MENU_ITEM_FUNCTION_P(_i("Temp. cal. [off]"), lcd_temp_calibration_set);////MSG_TEMP_CALIBRATION_OFF c=20 r=1 @@ -4609,45 +4746,9 @@ static void lcd_settings_menu() MENU_ITEM_SUBMENU_P(_i("Select language"), lcd_language_menu);////MSG_LANGUAGE_SELECT c=0 r=0 #endif //(LANG_MODE != 0) - if (card.ToshibaFlashAir_isEnabled()) - MENU_ITEM_FUNCTION_P(_i("SD card [flshAir]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1 - else - MENU_ITEM_FUNCTION_P(_i("SD card [normal]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1 + SETTINGS_SD; + SETTINGS_SOUND; -#ifdef SDCARD_SORT_ALPHA - if (!farm_mode) - { - uint8_t sdSort; - EEPROM_read(EEPROM_SD_SORT, (uint8_t*)&sdSort, sizeof(sdSort)); - switch (sdSort) - { - case SD_SORT_TIME: MENU_ITEM_FUNCTION_P(_i("Sort: [time]"), lcd_sort_type_set); break;////MSG_SORT_TIME c=17 r=1 - case SD_SORT_ALPHA: MENU_ITEM_FUNCTION_P(_i("Sort: [alphabet]"), lcd_sort_type_set); break;////MSG_SORT_ALPHA c=17 r=1 - default: MENU_ITEM_FUNCTION_P(_i("Sort: [none]"), lcd_sort_type_set);////MSG_SORT_NONE c=17 r=1 - } - } -#endif // SDCARD_SORT_ALPHA - - -//-// -switch(eSoundMode) - { - case e_SOUND_MODE_LOUD: - MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_LOUD),lcd_sound_state_set); - break; - case e_SOUND_MODE_ONCE: - MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_ONCE),lcd_sound_state_set); - break; - case e_SOUND_MODE_SILENT: - MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_SILENT),lcd_sound_state_set); - break; - case e_SOUND_MODE_MUTE: - MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_MUTE),lcd_sound_state_set); - break; - default: - MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_LOUD),lcd_sound_state_set); - } -//-// if (farm_mode) { MENU_ITEM_SUBMENU_P(PSTR("Farm number"), lcd_farm_no); @@ -4672,8 +4773,8 @@ static void lcd_ustep_linearity_menu_save() } #endif //TMC2130 -/* -static void lcd_settings_menu_back() + +static void lcd_settings_linearity_correction_menu_save() { #ifdef TMC2130 bool changed = false; @@ -4688,10 +4789,8 @@ static void lcd_settings_menu_back() lcd_ustep_linearity_menu_save(); if (changed) tmc2130_init(); #endif //TMC2130 - menu_menu = lcd_main_menu; -// lcd_main_menu(); } -*/ + static void lcd_calibration_menu() { @@ -4722,7 +4821,9 @@ static void lcd_calibration_menu() MENU_ITEM_SUBMENU_P(_i("Bed level correct"), lcd_adjust_bed);////MSG_BED_CORRECTION_MENU c=0 r=0 MENU_ITEM_SUBMENU_P(_i("PID calibration"), pid_extruder);////MSG_PID_EXTRUDER c=17 r=1 -#ifndef TMC2130 +#ifdef TMC2130 + MENU_ITEM_SUBMENU_P(_i("Show pinda state"), menu_show_pinda_state); +#else MENU_ITEM_SUBMENU_P(_i("Show end stops"), menu_show_end_stops);////MSG_SHOW_END_STOPS c=17 r=1 #endif #ifndef MK1BP @@ -5110,6 +5211,19 @@ static void fil_load_menu() MENU_END(); } +static void mmu_fil_eject_menu() +{ + MENU_BEGIN(); + MENU_ITEM_BACK_P(_T(MSG_MAIN)); + MENU_ITEM_FUNCTION_P(_i("Eject filament 1"), mmu_eject_fil_0); + MENU_ITEM_FUNCTION_P(_i("Eject filament 2"), mmu_eject_fil_1); + MENU_ITEM_FUNCTION_P(_i("Eject filament 3"), mmu_eject_fil_2); + MENU_ITEM_FUNCTION_P(_i("Eject filament 4"), mmu_eject_fil_3); + MENU_ITEM_FUNCTION_P(_i("Eject filament 5"), mmu_eject_fil_4); + + MENU_END(); +} + static void fil_unload_menu() { MENU_BEGIN(); @@ -5489,7 +5603,7 @@ static void lcd_main_menu() }*/ - + if ( ( IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL)) && (current_position[Z_AXIS] < Z_HEIGHT_HIDE_LIVE_ADJUST_MENU) && !homing_flag && !mesh_bed_leveling_flag) { MENU_ITEM_SUBMENU_P(_T(MSG_BABYSTEP_Z), lcd_babystep_z);//8 @@ -5558,6 +5672,7 @@ static void lcd_main_menu() if (mmu_enabled) { MENU_ITEM_SUBMENU_P(_T(MSG_LOAD_FILAMENT), fil_load_menu); + MENU_ITEM_SUBMENU_P(_i("Eject filament"), mmu_fil_eject_menu); if (mmu_enabled) MENU_ITEM_GCODE_P(_T(MSG_UNLOAD_FILAMENT), PSTR("M702 C")); else @@ -5569,7 +5684,7 @@ static void lcd_main_menu() else { #ifdef FILAMENT_SENSOR - if ( ((fsensor_autoload_enabled == true) && (fsensor_enabled == true))) + if ((fsensor_autoload_enabled == true) && (fsensor_enabled == true) && (mmu_enabled == false)) MENU_ITEM_SUBMENU_P(_i("AutoLoad filament"), lcd_menu_AutoLoadFilament);////MSG_AUTOLOAD_FILAMENT c=17 r=0 else #endif //FILAMENT_SENSOR @@ -5671,16 +5786,14 @@ static void lcd_colorprint_change() { static void lcd_tune_menu() { typedef struct - { // 3bytes total - // To recognize, whether the menu has been just initialized. - int8_t status; // 1byte - // Backup of extrudemultiply, to recognize, that the value has been changed and - // it needs to be applied. - int16_t extrudemultiply; // 2byte + { + menu_data_edit_t reserved; //!< reserved for number editing functions + int8_t status; //!< To recognize, whether the menu has been just initialized. + //! Backup of extrudemultiply, to recognize, that the value has been changed and + //! it needs to be applied. + int16_t extrudemultiply; } _menu_data_t; -#if (3 > MENU_DATA_SIZE) -#error "check MENU_DATA_SIZE definition!" -#endif + static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); if (_md->status == 0) { @@ -6092,14 +6205,19 @@ bool lcd_selftest() { _progress = lcd_selftest_screen(8, _progress, 3, true, 2000); //bed ok #ifdef FILAMENT_SENSOR - _progress = lcd_selftest_screen(9, _progress, 3, true, 2000); //check filaments sensor - _result = lcd_selftest_fsensor(); + if (mmu_enabled == false) { + _progress = lcd_selftest_screen(9, _progress, 3, true, 2000); //check filaments sensor + _result = lcd_selftest_fsensor(); + } #endif // FILAMENT_SENSOR } if (_result) { #ifdef FILAMENT_SENSOR - _progress = lcd_selftest_screen(10, _progress, 3, true, 2000); //fil sensor OK + if (mmu_enabled == false) + { + _progress = lcd_selftest_screen(10, _progress, 3, true, 2000); //fil sensor OK + } #endif // FILAMENT_SENSOR _progress = lcd_selftest_screen(11, _progress, 3, true, 5000); //all correct } @@ -6997,6 +7115,12 @@ void menu_action_sddirectory(const char* filename, char* longFilename) void ultralcd_init() { + { + uint8_t autoDepleteRaw = eeprom_read_byte(reinterpret_cast(EEPROM_AUTO_DEPLETE)); + if (0xff == autoDepleteRaw) lcd_autoDeplete = false; + else lcd_autoDeplete = autoDepleteRaw; + + } lcd_init(); lcd_refresh(); lcd_longpress_func = menu_lcd_longpress_func; diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 29a13a9c7..fe7408222 100644 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -45,6 +45,7 @@ void lcd_menu_statistics(); extern const char* lcd_display_message_fullscreen_P(const char *msg, uint8_t &nlines); extern const char* lcd_display_message_fullscreen_P(const char *msg); +extern void lcd_return_to_status(); extern void lcd_wait_for_click(); extern void lcd_show_fullscreen_message_and_wait_P(const char *msg); // 0: no, 1: yes, -1: timeouted @@ -111,6 +112,7 @@ extern int8_t SilentModeMenu; extern bool cancel_heatup; extern bool isPrintPaused; +extern bool lcd_autoDeplete; void lcd_ignore_click(bool b=true); diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index dbce6a962..7cde630b7 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -100,7 +100,7 @@ //Silent mode limits #define SILENT_MAX_ACCEL_XY 960ul // max acceleration in silent mode in mm/s^2 -#define SILENT_MAX_FEEDRATE_XY 172 // max feedrate in mm/s +#define SILENT_MAX_FEEDRATE_XY 100 // max feedrate in mm/s //Normal mode limits #define NORMAL_MAX_ACCEL_XY 2500ul // max acceleration in normal mode in mm/s^2 @@ -183,6 +183,7 @@ #define CMD_DIAGNOSTICS //Show cmd queue length on printer display #endif /* DEBUG_BUILD */ +#define LINEARITY_CORRECTION #define TMC2130_LINEARITY_CORRECTION #define TMC2130_LINEARITY_CORRECTION_XYZ //#define TMC2130_VARIABLE_RESOLUTION