From 4c4b4c489cf632b9c7535e1971b96782f3b5f78e Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 7 Apr 2020 17:09:48 +0300 Subject: [PATCH 01/50] :bug::recycle: Update the feedrate percentage before drawing the screen --- Firmware/ultralcd.cpp | 60 +++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 62c41072..c60b6e42 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -997,6 +997,36 @@ void lcd_status_screen() // NOT static due to using ins } } +#ifdef ULTIPANEL_FEEDMULTIPLY + // Dead zone at 100% feedrate + if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) || + (feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100)) + { + lcd_encoder = 0; + feedmultiply = 100; + } + if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE) + { + feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE; + lcd_encoder = 0; + } + else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE) + { + feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE; + lcd_encoder = 0; + } + else if (feedmultiply != 100) + { + feedmultiply += int(lcd_encoder); + lcd_encoder = 0; + } +#endif //ULTIPANEL_FEEDMULTIPLY + + if (feedmultiply < 10) + feedmultiply = 10; + else if (feedmultiply > 999) + feedmultiply = 999; + if (lcd_status_update_delay) lcd_status_update_delay--; else @@ -1073,36 +1103,6 @@ void lcd_status_screen() // NOT static due to using ins menu_submenu(lcd_main_menu); lcd_refresh(); // to maybe revive the LCD if static electricity killed it. } - -#ifdef ULTIPANEL_FEEDMULTIPLY - // Dead zone at 100% feedrate - if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) || - (feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100)) - { - lcd_encoder = 0; - feedmultiply = 100; - } - if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE) - { - feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE; - lcd_encoder = 0; - } - else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE) - { - feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE; - lcd_encoder = 0; - } - else if (feedmultiply != 100) - { - feedmultiply += int(lcd_encoder); - lcd_encoder = 0; - } -#endif //ULTIPANEL_FEEDMULTIPLY - - if (feedmultiply < 10) - feedmultiply = 10; - else if (feedmultiply > 999) - feedmultiply = 999; } void lcd_commands() From 1bac0c176518a13a320d7dd69d400f21902927c7 Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Sat, 18 Apr 2020 16:39:04 +0200 Subject: [PATCH 02/50] Add dummy G21 to prevent UNKOWN warnings in serial And as Prusa firmware operates ONLY in milimeters it kind of does what G21 is supposed to do. --- Firmware/Marlin_main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index e4e1e0b2..d6955f89 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -4276,6 +4276,14 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) #endif //FWRETRACT + /*! + ### G21 - Sets Units to Millimters G21: Set Units to Millimeters + Units are in millimeters. Prusa doesn't support inches. + */ + case 21: + break; //Doing nothing. This is just to prevent serial UNKOWN warnings. + + /*! ### G28 - Home all Axes one at a time G28: Move to Origin (Home) Using `G28` without any parameters will perfom homing of all axes AND mesh bed leveling, while `G28 W` will just home all axes (no mesh bed leveling). From 4c5fe053337dc111e5cde9a3563ccaecd8b1e14e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20B=C4=9Bl?= <35807926+mkbel@users.noreply.github.com> Date: Thu, 11 Jun 2020 18:32:36 +0200 Subject: [PATCH 03/50] Update README.md Mention gawk dependency for multi language. --- README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fb1c7968..79ab9b74 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,28 @@ The firmware for the Original Prusa i3 printers is proudly based on [Marlin 1.0. 1. Clone this repository and checkout the correct branch for your desired release version. -2. Set your printer model. +1. Set your printer model. - For MK3 --> skip to step 3. - If you have a different printer model, follow step [2.b](#2b) from Windows build +1. Install GNU AWK `sudo apt-get install gawk` +If you use mawk instead of gawk you get strange errors when multi language support is generated like: +`awk: line 2: function strtonum never defined +sed: couldn't write 4 items to stdout: Broken pipe +./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined +sed: couldn't write 4 items to stdout: Broken pipe +tr: write error: Broken pipe +./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined +sed: couldn't write 4 items to stdout: Broken pipe +tr: write error: Broken pipe +tr: write error +cut: write error: Broken pipeNG! - some texts not found in lang_en.txt! updating binary: + primary language ids...awk: line 2: function strtonum never defined +sed: couldn't flush stdout: Broken pipe` -3. Run `./build.sh` +1. Run `./build.sh` - Output hex file is at `"PrusaFirmware/lang/firmware.hex"` . In the same folder you can hex files for other languages as well. -4. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE. +1. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE. - If you wish to flash from Arduino, follow step [2.c](#2c) from Windows build first. From a0cf5714ceca7d60c5874c376898ecd8badd7d13 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 19 Jun 2020 15:39:16 +0300 Subject: [PATCH 04/50] M220 M221 --- Firmware/Marlin_main.cpp | 58 ++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 8dbc0d84..d4ed0c51 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -7300,17 +7300,26 @@ Sigma_Exit: */ case 220: // M220 S- set speed factor override percentage { - if (code_seen('B')) //backup current speed factor - { - saved_feedmultiply_mm = feedmultiply; - } - if(code_seen('S')) - { - feedmultiply = code_value() ; - } - if (code_seen('R')) { //restore previous feedmultiply - feedmultiply = saved_feedmultiply_mm; - } + bool codesWereSeen = false; + if (code_seen('B')) //backup current speed factor + { + saved_feedmultiply_mm = feedmultiply; + codesWereSeen = true; + } + if (code_seen('S')) + { + feedmultiply = code_value(); + codesWereSeen = true; + } + if (code_seen('R')) //restore previous feedmultiply + { + feedmultiply = saved_feedmultiply_mm; + codesWereSeen = true; + } + if (!codesWereSeen) + { + printf_P(PSTR("%i%%\n"), feedmultiply); + } } break; @@ -7326,23 +7335,26 @@ Sigma_Exit: */ case 221: // M221 S- set extrude factor override percentage { - if(code_seen('S')) - { - int tmp_code = code_value(); - if (code_seen('T')) + if (code_seen('S')) { - uint8_t extruder; - if(setTargetedHotend(221, extruder)){ - break; - } - extruder_multiply[extruder] = tmp_code; + int tmp_code = code_value(); + if (code_seen('T')) + { + uint8_t extruder; + if (setTargetedHotend(221, extruder)) + break; + extruder_multiply[extruder] = tmp_code; + } + else + { + extrudemultiply = tmp_code ; + } } else { - extrudemultiply = tmp_code ; + printf_P(PSTR("%i%%\n"), extrudemultiply); } - } - calculate_extruder_multipliers(); + calculate_extruder_multipliers(); } break; From 15548958e98ddae4de263d77aa68aa025226e2d2 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 21 Jun 2020 15:19:31 +0200 Subject: [PATCH 05/50] Remove cumulative error in segments without cruising (take 1) PR #2591 made LA compression always account for retractions instead of discarding the current compression steps. While this fixed overextrusion in short segments followed by wipes, it uncovered another issue in how the compression steps are spread during the trapezoid calculations leading to gaps in segments followed by retractions (as highlighted by /some/ prints in #2693). LA1.5 always computes the required target compression steps for a segment at nominal speed. Because of how the extra steps are allocated using multiples of the accelerating frequency, if the segment is truncated before cruising is reached, an additional cycle of steps can be inserted before deceleration starts. Deceleration is also not guaranteed to be symmetric where up to _two_ cycles can be skipped depending on the stepping cycle, leading to a situation where a symmetric acceleration/deceleration block will lead up to a cycle of accumulated compression. While forcing an the extra step during deceleration is possible by tweaking the error term (eISR_Err), this doesn't guarantee balance in all cases. The underlying issue is that the function is aiming a compression which cannot be reached (nominal speed), and not at the effective max speed reached in the trapezoid, thus moving the average result higher over time. We fix this by calculating the effective maximum speed (and compression) reached during the trapezoid, which stops compression on the required cycle irregardless of the error term, balancing the result. This is the first unoptimized POC: this is not for production: a lot of calculations are redundand and could work directly in steps/s^2. --- Firmware/planner.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index c0f465c2..049dd202 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -225,12 +225,15 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit uint32_t accel_decel_steps = accelerate_steps + decelerate_steps; // Size of Plateau of Nominal Rate. uint32_t plateau_steps = 0; + // Maximum effective speed reached in the trapezoid (mm/s) + float max_speed; // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will // have to use intersection_distance() to calculate when to abort acceleration and start braking // in order to reach the final_rate exactly at the end of this block. if (accel_decel_steps < block->step_event_count.wide) { plateau_steps = block->step_event_count.wide - accel_decel_steps; + max_speed = block->nominal_speed; } else { uint32_t acceleration_x4 = acceleration << 2; // Avoid negative numbers @@ -263,12 +266,18 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit decelerate_steps = block->step_event_count.wide; accelerate_steps = block->step_event_count.wide - decelerate_steps; } + + // TODO: not for production + float dist = intersection_distance(entry_speed, exit_speed, block->acceleration, block->millimeters); + max_speed = sqrt(2 * block->acceleration * dist + entry_speed*entry_speed); } #ifdef LIN_ADVANCE uint16_t final_adv_steps = 0; + uint16_t max_adv_steps = 0; if (block->use_advance_lead) { final_adv_steps = exit_speed * block->adv_comp; + max_adv_steps = max_speed * block->adv_comp; } #endif @@ -284,6 +293,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit block->final_rate = final_rate; #ifdef LIN_ADVANCE block->final_adv_steps = final_adv_steps; + block->max_adv_steps = max_adv_steps; #endif } CRITICAL_SECTION_END; @@ -1137,9 +1147,8 @@ Having the real displacement of the head, we can calculate the total movement le #ifdef LIN_ADVANCE if (block->use_advance_lead) { // the nominal speed doesn't change past this point: calculate the compression ratio for the - // segment and the required advance steps + // segment (the required advance steps are computed during trapezoid planning) block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; - block->max_adv_steps = block->nominal_speed * block->adv_comp; float advance_speed; if (e_D_ratio > 0) From 753e651af3026fba344169e45f677476741cf485 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 21 Jun 2020 16:01:13 +0200 Subject: [PATCH 06/50] Remove cumulative error in segments without cruising (take 2) Reduce per-trapezoid calculations --- Firmware/planner.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index 049dd202..8687055b 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -267,9 +267,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit accelerate_steps = block->step_event_count.wide - decelerate_steps; } - // TODO: not for production - float dist = intersection_distance(entry_speed, exit_speed, block->acceleration, block->millimeters); - max_speed = sqrt(2 * block->acceleration * dist + entry_speed*entry_speed); + max_speed = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr) / block->speed_factor; } #ifdef LIN_ADVANCE From 7c140bc497d50d1ebda861d79c7fb5fe64d5c673 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 21 Jun 2020 16:19:46 +0200 Subject: [PATCH 07/50] Remove cumulative error in segments without cruising (take 3) Remove another division by precomputing the division directly in adv_comp. --- Firmware/planner.cpp | 104 ++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index 8687055b..54bc692d 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -225,15 +225,15 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit uint32_t accel_decel_steps = accelerate_steps + decelerate_steps; // Size of Plateau of Nominal Rate. uint32_t plateau_steps = 0; - // Maximum effective speed reached in the trapezoid (mm/s) - float max_speed; + // Maximum effective speed reached in the trapezoid (step/min) + float max_rate; // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will // have to use intersection_distance() to calculate when to abort acceleration and start braking // in order to reach the final_rate exactly at the end of this block. if (accel_decel_steps < block->step_event_count.wide) { plateau_steps = block->step_event_count.wide - accel_decel_steps; - max_speed = block->nominal_speed; + max_rate = block->nominal_rate; } else { uint32_t acceleration_x4 = acceleration << 2; // Avoid negative numbers @@ -267,15 +267,15 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit accelerate_steps = block->step_event_count.wide - decelerate_steps; } - max_speed = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr) / block->speed_factor; + max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr); } #ifdef LIN_ADVANCE uint16_t final_adv_steps = 0; uint16_t max_adv_steps = 0; if (block->use_advance_lead) { - final_adv_steps = exit_speed * block->adv_comp; - max_adv_steps = max_speed * block->adv_comp; + final_adv_steps = final_rate * block->adv_comp; + max_adv_steps = max_rate * block->adv_comp; } #endif @@ -1142,51 +1142,6 @@ Having the real displacement of the head, we can calculate the total movement le block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0))); -#ifdef LIN_ADVANCE - if (block->use_advance_lead) { - // the nominal speed doesn't change past this point: calculate the compression ratio for the - // segment (the required advance steps are computed during trapezoid planning) - block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; - - float advance_speed; - if (e_D_ratio > 0) - advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]); - else - advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS]; - - // to save more space we avoid another copy of calc_timer and go through slow division, but we - // still need to replicate the *exact* same step grouping policy (see below) - if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY; - float advance_rate = (F_CPU / 8.0) / advance_speed; - if (advance_speed > 20000) { - block->advance_rate = advance_rate * 4; - block->advance_step_loops = 4; - } - else if (advance_speed > 10000) { - block->advance_rate = advance_rate * 2; - block->advance_step_loops = 2; - } - else - { - // never overflow the internal accumulator with very low rates - if (advance_rate < UINT16_MAX) - block->advance_rate = advance_rate; - else - block->advance_rate = UINT16_MAX; - block->advance_step_loops = 1; - } - - #ifdef LA_DEBUG - if (block->advance_step_loops > 2) - // @wavexx: we should really check for the difference between step_loops and - // advance_step_loops instead. A difference of more than 1 will lead - // to uneven speed and *should* be adjusted here by furthermore - // reducing the speed. - SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed."); - #endif - } -#endif - // Start with a safe speed. // Safe speed is the speed, from which the machine may halt to stop immediately. float safe_speed = block->nominal_speed; @@ -1312,6 +1267,53 @@ Having the real displacement of the head, we can calculate the total movement le // Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated. block->speed_factor = block->nominal_rate / block->nominal_speed; + +#ifdef LIN_ADVANCE + if (block->use_advance_lead) { + // calculate the compression ratio for the segment (the required advance steps are computed + // during trapezoid planning) + float adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; // (step/(mm/s)) + block->adv_comp = adv_comp / block->speed_factor; // step/(step/min) + + float advance_speed; + if (e_D_ratio > 0) + advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]); + else + advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS]; + + // to save more space we avoid another copy of calc_timer and go through slow division, but we + // still need to replicate the *exact* same step grouping policy (see below) + if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY; + float advance_rate = (F_CPU / 8.0) / advance_speed; + if (advance_speed > 20000) { + block->advance_rate = advance_rate * 4; + block->advance_step_loops = 4; + } + else if (advance_speed > 10000) { + block->advance_rate = advance_rate * 2; + block->advance_step_loops = 2; + } + else + { + // never overflow the internal accumulator with very low rates + if (advance_rate < UINT16_MAX) + block->advance_rate = advance_rate; + else + block->advance_rate = UINT16_MAX; + block->advance_step_loops = 1; + } + + #ifdef LA_DEBUG + if (block->advance_step_loops > 2) + // @wavexx: we should really check for the difference between step_loops and + // advance_step_loops instead. A difference of more than 1 will lead + // to uneven speed and *should* be adjusted here by furthermore + // reducing the speed. + SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed."); + #endif + } +#endif + calculate_trapezoid_for_block(block, block->entry_speed, safe_speed); if (block->step_event_count.wide <= 32767) From 51a539608cafafb41fe8ee248c41a91c70f7b145 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 22 Jun 2020 00:19:47 +0200 Subject: [PATCH 08/50] Reset LA_phase at each trapezoid stage There used to be a single stage where an extruder reversal could occur, but since PR #2591 reversals can happen up to two times per trapezoid. Reset LA_phase when ADV_INIT is set, since it is re-inizialized only when needed a few lines afterward. This improves performance by avoiding to check the phase continuosly to the end of the trapezoid. Likewise, always set ADV_INIT during the first cruising step, also to force a LA_phase reset. --- Firmware/stepper.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index de250ec9..57520070 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -848,12 +848,10 @@ FORCE_INLINE void isr() { #ifdef LIN_ADVANCE if(current_block->use_advance_lead) { - if (!nextAdvanceISR) { - // Due to E-jerk, there can be discontinuities in pressure state where an - // acceleration or deceleration can be skipped or joined with the previous block. - // If LA was not previously active, re-check the pressure level - la_state = ADV_INIT; - } + // Due to E-jerk, there can be discontinuities in pressure state where an + // acceleration or deceleration can be skipped or joined with the previous block. + // If LA was not previously active, re-check the pressure level + la_state = ADV_INIT; } #endif } @@ -865,6 +863,7 @@ FORCE_INLINE void isr() { #ifdef LIN_ADVANCE // avoid multiple instances or function calls to advance_spread if (la_state & ADV_INIT) { + LA_phase = -1; if (current_adv_steps == target_adv_steps) { // nothing to be done in this phase la_state = 0; From 173aa2debad36da6590c53ad0a4114bfcda6a710 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 22 Jun 2020 00:54:50 +0200 Subject: [PATCH 09/50] Fix bogus timer check preventing fast LA steps to be scheduled Simplify and fix the broken timer check when scheduling advance ticks. This dates back to the original LA15 PR, an old bug... --- Firmware/stepper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 57520070..b1c3d286 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -1016,7 +1016,7 @@ FORCE_INLINE void advance_isr_scheduler() { // Schedule the next closest tick, ignoring advance if scheduled too // soon in order to avoid skewing the regular stepper acceleration - if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + TCNT1 + 40) < nextMainISR) + if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + 40) < nextMainISR) OCR1A = nextAdvanceISR; else OCR1A = nextMainISR; From a36efcb347bc3c1312f401ecaac383073d3856ba Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 22 Jun 2020 15:03:49 +0200 Subject: [PATCH 10/50] Remove cumulative error in segments without cruising (take 4) Avoid sqrt when possible --- Firmware/planner.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index 54bc692d..b5b251ec 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -225,15 +225,24 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit uint32_t accel_decel_steps = accelerate_steps + decelerate_steps; // Size of Plateau of Nominal Rate. uint32_t plateau_steps = 0; - // Maximum effective speed reached in the trapezoid (step/min) - float max_rate; + +#ifdef LIN_ADVANCE + uint16_t final_adv_steps = 0; + uint16_t max_adv_steps = 0; + if (block->use_advance_lead) { + final_adv_steps = final_rate * block->adv_comp; + } +#endif // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will // have to use intersection_distance() to calculate when to abort acceleration and start braking // in order to reach the final_rate exactly at the end of this block. if (accel_decel_steps < block->step_event_count.wide) { plateau_steps = block->step_event_count.wide - accel_decel_steps; - max_rate = block->nominal_rate; +#ifdef LIN_ADVANCE + if (block->use_advance_lead) + max_adv_steps = block->nominal_rate * block->adv_comp; +#endif } else { uint32_t acceleration_x4 = acceleration << 2; // Avoid negative numbers @@ -267,17 +276,19 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit accelerate_steps = block->step_event_count.wide - decelerate_steps; } - max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr); - } - #ifdef LIN_ADVANCE - uint16_t final_adv_steps = 0; - uint16_t max_adv_steps = 0; - if (block->use_advance_lead) { - final_adv_steps = final_rate * block->adv_comp; - max_adv_steps = max_rate * block->adv_comp; - } + if (block->use_advance_lead) { + if(!accelerate_steps || !decelerate_steps) { + // accelerate_steps=0: deceleration-only ramp, max_rate is effectively unused + // decelerate_steps=0: acceleration-only ramp, max_rate _is_ final_rate + max_adv_steps = final_adv_steps; + } else { + uint16_t max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr); + max_adv_steps = max_rate * block->adv_comp; + } + } #endif + } CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section // This block locks the interrupts globally for 4.38 us, From 1206fc316402012c4607865d32cbc8ad470b71aa Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 22 Jun 2020 15:34:34 +0200 Subject: [PATCH 11/50] Avoid useless cast --- Firmware/planner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index b5b251ec..bc991fdf 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -283,7 +283,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit // decelerate_steps=0: acceleration-only ramp, max_rate _is_ final_rate max_adv_steps = final_adv_steps; } else { - uint16_t max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr); + float max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr); max_adv_steps = max_rate * block->adv_comp; } } From 50a09824fd8b3d33d62940b6836db350ea8670d5 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 23 Jun 2020 15:20:46 +0200 Subject: [PATCH 12/50] Avoid scheduling useless eISR ticks When switching to a new trapezoid step with the right pressure, cancel any pending eISR right away. Similarly do not schedule another eISR if the pressure will be reached by the end of the eISR. This was done in the past to preserve the current LA_phase. This is not needed anymore, since it will be reset at each trapezoid step when LA is re-initialized. --- Firmware/stepper.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index b1c3d286..0c7ecae5 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -864,9 +864,11 @@ FORCE_INLINE void isr() { // avoid multiple instances or function calls to advance_spread if (la_state & ADV_INIT) { LA_phase = -1; + if (current_adv_steps == target_adv_steps) { - // nothing to be done in this phase + // nothing to be done in this phase, cancel any pending eisr la_state = 0; + nextAdvanceISR = ADV_NEVER; } else { eISR_Err = current_block->advance_rate / 4; @@ -933,20 +935,21 @@ FORCE_INLINE void advance_isr() { current_adv_steps -= e_step_loops; else current_adv_steps = 0; - nextAdvanceISR = eISR_Rate; } else if (current_adv_steps < target_adv_steps) { // compression e_steps += e_step_loops; if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); current_adv_steps += e_step_loops; - nextAdvanceISR = eISR_Rate; } - else { + + if (current_adv_steps == target_adv_steps) { // advance steps completed nextAdvanceISR = ADV_NEVER; - LA_phase = -1; - e_step_loops = 1; + } + else { + // schedule another tick + nextAdvanceISR = eISR_Rate; } } From f1efce7e525a651f0fcd08005e310ff7f21e6c8b Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 23 Jun 2020 16:40:39 +0200 Subject: [PATCH 13/50] Handle LA termination with double/quad stepping properly Before PR #2591 LA was automatically capped during cruising or deceleration. However we now rely on reaching the current pressure state exactly to stop. When dual/quad stepping inside the eISR we might incur in oscillating behavior if we do not handle it correctly. This might be the cause behind #2757 This now changes e_step_loops to be a phase-local variable, so we now reset it each phase too (instead of per-segment). --- Firmware/stepper.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 0c7ecae5..13724cc9 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -348,10 +348,7 @@ FORCE_INLINE void stepper_next_block() #ifdef LIN_ADVANCE if (current_block->use_advance_lead) { - e_step_loops = current_block->advance_step_loops; target_adv_steps = current_block->max_adv_steps; - } else { - e_step_loops = 1; } e_steps = 0; nextAdvanceISR = ADV_NEVER; @@ -871,7 +868,10 @@ FORCE_INLINE void isr() { nextAdvanceISR = ADV_NEVER; } else { + // reset error and iterations per loop for this phase eISR_Err = current_block->advance_rate / 4; + e_step_loops = current_block->advance_step_loops; + if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) { // LA could reverse the direction of extrusion in this phase LA_phase = 0; @@ -929,15 +929,22 @@ FORCE_INLINE void isr() { FORCE_INLINE void advance_isr() { if (current_adv_steps > target_adv_steps) { // decompression + if (e_step_loops != 1) { + uint16_t d_steps = current_adv_steps - target_adv_steps; + if (d_steps < e_step_loops) + e_step_loops = d_steps; + } e_steps -= e_step_loops; if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); - if(current_adv_steps > e_step_loops) - current_adv_steps -= e_step_loops; - else - current_adv_steps = 0; + current_adv_steps -= e_step_loops; } else if (current_adv_steps < target_adv_steps) { // compression + if (e_step_loops != 1) { + uint16_t d_steps = target_adv_steps - current_adv_steps; + if (d_steps < e_step_loops) + e_step_loops = d_steps; + } e_steps += e_step_loops; if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); current_adv_steps += e_step_loops; From c08f37da9661feb946a6602dae49bab3a76071cb Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 24 Jun 2020 16:56:25 +0200 Subject: [PATCH 14/50] Use nominal rate for phase calculations The local interval calculated by advance_spread() might oscillate too much in narrow intervals. --- Firmware/stepper.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 13724cc9..80c5be29 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -883,11 +883,13 @@ FORCE_INLINE void isr() { advance_spread(main_Rate); if (LA_phase >= 0) { if (step_loops == e_step_loops) - LA_phase = (eISR_Rate > main_Rate); + LA_phase = (current_block->advance_rate > main_Rate); else { // avoid overflow through division. warning: we need to _guarantee_ step_loops // and e_step_loops are <= 4 due to fastdiv's limit - LA_phase = (fastdiv(eISR_Rate, step_loops) > fastdiv(main_Rate, e_step_loops)); + auto adv_rate_n = fastdiv(current_block->advance_rate, step_loops); + auto main_rate_n = fastdiv(main_Rate, e_step_loops); + LA_phase = (adv_rate_n > main_rate_n); } } } From fb5f09da6d365cb03db7abc01b18532740db3e6b Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 16 Jul 2020 17:47:48 +0200 Subject: [PATCH 15/50] Fix incorrect precedence for retraction phase The logic was inverted, causing the fastest isr to always retract instead of counter-balance the acceleration properly. --- Firmware/stepper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 80c5be29..c5a6b69c 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -883,13 +883,13 @@ FORCE_INLINE void isr() { advance_spread(main_Rate); if (LA_phase >= 0) { if (step_loops == e_step_loops) - LA_phase = (current_block->advance_rate > main_Rate); + LA_phase = (current_block->advance_rate < main_Rate); else { // avoid overflow through division. warning: we need to _guarantee_ step_loops // and e_step_loops are <= 4 due to fastdiv's limit auto adv_rate_n = fastdiv(current_block->advance_rate, step_loops); auto main_rate_n = fastdiv(main_Rate, e_step_loops); - LA_phase = (adv_rate_n > main_rate_n); + LA_phase = (adv_rate_n < main_rate_n); } } } From c54474f2db5cf9f04e0308c3c6694fff671a7d65 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 16 Jul 2020 13:26:15 +0200 Subject: [PATCH 16/50] Guard against planning/numerical errors in short segments Turns out for high-res curved models the numerical error and the SLOWDOWN handling in the planner can cause enough variance in the calculated pressure to trigger LA to continuosly, making matters worse. Clamp LA again, but only during extrusion, so that the runaway error is limited by the current segment length. --- Firmware/stepper.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index c5a6b69c..949ffd58 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -809,8 +809,11 @@ FORCE_INLINE void isr() { acceleration_time += timer; #ifdef LIN_ADVANCE if (current_block->use_advance_lead) { - if (step_events_completed.wide <= (unsigned long int)step_loops) + if (step_events_completed.wide <= (unsigned long int)step_loops) { la_state = ADV_INIT | ADV_ACC_VARY; + if (e_extruding && current_adv_steps > target_adv_steps) + target_adv_steps = current_adv_steps; + } } #endif } @@ -832,6 +835,8 @@ FORCE_INLINE void isr() { if (step_events_completed.wide <= (unsigned long int)current_block->decelerate_after + step_loops) { target_adv_steps = current_block->final_adv_steps; la_state = ADV_INIT | ADV_ACC_VARY; + if (e_extruding && current_adv_steps < target_adv_steps) + target_adv_steps = current_adv_steps; } } #endif @@ -849,6 +854,8 @@ FORCE_INLINE void isr() { // acceleration or deceleration can be skipped or joined with the previous block. // If LA was not previously active, re-check the pressure level la_state = ADV_INIT; + if (e_extruding) + target_adv_steps = current_adv_steps; } #endif } From 9b8f642b28eb5441a8342c73043d1570c0544bd2 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 19 Jul 2020 17:41:38 +0200 Subject: [PATCH 17/50] Account for flow adjustments in LA The e/D ratio should be calculated using the extrusion length. As such, purify the e_D_ratio from the current extruder multiplier in order to account correctly for flow adjustments. --- Firmware/Marlin.h | 2 +- Firmware/planner.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 5c03552b..697f2f72 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -299,7 +299,7 @@ extern float feedrate; extern int feedmultiply; extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in percent) for each extruder individually -extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner +extern float extruder_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner extern float current_position[NUM_AXIS] ; extern float destination[NUM_AXIS] ; extern float min_pos[3]; diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index bc991fdf..a994c74f 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -1098,7 +1098,7 @@ Having the real displacement of the head, we can calculate the total movement le if (block->use_advance_lead) { // all extrusion moves with LA require a compression which is proportional to the // extrusion_length to distance ratio (e/D) - e_D_ratio = (e - position_float[E_AXIS]) / + e_D_ratio = ((e - position_float[E_AXIS]) / extruder_multiplier[extruder]) / sqrt(sq(x - position_float[X_AXIS]) + sq(y - position_float[Y_AXIS]) + sq(z - position_float[Z_AXIS])); From a08ca19adeec3da70725e5b9555bf37bd3e276ba Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 20 Jul 2020 12:42:28 +0200 Subject: [PATCH 18/50] Make flow correction optional, disabled by default If you're using flow to correct for an incorrect source diameter, which is probably the main usage when using the LCD, then LA shouldn't be adjusted. It's still unclear what the effect of M221 in gcode should be regarding overall extrusion width. If M221 means "thicker lines", then LA should also be adjusted accordingly. This stems from the fact that the source diameter/length needs to be known in order to determine a compression factor which is independent of the extrusion width, but the FW only ever sees one value currently (the extrusion length) which combines both. This makes it impossible for the FW to adjust for one OR the other scenario, depending on what you expect for M221 to mean. --- Firmware/Configuration_adv.h | 1 + Firmware/planner.cpp | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Firmware/Configuration_adv.h b/Firmware/Configuration_adv.h index 5386c281..7deff3c1 100644 --- a/Firmware/Configuration_adv.h +++ b/Firmware/Configuration_adv.h @@ -288,6 +288,7 @@ #define LA_K_DEF 0 // Default K factor (Unit: mm compression per 1mm/s extruder speed) #define LA_K_MAX 10 // Maximum acceptable K factor (exclusive, see notes in planner.cpp:plan_buffer_line) #define LA_LA10_MIN LA_K_MAX // Lin. Advance 1.0 threshold value (inclusive) + //#define LA_FLOWADJ // Adjust LA along with flow/M221 for uniform width //#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility //#define LA_LIVE_K // Allow adjusting K in the Tune menu //#define LA_DEBUG // If enabled, this will generate debug information output over USB. diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index a994c74f..4789b033 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -1096,12 +1096,20 @@ Having the real displacement of the head, we can calculate the total movement le && delta_mm[E_AXIS] >= 0 && abs(delta_mm[Z_AXIS]) < 0.5; if (block->use_advance_lead) { +#ifdef LA_FLOWADJ + // M221/FLOW should change uniformly the extrusion thickness + float delta_e = (e - position_float[E_AXIS]) / extruder_multiplier[extruder]; +#else + // M221/FLOW only adjusts for an incorrect source diameter + float delta_e = (e - position_float[E_AXIS]); +#endif + float delta_D = sqrt(sq(x - position_float[X_AXIS]) + + sq(y - position_float[Y_AXIS]) + + sq(z - position_float[Z_AXIS])); + // all extrusion moves with LA require a compression which is proportional to the // extrusion_length to distance ratio (e/D) - e_D_ratio = ((e - position_float[E_AXIS]) / extruder_multiplier[extruder]) / - sqrt(sq(x - position_float[X_AXIS]) - + sq(y - position_float[Y_AXIS]) - + sq(z - position_float[Z_AXIS])); + e_D_ratio = delta_e / delta_D; // Check for unusual high e_D ratio to detect if a retract move was combined with the last // print move due to min. steps per segment. Never execute this with advance! This assumes From a95feb56d9cc9bccc185d989272c2c6e258fc553 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 20 Jul 2020 19:35:25 +0300 Subject: [PATCH 19/50] ALTFAN override --- Firmware/Marlin_main.cpp | 10 +++++++++- Firmware/eeprom.h | 4 +++- Firmware/temperature.cpp | 27 ++++++++++++++++++++++++--- Firmware/temperature.h | 2 ++ Firmware/ultralcd.cpp | 12 ++++++++++++ Firmware/ultralcd.h | 2 ++ 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 8dbc0d84..f3528ca9 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -8570,7 +8570,15 @@ Sigma_Exit: break; /*! - ### M999 - Restart after being stopped M999: Restart after being stopped by error + ### M666 - Enter experimental menu + Only used by Prusa + */ + case 666: + menu_submenu(lcd_experimental_menu); + break; + + /*! + ### M999 - Restart after being stopped M999: Restart after being stopped by error @todo Usually doesn't work. Should be fixed or removed. Most of the time, if `Stopped` it set, the print fails and is unrecoverable. */ case 999: diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 89d7e7f9..bfc81d82 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -561,8 +561,10 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float +#define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8 + //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_UVLO_LA_K +#define EEPROM_LAST_ITEM EEPROM_ALTFAN_OVERRIDE // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 6e9b6985..084ed272 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -153,6 +153,7 @@ uint8_t fanSpeedBckp = 255; uint8_t fanState = 0; #ifdef EXTRUDER_ALTFAN_DETECT bool extruderFanIsAltfan = false; //set to Noctua + uint8_t altfanOverride = 0; #endif //EXTRUDER_ALTFAN_DETECT #endif @@ -224,6 +225,14 @@ bool extruder_altfan_detect() setExtruderAutoFanState(3); SET_INPUT(TACH_0); + + altfanOverride = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE); + if (altfanOverride == EEPROM_EMPTY_VALUE) + { + altfanOverride = 0; + eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanOverride); + } + CRITICAL_SECTION_START; EICRB &= ~(1 << ISC61); EICRB |= (1 << ISC60); @@ -241,6 +250,18 @@ bool extruder_altfan_detect() setExtruderAutoFanState(1); return extruderFanIsAltfan; } + +void altfanOverride_toggle() +{ + altfanOverride = !altfanOverride; + eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanOverride); +} + +bool altfanOverride_get() +{ + return altfanOverride; +} + #endif //EXTRUDER_ALTFAN_DETECT // return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on') @@ -494,7 +515,7 @@ void setExtruderAutoFanState(uint8_t state) if (fanState & 0x01) { #ifdef EXTRUDER_ALTFAN_DETECT - if (extruderFanIsAltfan) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT; + if (extruderFanIsAltfan && !altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT; else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; #else //EXTRUDER_ALTFAN_DETECT newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; @@ -1356,7 +1377,7 @@ void temp_runaway_stop(bool isPreheat, bool isBed) SERIAL_ERROR_START; isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)"); #ifdef EXTRUDER_ALTFAN_DETECT - extruderFanIsAltfan = false; //full speed + altfanOverride = true; //full speed #endif //EXTRUDER_ALTFAN_DETECT setExtruderAutoFanState(3); SET_OUTPUT(FAN_PIN); @@ -1446,7 +1467,7 @@ void max_temp_error(uint8_t e) { WRITE(FAN_PIN, 1); WRITE(BEEPER, 1); #ifdef EXTRUDER_ALTFAN_DETECT - extruderFanIsAltfan = false; //full speed + altfanOverride = true; //full speed #endif //EXTRUDER_ALTFAN_DETECT setExtruderAutoFanState(3); // fanSpeed will consumed by the check_axes_activity() routine. diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 32ff6961..da88a53c 100755 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -273,6 +273,8 @@ void check_max_temp(); #ifdef EXTRUDER_ALTFAN_DETECT extern bool extruder_altfan_detect(); + extern void altfanOverride_toggle(); + extern bool altfanOverride_get(); #endif //EXTRUDER_ALTFAN_DETECT extern unsigned long extruder_autofan_last_check; diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 87266914..bb1d2c71 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -9160,3 +9160,15 @@ void lcd_crash_detect_disable() eeprom_update_byte((uint8_t*)EEPROM_CRASH_DET, 0x00); } #endif + +void lcd_experimental_menu() +{ + MENU_BEGIN(); + MENU_ITEM_BACK_P(_T(MSG_BACK)); + +#ifdef EXTRUDER_ALTFAN_DETECT + MENU_ITEM_TOGGLE_P(_N("ALTFAN det."), altfanOverride_get()?_T(MSG_OFF):_T(MSG_ON), altfanOverride_toggle); +#endif //EXTRUDER_ALTFAN_DETECT + + MENU_END(); +} diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 844c7c7d..971c07b6 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -257,4 +257,6 @@ enum class WizState : uint8_t void lcd_wizard(WizState state); +extern void lcd_experimental_menu(); + #endif //ULTRALCD_H From e2856ba4f579c51c6aa58e8614f71a498e021a6c Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 21 Jul 2020 12:52:04 +0300 Subject: [PATCH 20/50] Make the serial number available to the user --- Firmware/Marlin_main.cpp | 45 +++++++++++++++------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 8dbc0d84..49470ae1 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3286,37 +3286,26 @@ void gcode_M701() */ static void gcode_PRUSA_SN() { - if (farm_mode) { - selectedSerialPort = 0; - putchar(';'); - putchar('S'); - int numbersRead = 0; - ShortTimer timeout; - timeout.start(); + uint8_t selectedSerialPort_bak = selectedSerialPort; + selectedSerialPort = 0; + putchar(';'); + putchar('S'); + int numbersRead = 0; + ShortTimer timeout; + timeout.start(); - while (numbersRead < 19) { - while (MSerial.available() > 0) { - uint8_t serial_char = MSerial.read(); - selectedSerialPort = 1; - putchar(serial_char); - numbersRead++; - selectedSerialPort = 0; - } - if (timeout.expired(100u)) break; + while (numbersRead < 19) { + while (MSerial.available() > 0) { + uint8_t serial_char = MSerial.read(); + selectedSerialPort = selectedSerialPort_bak; + putchar(serial_char); + numbersRead++; + selectedSerialPort = 0; } - selectedSerialPort = 1; - putchar('\n'); -#if 0 - for (int b = 0; b < 3; b++) { - _tone(BEEPER, 110); - _delay(50); - _noTone(BEEPER); - _delay(50); - } -#endif - } else { - puts_P(_N("Not in farm mode.")); + if (timeout.expired(100u)) break; } + selectedSerialPort = selectedSerialPort_bak; + putchar('\n'); } //! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors //! at the TACH_1 pin, which causes bad detection of print fan speed. From ec6a20971e495ea4a97049434ac3e247c7391501 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Wed, 29 Jul 2020 11:23:24 +0300 Subject: [PATCH 21/50] Add experimental menu to HW_setup --- Firmware/Marlin_main.cpp | 8 -------- Firmware/eeprom.h | 5 ++++- Firmware/ultralcd.cpp | 32 ++++++++++++++++++++++++++++++++ Firmware/ultralcd.h | 1 + 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index f3528ca9..2a261db2 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -8569,14 +8569,6 @@ Sigma_Exit: } break; - /*! - ### M666 - Enter experimental menu - Only used by Prusa - */ - case 666: - menu_submenu(lcd_experimental_menu); - break; - /*! ### M999 - Restart after being stopped M999: Restart after being stopped by error @todo Usually doesn't work. Should be fixed or removed. Most of the time, if `Stopped` it set, the print fails and is unrecoverable. diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index bfc81d82..ee7fa39e 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -359,6 +359,8 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | ^ | ^ | ^ | 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 +| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | 0-1 | 00h | ALTFAN override | LCD menu | D3 Ax0d2b C1 +| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | 0-1 | 00h | Experimental menu visibility | LCD menu | D3 Ax0d2a C1 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code @@ -562,9 +564,10 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float #define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8 +#define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8 //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_ALTFAN_OVERRIDE +#define EEPROM_LAST_ITEM EEPROM_EXPERIMENTAL_VISIBILITY // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index bb1d2c71..24e33168 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2113,6 +2113,7 @@ static void lcd_support_menu() bool is_flash_air; // 1byte uint8_t ip[4]; // 4bytes char ip_str[3*4+3+1]; // 16bytes + uint8_t experimental_menu_visibility; } _menu_data_t; 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]); @@ -2126,6 +2127,14 @@ static void lcd_support_menu() sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"), _md->ip[0], _md->ip[1], _md->ip[2], _md->ip[3]); + + _md->experimental_menu_visibility = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY); + if (_md->experimental_menu_visibility == EEPROM_EMPTY_VALUE) + { + _md->experimental_menu_visibility = 0; + eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, _md->experimental_menu_visibility); + } + } else if (_md->is_flash_air && _md->ip[0] == 0 && _md->ip[1] == 0 && _md->ip[2] == 0 && _md->ip[3] == 0 && @@ -2210,6 +2219,12 @@ static void lcd_support_menu() MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN + if (_md->experimental_menu_visibility) + { + MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu); + } + + #ifdef DEBUG_BUILD MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1 #endif /* DEBUG_BUILD */ @@ -8997,6 +9012,13 @@ void menu_lcd_longpress_func(void) lcd_quick_feedback(); return; } + if (menu_menu == lcd_hw_setup_menu) + { + // only toggle the experimental menu visibility flag + lcd_quick_feedback(); + lcd_experimental_toggle(); + return; + } // explicitely listed menus which are allowed to rise the move-z or live-adj-z functions // The lists are not the same for both functions, so first decide which function is to be performed @@ -9161,6 +9183,16 @@ void lcd_crash_detect_disable() } #endif +void lcd_experimental_toggle() +{ + uint8_t oldVal = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY); + if (oldVal == EEPROM_EMPTY_VALUE) + oldVal = 0; + else + oldVal = !oldVal; + eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, oldVal); +} + void lcd_experimental_menu() { MENU_BEGIN(); diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 971c07b6..95a3cec1 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -257,6 +257,7 @@ enum class WizState : uint8_t void lcd_wizard(WizState state); +extern void lcd_experimental_toggle(); extern void lcd_experimental_menu(); #endif //ULTRALCD_H From 773c6997efcbb947c5eeca5c3daf387c83ef4743 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Wed, 29 Jul 2020 17:36:03 +0300 Subject: [PATCH 22/50] Add comments --- Firmware/ultralcd.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 24e33168..c2a3a890 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2096,6 +2096,9 @@ static void lcd_preheat_menu() //! @code{.unparsed} //! | Voltages | MSG_MENU_VOLTAGES //! @endcode +//! +//! +//! | Experimental | c=18 r=1 //! //! //! If DEBUG_BUILD is defined @@ -2108,12 +2111,12 @@ static void lcd_preheat_menu() static void lcd_support_menu() { typedef struct - { // 22bytes total + { // 23bytes total int8_t status; // 1byte bool is_flash_air; // 1byte uint8_t ip[4]; // 4bytes char ip_str[3*4+3+1]; // 16bytes - uint8_t experimental_menu_visibility; + uint8_t experimental_menu_visibility; //1byte } _menu_data_t; 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]); From feafc5e5abdc1acee8683411c83c4595885332f5 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 27 Jul 2020 19:12:56 +0200 Subject: [PATCH 23/50] Alternative schedule for LA ticks Remove most of the original complexity from advance_spread. Instead of accumulating time to be scheduled, plan ahead of time each eISR tick using the next main interval + an accumulator (eISR_Err), which keeps everything much simpler. The distribution of the advance ticks is now using the real LA frequency, which leaves a bit more time between the last LA tick and the main stepper isr. We take advantage of the accumulator to force a LA tick right after the first main tick, which removes a +/- 1 scheduling error at higher step rates. When decompressing, we force 2 steps instead, so that the direction reversal happens immediately (first tick zeros esteps, second inverts the sign), removing another +/- 1 error at higher step rates. --- Firmware/stepper.cpp | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 949ffd58..8b21ee67 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -125,7 +125,7 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; static uint16_t main_Rate; static uint16_t eISR_Rate; - static uint16_t eISR_Err; + static uint32_t eISR_Err; static uint16_t current_adv_steps; static uint16_t target_adv_steps; @@ -733,38 +733,30 @@ FORCE_INLINE uint16_t fastdiv(uint16_t q, uint8_t d) FORCE_INLINE void advance_spread(uint16_t timer) { - if(eISR_Err > timer) + eISR_Err += timer; + + uint8_t ticks = 0; + while(eISR_Err >= current_block->advance_rate) + { + ++ticks; + eISR_Err -= current_block->advance_rate; + } + if(!ticks) { - // advance-step skipped - eISR_Err -= timer; eISR_Rate = timer; nextAdvanceISR = timer; return; } - // at least one step - uint8_t ticks = 1; - uint32_t block = current_block->advance_rate; - uint16_t max_t = timer - eISR_Err; - while (block < max_t) - { - ++ticks; - block += current_block->advance_rate; - } - if (block > timer) - eISR_Err += block - timer; - else - eISR_Err -= timer - block; - - if (ticks <= 4) - eISR_Rate = fastdiv(timer, ticks); + if (ticks <= 3) + eISR_Rate = fastdiv(timer, ticks + 1); else { // >4 ticks are still possible on slow moves - eISR_Rate = timer / ticks; + eISR_Rate = timer / (ticks + 1); } - nextAdvanceISR = eISR_Rate / 2; + nextAdvanceISR = eISR_Rate; } #endif @@ -876,11 +868,12 @@ FORCE_INLINE void isr() { } else { // reset error and iterations per loop for this phase - eISR_Err = current_block->advance_rate / 4; + eISR_Err = current_block->advance_rate; e_step_loops = current_block->advance_step_loops; if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) { // LA could reverse the direction of extrusion in this phase + eISR_Err += current_block->advance_rate; LA_phase = 0; } } From 87bc5a78b6b787bc6415a49495aee40fa10f7175 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 1 Jun 2020 17:03:48 +0200 Subject: [PATCH 24/50] Remove bogus comment (BED_MINTEMP *is* implemented) --- Firmware/temperature.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 6e9b6985..a7b9a3cd 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1165,7 +1165,6 @@ void tp_init() #endif //MAXTEMP 2 #ifdef BED_MINTEMP - /* No bed MINTEMP error implemented?!? */ while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) { #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP bed_minttemp_raw += OVERSAMPLENR; @@ -1173,7 +1172,6 @@ void tp_init() bed_minttemp_raw -= OVERSAMPLENR; #endif } - #endif //BED_MINTEMP #ifdef BED_MAXTEMP while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) { From 942fca5b660bada0dfdea9d7b2945c8a0ce6ebf0 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 7 Jun 2020 23:15:06 +0200 Subject: [PATCH 25/50] Remove useless assignment target_temperature_bed is already reset by disable_heaters() in Stop() --- Firmware/temperature.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index a7b9a3cd..9ac97aec 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2002,7 +2002,6 @@ void check_max_temp() #else if (current_temperature_bed_raw >= bed_maxttemp_raw) { #endif - target_temperature_bed = 0; bed_max_temp_error(); } #endif From 65f25b0d7e4260d06073af2aeea3f39ba6cb6990 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 8 Jun 2020 02:16:00 +0200 Subject: [PATCH 26/50] Remove redundant disable_heater() calls in max/min_temp handling In max/min_temp handlers remove the redundant disable_heater() call. Handlers already need to call Stop(), which will disable all heaters as the first step. Fix comments in order to mention that all heaters get disabled. Use "MAX/MINTEMP BED" correctly in both the LCD and serial. --- Firmware/temperature.cpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 9ac97aec..c9e63def 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1426,19 +1426,16 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_ uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; void max_temp_error(uint8_t e) { - disable_heater(); if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); + SERIAL_ERRORLNPGM(": Heaters switched off. MAXTEMP triggered !"); LCD_ALERTMESSAGEPGM("Err: MAXTEMP"); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); - - - #endif + SET_OUTPUT(FAN_PIN); SET_OUTPUT(BEEPER); WRITE(FAN_PIN, 1); @@ -1457,12 +1454,11 @@ void min_temp_error(uint8_t e) { return; #endif //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; - disable_heater(); static const char err[] PROGMEM = "Err: MINTEMP"; if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); + SERIAL_ERRORLNPGM(": Heaters switched off. MINTEMP triggered !"); lcd_setalertstatuspgm(err); last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; } else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) @@ -1482,32 +1478,24 @@ void min_temp_error(uint8_t e) { } void bed_max_temp_error(void) { -#if HEATER_BED_PIN > -1 - //WRITE(HEATER_BED_PIN, 0); -#endif if(IsStopped() == false) { SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !"); + SERIAL_ERRORLNPGM("Heaters switched off. MAXTEMP BED triggered !"); LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED"); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); #endif - } void bed_min_temp_error(void) { #ifdef DEBUG_DISABLE_MINTEMP return; -#endif -//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; -#if HEATER_BED_PIN > -1 - //WRITE(HEATER_BED_PIN, 0); #endif static const char err[] PROGMEM = "Err: MINTEMP BED"; if(IsStopped() == false) { SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MINTEMP triggered !"); + SERIAL_ERRORLNPGM("Heaters switched off. MINTEMP BED triggered !"); lcd_setalertstatuspgm(err); last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; } else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) From 3336db7954a7204dbf5ae859515dcc11e9dcba18 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 8 Jun 2020 02:56:11 +0200 Subject: [PATCH 27/50] Add some important notes about thermistor ADC handling --- Firmware/temperature.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index c9e63def..7f293f2e 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -639,6 +639,7 @@ void manage_heater() return; // more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms) + // ADC values need to be converted before checking: converted values are later used in MINTEMP updateTemperaturesFromRawValues(); check_max_temp(); From a60ed81a3507814c60354534e4c4f4f9230d2aa6 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 8 Jun 2020 03:14:49 +0200 Subject: [PATCH 28/50] Implement MIN/MAX AMBIENT safety checks Take advantage of the NTC thermistor found on the Einsy as an additional safety measure, following the steps of the other MIN/MAXTEMP errors. Introduce two configurable params AMBIENT_MINTEMP and AMBIENT_MAXTEMP in the variant defines and set them for the MK3/MK3S to -30/+100 respectively. AMBIENT_MINTEMP is primarily intended to catch a defective board thermistor (to ensure MAXTEMP would be properly triggered) and thus the trigger temperature is set just above the sensing limit and well below the operating range. AMBIENT_MAXTEMP is set at 100C, which is instead 20C above the maximum recommended operating temperature of the Einsy. The NTC thermistor is located just above the main power connector on the bottom of the board, and could also help in detecting a faulty connection which can result in rapid overheating of the contacts. As for MAXTEMP, we cut power to the heaters, print fan and motors to reduce power draw. Resume is not possible except by resetting the printer, since the user is highly advised to inspect the board for problems before attempting to continue. --- Firmware/Configuration_adv.h | 4 + Firmware/temperature.cpp | 87 ++++++++++++++++++- Firmware/thermistortables.h | 2 + .../variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 2 + .../variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 2 + 5 files changed, 95 insertions(+), 2 deletions(-) diff --git a/Firmware/Configuration_adv.h b/Firmware/Configuration_adv.h index 5386c281..f206c43c 100644 --- a/Firmware/Configuration_adv.h +++ b/Firmware/Configuration_adv.h @@ -436,6 +436,10 @@ const unsigned int dropsegments=5; //everything with less than this number of st #undef BED_MINTEMP #undef BED_MAXTEMP #endif +#if TEMP_SENSOR_AMBIENT == 0 + #undef AMBIENT_MINTEMP + #undef AMBIENT_MAXTEMP +#endif #endif //__CONFIGURATION_ADV_H diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 7f293f2e..75d52817 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -180,6 +180,12 @@ static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP; #ifdef BED_MAXTEMP static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP; #endif +#ifdef AMBIENT_MINTEMP +static int ambient_minttemp_raw = AMBIENT_RAW_LO_TEMP; +#endif +#ifdef AMBIENT_MAXTEMP +static int ambient_maxttemp_raw = AMBIENT_RAW_HI_TEMP; +#endif static void *heater_ttbl_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( (void *)HEATER_0_TEMPTABLE, (void *)HEATER_1_TEMPTABLE, (void *)HEATER_2_TEMPTABLE ); static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN ); @@ -1183,6 +1189,25 @@ void tp_init() #endif } #endif //BED_MAXTEMP + +#ifdef AMBIENT_MINTEMP + while(analog2tempAmbient(ambient_minttemp_raw) < AMBIENT_MINTEMP) { +#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP + ambient_minttemp_raw += OVERSAMPLENR; +#else + ambient_minttemp_raw -= OVERSAMPLENR; +#endif + } +#endif //AMBIENT_MINTEMP +#ifdef AMBIENT_MAXTEMP + while(analog2tempAmbient(ambient_maxttemp_raw) > AMBIENT_MAXTEMP) { +#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP + ambient_maxttemp_raw -= OVERSAMPLENR; +#else + ambient_maxttemp_raw += OVERSAMPLENR; +#endif + } +#endif //AMBIENT_MAXTEMP } #if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0) @@ -1509,6 +1534,35 @@ void bed_min_temp_error(void) { #endif } + +#ifdef AMBIENT_THERMISTOR +void ambient_max_temp_error(void) { + if(IsStopped() == false) { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Heaters switched off. MAXTEMP AMBIENT triggered !"); + LCD_ALERTMESSAGEPGM("Err: MAXTEMP AMBIENT"); + } +#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE + Stop(); +#endif +} + +void ambient_min_temp_error(void) { +#ifdef DEBUG_DISABLE_MINTEMP + return; +#endif + if(IsStopped() == false) { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Heaters switched off. MINTEMP AMBIENT triggered !"); + LCD_ALERTMESSAGEPGM("Err: MINTEMP AMBIENT"); + } +#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE + Stop(); +#endif +} +#endif + + #ifdef HEATER_0_USES_MAX6675 #define MAX6675_HEAT_INTERVAL 250 long max6675_previous_millis = MAX6675_HEAT_INTERVAL; @@ -1994,7 +2048,16 @@ void check_max_temp() bed_max_temp_error(); } #endif - +//ambient +#if defined(AMBIENT_MAXTEMP) && (TEMP_SENSOR_AMBIENT != 0) +#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP + if (current_temperature_raw_ambient <= ambient_maxttemp_raw) { +#else + if (current_temperature_raw_ambient >= ambient_maxttemp_raw) { +#endif + ambient_max_temp_error(); + } +#endif } //! number of repeating the same state with consecutive step() calls //! used to slow down text switching @@ -2089,12 +2152,32 @@ void check_min_temp_bed() } } +#ifdef AMBIENT_MINTEMP +void check_min_temp_ambient() +{ +#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP + if (current_temperature_raw_ambient >= ambient_minttemp_raw) { +#else + if (current_temperature_raw_ambient <= ambient_minttemp_raw) { +#endif + ambient_min_temp_error(); + } +} +#endif + void check_min_temp() { static bool bCheckingOnHeater=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp) static bool bCheckingOnBed=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp) #ifdef AMBIENT_THERMISTOR -if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type, so operator is ">" ;-) +#ifdef AMBIENT_MINTEMP +check_min_temp_ambient(); +#endif +#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP +if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type +#else +if(current_temperature_raw_ambient=<(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) +#endif { // ambient temperature is low #endif //AMBIENT_THERMISTOR // *** 'common' part of code for MK2.5 & MK3 diff --git a/Firmware/thermistortables.h b/Firmware/thermistortables.h index dc934ccf..721c6b35 100644 --- a/Firmware/thermistortables.h +++ b/Firmware/thermistortables.h @@ -1213,6 +1213,8 @@ const short temptable_1047[][2] PROGMEM = { #endif #if (THERMISTORAMBIENT == 2000) //100k thermistor NTCG104LH104JT1 +# define AMBIENT_RAW_HI_TEMP 0 +# define AMBIENT_RAW_LO_TEMP 16383 const short temptable_2000[][2] PROGMEM = { // Source: https://product.tdk.com/info/en/catalog/datasheets/503021/tpd_ntc-thermistor_ntcg_en.pdf // Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index b135d8d1..04b4c526 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -296,6 +296,7 @@ #endif #define DETECT_SUPERPINDA #define PINDA_MINTEMP BED_MINTEMP +#define AMBIENT_MINTEMP -30 // Maxtemps #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) @@ -306,6 +307,7 @@ #define HEATER_1_MAXTEMP 305 #define HEATER_2_MAXTEMP 305 #define BED_MAXTEMP 125 +#define AMBIENT_MAXTEMP 100 #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) // Define PID constants for extruder with PT100 diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index e618c54e..c869ec51 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -298,6 +298,7 @@ #endif #define DETECT_SUPERPINDA #define PINDA_MINTEMP BED_MINTEMP +#define AMBIENT_MINTEMP -30 // Maxtemps #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) @@ -308,6 +309,7 @@ #define HEATER_1_MAXTEMP 305 #define HEATER_2_MAXTEMP 305 #define BED_MAXTEMP 125 +#define AMBIENT_MAXTEMP 100 #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) // Define PID constants for extruder with PT100 From e1c79c342d75191ea759bfbecba00d9a907df7e0 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 30 Jul 2020 17:14:13 +0200 Subject: [PATCH 29/50] Re-introduce redundant disable_heaters() calls Partially revert 285b505c73a54e9af01816e3a614de73ad181851 so that we ensure heaters are disabled ASAP in case of potential bugs in the max_*_error functions. --- Firmware/temperature.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 75d52817..f9fa48ff 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1452,6 +1452,7 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_ uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; void max_temp_error(uint8_t e) { + disable_heater(); if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLN((int)e); @@ -1479,6 +1480,7 @@ void min_temp_error(uint8_t e) { #ifdef DEBUG_DISABLE_MINTEMP return; #endif + disable_heater(); //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; static const char err[] PROGMEM = "Err: MINTEMP"; if(IsStopped() == false) { @@ -1504,6 +1506,7 @@ void min_temp_error(uint8_t e) { } void bed_max_temp_error(void) { + disable_heater(); if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Heaters switched off. MAXTEMP BED triggered !"); @@ -1518,7 +1521,8 @@ void bed_min_temp_error(void) { #ifdef DEBUG_DISABLE_MINTEMP return; #endif - static const char err[] PROGMEM = "Err: MINTEMP BED"; + disable_heater(); + static const char err[] PROGMEM = "MINTEMP BED"; if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Heaters switched off. MINTEMP BED triggered !"); @@ -1537,6 +1541,7 @@ void bed_min_temp_error(void) { #ifdef AMBIENT_THERMISTOR void ambient_max_temp_error(void) { + disable_heater(); if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Heaters switched off. MAXTEMP AMBIENT triggered !"); @@ -1551,6 +1556,7 @@ void ambient_min_temp_error(void) { #ifdef DEBUG_DISABLE_MINTEMP return; #endif + disable_heater(); if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Heaters switched off. MINTEMP AMBIENT triggered !"); From a8ce9358e55f509f7efde3905261fa702d0cbc5a Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 31 Jul 2020 20:19:51 +0200 Subject: [PATCH 30/50] Avoid redundant temperature error strings Factor-out MIN/MAXTEMP [BED/AMB] out of the error message, which is now built at runtime instead. Introduce two missing ultralcd functions lcd_setalertstatus and lcd_updatestatus to handle regular strings. 246272 -> 246084 = 188 bytes saved --- Firmware/temperature.cpp | 64 +++++++++++++++++++++++++--------------- Firmware/ultralcd.cpp | 22 ++++++++++++-- Firmware/ultralcd.h | 2 ++ 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index f9fa48ff..657b23fb 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1451,13 +1451,42 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_ //! to prevent flicker and improve speed uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; + +//! update the current temperature error message +//! @param type short error abbreviation (PROGMEM) +//! @param func optional lcd update function (lcd_setalertstatus when first setting the error) +void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) = lcd_updatestatus) +{ + char msg[LCD_WIDTH]; + strcpy_P(msg, PSTR("Err: ")); + strcat_P(msg, type); + (*func)(msg); +} + +//! signal a temperature error on both the lcd and serial +//! @param type short error abbreviation (PROGMEM) +//! @param e optional extruder index for hotend errors +void temp_error_messagepgm(const char* PROGMEM type, uint8_t e = EXTRUDERS) +{ + temp_update_messagepgm(type, lcd_setalertstatus); + + SERIAL_ERROR_START; + + if(e != EXTRUDERS) { + SERIAL_ERROR((int)e); + SERIAL_ERRORPGM(": "); + } + + SERIAL_ERRORPGM("Heaters switched off. "); + SERIAL_ERRORRPGM(type); + SERIAL_ERRORLNPGM(" triggered!"); +} + + void max_temp_error(uint8_t e) { disable_heater(); if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Heaters switched off. MAXTEMP triggered !"); - LCD_ALERTMESSAGEPGM("Err: MAXTEMP"); + temp_error_messagepgm(PSTR("MAXTEMP"), e); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); @@ -1482,16 +1511,13 @@ void min_temp_error(uint8_t e) { #endif disable_heater(); //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; - static const char err[] PROGMEM = "Err: MINTEMP"; + static const char err[] PROGMEM = "MINTEMP"; if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Heaters switched off. MINTEMP triggered !"); - lcd_setalertstatuspgm(err); + temp_error_messagepgm(err, e); last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; } else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) // we are already stopped due to some error, only update the status message without flickering - lcd_updatestatuspgm(err); + temp_update_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE @@ -1508,9 +1534,7 @@ void min_temp_error(uint8_t e) { void bed_max_temp_error(void) { disable_heater(); if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Heaters switched off. MAXTEMP BED triggered !"); - LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED"); + temp_error_messagepgm(PSTR("MAXTEMP BED")); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); @@ -1524,13 +1548,11 @@ void bed_min_temp_error(void) { disable_heater(); static const char err[] PROGMEM = "MINTEMP BED"; if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Heaters switched off. MINTEMP BED triggered !"); - lcd_setalertstatuspgm(err); + temp_error_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; } else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) // we are already stopped due to some error, only update the status message without flickering - lcd_updatestatuspgm(err); + temp_update_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE @@ -1543,9 +1565,7 @@ void bed_min_temp_error(void) { void ambient_max_temp_error(void) { disable_heater(); if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Heaters switched off. MAXTEMP AMBIENT triggered !"); - LCD_ALERTMESSAGEPGM("Err: MAXTEMP AMBIENT"); + temp_error_messagepgm(PSTR("MAXTEMP AMB")); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); @@ -1558,9 +1578,7 @@ void ambient_min_temp_error(void) { #endif disable_heater(); if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Heaters switched off. MINTEMP AMBIENT triggered !"); - LCD_ALERTMESSAGEPGM("Err: MINTEMP AMBIENT"); + temp_error_messagepgm(PSTR("MINTEMP AMB")); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 87266914..a08f8a36 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -8951,13 +8951,14 @@ void lcd_finishstatus() { lcd_draw_update = 2; } + void lcd_setstatus(const char* message) { if (lcd_status_message_level > 0) return; - strncpy(lcd_status_message, message, LCD_WIDTH); - lcd_finishstatus(); + lcd_updatestatus(message); } + void lcd_updatestatuspgm(const char *message){ strncpy_P(lcd_status_message, message, LCD_WIDTH); lcd_status_message[LCD_WIDTH] = 0; @@ -8972,12 +8973,29 @@ void lcd_setstatuspgm(const char* message) return; lcd_updatestatuspgm(message); } + +void lcd_updatestatus(const char *message){ + strncpy(lcd_status_message, message, LCD_WIDTH); + lcd_status_message[LCD_WIDTH] = 0; + lcd_finishstatus(); + // hack lcd_draw_update to 1, i.e. without clear + lcd_draw_update = 1; +} + void lcd_setalertstatuspgm(const char* message) { lcd_setstatuspgm(message); lcd_status_message_level = 1; lcd_return_to_status(); } + +void lcd_setalertstatus(const char* message) +{ + lcd_setstatus(message); + lcd_status_message_level = 1; + lcd_return_to_status(); +} + void lcd_reset_alert_level() { lcd_status_message_level = 0; diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 844c7c7d..a5f07673 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -23,9 +23,11 @@ void lcd_setstatuspgm(const char* message); //! - always returns the display to the main status screen //! - always makes lcd_reset (which is slow and causes flicker) //! - does not update the message if there is already one (i.e. lcd_status_message_level > 0) +void lcd_setalertstatus(const char* message); void lcd_setalertstatuspgm(const char* message); //! only update the alert message on the main status screen //! has no sideeffects, may be called multiple times +void lcd_updatestatus(const char *message); void lcd_updatestatuspgm(const char *message); void lcd_reset_alert_level(); From ae0d8082de01fe38dee9ebf3b7343c1e4a1a93a2 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Mon, 3 Aug 2020 09:00:36 +0200 Subject: [PATCH 31/50] Update README.md Fix small typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb1c7968..7aa50c4a 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ Example: `ninja` -## Runing +## Running `./tests` # 4. Documentation From 12be141188c3511e13978d366164c3afcb0c04b8 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 6 Jun 2020 19:32:48 +0300 Subject: [PATCH 32/50] Fix high speed deceleration --- Firmware/planner.h | 9 ++++----- Firmware/stepper.cpp | 13 ++++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Firmware/planner.h b/Firmware/planner.h index 2096111e..5978793b 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -77,8 +77,8 @@ typedef struct { unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) unsigned char active_extruder; // Selects the active extruder // accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller. - long accelerate_until; // The index of the step event on which to stop acceleration - long decelerate_after; // The index of the step event on which to start decelerating + uint32_t accelerate_until; // The index of the step event on which to stop acceleration + uint32_t decelerate_after; // The index of the step event on which to start decelerating // Fields used by the motion planner to manage acceleration // float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis @@ -100,13 +100,12 @@ typedef struct { // Settings for the trapezoid generator (runs inside an interrupt handler). // Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts. - //FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway! unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec unsigned long initial_rate; // The jerk-adjusted step rate at start of block unsigned long final_rate; // The minimal rate at exit unsigned long acceleration_st; // acceleration steps/sec^2 - //FIXME does it have to be unsigned long? Probably uint8_t would be just fine. - unsigned long fan_speed; + //FIXME does it have to be int? Probably uint8_t would be just fine. Need to change in other places as well + int fan_speed; volatile char busy; diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index de250ec9..5f72b5bd 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -71,8 +71,7 @@ static dda_isteps_t counter_z, counter_e; volatile dda_usteps_t step_events_completed; // The number of step events executed in the current block -static int32_t acceleration_time, deceleration_time; -//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; +static uint32_t acceleration_time, deceleration_time; static uint16_t acc_step_rate; // needed for deccelaration start point static uint8_t step_loops; static uint16_t OCR1A_nominal; @@ -799,7 +798,7 @@ FORCE_INLINE void isr() { // 25.12us for acceleration / deceleration. { //WRITE_NC(LOGIC_ANALYZER_CH1, true); - if (step_events_completed.wide <= (unsigned long int)current_block->accelerate_until) { + if (step_events_completed.wide <= current_block->accelerate_until) { // v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); acc_step_rate += uint16_t(current_block->initial_rate); @@ -817,12 +816,12 @@ FORCE_INLINE void isr() { } #endif } - else if (step_events_completed.wide > (unsigned long int)current_block->decelerate_after) { + else if (step_events_completed.wide > current_block->decelerate_after) { uint16_t step_rate; MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - if ((step_rate & 0x8000) || step_rate < uint16_t(current_block->final_rate)) { - // Result is negative or too small. + if (step_rate < uint16_t(current_block->final_rate)) { + // Result is too small. step_rate = uint16_t(current_block->final_rate); } // Step_rate to timer interval. @@ -832,7 +831,7 @@ FORCE_INLINE void isr() { #ifdef LIN_ADVANCE if (current_block->use_advance_lead) { - if (step_events_completed.wide <= (unsigned long int)current_block->decelerate_after + step_loops) { + if (step_events_completed.wide <= current_block->decelerate_after + step_loops) { target_adv_steps = current_block->final_adv_steps; la_state = ADV_INIT | ADV_ACC_VARY; } From 4654283f542f661a872c9d6d4fd6612a4db0e9f8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 3 Aug 2020 18:16:20 +0200 Subject: [PATCH 33/50] Restore indentation --- Firmware/planner.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/planner.h b/Firmware/planner.h index 5978793b..425ed9b5 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -77,8 +77,8 @@ typedef struct { unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) unsigned char active_extruder; // Selects the active extruder // accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller. - uint32_t accelerate_until; // The index of the step event on which to stop acceleration - uint32_t decelerate_after; // The index of the step event on which to start decelerating + uint32_t accelerate_until; // The index of the step event on which to stop acceleration + uint32_t decelerate_after; // The index of the step event on which to start decelerating // Fields used by the motion planner to manage acceleration // float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis From 8108d50b59fc13c62b72cba065193928c5b67f33 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 3 Aug 2020 18:42:40 +0200 Subject: [PATCH 34/50] Reintroduce/fix check for step_rate underflow during deceleration Check for negative results and results under the final_rate --- Firmware/stepper.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 5f72b5bd..848cd3c6 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -819,11 +819,18 @@ FORCE_INLINE void isr() { else if (step_events_completed.wide > current_block->decelerate_after) { uint16_t step_rate; MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - if (step_rate < uint16_t(current_block->final_rate)) { - // Result is too small. - step_rate = uint16_t(current_block->final_rate); + + if (step_rate > acc_step_rate) { // Check step_rate stays positive + step_rate = uint16_t(current_block->final_rate); } + else { + step_rate = acc_step_rate - step_rate; // Decelerate from acceleration end point. + + // lower limit + if (step_rate < current_block->final_rate) + step_rate = uint16_t(current_block->final_rate); + } + // Step_rate to timer interval. uint16_t timer = calc_timer(step_rate, step_loops); _NEXT_ISR(timer); From aebaca5cdc35c129c9e41acb3a8f08ef483ba3f8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 3 Aug 2020 18:48:53 +0200 Subject: [PATCH 35/50] Correct comments regarding acceleration ramp Backport fixes from upstream Marlin --- Firmware/stepper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 848cd3c6..ef57ec0d 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -233,7 +233,7 @@ void invert_z_endstop(bool endstop_invert) // The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates // first block->accelerate_until step_events_completed, then keeps going at constant speed until // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. -// The slope of acceleration is calculated with the leib ramp alghorithm. +// The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far. // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. From 30a806608fca111cab82f7ac07c2804abf8f8225 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 3 Aug 2020 19:01:38 +0200 Subject: [PATCH 36/50] Also convert acceleration_rate to uint32_t acceleration_rate is also unsigned --- Firmware/planner.cpp | 2 +- Firmware/planner.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index c0f465c2..9ff291a0 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -1132,7 +1132,7 @@ Having the real displacement of the head, we can calculate the total movement le block->acceleration_st = (block->acceleration_st + (bresenham_oversample >> 1)) / bresenham_oversample; #endif - block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0))); + block->acceleration_rate = ((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0))); #ifdef LIN_ADVANCE if (block->use_advance_lead) { diff --git a/Firmware/planner.h b/Firmware/planner.h index 425ed9b5..34899cac 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -73,7 +73,7 @@ typedef struct { // steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line(). dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis dda_usteps_t step_event_count; // The number of step events required to complete this block - long acceleration_rate; // The acceleration rate used for acceleration calculation + uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) unsigned char active_extruder; // Selects the active extruder // accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller. From b8e8f182ca6ffba4b565e6b600df212381c808c5 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 3 Aug 2020 19:03:13 +0200 Subject: [PATCH 37/50] Add reference C implementations for MultiU16X8toH16/MultiU24X24toH16 Higher step counts might still overflow the ASM MultiU24X24toH16. https://github.com/MarlinFirmware/Marlin/commit/e4595fa24a2051e95df8a4ed044d2c94cca18e63 --- Firmware/speed_lookuptable.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Firmware/speed_lookuptable.h b/Firmware/speed_lookuptable.h index 2748dd71..21c6c767 100644 --- a/Firmware/speed_lookuptable.h +++ b/Firmware/speed_lookuptable.h @@ -80,15 +80,21 @@ asm volatile ( \ #else //_NO_ASM -// NOTE: currently not implemented -void MultiU16X8toH16(unsigned short& intRes, unsigned char& charIn1, unsigned short& intIn2); -void MultiU24X24toH16(uint16_t& intRes, int32_t& longIn1, long& longIn2); +static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2) +{ + intRes = ((uint32_t)charIn1 * (uint32_t)intIn2) >> 16; +} + +static inline void MultiU24X24toH16(uint16_t& intRes, uint32_t& longIn1, uint32_t& longIn2) +{ + intRes = ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24; +} #endif //_NO_ASM FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) { - unsigned short timer; + uint16_t timer; if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times @@ -108,7 +114,7 @@ FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) if(step_rate >= (8*256)){ // higher step rate unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; unsigned char tmp_step_rate = (step_rate & 0x00ff); - unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); + uint16_t gain = (uint16_t)pgm_read_word_near(table_address+2); MultiU16X8toH16(timer, tmp_step_rate, gain); timer = (unsigned short)pgm_read_word_near(table_address) - timer; } From e0bf92cd4e7b98fe0628c8584a8f263aadf0405b Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 4 Aug 2020 09:54:57 +0300 Subject: [PATCH 38/50] Change bool literal to int --- Firmware/temperature.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 084ed272..854a884a 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1377,7 +1377,7 @@ void temp_runaway_stop(bool isPreheat, bool isBed) SERIAL_ERROR_START; isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)"); #ifdef EXTRUDER_ALTFAN_DETECT - altfanOverride = true; //full speed + altfanOverride = 1; //full speed #endif //EXTRUDER_ALTFAN_DETECT setExtruderAutoFanState(3); SET_OUTPUT(FAN_PIN); @@ -1467,7 +1467,7 @@ void max_temp_error(uint8_t e) { WRITE(FAN_PIN, 1); WRITE(BEEPER, 1); #ifdef EXTRUDER_ALTFAN_DETECT - altfanOverride = true; //full speed + altfanOverride = 1; //full speed #endif //EXTRUDER_ALTFAN_DETECT setExtruderAutoFanState(3); // fanSpeed will consumed by the check_axes_activity() routine. From 654a3a0d7942c03107f293fde033ef502d9601d4 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 4 Aug 2020 10:43:30 +0300 Subject: [PATCH 39/50] Other requested changes --- Firmware/temperature.cpp | 32 ++++++++++++++++++-------------- Firmware/ultralcd.cpp | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 854a884a..f08c682a 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -152,8 +152,11 @@ uint8_t fanSpeedBckp = 255; bool fan_measuring = false; uint8_t fanState = 0; #ifdef EXTRUDER_ALTFAN_DETECT - bool extruderFanIsAltfan = false; //set to Noctua - uint8_t altfanOverride = 0; + struct + { + uint8_t isAltfan : 1; + uint8_t altfanOverride : 1; + } altfanStatus; #endif //EXTRUDER_ALTFAN_DETECT #endif @@ -226,12 +229,13 @@ bool extruder_altfan_detect() SET_INPUT(TACH_0); - altfanOverride = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE); - if (altfanOverride == EEPROM_EMPTY_VALUE) + uint8_t overrideVal = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE); + if (overrideVal == EEPROM_EMPTY_VALUE) { - altfanOverride = 0; - eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanOverride); + overrideVal = 0; + eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, overrideVal); } + altfanStatus.altfanOverride = overrideVal; CRITICAL_SECTION_START; EICRB &= ~(1 << ISC61); @@ -246,20 +250,20 @@ bool extruder_altfan_detect() EIMSK &= ~(1 << INT6); countFanSpeed(); - extruderFanIsAltfan = fan_speed[0] > 100; + altfanStatus.isAltfan = fan_speed[0] > 100; setExtruderAutoFanState(1); - return extruderFanIsAltfan; + return altfanStatus.isAltfan; } void altfanOverride_toggle() { - altfanOverride = !altfanOverride; - eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanOverride); + altfanStatus.altfanOverride = !altfanStatus.altfanOverride; + eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanStatus.altfanOverride); } bool altfanOverride_get() { - return altfanOverride; + return altfanStatus.altfanOverride; } #endif //EXTRUDER_ALTFAN_DETECT @@ -515,7 +519,7 @@ void setExtruderAutoFanState(uint8_t state) if (fanState & 0x01) { #ifdef EXTRUDER_ALTFAN_DETECT - if (extruderFanIsAltfan && !altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT; + if (altfanStatus.isAltfan && !altfanStatus.altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT; else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; #else //EXTRUDER_ALTFAN_DETECT newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; @@ -1377,7 +1381,7 @@ void temp_runaway_stop(bool isPreheat, bool isBed) SERIAL_ERROR_START; isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)"); #ifdef EXTRUDER_ALTFAN_DETECT - altfanOverride = 1; //full speed + altfanStatus.altfanOverride = 1; //full speed #endif //EXTRUDER_ALTFAN_DETECT setExtruderAutoFanState(3); SET_OUTPUT(FAN_PIN); @@ -1467,7 +1471,7 @@ void max_temp_error(uint8_t e) { WRITE(FAN_PIN, 1); WRITE(BEEPER, 1); #ifdef EXTRUDER_ALTFAN_DETECT - altfanOverride = 1; //full speed + altfanStatus.altfanOverride = 1; //full speed #endif //EXTRUDER_ALTFAN_DETECT setExtruderAutoFanState(3); // fanSpeed will consumed by the check_axes_activity() routine. diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index c2a3a890..3207389d 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2116,7 +2116,7 @@ static void lcd_support_menu() bool is_flash_air; // 1byte uint8_t ip[4]; // 4bytes char ip_str[3*4+3+1]; // 16bytes - uint8_t experimental_menu_visibility; //1byte + uint8_t experimental_menu_visibility; // 1byte } _menu_data_t; 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]); From a2c7dcbbf8484450614abf0c59c63b5494fa0442 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 4 Aug 2020 13:14:35 +0200 Subject: [PATCH 40/50] Fix indentation --- Firmware/temperature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 657b23fb..2d09f8e0 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1546,7 +1546,7 @@ void bed_min_temp_error(void) { return; #endif disable_heater(); - static const char err[] PROGMEM = "MINTEMP BED"; + static const char err[] PROGMEM = "MINTEMP BED"; if(IsStopped() == false) { temp_error_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; From b3af08d94ad77a2ae8912149f2875f7a136b452a Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 5 Aug 2020 17:04:11 +0200 Subject: [PATCH 41/50] Fix stack smashing in temperature/fsensor ISR The temperature and fsensor ISR re-enable interrupts while executing. However, we still need to protect the epilogue of the ISR so that the saved return address is not altered while returning. We hoist the body of the function out of the isr in both cases for clarity (and to avoid a stray return bypassing the lock/cli), so that the re-entrant portion is clearly indicated. This should fix the "STATIC MEMORY OVERWRITTEN" error messages randomly happening when stepping at high frequency (where either isr is preempted more frequently). --- Firmware/fsensor.cpp | 40 +++++++++++++++++++++++----------------- Firmware/temperature.cpp | 30 ++++++++++++++++++------------ 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/Firmware/fsensor.cpp b/Firmware/fsensor.cpp index 2753ede0..7908c5db 100755 --- a/Firmware/fsensor.cpp +++ b/Firmware/fsensor.cpp @@ -478,22 +478,8 @@ bool fsensor_oq_result(void) } #endif //FSENSOR_QUALITY -ISR(FSENSOR_INT_PIN_VECT) +FORCE_INLINE static void fsensor_isr(int st_cnt) { - 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) @@ -578,8 +564,28 @@ ISR(FSENSOR_INT_PIN_VECT) #endif //DEBUG_FSENSOR_LOG pat9125_y = 0; - _lock = false; - return; +} + +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) + { + // fetch fsensor_st_cnt atomically + int st_cnt = fsensor_st_cnt; + fsensor_st_cnt = 0; + + _lock = true; + sei(); + fsensor_isr(st_cnt); + cli(); + _lock = false; + } } void fsensor_setup_interrupt(void) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 6e9b6985..d98a3c5e 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1606,18 +1606,8 @@ void adc_ready(void) //callback from adc when sampling finished } // extern "C" -// Timer2 (originaly timer0) is shared with millies -#ifdef SYSTEM_TIMER_2 -ISR(TIMER2_COMPB_vect) -#else //SYSTEM_TIMER_2 -ISR(TIMER0_COMPB_vect) -#endif //SYSTEM_TIMER_2 +FORCE_INLINE static void temperature_isr() { - static bool _lock = false; - if (_lock) return; - _lock = true; - asm("sei"); - if (!temp_meas_ready) adc_cycle(); lcd_buttons_update(); @@ -1983,8 +1973,24 @@ ISR(TIMER0_COMPB_vect) #if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1)) check_fans(); #endif //(defined(TACH_0)) +} - _lock = false; +// Timer2 (originaly timer0) is shared with millies +#ifdef SYSTEM_TIMER_2 +ISR(TIMER2_COMPB_vect) +#else //SYSTEM_TIMER_2 +ISR(TIMER0_COMPB_vect) +#endif //SYSTEM_TIMER_2 +{ + static bool _lock = false; + if (!_lock) + { + _lock = true; + sei(); + temperature_isr(); + cli(); + _lock = false; + } } void check_max_temp() From f1a8657093f563be694c6fd832da577c7d51cb00 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Thu, 6 Aug 2020 12:20:38 +0300 Subject: [PATCH 42/50] Minor documentation fixes Add even more comments a --- Firmware/eeprom.h | 4 ++-- Firmware/ultralcd.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index ee7fa39e..b8bec384 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -359,8 +359,8 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | ^ | ^ | ^ | 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 -| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | 0-1 | 00h | ALTFAN override | LCD menu | D3 Ax0d2b C1 -| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | 0-1 | 00h | Experimental menu visibility | LCD menu | D3 Ax0d2a C1 +| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | 0-1 | 00h 0 | ALTFAN override | LCD menu | D3 Ax0d2b C1 +| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | 0-1 | 00h 0 | Experimental menu visibility | LCD menu | D3 Ax0d2a C1 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 3207389d..68378698 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2098,7 +2098,7 @@ static void lcd_preheat_menu() //! @endcode //! //! -//! | Experimental | c=18 r=1 +//! | Experimental | c=18 //! //! //! If DEBUG_BUILD is defined @@ -2224,7 +2224,7 @@ static void lcd_support_menu() if (_md->experimental_menu_visibility) { - MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu); + MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu);////MSG_MENU_EXPERIMENTAL c=18 } @@ -9202,7 +9202,7 @@ void lcd_experimental_menu() MENU_ITEM_BACK_P(_T(MSG_BACK)); #ifdef EXTRUDER_ALTFAN_DETECT - MENU_ITEM_TOGGLE_P(_N("ALTFAN det."), altfanOverride_get()?_T(MSG_OFF):_T(MSG_ON), altfanOverride_toggle); + MENU_ITEM_TOGGLE_P(_N("ALTFAN det."), altfanOverride_get()?_T(MSG_OFF):_T(MSG_ON), altfanOverride_toggle);////MSG_MENU_ALTFAN c=18 #endif //EXTRUDER_ALTFAN_DETECT MENU_END(); From 96435ad0849cb44a632afb64f69de945e2c4e71e Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Wed, 12 Aug 2020 08:48:12 +0300 Subject: [PATCH 43/50] Move experimental menu to HW setup --- Firmware/ultralcd.cpp | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 68378698..c4b28736 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2096,9 +2096,6 @@ static void lcd_preheat_menu() //! @code{.unparsed} //! | Voltages | MSG_MENU_VOLTAGES //! @endcode -//! -//! -//! | Experimental | c=18 //! //! //! If DEBUG_BUILD is defined @@ -2111,12 +2108,11 @@ static void lcd_preheat_menu() static void lcd_support_menu() { typedef struct - { // 23bytes total + { // 22bytes total int8_t status; // 1byte bool is_flash_air; // 1byte uint8_t ip[4]; // 4bytes char ip_str[3*4+3+1]; // 16bytes - uint8_t experimental_menu_visibility; // 1byte } _menu_data_t; 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]); @@ -2131,13 +2127,6 @@ static void lcd_support_menu() _md->ip[0], _md->ip[1], _md->ip[2], _md->ip[3]); - _md->experimental_menu_visibility = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY); - if (_md->experimental_menu_visibility == EEPROM_EMPTY_VALUE) - { - _md->experimental_menu_visibility = 0; - eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, _md->experimental_menu_visibility); - } - } else if (_md->is_flash_air && _md->ip[0] == 0 && _md->ip[1] == 0 && _md->ip[2] == 0 && _md->ip[3] == 0 && @@ -2222,11 +2211,6 @@ static void lcd_support_menu() MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN - if (_md->experimental_menu_visibility) - { - MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu);////MSG_MENU_EXPERIMENTAL c=18 - } - #ifdef DEBUG_BUILD MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1 @@ -5730,6 +5714,25 @@ static void sheets_menu() void lcd_hw_setup_menu(void) // can not be "static" { + typedef struct + {// 2bytes total + int8_t status; + uint8_t experimental_menu_visibility; + } _menu_data_t; + 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) + { + _md->experimental_menu_visibility = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY); + if (_md->experimental_menu_visibility == EEPROM_EMPTY_VALUE) + { + _md->experimental_menu_visibility = 0; + eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, _md->experimental_menu_visibility); + } + } + + MENU_BEGIN(); MENU_ITEM_BACK_P(_T(bSettings?MSG_SETTINGS:MSG_BACK)); // i.e. default menu-item / menu-item after checking mismatch @@ -5743,6 +5746,12 @@ void lcd_hw_setup_menu(void) // can not be "static" //! @todo Don't forget to remove this as soon Fsensor Detection works with mmu if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor); #endif //IR_SENSOR_ANALOG + + if (_md->experimental_menu_visibility) + { + MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu);////MSG_MENU_EXPERIMENTAL c=18 + } + MENU_END(); } From 6b853a4cc335d513a949b3530662e8fa5575bdf8 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Wed, 12 Aug 2020 12:19:08 +0300 Subject: [PATCH 44/50] Auto-detect ALTFAN after fw. update --- Firmware/temperature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index f08c682a..f01fbab2 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -232,7 +232,7 @@ bool extruder_altfan_detect() uint8_t overrideVal = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE); if (overrideVal == EEPROM_EMPTY_VALUE) { - overrideVal = 0; + overrideVal = (calibration_status() == CALIBRATION_STATUS_CALIBRATED) ? 1 : 0; eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, overrideVal); } altfanStatus.altfanOverride = overrideVal; From 5530b99882c90bbc67b69eb18d64743abf4643ab Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Wed, 12 Aug 2020 12:46:35 +0300 Subject: [PATCH 45/50] Reboot after factory reset --- Firmware/Dcodes.cpp | 13 ++++--------- Firmware/Marlin.h | 2 ++ Firmware/Marlin_main.cpp | 11 ++++++++--- Firmware/bootapp.c | 8 ++++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 1f902c5e..85d78001 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -226,9 +226,7 @@ void dcode_0() LOG("D0 - Reset\n"); if (code_seen('B')) //bootloader { - cli(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } else //reset { @@ -252,8 +250,7 @@ void dcode_1() cli(); for (int i = 0; i < 8192; i++) eeprom_write_byte((unsigned char*)i, (unsigned char)0xff); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } /*! @@ -420,8 +417,7 @@ void dcode_5() boot_dst_addr = (uint32_t)address; boot_src_addr = (uint32_t)(&data); bootapp_print_vars(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } while (count) { @@ -467,8 +463,7 @@ void dcode_7() boot_copy_size = (uint16_t)0xc00; boot_src_addr = (uint32_t)0x0003e400; boot_dst_addr = (uint32_t)0x0003f400; - wdt_enable(WDTO_15MS); - while(1); + softReset(); */ } diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 5c03552b..2585d0c8 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -512,4 +512,6 @@ void load_filament_final_feed(); void marlin_wait_for_click(); void raise_z_above(float target, bool plan=true); +void softReset(); + #endif diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 2a261db2..fa02a956 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -762,6 +762,7 @@ static void factory_reset(char level) } } + softReset(); break; @@ -3813,9 +3814,7 @@ void process_commands() #if (defined(WATCHDOG) && (MOTHERBOARD == BOARD_EINSY_1_0a)) boot_app_magic = BOOT_APP_MAGIC; boot_app_flags = BOOT_APP_FLG_RUN; - wdt_enable(WDTO_15MS); - cli(); - while(1); + softReset(); #else //WATCHDOG asm volatile("jmp 0x3E000"); #endif //WATCHDOG @@ -11716,6 +11715,12 @@ void disable_force_z() #endif // TMC2130 } +void softReset() +{ + cli(); + wdt_enable(WDTO_15MS); + while(1); +} void enable_force_z() { diff --git a/Firmware/bootapp.c b/Firmware/bootapp.c index 4fd67db2..c4585af5 100644 --- a/Firmware/bootapp.c +++ b/Firmware/bootapp.c @@ -9,6 +9,8 @@ extern FILE _uartout; #define uartout (&_uartout) +extern void softReset(); + void bootapp_print_vars(void) { fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr); @@ -39,8 +41,7 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size) boot_src_addr = (uint32_t)rptr; boot_dst_addr = (uint32_t)fptr; bootapp_print_vars(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } void bootapp_reboot_user0(uint8_t reserved) @@ -50,6 +51,5 @@ void bootapp_reboot_user0(uint8_t reserved) boot_app_flags = BOOT_APP_FLG_USER0; boot_reserved = reserved; bootapp_print_vars(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } From 8d9dc73d1b8c06a7c7c4f308203227c6ee112bd1 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Wed, 12 Aug 2020 17:25:49 +0300 Subject: [PATCH 46/50] Fix compile error fix compile Fix compile error --- Firmware/Dcodes.cpp | 2 +- Firmware/Marlin.h | 2 +- Firmware/Marlin_main.cpp | 13 ++++++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 85d78001..c77cd96e 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -1,5 +1,5 @@ #include "Dcodes.h" -//#include "Marlin.h" +#include "Marlin.h" #include "Configuration.h" #include "language.h" #include "cmdqueue.h" diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 2585d0c8..3a4b4259 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -512,6 +512,6 @@ void load_filament_final_feed(); void marlin_wait_for_click(); void raise_z_above(float target, bool plan=true); -void softReset(); +extern "C" void softReset(); #endif diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index fa02a956..a83d64b8 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -648,6 +648,12 @@ void failstats_reset_print() #endif } +void softReset() +{ + cli(); + wdt_enable(WDTO_15MS); + while(1); +} #ifdef MESH_BED_LEVELING @@ -11715,13 +11721,6 @@ void disable_force_z() #endif // TMC2130 } -void softReset() -{ - cli(); - wdt_enable(WDTO_15MS); - while(1); -} - void enable_force_z() { if(bEnableForce_z) From 2c2926882a924d1deabaf046f8a9a82eae9f3594 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 18 Aug 2020 19:29:18 +0300 Subject: [PATCH 47/50] Don't switch unnecessarily. Also "\n" the ";S" request --- Firmware/Marlin_main.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 49470ae1..70a8f7e5 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3287,25 +3287,23 @@ void gcode_M701() static void gcode_PRUSA_SN() { uint8_t selectedSerialPort_bak = selectedSerialPort; + char SN[20]; selectedSerialPort = 0; - putchar(';'); - putchar('S'); - int numbersRead = 0; + SERIAL_ECHOLNRPGM(PSTR(";S")); + uint8_t numbersRead = 0; ShortTimer timeout; timeout.start(); - while (numbersRead < 19) { - while (MSerial.available() > 0) { - uint8_t serial_char = MSerial.read(); - selectedSerialPort = selectedSerialPort_bak; - putchar(serial_char); + while (numbersRead < (sizeof(SN) - 1)) { + if (MSerial.available() > 0) { + SN[numbersRead] = MSerial.read(); numbersRead++; - selectedSerialPort = 0; } if (timeout.expired(100u)) break; } + SN[numbersRead] = 0; selectedSerialPort = selectedSerialPort_bak; - putchar('\n'); + SERIAL_ECHOLN(SN); } //! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors //! at the TACH_1 pin, which causes bad detection of print fan speed. From 90c36a588746e2d53c9d41acc6a8de08ecb57c27 Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Thu, 20 Aug 2020 15:14:39 +0200 Subject: [PATCH 48/50] Update ALTFAN eeprom documentation EEPROM_ALTFAN_OVERRIDE and EEPROM_EXPERIMENTAL_VISIBILITY are compared to 0xFF in the code that's why I keep the uint8. --- Firmware/eeprom.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index b8bec384..5cb7ddb8 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -359,8 +359,12 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | ^ | ^ | ^ | 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 -| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | 0-1 | 00h 0 | ALTFAN override | LCD menu | D3 Ax0d2b C1 -| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | 0-1 | 00h 0 | Experimental menu visibility | LCD menu | D3 Ax0d2a C1 +| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | ffh 255 | ffh 255 | ALTFAN override unknown state | LCD menu | D3 Ax0d2b C1 +| ^ | ^ | ^ | 00h 0 | ^ | ALTFAN override deactivated | ^ | ^ +| ^ | ^ | ^ | 01h 1 | ^ | ALTFAN override activated | ^ | ^ +| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | ffh 255 | ffh 255 | Experimental menu visibility unknown state | LCD menu | D3 Ax0d2a C1 +| ^ | ^ | ^ | 00h 0 | ^ | Experimental menu visibility hidden | ^ | ^ +| ^ | ^ | ^ | 01h 1 | ^ | Experimental menu visibility visible | ^ | ^ | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code From 1659f61dd52ed0be9bc4e825fb10df4414176c2a Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Fri, 21 Aug 2020 10:51:46 +0300 Subject: [PATCH 49/50] Fix fastio extra parenthesis --- Firmware/fastio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/fastio.h b/Firmware/fastio.h index e4f25ed8..acded8cb 100644 --- a/Firmware/fastio.h +++ b/Firmware/fastio.h @@ -58,7 +58,7 @@ #define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) /// check if pin is an timer -#define _GET_TIMER(IO) ((DIO ## IO ## _PWM) +#define _GET_TIMER(IO) (DIO ## IO ## _PWM) // why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html From 7ac16d5f045aef836a1cf7d36b9f9cfeee45192d Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 7 Sep 2020 19:42:53 +0300 Subject: [PATCH 50/50] Menu view return patch --- Firmware/menu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/menu.cpp b/Firmware/menu.cpp index d31dce7e..3c4e8926 100755 --- a/Firmware/menu.cpp +++ b/Firmware/menu.cpp @@ -48,6 +48,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo { menu_menu = menu; lcd_encoder = encoder; + menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support asm("sei"); if (reset_menu_state) {