Skip to content

Commit

Permalink
CURA-6410 buggy fan speed interpolation (#2111)
Browse files Browse the repository at this point in the history
  • Loading branch information
HellAholic committed Jul 5, 2024
2 parents d2851fd + 9040b6a commit ac9584b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 46 deletions.
6 changes: 6 additions & 0 deletions include/utils/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef UTILS_STRING_H
#define UTILS_STRING_H

#include <cmath>
#include <cstdio> // sprintf
#include <ctype.h>
#include <sstream> // ostringstream
Expand Down Expand Up @@ -169,6 +170,11 @@ struct PrecisionedDouble
uint8_t precision; //!< Number of digits after the decimal mark with which to convert to string
double value; //!< The double value

bool wouldWriteZero() const
{
return (std::abs(value) * std::pow(10.0, precision)) < 1.0;
}

friend inline std::ostream& operator<<(std::ostream& out, const PrecisionedDouble precision_and_input)
{
writeDoubleToStream(precision_and_input.precision, precision_and_input.value, out);
Expand Down
29 changes: 7 additions & 22 deletions src/LayerPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1881,7 +1881,8 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates(Point2LL starting_

void ExtruderPlan::processFanSpeedForMinimalLayerTime(Duration minTime, double time_other_extr_plans)
{
/*
/* interpolate fan speed
min layer time
:
: min layer time fan speed min
Expand All @@ -1892,28 +1893,12 @@ void ExtruderPlan::processFanSpeedForMinimalLayerTime(Duration minTime, double t
speed min..|... \:___________
|________________
layer time >
*/
// interpolate fan speed (for cool_fan_full_layer and for cool_min_layer_time_fan_speed_max)
double totalLayerTime = estimates_.getTotalTime() + time_other_extr_plans;
if (totalLayerTime < minTime)
{
fan_speed = fan_speed_layer_time_settings_.cool_fan_speed_max;
}
else if (minTime >= fan_speed_layer_time_settings_.cool_min_layer_time_fan_speed_max)
{
// ignore gradual increase of fan speed
return;
}
else if (totalLayerTime < fan_speed_layer_time_settings_.cool_min_layer_time_fan_speed_max)
{
// when forceMinimalLayerTime didn't change the extrusionSpeedFactor, we adjust the fan speed
double fan_speed_diff = fan_speed_layer_time_settings_.cool_fan_speed_max - fan_speed;
double layer_time_diff = fan_speed_layer_time_settings_.cool_min_layer_time_fan_speed_max - minTime;
double fraction_of_slope = (totalLayerTime - minTime) / layer_time_diff;
fan_speed = fan_speed_layer_time_settings_.cool_fan_speed_max - fan_speed_diff * fraction_of_slope;
}

const double total_layer_time = estimates_.getTotalTime() + time_other_extr_plans;
const double layer_time_diff = fan_speed_layer_time_settings_.cool_min_layer_time_fan_speed_max - minTime;
const double fraction_of_slope = std::clamp((total_layer_time - minTime) / layer_time_diff, 0.0, 1.0);
fan_speed = std::lerp(fan_speed_layer_time_settings_.cool_fan_speed_max, fan_speed, fraction_of_slope);
}

void ExtruderPlan::processFanSpeedForFirstLayers()
Expand Down
75 changes: 51 additions & 24 deletions src/gcodeExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1434,44 +1434,71 @@ void GCodeExport::writeFanCommand(double speed, std::optional<size_t> extruder)

void GCodeExport::writeSpecificFanCommand(double speed, size_t fan_number)
{
auto iterator = current_fans_speeds_.find(fan_number);

if (iterator != current_fans_speeds_.end() && std::abs(iterator->second - speed) < 0.1)
{
return;
}
const auto iterator = current_fans_speeds_.find(fan_number);
const std::optional<double> current_fan_speed = (iterator != current_fans_speeds_.end()) ? std::optional<double>(iterator->second) : std::nullopt;

if (flavor_ == EGCodeFlavor::MAKERBOT)
{
if (speed >= 50)
// Makerbot cannot PWM the fan speed, only turn it on or off

bool write_value = true;
const bool new_on = speed >= 50;
if (current_fan_speed.has_value())
{
*output_stream_ << "M126 T0" << new_line_; // Makerbot cannot PWM the fan speed...
const bool old_on = current_fan_speed.value() >= 50;
write_value = new_on != old_on;
}
else

if (write_value)
{
*output_stream_ << "M127 T0" << new_line_;
if (new_on)
{
*output_stream_ << "M126 T0" << new_line_;
}
else
{
*output_stream_ << "M127 T0" << new_line_;
}
}
}
else if (speed > 0)
else
{
const bool should_scale_zero_to_one = Application::getInstance().current_slice_->scene.settings.get<bool>("machine_scale_fan_speed_zero_to_one");
*output_stream_ << "M106 S"
<< PrecisionedDouble{ (should_scale_zero_to_one ? static_cast<uint8_t>(2) : static_cast<uint8_t>(1)),
(should_scale_zero_to_one ? speed : speed * 255) / 100 };
if (fan_number)
const auto scale_zero_to_one_optional = [should_scale_zero_to_one](double value) -> PrecisionedDouble
{
return { (should_scale_zero_to_one ? static_cast<uint8_t>(2) : static_cast<uint8_t>(1)), (should_scale_zero_to_one ? value : value * 255.0) / 100.0 };
};
bool write_value = true;
std::ostringstream new_value;
const auto num_new_val = scale_zero_to_one_optional(speed);
new_value << num_new_val;
const std::string new_value_str = new_value.str();
if (current_fan_speed.has_value())
{
*output_stream_ << " P" << fan_number;
std::ostringstream old_value;
old_value << scale_zero_to_one_optional(current_fan_speed.value());
write_value = new_value_str != old_value.str();
}
*output_stream_ << new_line_;
}
else
{
*output_stream_ << "M107";
if (fan_number)

if (write_value)
{
*output_stream_ << " P" << fan_number;
if (num_new_val.wouldWriteZero())
{
// Turn off when the fan value is zero.
*output_stream_ << "M107";
}
else
{
*output_stream_ << "M106 S" << new_value_str;
}

if (fan_number)
{
*output_stream_ << " P" << fan_number;
}

*output_stream_ << new_line_;
}
*output_stream_ << new_line_;
}

current_fans_speeds_[fan_number] = speed;
Expand Down

0 comments on commit ac9584b

Please sign in to comment.