Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CURA-6410 buggy fan speed interpolation #2111

Merged
merged 8 commits into from
Jul 5, 2024
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