diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 16ae8f4a6328..fcf907c21722 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -452,13 +452,13 @@ #define D_FILAMENT 2.85 #endif -//Implementation of a linear pressure control -//Assumption: advance = k * (delta velocity) -//K=0 means advance disabled. A good value for a gregs wade extruder will be around K=75 -#define LIN_ADVANCE +// Implementation of a linear pressure control +// Assumption: advance = k * (delta velocity) +// K=0 means advance disabled. A good value for a gregs wade extruder will be around K=75 +//#define LIN_ADVANCE #if ENABLED(LIN_ADVANCE) - #define LIN_K 75 + #define LIN_ADVANCE_K 75 #endif // @section extras diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 1a4f04d07215..8cfd2d45a462 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -134,6 +134,10 @@ void idle( void manage_inactivity(bool ignore_stepper_queue = false); +#if ENABLED(DUAL_X_CARRIAGE) + extern bool extruder_duplication_enabled; +#endif + #if ENABLED(DUAL_X_CARRIAGE) && HAS_X_ENABLE && HAS_X2_ENABLE #define enable_x() do { X_ENABLE_WRITE( X_ENABLE_ON); X2_ENABLE_WRITE( X_ENABLE_ON); } while (0) #define disable_x() do { X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; } while (0) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 6c92d2c351a7..a9489f9dee5e 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -6155,13 +6155,13 @@ inline void gcode_M503() { #endif // DUAL_X_CARRIAGE #if ENABLED(LIN_ADVANCE) -/** - * M905: Set advance factor - */ -inline void gcode_M905() { - stepper.synchronize(); - stepper.advance_M905(); -} + /** + * M905: Set advance factor + */ + inline void gcode_M905() { + stepper.synchronize(); + stepper.advance_M905(); + } #endif /** diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index 70553f6f557a..55baded01951 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -306,6 +306,13 @@ #endif // AUTO_BED_LEVELING_FEATURE +/** + * Advance Extrusion + */ +#if ENABLED(ADVANCE) && ENABLED(LIN_ADVANCE) + #error You can enable ADVANCE or LIN_ADVANCE, but not both. +#endif + /** * Filament Width Sensor */ @@ -313,7 +320,6 @@ #error FILAMENT_WIDTH_SENSOR requires a FILWIDTH_PIN to be defined. #endif - /** * ULTIPANEL encoder */ diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index e529fa7465df..14ca7961eca2 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -966,24 +966,28 @@ void Planner::check_axes_activity() { // the maximum junction speed and may always be ignored for any speed reduction checks. block->nominal_length_flag = (block->nominal_speed <= v_allowable); block->recalculate_flag = true; // Always calculate trapezoid for new block - - #ifdef LIN_ADVANCE - //bse = allsteps: A problem occures if there is a very tiny move before a retract. - //In this case, the retract and the move will be executed together. This leads to an enormus amount advance steps due to a hughe e_acceleration. - //The math is correct, but you don't want a retract move done with advance! This situation has to be filtered out. - if ((!bse || (!bsx && !bsy && !bsz)) || (stepper.get_advance_k() == 0) || (bse == allsteps)) { + + // Update previous path unit_vector and nominal speed + for (int i = 0; i < NUM_AXIS; i++) previous_speed[i] = current_speed[i]; + previous_nominal_speed = block->nominal_speed; + + #if ENABLED(LIN_ADVANCE) + + // bse == allsteps: A problem occurs when there's a very tiny move before a retract. + // In this case, the retract and the move will be executed together. + // This leads to an enormous number of advance steps due to a huge e_acceleration. + // The math is correct, but you don't want a retract move done with advance! + // So this situation is filtered out here. + if (!bse || (!bsx && !bsy && !bsz) || stepper.get_advance_k() == 0 || bse == allsteps) { block->use_advance_lead = false; - } else { + } + else { block->use_advance_lead = true; block->e_speed_multiplier8 = (block->steps[E_AXIS] << 8) / block->step_event_count; } - #endif - // Update previous path unit_vector and nominal speed - for (int i = 0; i < NUM_AXIS; i++) previous_speed[i] = current_speed[i]; - previous_nominal_speed = block->nominal_speed; + #elif ENABLED(ADVANCE) - #if ENABLED(ADVANCE) // Calculate advance rate if (!bse || (!bsx && !bsy && !bsz)) { block->advance_rate = 0; @@ -1002,7 +1006,8 @@ void Planner::check_axes_activity() { SERIAL_ECHOPGM("advance rate :"); SERIAL_ECHOLN(block->advance_rate/256.0); */ - #endif // ADVANCE + + #endif // ADVANCE or LIN_ADVANCE calculate_trapezoid_for_block(block, block->entry_speed / block->nominal_speed, safe_speed / block->nominal_speed); diff --git a/Marlin/planner.h b/Marlin/planner.h index 7578f6c4488f..81dc45112d01 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -64,16 +64,16 @@ typedef struct { unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) - #if ENABLED(ADVANCE) + // Advance extrusion + #if ENABLED(LIN_ADVANCE) + bool use_advance_lead; + int e_speed_multiplier8; // Factorised by 2^8 to avoid float + #elif ENABLED(ADVANCE) long advance_rate; volatile long initial_advance; volatile long final_advance; float advance; #endif - #ifdef LIN_ADVANCE - bool use_advance_lead; - int e_speed_multiplier8; //factorised by 2^8 to avoid float - #endif // Fields used by the motion planner to manage acceleration float nominal_speed; // The nominal speed for this block in mm/sec @@ -169,10 +169,6 @@ class Planner { static long axis_segment_time[2][3] = { {MAX_FREQ_TIME + 1, 0, 0}, {MAX_FREQ_TIME + 1, 0, 0} }; #endif - #if ENABLED(DUAL_X_CARRIAGE) - extern bool extruder_duplication_enabled; - #endif - public: Planner(); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index b99d60c55e07..97755f1ed5b4 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -294,30 +294,32 @@ void Stepper::isr() { customizedSerial.checkRx(); // Check for serial chars. #endif - #if ENABLED(ADVANCE) - counter_E += current_block->steps[E_AXIS]; - if (counter_E > 0) { - counter_E -= current_block->step_event_count; - e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1; - } - #endif //ADVANCE - #if ENABLED(LIN_ADVANCE) + counter_E += current_block->steps[E_AXIS]; if (counter_E > 0) { counter_E -= current_block->step_event_count; - count_position[_AXIS(E)] += count_direction[_AXIS(E)]; + count_position[E_AXIS] += count_direction[E_AXIS]; e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1; } - - if (current_block->use_advance_lead){ + + if (current_block->use_advance_lead) { int delta_adv_steps; //Maybe a char would be enough? delta_adv_steps = (((long)extruder_advance_k * current_estep_rate[current_block->active_extruder]) >> 9) - current_adv_steps[current_block->active_extruder]; e_steps[current_block->active_extruder] += delta_adv_steps; current_adv_steps[current_block->active_extruder] += delta_adv_steps; } - #endif //LIN_ADVANCE + #elif ENABLED(ADVANCE) + + counter_E += current_block->steps[E_AXIS]; + if (counter_E > 0) { + counter_E -= current_block->step_event_count; + e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1; + } + + #endif // ADVANCE or LIN_ADVANCE + #define _COUNTER(AXIS) counter_## AXIS #define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP #define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN @@ -329,7 +331,7 @@ void Stepper::isr() { STEP_ADD(X); STEP_ADD(Y); STEP_ADD(Z); - #if (DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)) + #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE) STEP_ADD(E); #endif @@ -343,7 +345,7 @@ void Stepper::isr() { STEP_IF_COUNTER(X); STEP_IF_COUNTER(Y); STEP_IF_COUNTER(Z); - #if (DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)) + #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE) STEP_IF_COUNTER(E); #endif @@ -366,12 +368,11 @@ void Stepper::isr() { acceleration_time += timer; #if ENABLED(LIN_ADVANCE) - if (current_block->use_advance_lead){ + + if (current_block->use_advance_lead) current_estep_rate[current_block->active_extruder] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8; - } - #endif - #if ENABLED(ADVANCE) + #elif ENABLED(ADVANCE) advance += advance_rate * step_loops; //NOLESS(advance, current_block->advance); @@ -380,7 +381,8 @@ void Stepper::isr() { e_steps[current_block->active_extruder] += ((advance >> 8) - old_advance); old_advance = advance >> 8; - #endif //ADVANCE + #endif // ADVANCE or LIN_ADVANCE + } else if (step_events_completed > (unsigned long)current_block->decelerate_after) { MultiU24X32toH16(step_rate, deceleration_time, current_block->acceleration_rate); @@ -398,12 +400,12 @@ void Stepper::isr() { deceleration_time += timer; #if ENABLED(LIN_ADVANCE) - if (current_block->use_advance_lead){ + + if (current_block->use_advance_lead) current_estep_rate[current_block->active_extruder] = ((unsigned long)step_rate * current_block->e_speed_multiplier8) >> 8; - } - #endif - #if ENABLED(ADVANCE) + #elif ENABLED(ADVANCE) + advance -= advance_rate * step_loops; NOLESS(advance, final_advance); @@ -411,15 +413,15 @@ void Stepper::isr() { uint32_t advance_whole = advance >> 8; e_steps[current_block->active_extruder] += advance_whole - old_advance; old_advance = advance_whole; - #endif //ADVANCE + + #endif // ADVANCE or LIN_ADVANCE } else { - #ifdef LIN_ADVANCE - if (current_block->use_advance_lead){ + #if ENABLED(LIN_ADVANCE) + if (current_block->use_advance_lead) current_estep_rate[current_block->active_extruder] = final_estep_rate; - } #endif - + OCR1A = OCR1A_nominal; // ensure we're running at the correct step rate, even if we just came off an acceleration step_loops = step_loops_nominal; @@ -435,12 +437,14 @@ void Stepper::isr() { } } -#if ENABLED(ADVANCE) +#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + // Timer interrupt for E. e_steps is set in the main routine; // Timer 0 is shared with millies ISR(TIMER0_COMPA_vect) { stepper.advance_isr(); } void Stepper::advance_isr() { + old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz) OCR0A = old_OCR0A; @@ -471,58 +475,10 @@ void Stepper::isr() { #endif #endif } - } - -#endif // ADVANCE -#if ENABLED(LIN_ADVANCE) -unsigned char old_OCR0A; -// Timer interrupt for E. e_steps is set in the main routine; -// Timer 0 is shared with millies -ISR(TIMER0_COMPA_vect) { stepper.advance_isr(); } - -void Stepper::advance_isr() { - old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz) war 52 - OCR0A = old_OCR0A; - -#define STEP_E_ONCE(INDEX) \ - if (e_steps[INDEX] != 0) { \ - E## INDEX ##_STEP_WRITE(INVERT_E_STEP_PIN); \ - if (e_steps[INDEX] < 0) { \ - E## INDEX ##_DIR_WRITE(INVERT_E## INDEX ##_DIR); \ - e_steps[INDEX]++; \ - } \ - else if (e_steps[INDEX] > 0) { \ - E## INDEX ##_DIR_WRITE(!INVERT_E## INDEX ##_DIR); \ - e_steps[INDEX]--; \ - } \ - E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN); \ } - // Step all E steppers that have steps, up to 4 steps per interrupt - for (unsigned char i = 0; i < 4; i++) { - #if EXTRUDERS > 3 - switch(current_block->active_extruder){case 3:STEP_E_ONCE(3);break;case 2:STEP_E_ONCE(2);break;case 1:STEP_E_ONCE(1);break;default:STEP_E_ONCE(0);} - #elif EXTRUDERS > 2 - switch(current_block->active_extruder){case 2:STEP_E_ONCE(2);break;case 1:STEP_E_ONCE(1);break;default:STEP_E_ONCE(0);} - #elif EXTRUDERS > 1 - #if DISABLED(DUAL_X_CARRIAGE) - if(current_block->active_extruder == 1){STEP_E_ONCE(1)}else{STEP_E_ONCE(0);} - #else - extern bool extruder_duplication_enabled; - if(extruder_duplication_enabled){ - STEP_E_ONCE(0); - STEP_E_ONCE(1); - }else { - if(current_block->active_extruder == 1){STEP_E_ONCE(1)}else{STEP_E_ONCE(0);} - } - #endif - #else - STEP_E_ONCE(0); - #endif - } -} -#endif // LIN_ADVANCE +#endif // ADVANCE or LIN_ADVANCE void Stepper::init() { digipot_init(); //Initialize Digipot Motor Current @@ -683,27 +639,29 @@ void Stepper::init() { OCR1A = 0x4000; TCNT1 = 0; ENABLE_STEPPER_DRIVER_INTERRUPT(); - - #if ENABLED(LIN_ADVANCE) - for (int i = 0; i < EXTRUDERS; i++){ - e_steps[i] = 0; - current_adv_steps[i] = 0; - } - #if defined(TCCR0A) && defined(WGM01) - CBI(TCCR0A, WGM01); - CBI(TCCR0A, WGM00); + + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + + #if ENABLED(LIN_ADVANCE) + + for (int i = 0; i < EXTRUDERS; i++) { + e_steps[i] = 0; + current_adv_steps[i] = 0; + } + + #elif ENABLED(ADVANCE) + + e_steps[0] = e_steps[1] = e_steps[2] = e_steps[3] = 0; + #endif - SBI(TIMSK0, OCIE0A); - #endif //LIN_ADVANCE - #if ENABLED(ADVANCE) #if defined(TCCR0A) && defined(WGM01) CBI(TCCR0A, WGM01); CBI(TCCR0A, WGM00); #endif - e_steps[0] = e_steps[1] = e_steps[2] = e_steps[3] = 0; SBI(TIMSK0, OCIE0A); - #endif //ADVANCE + + #endif // ADVANCE or LIN_ADVANCE endstops.enable(true); // Start with endstops active. After homing they can be disabled sei(); @@ -1076,15 +1034,12 @@ void Stepper::microstep_readings() { } #if ENABLED(LIN_ADVANCE) + void Stepper::advance_M905() { if (code_seen('K')) extruder_advance_k = code_value(); SERIAL_ECHO_START; - SERIAL_ECHOPGM("Advance factor:"); - SERIAL_CHAR(' '); - SERIAL_ECHOLN(extruder_advance_k); + SERIAL_ECHOPAIR("Advance factor: ", extruder_advance_k); + SERIAL_EOL; } - int Stepper::get_advance_k(){ - return extruder_advance_k; - } -#endif +#endif // LIN_ADVANCE diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 17a8f3fa6725..8f75726ab5e1 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -90,14 +90,6 @@ class Stepper { bool performing_homing = false; #endif - #if ENABLED(ADVANCE) - long e_steps[4]; - #endif - - #if ENABLED(LIN_ADVANCE) - int extruder_advance_k = LIN_K; - #endif - private: unsigned char last_direction_bits = 0; // The next stepping-bits to be output @@ -112,19 +104,28 @@ class Stepper { long counter_X = 0, counter_Y = 0, counter_Z = 0, counter_E = 0; volatile unsigned long step_events_completed = 0; // The number of step events executed in the current block - #if ENABLED(ADVANCE) - unsigned char old_OCR0A; - long advance_rate, advance, final_advance = 0; - long old_advance = 0; - #endif - - #if ENABLED(LIN_ADVANCE) + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + unsigned char old_OCR0A; - volatile int e_steps[EXTRUDERS]; - int final_estep_rate; - int current_estep_rate[EXTRUDERS]; //Actual extruder speed [steps/s] - int current_adv_steps[EXTRUDERS]; //The amount of current added esteps due to advance. Think of it as the current amount of pressure applied to the spring (=filament). - #endif + + #if ENABLED(LIN_ADVANCE) + + int extruder_advance_k = LIN_ADVANCE_K; + volatile int e_steps[EXTRUDERS]; + int final_estep_rate; + int current_estep_rate[EXTRUDERS]; // Actual extruder speed [steps/s] + int current_adv_steps[EXTRUDERS]; // The amount of current added esteps due to advance. + // i.e., the current amount of pressure applied + // to the spring (=filament). + #elif ENABLED(ADVANCE) + + long e_steps[4]; + long advance_rate, advance, final_advance = 0; + long old_advance = 0; + + #endif + + #endif // ADVANCE or LIN_ADVANCE long acceleration_time, deceleration_time; //unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; @@ -171,14 +172,8 @@ class Stepper { void isr(); - #if ENABLED(ADVANCE) - void advance_isr(); - #endif - - #if ENABLED(LIN_ADVANCE) + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) void advance_isr(); - void advance_M905(); - int get_advance_k(); #endif // @@ -267,6 +262,11 @@ class Stepper { return endstops_trigsteps[axis] / planner.axis_steps_per_unit[axis]; } + #if ENABLED(LIN_ADVANCE) + void advance_M905(); + FORCE_INLINE int get_advance_k() { return extruder_advance_k; } + #endif + private: FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { @@ -334,7 +334,7 @@ class Stepper { OCR1A = acceleration_time; #if ENABLED(LIN_ADVANCE) - if (current_block->use_advance_lead){ + if (current_block->use_advance_lead) { current_estep_rate[current_block->active_extruder] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8; final_estep_rate = (current_block->nominal_rate * current_block->e_speed_multiplier8) >> 8; } @@ -356,4 +356,4 @@ class Stepper { }; -#endif // STEPPER_H +#endif // STEPPER_H \ No newline at end of file diff --git a/Marlin/stepper_indirection.h b/Marlin/stepper_indirection.h index 0a534efdd7b0..c013d268e3e6 100644 --- a/Marlin/stepper_indirection.h +++ b/Marlin/stepper_indirection.h @@ -193,7 +193,6 @@ #define NORM_E_DIR() _NORM_E_DIR() #define REV_E_DIR() _REV_E_DIR() #else - extern bool extruder_duplication_enabled; #define E_STEP_WRITE(v) {if(extruder_duplication_enabled){E0_STEP_WRITE(v);E1_STEP_WRITE(v);}else _E_STEP_WRITE(v);} #define NORM_E_DIR() {if(extruder_duplication_enabled){E0_DIR_WRITE(!INVERT_E0_DIR);E1_DIR_WRITE(!INVERT_E1_DIR);}else _NORM_E_DIR();} #define REV_E_DIR() {if(extruder_duplication_enabled){E0_DIR_WRITE(INVERT_E0_DIR);E1_DIR_WRITE(INVERT_E1_DIR);}else _REV_E_DIR();}