diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index b90a2ee7e..43b51115e 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -445,6 +445,15 @@ #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 + +#if ENABLED(LIN_ADVANCE) + #define LIN_ADVANCE_K 75 +#endif + // @section leveling // Default mesh area is an area with an inset margin on the print area. @@ -457,15 +466,6 @@ #define MESH_MAX_Y (Y_MAX_POS - (MESH_INSET)) #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 - -#if ENABLED(LIN_ADVANCE) - #define LIN_K 75 -#endif - // @section extras // Arc interpretation settings: diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index e48ef2e59..b41ea10ee 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -6469,13 +6469,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 a913cb1b0..4110d6705 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -351,6 +351,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 */ @@ -358,7 +365,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 a0489c99f..699987f15 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -1045,24 +1045,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; @@ -1081,7 +1085,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 5c0d5e12a..51219743e 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 diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 46d0f21e9..0ede6d3b7 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -89,13 +89,24 @@ long Stepper::counter_X = 0, volatile unsigned long Stepper::step_events_completed = 0; // The number of step events executed in the current block -#if ENABLED(ADVANCE) +#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + unsigned char Stepper::old_OCR0A; - long Stepper::final_advance = 0, - Stepper::old_advance = 0, - Stepper::e_steps[EXTRUDERS], - Stepper::advance_rate, - Stepper::advance; + volatile unsigned char Stepper::eISR_Rate = 200; // Keep the ISR at a low rate until needed + + #if ENABLED(LIN_ADVANCE) + volatile int Stepper::e_steps[EXTRUDERS]; + int Stepper::extruder_advance_k = LIN_ADVANCE_K, + Stepper::final_estep_rate, + Stepper::current_estep_rate[EXTRUDERS], + Stepper::current_adv_steps[EXTRUDERS]; + #else + long Stepper::e_steps[EXTRUDERS], + Stepper::final_advance = 0, + Stepper::old_advance = 0, + Stepper::advance_rate, + Stepper::advance; + #endif #endif long Stepper::acceleration_time, Stepper::deceleration_time; @@ -344,30 +355,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 @@ -379,7 +392,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 @@ -393,7 +406,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 @@ -416,12 +429,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); @@ -430,7 +442,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); @@ -448,12 +461,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); @@ -461,15 +474,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; @@ -485,12 +498,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; @@ -521,58 +536,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() { @@ -738,27 +705,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) + + for (uint8_t i = 0; i < EXTRUDERS; i++) e_steps[i] = 0; + #endif - SBI(TIMSK0, OCIE0A); - #endif //LIN_ADVANCE - #if ENABLED(ADVANCE) #if defined(TCCR0A) && defined(WGM01) CBI(TCCR0A, WGM01); CBI(TCCR0A, WGM00); #endif - for (uint8_t i = 0; i < EXTRUDERS; i++) e_steps[i] = 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(); @@ -1137,15 +1106,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 e9d1191bc..684ec21bc 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -90,14 +90,6 @@ class Stepper { static bool performing_homing; #endif - #if ENABLED(ADVANCE) - static long e_steps[EXTRUDERS]; - #endif - - #if ENABLED(LIN_ADVANCE) - int extruder_advance_k = LIN_K; - #endif - private: static unsigned char last_direction_bits; // The next stepping-bits to be output @@ -111,18 +103,23 @@ class Stepper { static long counter_X, counter_Y, counter_Z, counter_E; static volatile unsigned long step_events_completed; // The number of step events executed in the current block - #if ENABLED(ADVANCE) + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) static unsigned char old_OCR0A; - static long advance_rate, advance, old_advance, final_advance; - #endif - - #if 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 + static volatile unsigned char eISR_Rate; + #if ENABLED(LIN_ADVANCE) + static volatile int e_steps[EXTRUDERS]; + static int extruder_advance_k; + static int final_estep_rate; + static int current_estep_rate[EXTRUDERS]; // Actual extruder speed [steps/s] + static 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). + #else + static long e_steps[EXTRUDERS]; + static long advance_rate, advance, final_advance; + static long old_advance; + #endif + #endif // ADVANCE or LIN_ADVANCE static long acceleration_time, deceleration_time; //unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; @@ -168,15 +165,9 @@ class Stepper { static void isr(); - #if ENABLED(ADVANCE) + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) static void advance_isr(); #endif - - #if ENABLED(LIN_ADVANCE) - void advance_isr(); - void advance_M905(); - int get_advance_k(); - #endif // // Block until all buffered steps are executed @@ -264,6 +255,11 @@ class Stepper { return endstops_trigsteps[axis] / planner.axis_steps_per_mm[axis]; } + #if ENABLED(LIN_ADVANCE) + void advance_M905(); + FORCE_INLINE int get_advance_k() { return extruder_advance_k; } + #endif + private: static FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { @@ -335,7 +331,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; } @@ -357,4 +353,4 @@ class Stepper { }; -#endif // STEPPER_H +#endif // STEPPER_H \ No newline at end of file