From fb8e880734bb099b80b031ee2b876e628a50135e Mon Sep 17 00:00:00 2001 From: Sebastianv650 Date: Wed, 4 May 2016 18:53:17 +0200 Subject: [PATCH 1/5] Add LIN_ADVANCE --- Marlin/Configuration_adv.h | 9 +++ Marlin/Marlin_main.cpp | 16 ++++++ Marlin/planner.cpp | 12 ++++ Marlin/planner.h | 4 ++ Marlin/stepper.cpp | 113 ++++++++++++++++++++++++++++++++++++- Marlin/stepper.h | 27 ++++++++- 6 files changed, 178 insertions(+), 3 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 952da0fa7e..b90a2ee7e2 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -457,6 +457,15 @@ #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 73c7478377..e48ef2e59e 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -6468,6 +6468,16 @@ 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(); +} +#endif + /** * M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S */ @@ -7339,6 +7349,12 @@ void process_next_command() { gcode_M605(); break; #endif // DUAL_X_CARRIAGE + + #if ENABLED(LIN_ADVANCE) + case 905: // M905 Set advance factor. + gcode_M905(); + break; + #endif case 907: // M907 Set digital trimpot motor current using axis codes. gcode_M907(); diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index bd60d75a1f..a0489c99fd 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -1045,6 +1045,18 @@ 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)) { + block->use_advance_lead = false; + } 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]; diff --git a/Marlin/planner.h b/Marlin/planner.h index 07de37134e..5c0d5e12aa 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -70,6 +70,10 @@ typedef struct { 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 f8e8a853c9..46d0f21e9d 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -351,6 +351,22 @@ void Stepper::isr() { 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)]; + e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1; + } + + 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 #define _COUNTER(AXIS) counter_## AXIS #define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP @@ -363,7 +379,7 @@ void Stepper::isr() { STEP_ADD(X); STEP_ADD(Y); STEP_ADD(Z); - #if DISABLED(ADVANCE) + #if (DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)) STEP_ADD(E); #endif @@ -377,7 +393,7 @@ void Stepper::isr() { STEP_IF_COUNTER(X); STEP_IF_COUNTER(Y); STEP_IF_COUNTER(Z); - #if DISABLED(ADVANCE) + #if (DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)) STEP_IF_COUNTER(E); #endif @@ -398,6 +414,12 @@ void Stepper::isr() { timer = calc_timer(acc_step_rate); OCR1A = timer; acceleration_time += timer; + + #if ENABLED(LIN_ADVANCE) + 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) @@ -424,6 +446,12 @@ void Stepper::isr() { timer = calc_timer(step_rate); OCR1A = timer; deceleration_time += timer; + + #if ENABLED(LIN_ADVANCE) + 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) advance -= advance_rate * step_loops; @@ -436,6 +464,12 @@ void Stepper::isr() { #endif //ADVANCE } else { + #ifdef 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; @@ -491,6 +525,55 @@ void Stepper::isr() { #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 + void Stepper::init() { digipot_init(); //Initialize Digipot Motor Current @@ -655,6 +738,18 @@ 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); + #endif + SBI(TIMSK0, OCIE0A); + #endif //LIN_ADVANCE #if ENABLED(ADVANCE) #if defined(TCCR0A) && defined(WGM01) @@ -1040,3 +1135,17 @@ void Stepper::microstep_readings() { SERIAL_PROTOCOLLN(digitalRead(E1_MS2_PIN)); #endif } + +#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); + } + + int Stepper::get_advance_k(){ + return extruder_advance_k; + } +#endif diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 1aebe366c0..e9d1191bc3 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -93,6 +93,10 @@ class Stepper { #if ENABLED(ADVANCE) static long e_steps[EXTRUDERS]; #endif + + #if ENABLED(LIN_ADVANCE) + int extruder_advance_k = LIN_K; + #endif private: @@ -111,6 +115,14 @@ class Stepper { 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 long acceleration_time, deceleration_time; //unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; @@ -159,6 +171,12 @@ class Stepper { #if ENABLED(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 @@ -315,6 +333,13 @@ class Stepper { acc_step_rate = current_block->initial_rate; acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; + + #if ENABLED(LIN_ADVANCE) + 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; + } + #endif // SERIAL_ECHO_START; // SERIAL_ECHOPGM("advance :"); @@ -332,4 +357,4 @@ class Stepper { }; -#endif // STEPPER_H \ No newline at end of file +#endif // STEPPER_H From 6d62a4ffc8010ca56f5f438a9da96e781ee65099 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 4 May 2016 12:10:42 -0700 Subject: [PATCH 2/5] Patch LIN_ADVANCE for style and forward-compatibility --- Marlin/Configuration_adv.h | 18 ++-- Marlin/Marlin_main.cpp | 14 +-- Marlin/SanityCheck.h | 8 +- Marlin/planner.cpp | 31 ++++--- Marlin/planner.h | 10 +-- Marlin/stepper.cpp | 176 +++++++++++++++---------------------- Marlin/stepper.h | 52 +++++------ 7 files changed, 141 insertions(+), 168 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index b90a2ee7e2..43b51115eb 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 e48ef2e59e..b41ea10ee1 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 a913cb1b0b..4110d67058 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 a0489c99fd..699987f159 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 5c0d5e12aa..51219743ed 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 46d0f21e9d..0ede6d3b72 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 e9d1191bc3..684ec21bc2 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 From 506d78b2f89bb8e50b9e54fbe51266653299abba Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 6 May 2016 11:03:56 -0700 Subject: [PATCH 3/5] Run the advance_isr faster instead of doing multiple e-steps per interrupt --- Marlin/stepper.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 0ede6d3b72..bc070178e3 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -506,7 +506,19 @@ void Stepper::isr() { void Stepper::advance_isr() { - old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz) + byte maxesteps = 0; + for (uint8_t i = 0; i < EXTRUDERS; i++) + if (abs(e_steps[i]) > maxesteps) maxesteps = abs(e_steps[i]); + + if (maxesteps > 3) + old_OCR0A += 13; // ~19kHz (250000/13 = 19230 Hz) + else if (maxesteps > 2) + old_OCR0A += 17; // ~15kHz (250000/17 = 14705 Hz) + else if (maxesteps > 1) + old_OCR0A += 26; // ~10kHz (250000/26 = 9615 Hz) + else + old_OCR0A += 52; // ~5kHz (250000/26 = 4807 Hz) + OCR0A = old_OCR0A; #define STEP_E_ONCE(INDEX) \ @@ -523,19 +535,17 @@ void Stepper::isr() { 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++) { - STEP_E_ONCE(0); - #if EXTRUDERS > 1 - STEP_E_ONCE(1); - #if EXTRUDERS > 2 - STEP_E_ONCE(2); - #if EXTRUDERS > 3 - STEP_E_ONCE(3); - #endif + // Step all E steppers that have steps + STEP_E_ONCE(0); + #if EXTRUDERS > 1 + STEP_E_ONCE(1); + #if EXTRUDERS > 2 + STEP_E_ONCE(2); + #if EXTRUDERS > 3 + STEP_E_ONCE(3); #endif #endif - } + #endif } From aad9c0ed8d6cb61c701aae4cd94da8d9619c4dd9 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 8 May 2016 12:16:26 -0700 Subject: [PATCH 4/5] Apply updated ISR timing code --- Marlin/stepper.cpp | 34 ++++++++++++++++++++-------------- Marlin/stepper.h | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index bc070178e3..c9d49cd12c 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -413,6 +413,12 @@ void Stepper::isr() { step_events_completed++; if (step_events_completed >= current_block->step_event_count) break; } + + #if ENABLED(LIN_ADVANCE) + // If we have esteps to execute, fire the next ISR "now" + if (e_steps[current_block->active_extruder]) OCR0A = TCNT0 + 2; + #endif + // Calculate new timer value unsigned short timer, step_rate; if (step_events_completed <= (unsigned long)current_block->accelerate_until) { @@ -427,7 +433,7 @@ void Stepper::isr() { timer = calc_timer(acc_step_rate); OCR1A = timer; acceleration_time += timer; - + #if ENABLED(LIN_ADVANCE) if (current_block->use_advance_lead) @@ -444,6 +450,9 @@ void Stepper::isr() { #endif // ADVANCE or LIN_ADVANCE + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + eISR_Rate = (timer >> 2) / abs(e_steps[current_block->active_extruder]); + #endif } else if (step_events_completed > (unsigned long)current_block->decelerate_after) { MultiU24X32toH16(step_rate, deceleration_time, current_block->acceleration_rate); @@ -476,11 +485,20 @@ void Stepper::isr() { old_advance = advance_whole; #endif // ADVANCE or LIN_ADVANCE + + #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + eISR_Rate = (timer >> 2) / abs(e_steps[current_block->active_extruder]); + #endif } else { + #if ENABLED(LIN_ADVANCE) + if (current_block->use_advance_lead) current_estep_rate[current_block->active_extruder] = final_estep_rate; + + eISR_Rate = (OCR1A_nominal >> 2) / abs(e_steps[current_block->active_extruder]); + #endif OCR1A = OCR1A_nominal; @@ -506,19 +524,7 @@ void Stepper::isr() { void Stepper::advance_isr() { - byte maxesteps = 0; - for (uint8_t i = 0; i < EXTRUDERS; i++) - if (abs(e_steps[i]) > maxesteps) maxesteps = abs(e_steps[i]); - - if (maxesteps > 3) - old_OCR0A += 13; // ~19kHz (250000/13 = 19230 Hz) - else if (maxesteps > 2) - old_OCR0A += 17; // ~15kHz (250000/17 = 14705 Hz) - else if (maxesteps > 1) - old_OCR0A += 26; // ~10kHz (250000/26 = 9615 Hz) - else - old_OCR0A += 52; // ~5kHz (250000/26 = 4807 Hz) - + old_OCR0A += eISR_Rate; OCR0A = old_OCR0A; #define STEP_E_ONCE(INDEX) \ diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 684ec21bc2..279db1807f 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -22,7 +22,7 @@ /** * stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors - * Part of Grbl + * Derived from Grbl * * Copyright (c) 2009-2011 Simen Svale Skogsrud * From 45b701d38c02892b5d1f233c22142aa578df7c3d Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 31 May 2016 19:29:47 -0700 Subject: [PATCH 5/5] Travis test for LIN_ADVANCE --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 24640918a0..2edc974ebf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,10 +76,12 @@ script: - build_marlin # # Test 3 extruders on RUMBA (can use any board with >=3 extruders defined) + # Include a test for LIN_ADVANCE here also # - opt_set MOTHERBOARD BOARD_RUMBA - opt_set EXTRUDERS 3 - opt_set TEMP_SENSOR_2 1 + - opt_enable_adv LIN_ADVANCE - build_marlin # # Test PIDTEMPBED