Merge branch 'MK2_LA_1.5' of https://github.com/Sebastianv650/Prusa-Firmware into LA-1.5-testing

This commit is contained in:
Ted Hess 2018-02-25 15:35:53 -05:00
commit fd9caa1f54
5 changed files with 147 additions and 127 deletions

View File

@ -319,43 +319,25 @@
#endif #endif
/** /**
* Implementation of linear pressure control * Linear Pressure Control v1.5
* *
* Assumption: advance = k * (delta velocity) * Assumption: advance [steps] = k * (delta velocity [steps/s])
* K=0 means advance disabled. * K=0 means advance disabled.
* See Marlin documentation for calibration instructions. *
* NOTE: K values for LIN_ADVANCE 1.5 differ from earlier versions!
*
* Set K around 0.22 for 3mm PLA Direct Drive with ~6.5cm between the drive gear and heatbreak.
* Larger K values will be needed for flexible filament and greater distances.
* If this algorithm produces a higher speed offset than the extruder can handle (compared to E jerk)
* print acceleration will be reduced during the affected moves to keep within the limit.
*
* See http://marlinfw.org/docs/features/lin_advance.html for full instructions.
* Mention @Sebastianv650 on GitHub to alert the author of any issues.
*/ */
#define LIN_ADVANCE //#define LIN_ADVANCE
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
#define LIN_ADVANCE_K 0 //Try around 45 for PLA, around 25 for ABS. #define LIN_ADVANCE_K 0 // Unit: mm compression per 1mm/s extruder speed
//#define LA_DEBUG // If enabled, this will generate debug information output over USB.
/**
* Some Slicers produce Gcode with randomly jumping extrusion widths occasionally.
* For example within a 0.4mm perimeter it may produce a single segment of 0.05mm width.
* While this is harmless for normal printing (the fluid nature of the filament will
* close this very, very tiny gap), it throws off the LIN_ADVANCE pressure adaption.
*
* For this case LIN_ADVANCE_E_D_RATIO can be used to set the extrusion:distance ratio
* to a fixed value. Note that using a fixed ratio will lead to wrong nozzle pressures
* if the slicer is using variable widths or layer heights within one print!
*
* This option sets the default E:D ratio at startup. Use `M900` to override this value.
*
* Example: `M900 W0.4 H0.2 D1.75`, where:
* - W is the extrusion width in mm
* - H is the layer height in mm
* - D is the filament diameter in mm
*
* Example: `M900 R0.0458` to set the ratio directly.
*
* Set to 0 to auto-detect the ratio based on given Gcode G1 print moves.
*
* Slic3r (including Prusa Slic3r) produces Gcode compatible with the automatic mode.
* Cura (as of this writing) may produce Gcode incompatible with the automatic mode.
*/
#define LIN_ADVANCE_E_D_RATIO 0 // The calculated ratio (or 0) according to the formula W * H / ((D / 2) ^ 2 * PI)
// Example: 0.4 * 0.2 / ((1.75 / 2) ^ 2 * PI) = 0.033260135
#endif #endif
// Arc interpretation settings: // Arc interpretation settings:

View File

@ -2089,34 +2089,19 @@ void gcode_M768() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
/** /**
* M900: Set and/or Get advance K factor and WH/D ratio * M900: Set and/or Get advance K factor
* *
* K<factor> Set advance K factor * K<factor> Set advance K factor
* R<ratio> Set ratio directly (overrides WH/D)
* W<width> H<height> D<diam> Set ratio from WH/D
*/ */
inline void gcode_M900() { inline void gcode_M900() {
st_synchronize(); st_synchronize();
const float newK = code_seen('K') ? code_value_float() : -1; const float newK = code_seen('K') ? code_value_float() : -1;
if (newK >= 0) extruder_advance_k = newK; if (newK >= 0) extruder_advance_K = newK;
float newR = code_seen('R') ? code_value_float() : -1;
if (newR < 0) {
const float newD = code_seen('D') ? code_value_float() : -1,
newW = code_seen('W') ? code_value_float() : -1,
newH = code_seen('H') ? code_value_float() : -1;
if (newD >= 0 && newW >= 0 && newH >= 0)
newR = newD ? (newW * newH) / (sq(newD * 0.5) * M_PI) : 0;
}
if (newR >= 0) advance_ed_ratio = newR;
SERIAL_ECHO_START; SERIAL_ECHO_START;
SERIAL_ECHOPGM("Advance K="); SERIAL_ECHOPGM("Advance K=");
SERIAL_ECHOLN(extruder_advance_k); SERIAL_ECHOLN(extruder_advance_K);
SERIAL_ECHOPGM(" E/D=");
const float ratio = advance_ed_ratio;
if (ratio) SERIAL_ECHOLN(ratio); else SERIAL_ECHOLNPGM("Auto");
} }
#endif // LIN_ADVANCE #endif // LIN_ADVANCE

View File

@ -127,8 +127,7 @@ float extrude_min_temp=EXTRUDE_MINTEMP;
#endif #endif
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
float extruder_advance_k = LIN_ADVANCE_K, float extruder_advance_K = LIN_ADVANCE_K,
advance_ed_ratio = LIN_ADVANCE_E_D_RATIO,
position_float[NUM_AXIS] = { 0 }; position_float[NUM_AXIS] = { 0 };
#endif #endif
@ -397,6 +396,13 @@ void planner_recalculate(const float &safe_final_speed)
if ((prev->flag | current->flag) & BLOCK_FLAG_RECALCULATE) { if ((prev->flag | current->flag) & BLOCK_FLAG_RECALCULATE) {
// NOTE: Entry and exit factors always > 0 by all previous logic operations. // NOTE: Entry and exit factors always > 0 by all previous logic operations.
calculate_trapezoid_for_block(prev, prev->entry_speed, current->entry_speed); calculate_trapezoid_for_block(prev, prev->entry_speed, current->entry_speed);
#ifdef LIN_ADVANCE
if (current->use_advance_lead) {
const float comp = current->e_D_ratio * extruder_advance_K * axis_steps_per_unit[E_AXIS];
current->max_adv_steps = current->nominal_speed * comp;
current->final_adv_steps = next->entry_speed * comp;
}
#endif
// Reset current only to ensure next trapezoid is computed. // Reset current only to ensure next trapezoid is computed.
prev->flag &= ~BLOCK_FLAG_RECALCULATE; prev->flag &= ~BLOCK_FLAG_RECALCULATE;
} }
@ -410,6 +416,13 @@ void planner_recalculate(const float &safe_final_speed)
// Last/newest block in buffer. Exit speed is set with safe_final_speed. Always recalculated. // Last/newest block in buffer. Exit speed is set with safe_final_speed. Always recalculated.
current = block_buffer + prev_block_index(block_buffer_head); current = block_buffer + prev_block_index(block_buffer_head);
calculate_trapezoid_for_block(current, current->entry_speed, safe_final_speed); calculate_trapezoid_for_block(current, current->entry_speed, safe_final_speed);
#ifdef LIN_ADVANCE
if (current->use_advance_lead) {
const float comp = current->e_D_ratio * extruder_advance_K * axis_steps_per_unit[E_AXIS];
current->max_adv_steps = current->nominal_speed * comp;
current->final_adv_steps = safe_final_speed * comp;
}
#endif
current->flag &= ~BLOCK_FLAG_RECALCULATE; current->flag &= ~BLOCK_FLAG_RECALCULATE;
// SERIAL_ECHOLNPGM("planner_recalculate - 4"); // SERIAL_ECHOLNPGM("planner_recalculate - 4");
@ -720,11 +733,6 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
#endif // ENABLE_MESH_BED_LEVELING #endif // ENABLE_MESH_BED_LEVELING
target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
#ifdef LIN_ADVANCE
const float mm_D_float = sqrt(sq(x - position_float[X_AXIS]) + sq(y - position_float[Y_AXIS]));
float de_float = e - position_float[E_AXIS];
#endif
#ifdef PREVENT_DANGEROUS_EXTRUDE #ifdef PREVENT_DANGEROUS_EXTRUDE
if(target[E_AXIS]!=position[E_AXIS]) if(target[E_AXIS]!=position[E_AXIS])
{ {
@ -733,7 +741,6 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
position_float[E_AXIS] = e; position_float[E_AXIS] = e;
de_float = 0;
#endif #endif
SERIAL_ECHO_START; SERIAL_ECHO_START;
SERIAL_ECHOLNRPGM(MSG_ERR_COLD_EXTRUDE_STOP); SERIAL_ECHOLNRPGM(MSG_ERR_COLD_EXTRUDE_STOP);
@ -745,7 +752,6 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
position_float[E_AXIS] = e; position_float[E_AXIS] = e;
de_float = 0;
#endif #endif
SERIAL_ECHO_START; SERIAL_ECHO_START;
SERIAL_ECHOLNRPGM(MSG_ERR_LONG_EXTRUDE_STOP); SERIAL_ECHOLNRPGM(MSG_ERR_LONG_EXTRUDE_STOP);
@ -1017,10 +1023,50 @@ Having the real displacement of the head, we can calculate the total movement le
if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)
{ {
block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2
#ifdef LIN_ADVANCE
block->use_advance_lead = false;
#endif
} }
else else
{ {
block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2
#ifdef LIN_ADVANCE
/**
*
* Use LIN_ADVANCE for blocks if all these are true:
*
* block->steps_e : This is a print move, because we checked for X, Y, Z steps before.
*
* extruder_advance_K : There is an advance factor set.
*
* delta_mm[E_AXIS] > 0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
*/
block->use_advance_lead = block->steps_e
&& extruder_advance_K
&& delta_mm[E_AXIS] > 0;
if (block->use_advance_lead) {
block->e_D_ratio = (e - position_float[E_AXIS]) /
sqrt(sq(x - position_float[X_AXIS])
+ sq(y - position_float[Y_AXIS])
+ sq(z - position_float[Z_AXIS]));
// 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 no one will use a retract length of 0mm < retr_length < ~0.2mm and no one will print 100mm wide lines using 3mm filament or 35mm wide lines using 1.75mm filament.
if (block->e_D_ratio > 3.0)
block->use_advance_lead = false;
else {
const uint32_t max_accel_steps_per_s2 = max_jerk[E_AXIS] / (extruder_advance_K * block->e_D_ratio) * steps_per_mm;
#ifdef LA_DEBUG
if (block->acceleration_st > max_accel_steps_per_s2)
SERIAL_ECHOLNPGM("Acceleration limited.");
#endif
NOMORE(block->acceleration_st, max_accel_steps_per_s2);
}
}
#endif
// Limit acceleration per axis // Limit acceleration per axis
//FIXME Vojtech: One shall rather limit a projection of the acceleration vector instead of using the limit. //FIXME Vojtech: One shall rather limit a projection of the acceleration vector instead of using the limit.
if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS])
@ -1057,6 +1103,18 @@ 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))); block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
#ifdef LIN_ADVANCE
if (block->use_advance_lead) {
block->advance_speed = ((F_CPU) * 0.125) / (extruder_advance_K * block->e_D_ratio * block->acceleration * axis_steps_per_unit[E_AXIS]);
#ifdef LA_DEBUG
if (extruder_advance_K * block->e_D_ratio * block->acceleration * 2 < block->nominal_speed * block->e_D_ratio)
SERIAL_ECHOLNPGM("More than 2 steps per eISR loop executed.");
if (block->advance_speed < 200)
SERIAL_ECHOLNPGM("eISR running at > 10kHz.");
#endif
}
#endif
// Start with a safe speed. // Start with a safe speed.
// Safe speed is the speed, from which the machine may halt to stop immediately. // Safe speed is the speed, from which the machine may halt to stop immediately.
float safe_speed = block->nominal_speed; float safe_speed = block->nominal_speed;
@ -1173,37 +1231,6 @@ Having the real displacement of the head, we can calculate the total movement le
previous_nominal_speed = block->nominal_speed; previous_nominal_speed = block->nominal_speed;
previous_safe_speed = safe_speed; previous_safe_speed = safe_speed;
#ifdef LIN_ADVANCE
//
// Use LIN_ADVANCE for blocks if all these are true:
//
// esteps : We have E steps todo (a printing move)
//
// block->steps[X_AXIS] || block->steps[Y_AXIS] : We have a movement in XY direction (i.e., not retract / prime).
//
// extruder_advance_k : There is an advance factor set.
//
// block->steps[E_AXIS] != block->step_event_count : A problem occurs if the move before a retract is too small.
// In that case, the retract and move will be executed together.
// This leads to too many advance steps due to a huge e_acceleration.
// The math is good, but we must avoid retract moves with advance!
// de_float > 0.0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
//
block->use_advance_lead = block->steps_e
&& (block->steps_x || block->steps_y)
&& extruder_advance_k
&& (uint32_t)block->steps_e != block->step_event_count
&& de_float > 0.0;
if (block->use_advance_lead)
block->abs_adv_steps_multiplier8 = lround(
extruder_advance_k
* ((advance_ed_ratio < 0.000001) ? de_float / mm_D_float : advance_ed_ratio) // Use the fixed ratio, if set
* (block->nominal_speed / (float)block->nominal_rate)
* axis_steps_per_unit[E_AXIS] * 256.0
);
#endif
// Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated. // 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; block->speed_factor = block->nominal_rate / block->nominal_speed;
calculate_trapezoid_for_block(block, block->entry_speed, safe_speed); calculate_trapezoid_for_block(block, block->entry_speed, safe_speed);
@ -1297,7 +1324,7 @@ void plan_set_position(float x, float y, float z, const float &e)
void plan_set_z_position(const float &z) void plan_set_z_position(const float &z)
{ {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
position_float[Z_AXIS] = z; position_float[Z_AXIS] = z;
#endif #endif
position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]); st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]);
@ -1306,7 +1333,7 @@ void plan_set_z_position(const float &z)
void plan_set_e_position(const float &e) void plan_set_e_position(const float &e)
{ {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
position_float[E_AXIS] = e; position_float[E_AXIS] = e;
#endif #endif
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
st_set_e_position(position[E_AXIS]); st_set_e_position(position[E_AXIS]);

View File

@ -91,12 +91,15 @@ typedef struct {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
bool use_advance_lead; bool use_advance_lead;
unsigned long abs_adv_steps_multiplier8; // Factorised by 2^8 to avoid float uint16_t advance_speed, // Timer value for extruder speed offset
max_adv_steps, // max. advance steps to get cruising speed pressure (not always nominal_speed!)
final_adv_steps; // advance steps due to exit speed
float e_D_ratio;
#endif #endif
} block_t; } block_t;
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
extern float extruder_advance_k, advance_ed_ratio; extern float extruder_advance_K;
#endif #endif
#ifdef ENABLE_AUTO_BED_LEVELING #ifdef ENABLE_AUTO_BED_LEVELING

View File

@ -95,18 +95,21 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
uint16_t ADV_NEVER = 65535; static uint32_t LA_decelerate_after;
static const uint16_t ADV_NEVER = 65535;
static uint16_t nextMainISR = 0; static uint16_t nextMainISR = 0;
static uint16_t nextAdvanceISR = ADV_NEVER; static uint16_t nextAdvanceISR = ADV_NEVER;
static uint16_t eISR_Rate = ADV_NEVER; static uint16_t eISR_Rate = ADV_NEVER;
static uint16_t current_adv_steps = 0;
static uint16_t final_adv_steps;
static uint16_t max_adv_steps;
static volatile int e_steps; //Extrusion steps to be executed by the stepper static volatile int8_t e_steps = 0;
static int final_estep_rate; //Speed of extruder at cruising speed
static int current_estep_rate; //The current speed of the extruder static bool use_advance_lead;
static int current_adv_steps; //The current pretension of filament expressed in steps
#define ADV_RATE(T, L) (e_steps ? (T) * (L) / abs(e_steps) : ADV_NEVER)
#define _NEXT_ISR(T) nextMainISR = T #define _NEXT_ISR(T) nextMainISR = T
#else #else
@ -320,9 +323,13 @@ void trapezoid_generator_reset() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) { if (current_block->use_advance_lead) {
current_estep_rate = ((unsigned long)acc_step_rate * current_block->abs_adv_steps_multiplier8) >> 17; LA_decelerate_after = current_block->decelerate_after;
final_estep_rate = (current_block->nominal_rate * current_block->abs_adv_steps_multiplier8) >> 17; final_adv_steps = current_block->final_adv_steps;
max_adv_steps = current_block->max_adv_steps;
use_advance_lead = true;
} }
else
use_advance_lead = false;
#endif #endif
} }
@ -637,16 +644,6 @@ void isr() {
step_events_completed += 1; step_events_completed += 1;
if(step_events_completed >= current_block->step_event_count) break; if(step_events_completed >= current_block->step_event_count) break;
} }
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
const int delta_adv_steps = current_estep_rate - current_adv_steps;
current_adv_steps += delta_adv_steps;
e_steps += delta_adv_steps;
}
// If we have esteps to execute, fire the next advance_isr "now"
if (e_steps) nextAdvanceISR = 0;
#endif
// Calculare new timer value // Calculare new timer value
unsigned short timer; unsigned short timer;
@ -667,9 +664,15 @@ void isr() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) { if (current_block->use_advance_lead) {
current_estep_rate = ((uint32_t)acc_step_rate * current_block->abs_adv_steps_multiplier8) >> 17; if (step_events_completed == step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) {
nextAdvanceISR = 0; // Wake up eISR on first acceleration loop and fire ISR if final adv_rate is reached
eISR_Rate = current_block->advance_speed;
}
}
else {
eISR_Rate = ADV_NEVER;
if (e_steps) nextAdvanceISR = 0;
} }
eISR_Rate = ADV_RATE(timer, step_loops);
#endif #endif
} }
else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
@ -693,17 +696,21 @@ void isr() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) { if (current_block->use_advance_lead) {
current_estep_rate = ((uint32_t)step_rate * current_block->abs_adv_steps_multiplier8) >> 17; if (step_events_completed <= (uint32_t)current_block->decelerate_after + step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) {
nextAdvanceISR = 0; // Wake up eISR on first deceleration loop
eISR_Rate = current_block->advance_speed;
}
}
else {
eISR_Rate = ADV_NEVER;
if (e_steps) nextAdvanceISR = 0;
} }
eISR_Rate = ADV_RATE(timer, step_loops);
#endif #endif
} }
else { else {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) // If we have esteps to execute, fire the next advance_isr "now"
current_estep_rate = final_estep_rate; if (e_steps && eISR_Rate != current_block->advance_speed) nextAdvanceISR = 0;
eISR_Rate = ADV_RATE(OCR1A_nominal, step_loops_nominal);
#endif #endif
_NEXT_ISR(OCR1A_nominal); _NEXT_ISR(OCR1A_nominal);
@ -729,6 +736,26 @@ void isr() {
void advance_isr() { void advance_isr() {
if (current_block->use_advance_lead) {
if (step_events_completed > LA_decelerate_after && current_adv_steps > final_adv_steps) {
e_steps--;
current_adv_steps--;
nextAdvanceISR = eISR_Rate;
}
else if (step_events_completed < LA_decelerate_after && current_adv_steps < max_adv_steps) {
//step_events_completed <= (uint32_t)current_block->accelerate_until) {
e_steps++;
current_adv_steps++;
nextAdvanceISR = eISR_Rate;
}
else {
nextAdvanceISR = ADV_NEVER;
eISR_Rate = ADV_NEVER;
}
}
else
nextAdvanceISR = ADV_NEVER;
if (e_steps) { if (e_steps) {
bool dir = bool dir =
#ifdef SNMM #ifdef SNMM
@ -739,16 +766,12 @@ void isr() {
? INVERT_E0_DIR : !INVERT_E0_DIR; //If we have SNMM, reverse every second extruder. ? INVERT_E0_DIR : !INVERT_E0_DIR; //If we have SNMM, reverse every second extruder.
WRITE(E0_DIR_PIN, dir); WRITE(E0_DIR_PIN, dir);
for (uint8_t i = step_loops; e_steps && i--;) { while (e_steps) {
WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
e_steps < 0 ? ++e_steps : --e_steps; e_steps < 0 ? ++e_steps : --e_steps;
WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN);
} }
} }
else{
eISR_Rate = ADV_NEVER;
}
nextAdvanceISR = eISR_Rate;
} }
void advance_isr_scheduler() { void advance_isr_scheduler() {