Skip to content

Commit

Permalink
new: fan startup delay. (or advanced speed-up)
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Feb 21, 2019
1 parent aec5a56 commit c623985
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 6 deletions.
18 changes: 17 additions & 1 deletion src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2452,11 +2452,27 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
return gcode;
}


void GCode::_post_process(std::string& what) {
//if enabled, move the fan startup earlier.
if (this->config().fan_speedup_time.value != 0) {
FanMover fen_post_process(std::abs(this->config().fan_speedup_time.value), this->config().fan_speedup_time.value>0);
what = fen_post_process.process_gcode(what);
}
}

void GCode::_write(FILE* file, const char *what)
{
if (what != nullptr) {

//const char * gcode_pp = _post_process(what).c_str();
std::string str_preproc = what;
_post_process(str_preproc);

const std::string str_ana = m_analyzer.process_gcode(str_preproc);

// apply analyzer, if enabled
const char* gcode = m_enable_analyzer ? m_analyzer.process_gcode(what).c_str() : what;
const char * gcode = m_enable_analyzer ? str_ana.c_str() : str_preproc.c_str();

// writes string to file
fwrite(gcode, 1, ::strlen(gcode), file);
Expand Down
4 changes: 4 additions & 0 deletions src/libslic3r/GCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ class GCode : ExtrusionVisitor {
// Write a string into a file.
void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str()); }
void _write(FILE* file, const char *what);


// Write a string into a file.
// Add a newline, if the string does not end with a newline already.
Expand All @@ -362,6 +363,9 @@ class GCode : ExtrusionVisitor {
// Formats and write into a file the given data.
void _write_format(FILE* file, const char* format, ...);

//some post-processing on the file, before the analyzer
void _post_process(std::string& what);

std::string _extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
std::string _before_extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
std::string _after_extrude(const ExtrusionPath &path);
Expand Down
105 changes: 105 additions & 0 deletions src/libslic3r/GCode/Analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -863,5 +863,110 @@ size_t GCodeAnalyzer::memory_used() const
out += m_process_output.size();
return out;
}
const std::string& FanMover::process_gcode(const std::string& gcode) {
m_process_output = "";
buffer.clear();
buffer_time_size = 0;
current_speed = 1000 / 60.0;
expected_fan_speed = 0;
current_fan_speed = 0;

m_parser.parse_buffer(gcode,
[this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { /*m_process_output += line.raw() + "\n";*/ this->_process_gcode_line(reader, line); });

while (!buffer.empty()) {
m_process_output += buffer.back().raw + "\n";
buffer.pop_back();
}

return m_process_output;
}

void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line)
{
// processes 'normal' gcode lines
std::string cmd = line.cmd();
double time = 0;
float fan_speed = -1;
if (cmd.length() > 1) {
if (line.has_f())
current_speed = line.f() / 60.0f;
switch (::toupper(cmd[0])) {
case 'G':
{
if (::atoi(&cmd[1]) == 1 || ::atoi(&cmd[1]) == 0) {
double dist = line.dist_X(reader)*line.dist_X(reader) + line.dist_Y(reader)*line.dist_Y(reader) + line.dist_Z(reader)*line.dist_Z(reader);
if (dist > 0) {
dist = std::sqrt(dist);
time = dist / current_speed;
}
}
break;
}
case 'M':
{
if (::atoi(&cmd[1]) == 106) {
if (line.has_value('S', fan_speed) ) {
int nb_M106_erased = 0;
if (fan_speed > expected_fan_speed) {
time = -1; // don't write!
//erase M106 in the buffer -> don't slowdown if you are in the process of step-up.
auto it = buffer.begin();
int i = 0;
while (it != buffer.end()) {
if (it->raw.compare(0, 4, "M106") == 0 && it->speed < fan_speed) {
//found somethign that is lower than us -> change is speed by ours and delete us
it->speed = fan_speed;
std::stringstream ss; ss << "S" << (int)fan_speed;
it->raw = std::regex_replace(it->raw, regex_fan_speed, ss.str());
nb_M106_erased++;
} else {
++it;
i++;
}
}

if (nb_M106_erased == 0) {
//print it
if (with_D_option) {
std::stringstream ss;
ss << " D" << (uint32_t)(buffer_time_size * 1000) << "\n";
m_process_output += line.raw() + ss.str();
} else {
m_process_output += line.raw() + "\n";
}
current_fan_speed = fan_speed;
}
}

//update
expected_fan_speed = fan_speed;
}
}
break;
}
}
}

if (time >= 0) {
buffer.emplace_front(BufferData(line.raw(), time, fan_speed));
buffer_time_size += time;
}
// puts the line back into the gcode
//if buffer too big, flush it.
if (time > 0) {
while (buffer_time_size - buffer.back().time > nb_seconds_delay) {
BufferData &backdata = buffer.back();
if (backdata.speed < 0 || (int)backdata.speed != (int)current_fan_speed) {
buffer_time_size -= backdata.time;
m_process_output += backdata.raw + "\n";
if (backdata.speed >= 0) {
current_fan_speed = backdata.speed;
}
}
buffer.pop_back();
}
}
}

} // namespace Slic3r
37 changes: 37 additions & 0 deletions src/libslic3r/GCode/Analyzer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "../Point.hpp"
#include "../GCodeReader.hpp"
#include <regex>

namespace Slic3r {

Expand Down Expand Up @@ -239,6 +240,42 @@ class GCodeAnalyzer
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data);
};

class BufferData {
public:
std::string raw;
float time;
float speed;
BufferData(std::string line, float time = 0, float speed = 0) : raw(line), time(time), speed(speed) {}
};
class FanMover
{
private:
const std::regex regex_fan_speed;
const float nb_seconds_delay;
const bool with_D_option;

// in unit/second
double current_speed;
float buffer_time_size;
GCodeReader m_parser;
int expected_fan_speed;
int current_fan_speed;

// The output of process_layer()
std::list<BufferData> buffer;
std::string m_process_output;

public:
FanMover(const float nb_seconds_delay, const bool with_D_option) : regex_fan_speed("S[0-9]+"), nb_seconds_delay(nb_seconds_delay), with_D_option(with_D_option){}

// Adds the gcode contained in the given string to the analysis and returns it after removing the workcodes
const std::string& process_gcode(const std::string& gcode);

private:
// Processes the given gcode line
void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
};

} // namespace Slic3r

#endif /* slic3r_GCode_Analyzer_hpp_ */
1 change: 1 addition & 0 deletions src/libslic3r/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"extrusion_multiplier",
"fan_always_on",
"fan_below_layer_time",
"fan_speedup_time",
"filament_colour",
"filament_diameter",
"filament_density",
Expand Down
16 changes: 14 additions & 2 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,18 +1338,30 @@ void PrintConfigDef::init_fff_params()

def = this->add("remaining_times", coBool);
def->label = L("Supports remaining times");
def->category = L("Firmware");
def->tooltip = L("Emit M73 P[percent printed] R[remaining time in minutes] at 1 minute"
" intervals into the G-code to let the firmware show accurate remaining time."
" As of now only the Prusa i3 MK3 firmware recognizes M73."
" Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode.");
def->cli = "remaining-times!";
def->mode = comExpert;
def->default_value = new ConfigOptionBool(false);

def = this->add("silent_mode", coBool);
def->label = L("Supports silent mode");
def->label = L("Supports silent mode");
def->category = L("Firmware");
def->tooltip = L("Set silent mode for the G-code flavor");
def->mode = comExpert;
def->default_value = new ConfigOptionBool(true);
def->default_value = new ConfigOptionBool(true);

def = this->add("fan_speedup_time", coFloat);
def->label = L("fan startup delay");
def->category = L("Firmware");
def->tooltip = L("Move the M106 in the past by at least this delay and add the 'D' option to it to tell to the firware when the fan have to be at this speed."
" It assume infinite acceleration for this time estimation, and only takes into account G1 and G0 moves. Use 0 to deactivate, negative to remove the 'D' option.");
def->cli = "fan-speedup-time=f";
def->mode = comExpert;
def->default_value = new ConfigOptionFloat(0);

const int machine_limits_opt_width = 70;
{
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,7 @@ class GCodeConfig : public StaticPrintConfig
ConfigOptionStrings end_filament_gcode;
ConfigOptionString extrusion_axis;
ConfigOptionFloats extrusion_multiplier;
ConfigOptionFloat fan_speedup_time;
ConfigOptionFloats filament_diameter;
ConfigOptionFloats filament_density;
ConfigOptionStrings filament_type;
Expand Down Expand Up @@ -795,6 +796,7 @@ class GCodeConfig : public StaticPrintConfig
OPT_PTR(end_filament_gcode);
OPT_PTR(extrusion_axis);
OPT_PTR(extrusion_multiplier);
OPT_PTR(fan_speedup_time);
OPT_PTR(filament_diameter);
OPT_PTR(filament_density);
OPT_PTR(filament_type);
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/SupportMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ namespace SupportMaterialInternal {
for (const ExtrusionEntity *ee : perimeters.entities) {
if (ee->is_collection()) {
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) {
assert(! ee2->is_collection());
//assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !!
if (ee2->is_loop())
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee2), expansion_scaled, out);
}
Expand Down
3 changes: 2 additions & 1 deletion src/slic3r/GUI/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ const std::vector<std::string>& Preset::printer_options()
"machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e",
"machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e",
"machine_min_extruding_rate", "machine_min_travel_rate",
"machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e"
"machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e",
"fan_speedup_time"
};
s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end());
}
Expand Down
3 changes: 2 additions & 1 deletion src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1939,7 +1939,8 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(_(L("Firmware")));
optgroup->append_single_option_line("gcode_flavor");
optgroup->append_single_option_line("silent_mode");
optgroup->append_single_option_line("remaining_times");
optgroup->append_single_option_line("remaining_times");
optgroup->append_single_option_line("fan_speedup_time");

optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) {
wxTheApp->CallAfter([this, opt_key, value]() {
Expand Down

0 comments on commit c623985

Please sign in to comment.