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-11795 Activate fans during switch #2107

Merged
merged 10 commits into from
Jul 3, 2024
32 changes: 24 additions & 8 deletions include/gcodeExport.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#ifdef BUILD_TESTS
#include <gtest/gtest_prod.h> //To allow tests to use protected members.
#endif
#include <optional>
#include <sstream> // for stream.str()
#include <stdio.h>

Expand Down Expand Up @@ -89,7 +90,7 @@ class GCodeExport : public NoCopy

double last_e_value_after_wipe_; //!< The current material amount extruded since last wipe

unsigned fan_number_; // nozzle print cooling fan number
size_t fan_number_; // nozzle print cooling fan number
Point2LL nozzle_offset_; //!< Cache of setting machine_nozzle_offset_[xy]
bool machine_firmware_retract_; //!< Cache of setting machine_firmware_retract

Expand Down Expand Up @@ -150,8 +151,8 @@ class GCodeExport : public NoCopy
//!< other layer parts)

size_t current_extruder_;
double current_fan_speed_;
unsigned fan_number_; // current print cooling fan number
std::map<size_t, double> current_fans_speeds_; //!< Current fan speed, by fan index. No value means the speed has never been set yet.
size_t fans_count_{ 0 };
EGCodeFlavor flavor_;

std::vector<Duration> total_print_times_; //!< The total estimated print time in seconds for each feature
Expand Down Expand Up @@ -533,13 +534,28 @@ class GCodeExport : public NoCopy
void writePrimeTrain(const Velocity& travel_speed);

/*!
* Set the print cooling fan number (used as P parameter to M10[67]) for the specified extruder
*
* \param extruder The current extruder
* \brief Write a set fan speed command, if different from the actual speed
* \param speed The new fan speed, which should be [0.0, 100.0]
* \param extruder The extruder for which we want to set the cooling fan speed, or nullopt to use the current extruder
*/
void writeFanCommand(double speed, std::optional<size_t> extruder = std::nullopt);

/*!
* \brief Write a set fan speed command for the given fan, if different from the actual speed
* \param speed The new fan speed, which should be [0.0, 100.0]
* \param fan_number The fan for which we want to set the speed
*/
void setExtruderFanNumber(int extruder);
void writeSpecificFanCommand(double speed, size_t fan_number);

void writeFanCommand(double speed);
/*! Write cooling fan speeds before proceeding an extruder switch */
void writePrepareFansForNozzleSwitch();

/*!
* \brief Write the cooling fan speeds before starting an actual extrusion
* \param current_extruder_new_speed The new speed for the currently active extruder
* \note All other cooling fans but the active one will be deactivaed
*/
void writePrepareFansForExtrusion(double current_extruder_new_speed);

/*!
* \brief Write a GCode temperature command
Expand Down
10 changes: 10 additions & 0 deletions include/settings/EnumSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,16 @@ enum class BrimLocation
EVERYWHERE = 0x03, // Brim on both the outside and inside of the model
};

/*!
* How to enable/disable cooling fan(s) during extruder switch
*/
enum class CoolDuringExtruderSwitch
{
UNCHANGED, // Let fans as they are during nozzle switch (historical behavior)
ONLY_LAST_EXTRUDER, // Turn on fan of the previously used extruder to cool it down, turn others off
ALL_FANS, // Turn on all fans
};

/*!
* Convenience binary operator to allow testing brim location easily, like (actual_location & BrimLocation::OUTSIDE)
*/
Expand Down
4 changes: 3 additions & 1 deletion src/LayerPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,8 @@ void LayerPlan::writeGCode(GCodeExport& gcode)
gcode.switchExtruder(extruder_nr, prev_retraction_config.extruder_switch_retraction_config);
}

gcode.writePrepareFansForNozzleSwitch();

{ // require printing temperature to be met
constexpr bool wait = true;
gcode.writeTemperatureCommand(extruder_nr, extruder_plan.required_start_temperature_, wait);
Expand Down Expand Up @@ -2121,7 +2123,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode)
}
}
}
gcode.writeFanCommand(extruder_plan.getFanSpeed());
gcode.writePrepareFansForExtrusion(extruder_plan.getFanSpeed());
std::vector<GCodePath>& paths = extruder_plan.paths_;

extruder_plan.inserts_.sort();
Expand Down
86 changes: 67 additions & 19 deletions src/gcodeExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ GCodeExport::GCodeExport()

current_e_value_ = 0;
current_extruder_ = 0;
current_fan_speed_ = -1;

total_print_times_ = std::vector<Duration>(static_cast<unsigned char>(PrintFeatureType::NumPrintFeatureTypes), 0.0);

Expand All @@ -64,7 +63,6 @@ GCodeExport::GCodeExport()
machine_heated_build_volume_ = false;
ppr_enable_ = false;

fan_number_ = 0;
use_extruder_offset_to_offset_coords_ = false;
machine_name_ = "";
relative_extrusion_ = false;
Expand Down Expand Up @@ -96,6 +94,7 @@ void GCodeExport::preSetup(const size_t start_extruder)
extruder_attr_[extruder_nr].last_retraction_prime_speed_
= train.settings_.get<Velocity>("retraction_prime_speed"); // the alternative would be switch_extruder_prime_speed, but dual extrusion might not even be configured...
extruder_attr_[extruder_nr].fan_number_ = train.settings_.get<size_t>("machine_extruder_cooling_fan_number");
fans_count_ = std::max(fans_count_, extruder_attr_[extruder_nr].fan_number_ + 1);

// Cache some settings that we use frequently.
const Settings& extruder_settings = Application::getInstance().current_slice_->scene.extruders[extruder_nr].settings_;
Expand Down Expand Up @@ -747,8 +746,6 @@ bool GCodeExport::initializeExtruderTrains(const SliceDataStorage& storage, cons
}
}

setExtruderFanNumber(start_extruder_nr);

return should_prime_extruder;
}

Expand Down Expand Up @@ -1313,8 +1310,6 @@ void GCodeExport::startExtruder(const size_t new_extruder)

// Change the Z position so it gets re-written again. We do not know if the switch code modified the Z position.
current_position_.z_ += 1;

setExtruderFanNumber(new_extruder);
}

void GCodeExport::switchExtruder(size_t new_extruder, const RetractionConfig& retraction_config_old_extruder, coord_t perform_z_hop /*= 0*/)
Expand Down Expand Up @@ -1429,21 +1424,23 @@ void GCodeExport::writePrimeTrain(const Velocity& travel_speed)
extruder_attr_[current_extruder_].is_primed_ = true;
}

void GCodeExport::setExtruderFanNumber(int extruder)
void GCodeExport::writeFanCommand(double speed, std::optional<size_t> extruder)
{
if (extruder_attr_[extruder].fan_number_ != fan_number_)
{
fan_number_ = extruder_attr_[extruder].fan_number_;
current_fan_speed_ = -1; // ensure fan speed gcode gets output for this fan
}
const size_t extruder_set_fan = extruder.value_or(current_extruder_);
const size_t fan_number = extruder_attr_[extruder_set_fan].fan_number_;

writeSpecificFanCommand(speed, fan_number);
}

void GCodeExport::writeFanCommand(double speed)
void GCodeExport::writeSpecificFanCommand(double speed, size_t fan_number)
{
if (std::abs(current_fan_speed_ - speed) < 0.1)
auto iterator = current_fans_speeds_.find(fan_number);

if (iterator != current_fans_speeds_.end() && std::abs(iterator->second - speed) < 0.1)
{
return;
}

if (flavor_ == EGCodeFlavor::MAKERBOT)
{
if (speed >= 50)
Expand All @@ -1461,23 +1458,23 @@ void GCodeExport::writeFanCommand(double speed)
*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_)
if (fan_number)
{
*output_stream_ << " P" << fan_number_;
*output_stream_ << " P" << fan_number;
}
*output_stream_ << new_line_;
}
else
{
*output_stream_ << "M107";
if (fan_number_)
if (fan_number)
{
*output_stream_ << " P" << fan_number_;
*output_stream_ << " P" << fan_number;
}
*output_stream_ << new_line_;
}

current_fan_speed_ = speed;
current_fans_speeds_[fan_number] = speed;
}

void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait, const bool force_write_on_equal)
Expand Down Expand Up @@ -1745,6 +1742,57 @@ void GCodeExport::insertWipeScript(const WipeScriptConfig& wipe_config)
writeComment("WIPE_SCRIPT_END");
}

void GCodeExport::writePrepareFansForNozzleSwitch()
{
const Settings& settings = Application::getInstance().current_slice_->scene.settings;
const auto cool_during_switch = settings.get<CoolDuringExtruderSwitch>("cool_during_extruder_switch");

if (cool_during_switch != CoolDuringExtruderSwitch::UNCHANGED)
{
const size_t current_extruder_fan_number = extruder_attr_[current_extruder_].fan_number_;

for (size_t fan_number = 0; fan_number < fans_count_; ++fan_number)
{
double fan_speed;
if (cool_during_switch == CoolDuringExtruderSwitch::ALL_FANS || fan_number == current_extruder_fan_number)
{
fan_speed = 100.0;
}
else
{
fan_speed = 0.0;
}

writeSpecificFanCommand(fan_speed, fan_number);
}
}
}

void GCodeExport::writePrepareFansForExtrusion(double current_extruder_new_speed)
{
const Settings& settings = Application::getInstance().current_slice_->scene.settings;
const auto cool_during_switch = settings.get<CoolDuringExtruderSwitch>("cool_during_extruder_switch");
const size_t current_extruder_fan_number = extruder_attr_[current_extruder_].fan_number_;

for (size_t fan_number = 0; fan_number < fans_count_; ++fan_number)
{
double new_fan_speed;
if (fan_number == current_extruder_fan_number)
{
new_fan_speed = current_extruder_new_speed;
}
else if (cool_during_switch == CoolDuringExtruderSwitch::UNCHANGED)
{
continue;
}
else
{
new_fan_speed = 0.0;
}
writeSpecificFanCommand(new_fan_speed, fan_number);
}
}

void GCodeExport::setSliceUUID(const std::string& slice_uuid)
{
slice_uuid_ = slice_uuid;
Expand Down
18 changes: 18 additions & 0 deletions src/settings/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,24 @@ BrimLocation Settings::get<BrimLocation>(const std::string& key) const
}
}

template<>
CoolDuringExtruderSwitch Settings::get<CoolDuringExtruderSwitch>(const std::string& key) const
{
const std::string& value = get<std::string>(key);
if (value == "all_fans")
{
return CoolDuringExtruderSwitch::ALL_FANS;
}
else if (value == "only_last_extruder")
{
return CoolDuringExtruderSwitch::ONLY_LAST_EXTRUDER;
}
else // Default.
{
return CoolDuringExtruderSwitch::UNCHANGED;
}
}

template<>
std::vector<double> Settings::get<std::vector<double>>(const std::string& key) const
{
Expand Down
4 changes: 0 additions & 4 deletions tests/GCodeExportTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class GCodeExportTest : public testing::Test
gcode.current_e_value_ = 0;
gcode.current_e_offset_ = 0;
gcode.current_extruder_ = 0;
gcode.current_fan_speed_ = -1;
gcode.total_print_times_ = std::vector<Duration>(static_cast<unsigned char>(PrintFeatureType::NumPrintFeatureTypes), 0.0);
gcode.current_speed_ = 1.0;
gcode.current_print_acceleration_ = -1.0;
Expand All @@ -61,7 +60,6 @@ class GCodeExportTest : public testing::Test
gcode.setFlavor(EGCodeFlavor::MARLIN);
gcode.bed_temperature_ = 0;
gcode.initial_bed_temp_ = 0;
gcode.fan_number_ = 0;
gcode.total_bounding_box_ = AABB3D();
gcode.current_layer_z_ = 0;
gcode.relative_extrusion_ = false;
Expand Down Expand Up @@ -211,7 +209,6 @@ class GriffinHeaderTest : public testing::TestWithParam<size_t>
gcode.layer_nr_ = 0;
gcode.current_e_value_ = 0;
gcode.current_extruder_ = 0;
gcode.current_fan_speed_ = -1;
gcode.total_print_times_ = std::vector<Duration>(static_cast<unsigned char>(PrintFeatureType::NumPrintFeatureTypes), 0.0);
gcode.current_speed_ = 1.0;
gcode.current_print_acceleration_ = -1.0;
Expand All @@ -221,7 +218,6 @@ class GriffinHeaderTest : public testing::TestWithParam<size_t>
gcode.setFlavor(EGCodeFlavor::MARLIN);
gcode.initial_bed_temp_ = 0;
gcode.bed_temperature_ = 0;
gcode.fan_number_ = 0;
gcode.total_bounding_box_ = AABB3D();

gcode.new_line_ = "\n"; // Not BFB flavour by default.
Expand Down
3 changes: 3 additions & 0 deletions tests/LayerPlanTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,19 @@ class LayerPlanTest : public testing::Test
settings->add("raft_surface_layers", "1");
settings->add("raft_base_line_width", "0.401");
settings->add("raft_base_acceleration", "5001");
settings->add("raft_base_flow", "100");
settings->add("raft_base_jerk", "5.1");
settings->add("raft_base_speed", "51");
settings->add("raft_base_thickness", "0.101");
settings->add("raft_interface_acceleration", "5002");
settings->add("raft_interface_flow", "100");
settings->add("raft_interface_jerk", "5.2");
settings->add("raft_interface_line_width", "0.402");
settings->add("raft_interface_speed", "52");
settings->add("raft_interface_thickness", "0.102");
settings->add("raft_interface_layers", "3");
settings->add("raft_surface_acceleration", "5003");
settings->add("raft_surface_flow", "100");
settings->add("raft_surface_jerk", "5.3");
settings->add("raft_surface_line_width", "0.403");
settings->add("raft_surface_speed", "53");
Expand Down
Loading