diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 2dc685e843..580d575675 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -9553,7 +9553,7 @@ inline void gcode_M400() { stepper.synchronize(); } } if (filwidth_delay_index[1] == -1) { // Initialize the ring buffer if not done since startup - const uint8_t temp_ratio = thermalManager.widthFil_to_size_ratio() - 100; // -100 to scale within a signed byte + const uint8_t temp_ratio = thermalManager.widthFil_to_size_ratio(); for (uint8_t i = 0; i < COUNT(measurement_delay); ++i) measurement_delay[i] = temp_ratio; @@ -9562,11 +9562,6 @@ inline void gcode_M400() { stepper.synchronize(); } } filament_sensor = true; - - //SERIAL_PROTOCOLPGM("Filament dia (measured mm):"); - //SERIAL_PROTOCOL(filament_width_meas); - //SERIAL_PROTOCOLPGM("Extrusion ratio(%):"); - //SERIAL_PROTOCOL(planner.flow_percentage[active_extruder]); } /** diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 67cf0b3911..d9d7deed85 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -550,10 +550,19 @@ void Planner::check_axes_activity() { #endif } +/** + * Get a volumetric multiplier from a filament diameter. + * This is the reciprocal of the circular cross-section area. + * Return 1.0 with volumetric off or a diameter of 0.0. + */ inline float calculate_volumetric_multiplier(const float &diameter) { return (parser.volumetric_enabled && diameter) ? 1.0 / CIRCLE_AREA(diameter * 0.5) : 1.0; } +/** + * Convert the filament sizes into volumetric multipliers. + * The multiplier converts a given E value into a length. + */ void Planner::calculate_volumetric_multipliers() { for (uint8_t i = 0; i < COUNT(filament_size); i++) { volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]); @@ -561,6 +570,25 @@ void Planner::calculate_volumetric_multipliers() { } } +#if ENABLED(FILAMENT_WIDTH_SENSOR) + /** + * Convert the ratio value given by the filament width sensor + * into a volumetric multiplier. Conversion differs when using + * linear extrusion vs volumetric extrusion. + */ + void Planner::calculate_volumetric_for_width_sensor(const int8_t encoded_ratio) { + // Reconstitute the nominal/measured ratio + const float nom_meas_ratio = 1.0 + 0.01 * encoded_ratio, + ratio_2 = sq(nom_meas_ratio); + + volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = parser.volumetric_enabled + ? ratio_2 / CIRCLE_AREA(filament_width_nominal * 0.5) // Volumetric uses a true volumetric multiplier + : ratio_2; // Linear squares the ratio, which scales the volume + + refresh_e_factor(FILAMENT_SENSOR_EXTRUDER_NUM); + } +#endif + #if PLANNER_LEVELING /** * rx, ry, rz - Cartesian positions in mm @@ -1046,7 +1074,7 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE], float fr_mm_s, const // If the index has changed (must have gone forward)... if (filwidth_delay_index[0] != filwidth_delay_index[1]) { filwidth_e_count = 0; // Reset the E movement counter - const uint8_t meas_sample = thermalManager.widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char + const uint8_t meas_sample = thermalManager.widthFil_to_size_ratio(); do { filwidth_delay_index[1] = (filwidth_delay_index[1] + 1) % MMD_CM; // The next unused slot measurement_delay[filwidth_delay_index[1]] = meas_sample; // Store the measurement diff --git a/Marlin/planner.h b/Marlin/planner.h index 631ccf4004..57160748d3 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -289,6 +289,10 @@ class Planner { // Update multipliers based on new diameter measurements static void calculate_volumetric_multipliers(); + #if ENABLED(FILAMENT_WIDTH_SENSOR) + void calculate_volumetric_for_width_sensor(const int8_t encoded_ratio); + #endif + FORCE_INLINE static void set_filament_size(const uint8_t e, const float &v) { filament_size[e] = v; // make sure all extruders have some sane value for the filament size diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index afc2f7b29b..48db5a8b62 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -723,7 +723,7 @@ void Stepper::isr() { // step_rate to timer interval const uint16_t interval = calc_timer_interval(acc_step_rate); - SPLIT(interval); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL + SPLIT(interval); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL _NEXT_ISR(ocr_val); acceleration_time += interval; @@ -756,7 +756,7 @@ void Stepper::isr() { // step_rate to timer interval const uint16_t interval = calc_timer_interval(step_rate); - SPLIT(interval); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL + SPLIT(interval); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL _NEXT_ISR(ocr_val); deceleration_time += interval; @@ -786,7 +786,7 @@ void Stepper::isr() { #endif - SPLIT(OCR1A_nominal); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL + SPLIT(OCR1A_nominal); // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL _NEXT_ISR(ocr_val); // ensure we're running at the correct step rate, even if we just came off an acceleration diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 8a0786e06e..7c6633d2ad 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -736,17 +736,6 @@ float Temperature::get_pid_output(const int8_t e) { * - Apply filament width to the extrusion rate (may move) * - Update the heated bed PID output value */ - -/** - * The following line SOMETIMES results in the dreaded "unable to find a register to spill in class 'POINTER_REGS'" - * compile error. - * thermal_runaway_protection(&thermal_runaway_state_machine[e], &thermal_runaway_timer[e], current_temperature[e], target_temperature[e], e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS); - * - * This is due to a bug in the C++ compiler used by the Arduino IDE from 1.6.10 to at least 1.8.1. - * - * The work around is to add the compiler flag "__attribute__((__optimize__("O2")))" to the declaration for manage_heater() - */ -//void Temperature::manage_heater() __attribute__((__optimize__("O2"))); void Temperature::manage_heater() { if (!temp_meas_ready) return; @@ -801,19 +790,16 @@ void Temperature::manage_heater() { } #endif - // Control the extruder rate based on the width sensor #if ENABLED(FILAMENT_WIDTH_SENSOR) + /** + * Filament Width Sensor dynamically sets the volumetric multiplier + * based on a delayed measurement of the filament diameter. + */ if (filament_sensor) { meas_shift_index = filwidth_delay_index[0] - meas_delay_cm; if (meas_shift_index < 0) meas_shift_index += MAX_MEASUREMENT_DELAY + 1; //loop around buffer if needed meas_shift_index = constrain(meas_shift_index, 0, MAX_MEASUREMENT_DELAY); - - // Get the delayed info and add 100 to reconstitute to a percent of - // the nominal filament diameter then square it to get an area - float vmroot = measurement_delay[meas_shift_index] * 0.01 + 1.0; - NOLESS(vmroot, 0.1); - planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = 1.0 / CIRCLE_AREA(vmroot / 2); - planner.refresh_e_factor(FILAMENT_SENSOR_EXTRUDER_NUM); + calculate_volumetric_for_width_sensor(measurement_delay[meas_shift_index]) } #endif // FILAMENT_WIDTH_SENSOR @@ -999,15 +985,20 @@ void Temperature::updateTemperaturesFromRawValues() { // Convert raw Filament Width to millimeters float Temperature::analog2widthFil() { return current_raw_filwidth * 5.0 * (1.0 / 16383.0); - //return current_raw_filwidth; } - // Convert raw Filament Width to a ratio - int Temperature::widthFil_to_size_ratio() { - float temp = filament_width_meas; - if (temp < MEASURED_LOWER_LIMIT) temp = filament_width_nominal; //assume sensor cut out - else NOMORE(temp, MEASURED_UPPER_LIMIT); - return filament_width_nominal / temp * 100; + /** + * Convert Filament Width (mm) to a simple ratio + * and reduce to an 8 bit value. + * + * A nominal width of 1.75 and measured width of 1.73 + * gives (100 * 1.75 / 1.73) for a ratio of 101 and + * a return value of 1. + */ + int8_t Temperature::widthFil_to_size_ratio() { + if (WITHIN(filament_width_meas, MEASURED_LOWER_LIMIT, MEASURED_UPPER_LIMIT)) + return int(100.0 * filament_width_nominal / filament_width_meas) - 100; + return 0; } #endif diff --git a/Marlin/temperature.h b/Marlin/temperature.h index f67c7d83d4..7dcef24bb0 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -333,8 +333,8 @@ class Temperature { #endif #if ENABLED(FILAMENT_WIDTH_SENSOR) - static float analog2widthFil(); // Convert raw Filament Width to millimeters - static int widthFil_to_size_ratio(); // Convert raw Filament Width to an extrusion ratio + static float analog2widthFil(); // Convert raw Filament Width to millimeters + static int8_t widthFil_to_size_ratio(); // Convert Filament Width (mm) to an extrusion ratio #endif diff --git a/Marlin/ultralcd_impl_DOGM.h b/Marlin/ultralcd_impl_DOGM.h index 57f4b8330f..2ecb8233b4 100644 --- a/Marlin/ultralcd_impl_DOGM.h +++ b/Marlin/ultralcd_impl_DOGM.h @@ -650,10 +650,12 @@ static void lcd_implementation_status_screen() { strcpy(zstring, ftostr52sp(FIXFLOAT(LOGICAL_Z_POSITION(current_position[Z_AXIS])))); #if ENABLED(FILAMENT_LCD_DISPLAY) strcpy(wstring, ftostr12ns(filament_width_meas)); - if (parser.volumetric_enabled) - strcpy(mstring, itostr3(100.0 * planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM])); - else - strcpy_P(mstring, PSTR("---")); + strcpy(mstring, itostr3(100.0 * ( + parser.volumetric_enabled + ? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] + : planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] + ) + )); #endif } diff --git a/Marlin/ultralcd_impl_HD44780.h b/Marlin/ultralcd_impl_HD44780.h index 4baa4820b8..5a8fd5fad8 100644 --- a/Marlin/ultralcd_impl_HD44780.h +++ b/Marlin/ultralcd_impl_HD44780.h @@ -881,12 +881,13 @@ static void lcd_implementation_status_screen() { lcd_printPGM(PSTR("Dia ")); lcd.print(ftostr12ns(filament_width_meas)); lcd_printPGM(PSTR(" V")); - if (parser.volumetric_enabled) { - lcd.print(itostr3(100.0 * planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM])); - lcd.write('%'); - } - else - lcd_printPGM(PSTR("--- ")); + lcd.print(itostr3(100.0 * ( + parser.volumetric_enabled + ? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] + : planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] + ) + )); + lcd.write('%'); return; }