new: fan startup delay. (or advanced speed-up)

This commit is contained in:
supermerill 2019-02-21 19:10:55 +01:00
parent aec5a563bb
commit c6239850b0
10 changed files with 185 additions and 6 deletions

View File

@ -2452,11 +2452,27 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
return gcode; 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) void GCode::_write(FILE* file, const char *what)
{ {
if (what != nullptr) { 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 // 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 // writes string to file
fwrite(gcode, 1, ::strlen(gcode), file); fwrite(gcode, 1, ::strlen(gcode), file);

View File

@ -353,6 +353,7 @@ protected:
// Write a string into a file. // 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 std::string& what) { this->_write(file, what.c_str()); }
void _write(FILE* file, const char *what); void _write(FILE* file, const char *what);
// Write a string into a file. // Write a string into a file.
// Add a newline, if the string does not end with a newline already. // Add a newline, if the string does not end with a newline already.
@ -362,6 +363,9 @@ protected:
// Formats and write into a file the given data. // Formats and write into a file the given data.
void _write_format(FILE* file, const char* format, ...); 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 _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 _before_extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
std::string _after_extrude(const ExtrusionPath &path); std::string _after_extrude(const ExtrusionPath &path);

View File

@ -863,5 +863,110 @@ size_t GCodeAnalyzer::memory_used() const
out += m_process_output.size(); out += m_process_output.size();
return out; 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 } // namespace Slic3r

View File

@ -7,6 +7,7 @@
#include "../Point.hpp" #include "../Point.hpp"
#include "../GCodeReader.hpp" #include "../GCodeReader.hpp"
#include <regex>
namespace Slic3r { namespace Slic3r {
@ -239,6 +240,42 @@ private:
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data); 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 } // namespace Slic3r
#endif /* slic3r_GCode_Analyzer_hpp_ */ #endif /* slic3r_GCode_Analyzer_hpp_ */

View File

@ -117,6 +117,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"extrusion_multiplier", "extrusion_multiplier",
"fan_always_on", "fan_always_on",
"fan_below_layer_time", "fan_below_layer_time",
"fan_speedup_time",
"filament_colour", "filament_colour",
"filament_diameter", "filament_diameter",
"filament_density", "filament_density",

View File

@ -1338,18 +1338,30 @@ void PrintConfigDef::init_fff_params()
def = this->add("remaining_times", coBool); def = this->add("remaining_times", coBool);
def->label = L("Supports remaining times"); 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" 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." " intervals into the G-code to let the firmware show accurate remaining time."
" As of now only the Prusa i3 MK3 firmware recognizes M73." " As of now only the Prusa i3 MK3 firmware recognizes M73."
" Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode."); " Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode.");
def->cli = "remaining-times!";
def->mode = comExpert; def->mode = comExpert;
def->default_value = new ConfigOptionBool(false); def->default_value = new ConfigOptionBool(false);
def = this->add("silent_mode", coBool); 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->tooltip = L("Set silent mode for the G-code flavor");
def->mode = comExpert; 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; const int machine_limits_opt_width = 70;
{ {

View File

@ -716,6 +716,7 @@ public:
ConfigOptionStrings end_filament_gcode; ConfigOptionStrings end_filament_gcode;
ConfigOptionString extrusion_axis; ConfigOptionString extrusion_axis;
ConfigOptionFloats extrusion_multiplier; ConfigOptionFloats extrusion_multiplier;
ConfigOptionFloat fan_speedup_time;
ConfigOptionFloats filament_diameter; ConfigOptionFloats filament_diameter;
ConfigOptionFloats filament_density; ConfigOptionFloats filament_density;
ConfigOptionStrings filament_type; ConfigOptionStrings filament_type;
@ -795,6 +796,7 @@ protected:
OPT_PTR(end_filament_gcode); OPT_PTR(end_filament_gcode);
OPT_PTR(extrusion_axis); OPT_PTR(extrusion_axis);
OPT_PTR(extrusion_multiplier); OPT_PTR(extrusion_multiplier);
OPT_PTR(fan_speedup_time);
OPT_PTR(filament_diameter); OPT_PTR(filament_diameter);
OPT_PTR(filament_density); OPT_PTR(filament_density);
OPT_PTR(filament_type); OPT_PTR(filament_type);

View File

@ -861,7 +861,7 @@ namespace SupportMaterialInternal {
for (const ExtrusionEntity *ee : perimeters.entities) { for (const ExtrusionEntity *ee : perimeters.entities) {
if (ee->is_collection()) { if (ee->is_collection()) {
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) { 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()) if (ee2->is_loop())
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee2), expansion_scaled, out); collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee2), expansion_scaled, out);
} }

View File

@ -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_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_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e",
"machine_min_extruding_rate", "machine_min_travel_rate", "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()); s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end());
} }

View File

@ -1939,7 +1939,8 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(_(L("Firmware"))); optgroup = page->new_optgroup(_(L("Firmware")));
optgroup->append_single_option_line("gcode_flavor"); optgroup->append_single_option_line("gcode_flavor");
optgroup->append_single_option_line("silent_mode"); 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) { optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) {
wxTheApp->CallAfter([this, opt_key, value]() { wxTheApp->CallAfter([this, opt_key, value]() {