From 12961a7eca5e350376c8d6e3b220855c665cb409 Mon Sep 17 00:00:00 2001 From: WHPThomas Date: Fri, 19 Apr 2013 01:01:37 +1000 Subject: [PATCH] 0.4 beta - filaments scale and temp overide All requested features have now been implemented and tested. This includes left and right filament scaling, tmperature overrides and ditto printing. Slic3r post processing is also supported natively. --- example.ini | 47 ++++++++++++-- gpx.c | 175 +++++++++++++++++++++++++++++++++++++++++++++------- gpx.h | 11 +++- gpx.ini | 73 ++++++++++++++++++++++ 4 files changed, 278 insertions(+), 28 deletions(-) create mode 100644 gpx.ini diff --git a/example.ini b/example.ini index 93d8685..724be62 100644 --- a/example.ini +++ b/example.ini @@ -1,13 +1,31 @@ ; ; example.ini (custom machine definition) ; -; Replicator 2 machine definition +; Replicator 2 machine definition file +; +; To create your own machine definition for different printers like the ; +; specifies the axis + [x] + +;sets the maximum feedrate for this axis in mm/s + max_feedrate=18000 + +;sets the home feedrate for this axis in mm/s + home_feedrate=2500 + +;sets the number of steps per mm of movement for this axis + steps_per_mm=88.573186 + +; sets the homing direction for this axis +; maximum = 1 +; minimum = 0 + endstop=1 [y] @@ -22,20 +40,41 @@ home_feedrate=1100 steps_per_mm=400 endstop=0 +; specifies the right extruder + [a] + +; sets the maximum feedrate for this axis in mm/s + max_feedrate=1600 + +; sets the number of steps per mm of extrusion + steps_per_mm=96.275201870333662468889989185642 + +; sets the number of steps per revolution + motor_steps=3200 + +; signals if this tool has a heated build platform (unually a does) + has_heated_build_platform=0 [b] max_feedrate=1600 steps_per_mm=96.275201870333662468889989185642 motor_steps=3200 -has_heated_build_platform=0 [machine] -;nominal filament diameter -filament_diameter=1.75 + +; specifies the nominal filament diameter (either 1.75 or 3.0) + +nominal_filament_diameter=1.75 + +; spesifies the number of extruders on this machine + extruder_count=1 + +; sets the timeout for homing in seconds + timeout=20 diff --git a/gpx.c b/gpx.c index 8641577..f5952d0 100644 --- a/gpx.c +++ b/gpx.c @@ -44,8 +44,8 @@ // Machine definitions -// Axis - maxfeedrate, stepspermm, endstop -// Extruder - maxfeedrate, stepspermm, motorsteps +// Axis - max_feedrate, home_feedrate, steps_per_mm, endstop; +// Extruder - max_feedrate, steps_per_mm, motor_steps, has_heated_build_platform; static Machine replicator_1 = { {18000, 2500, 94.139704, ENDSTOP_IS_MAX}, // x axis @@ -119,9 +119,12 @@ double currentFeedrate; // the current feed rate int currentOffset; // current G10 offset Point3d offset[7]; // G10 offsets Tool tool[2]; // tool state +Override override[2]; // gcode override int isRelative; // signals relitive or absolute coordinates int positionKnown; // is the current extruder position known int programState; // gcode program state used to trigger start and end code sequences +int dittoPrinting; // enable ditto printing +int buildPercent; // override build percent unsigned line_number; // the current line number in the gcode file static char buffer[256]; // the statically allocated parse-in-place buffer double scale[2]; // A & B scaling for n x 0.01 mm change in nominal diameter @@ -199,11 +202,19 @@ static void initialize_globals(void) tool[i].rpm = 0; tool[i].nozzle_temperature = 0; tool[i].build_platform_temperature = 0; + + override[i].actual_filament_diameter = 0; + override[i].filament_scale = 1.0; + override[i].nozzle_temperature = 0; + override[i].build_platform_temperature = 0; } - + isRelative = 0; positionKnown = 0; programState = 0; + + dittoPrinting = 0; + buildPercent = 0; line_number = 1; @@ -269,12 +280,33 @@ static int write_float(float value) { // Custom machine definition ini handler -#define SECTION_IS(s) strcmp(section, s) == 0 -#define NAME_IS(n) strcmp(name, n) == 0 +#define SECTION_IS(s) strcasecmp(section, s) == 0 +#define NAME_IS(n) strcasecmp(name, n) == 0 +#define VALUE_IS(v) strcasecmp(value, v) == 0 static int config_handler(void* user, const char* section, const char* name, const char* value) { - if(SECTION_IS("x")) { + if(SECTION_IS("options")) { + if(NAME_IS("ditto_printing")) dittoPrinting = atoi(value); + else if(NAME_IS("build_percent")) buildPercent = atoi(value); + else if(NAME_IS("printer_type")) { + // use on-board machine definition + if(VALUE_IS("r1")) { + machine = replicator_1; + } + else if(VALUE_IS("r1d")) { + machine = replicator_1D; + } + else if(VALUE_IS("r2")) { + machine = replicator_2; + } + else if(VALUE_IS("r2x")) { + machine = replicator_2X; + } + } + else return 0; + } + else if(SECTION_IS("x")) { if(NAME_IS("max_feedrate")) machine.x.max_feedrate = strtod(value, NULL); else if(NAME_IS("home_feedrate")) machine.x.home_feedrate = strtod(value, NULL); else if(NAME_IS("steps_per_mm")) machine.x.steps_per_mm = strtod(value, NULL); @@ -300,6 +332,10 @@ static int config_handler(void* user, const char* section, const char* name, con else if(NAME_IS("steps_per_mm")) machine.a.steps_per_mm = strtod(value, NULL); else if(NAME_IS("motor_steps")) machine.a.motor_steps = strtod(value, NULL); else if(NAME_IS("has_heated_build_platform")) machine.a.has_heated_build_platform = atoi(value); + // overrides + else if(NAME_IS("nozzle_temperature")) override[0].nozzle_temperature = atoi(value); + else if(NAME_IS("build_platform_temperature")) override[0].build_platform_temperature = atoi(value); + else if(NAME_IS("actual_filament_diameter")) override[0].actual_filament_diameter = strtod(value, NULL); else return 0; } else if(SECTION_IS("b")) { @@ -307,10 +343,14 @@ static int config_handler(void* user, const char* section, const char* name, con else if(NAME_IS("steps_per_mm")) machine.b.steps_per_mm = strtod(value, NULL); else if(NAME_IS("motor_steps")) machine.b.motor_steps = strtod(value, NULL); else if(NAME_IS("has_heated_build_platform")) machine.b.has_heated_build_platform = atoi(value); + // overrides + else if(NAME_IS("nozzle_temperature")) override[1].nozzle_temperature = atoi(value); + else if(NAME_IS("build_platform_temperature")) override[1].build_platform_temperature = atoi(value); + else if(NAME_IS("actual_filament_diameter")) override[1].actual_filament_diameter = strtod(value, NULL); else return 0; } else if(SECTION_IS("machine")) { - if(NAME_IS("filament_diameter")) machine.filament_diameter = strtod(value, NULL); + if(NAME_IS("nominal_filament_diameter")) machine.nominal_filament_diameter = strtod(value, NULL); else if(NAME_IS("extruder_count")) machine.extruder_count = atoi(value); else if(NAME_IS("timeout")) machine.timeout = atoi(value); else return 0; @@ -323,6 +363,16 @@ static int config_handler(void* user, const char* section, const char* name, con // 5D VECTOR FUNCTIONS +// compute the filament scaling factor + +void set_filament_scale(unsigned extruder_id) { + double actual_radious = override[extruder_id].actual_filament_diameter / 2; + double actual = actual_radious * actual_radious; + double nominal_radious = machine.nominal_filament_diameter / 2; + double nominal = nominal_radious * nominal_radious; + override[extruder_id].filament_scale = nominal / actual; +} + // return the magnitude (length) of the 5D vector static double magnitude(int flag, Ptr5d vector) @@ -598,7 +648,7 @@ static void wait_for_extruder(unsigned extruder_id, unsigned timeout) // Action 03 - Set toolhead target temperature -static void set_extruder_temperature(unsigned extruder_id, unsigned temperature) +static void set_nozzle_temperature(unsigned extruder_id, unsigned temperature) { assert(extruder_id < machine.extruder_count); if(write_8(136) == EOF) exit(1); @@ -1186,14 +1236,14 @@ static char *normalize_comment(char *p) { static void usage() { fputs("GPX " GPX_VERSION " Copyright (c) 2013 WHPThomas, All rights reserved." EOL, stderr); - fputs(EOL "Usage: gpx [-ps] [-m | -c ] INPUT [OUTPUT]" EOL, stderr); + fputs(EOL "Usage: gpx [-ps] [-m ] [-c ] INPUT [OUTPUT]" EOL, stderr); fputs(EOL "Switches:" EOL EOL, stderr); fputs("\t-p\toverride build percentage" EOL, stderr); fputs("\t-s\tenable stdin and stdout support for command pipes" EOL, stderr); fputs(EOL "MACHINE is the predefined machine type" EOL EOL, stderr); fputs("\tr1 = Replicator 1 - single extruder" EOL, stderr); - fputs("\tr1d = Replicator 1 - dual extruder" EOL, stderr); - fputs("\tr2 = Replicator 2 (default config)" EOL, stderr); + fputs("\tr1d = Replicator 1 - dual extruder" EOL, stderr); + fputs("\tr2 = Replicator 2 (default config)" EOL, stderr); fputs("\tr2x = Replicator 2X" EOL, stderr); fputs(EOL "CONFIG is the filename of a custom machine definition (ini)" EOL, stderr); fputs(EOL "INPUT is the name of the sliced gcode input filename" EOL, stderr); @@ -1213,7 +1263,6 @@ int main(int argc, char * argv[]) int c, i; int next_line = 0; int command_line = 0; - int build_percent = 0; int standard_io = 0; initialize_globals(); @@ -1221,13 +1270,23 @@ int main(int argc, char * argv[]) // READ COMMAND LINE // get the command line options - while ((c = getopt(argc, argv, "pm:c:")) != -1) { + while ((c = getopt(argc, argv, "c:m:ps")) != -1) { + command_line++; switch (c) { case 'c': if (ini_parse(optarg, config_handler, NULL) < 0) { fprintf(stderr, "Command line error: cannot load custom machine definition '%s'" EOL, optarg); usage(); } + // check if the filament diameter has been overridden + if(override[0].actual_filament_diameter > 0.0 || override[0].actual_filament_diameter > 0.0) { + if(override[0].actual_filament_diameter != machine.nominal_filament_diameter) { + + } + if(override[1].actual_filament_diameter != machine.nominal_filament_diameter) { + + } + } break; case 'm': if(strcasecmp(optarg, "r1") == 0) { @@ -1247,7 +1306,7 @@ int main(int argc, char * argv[]) } break; case 'p': - build_percent = 1; + buildPercent = 1; break; case 's': standard_io = 1; @@ -1257,6 +1316,49 @@ int main(int argc, char * argv[]) usage(); } } + + // READ GPX.INI + + // if no command line arguments then read gpx.ini file from program directory + if(command_line == 0) { + char *filename = argv[0]; + // check for .exe extension + char *dot = strrchr(filename, '.'); + if(dot) { + long l = dot - filename; + memcpy(buffer, filename, l); + filename = buffer + l; + } + // or just append .ini if no extension is present + else { + filename = stpncpy(buffer, filename, 256 - 5); + } + *filename++ = '.'; + *filename++ = 'i'; + *filename++ = 'n'; + *filename++ = 'i'; + *filename++ = '\0'; + filename = buffer; + ini_parse(filename, config_handler, NULL); + + if(dittoPrinting && machine.extruder_count == 1) { + fputs("Command line error: ditto printing cannot access non-existant extruder" EOL, stderr); + dittoPrinting = 0; + } + } + + // CALCULATE FILAMENT SCALING + + if(override[0].actual_filament_diameter + && override[0].actual_filament_diameter != machine.nominal_filament_diameter) { + set_filament_scale(0); + } + + if(override[1].actual_filament_diameter + && override[1].actual_filament_diameter != machine.nominal_filament_diameter) { + set_filament_scale(1); + } + argc -= optind; argv += optind; @@ -1458,7 +1560,7 @@ int main(int argc, char * argv[]) } else if(*p == '(') { // Comment - char *e = strchr(p + 1, ')'); + char *e = strrchr(p + 1, ')'); if(e) { *e = 0; command.comment = normalize_comment(p + 1); @@ -1564,15 +1666,34 @@ int main(int argc, char * argv[]) currentFeedrate = command.f; } - // CALCULATE OFFSET + // ADD ANY G10 OFFSETS if(command.flag & X_IS_SET) targetPosition.x += offset[currentOffset].x; if(command.flag & Y_IS_SET) targetPosition.y += offset[currentOffset].y; if(command.flag & Z_IS_SET) targetPosition.z += offset[currentOffset].z; + + // DITTO PRINTING + + if(dittoPrinting) { + if(command.flag & A_IS_SET) { + targetPosition.b = targetPosition.a; + command.flag |= B_IS_SET; + } + else if(command.flag & B_IS_SET) { + targetPosition.a = targetPosition.b; + command.flag |= A_IS_SET; + } + } + + // SCALE FILAMENT INDEPENDENTLY + + if(command.flag & A_IS_SET && override[0].filament_scale != 1.0) targetPosition.a *= override[0].filament_scale; + if(command.flag & B_IS_SET && override[1].filament_scale != 1.0) targetPosition.b *= override[1].filament_scale; // INTERPRET COMMAND if(command.flag & G_IS_SET) { + // command line incremented to ensure that at least one command is emmited before each build percent command_line++; switch(command.g) { // G0 - Rapid Positioning @@ -1891,7 +2012,7 @@ int main(int argc, char * argv[]) set_build_percent(100); end_build(); } - else if(filesize == 0 || build_percent == 0) { + else if(filesize == 0 || buildPercent == 0) { set_build_percent(percent); } } @@ -1953,7 +2074,10 @@ int main(int argc, char * argv[]) if(command.flag & T_IS_SET) { unsigned extruder_id = (unsigned)command.t; if(extruder_id < machine.extruder_count) { - set_extruder_temperature(extruder_id, temperature); + if(temperature && override[extruder_id].nozzle_temperature) { + temperature = override[extruder_id].nozzle_temperature; + } + set_nozzle_temperature(extruder_id, temperature); tool[extruder_id].nozzle_temperature = temperature; } else { @@ -1961,7 +2085,10 @@ int main(int argc, char * argv[]) } } else { - set_extruder_temperature(currentExtruder, temperature); + if(temperature && override[currentExtruder].nozzle_temperature) { + temperature = override[currentExtruder].nozzle_temperature; + } + set_nozzle_temperature(currentExtruder, temperature); tool[currentExtruder].nozzle_temperature = temperature; } } @@ -2037,7 +2164,11 @@ int main(int argc, char * argv[]) if(command.flag & T_IS_SET) { extruder_id = (unsigned)command.t; } - if(extruder_id < machine.extruder_count && (extruder_id ? machine.b.has_heated_build_platform : machine.a.has_heated_build_platform)) { + if(extruder_id < machine.extruder_count + && (extruder_id ? machine.b.has_heated_build_platform : machine.a.has_heated_build_platform)) { + if(temperature && override[extruder_id].build_platform_temperature) { + temperature = override[extruder_id].build_platform_temperature; + } set_build_platform_temperature(extruder_id, temperature); tool[currentExtruder].build_platform_temperature = temperature; } @@ -2175,7 +2306,7 @@ int main(int argc, char * argv[]) } } // update progress - if(filesize && build_percent && command_line) { + if(filesize && buildPercent && command_line) { unsigned percent = (unsigned)round(100.0 * (double)ftell(in) / (double)filesize); if(percent > progress) { if(program_is_ready()) { @@ -2183,7 +2314,7 @@ int main(int argc, char * argv[]) start_build(); set_build_percent(0); } - else if(percent < 100) { + else if(percent < 100 && program_is_running()) { set_build_percent(percent); progress = percent; } diff --git a/gpx.h b/gpx.h index 48a01ca..250f156 100644 --- a/gpx.h +++ b/gpx.h @@ -29,7 +29,7 @@ #include -#define GPX_VERSION "0.3 (beta)" +#define GPX_VERSION "0.4 (beta)" // x3g axes bitfields @@ -142,7 +142,7 @@ typedef struct tMachine { Axis z; Extruder a; Extruder b; - double filament_diameter; + double nominal_filament_diameter; unsigned extruder_count; unsigned timeout; } Machine; @@ -154,6 +154,13 @@ typedef struct tTool { unsigned build_platform_temperature; } Tool; +typedef struct tOverride { + double actual_filament_diameter; + double filament_scale; + unsigned nozzle_temperature; + unsigned build_platform_temperature; +} Override; + #define EOL "\n" #endif diff --git a/gpx.ini b/gpx.ini new file mode 100644 index 0000000..af2ddef --- /dev/null +++ b/gpx.ini @@ -0,0 +1,73 @@ +; +; gpx.ini +; +; gcode to x3g conversion configuration file +; + +; POST PROCESSING OPTIONS + +[options] + +; specify the machine definition using a built-in printer type +; r1 = Replicator 1 single +; r1d = Replicator 1 dual +; r2 = Replicator 2 (default) +; r2x = Replicator 2X + +printer_type=r2 + +; print simultaniously with both nozzles +; 1 = enabled +; 0 = disabled + +ditto_printing=0 + +; override gcode for the build percentage +; this should be enabled for slic3r and kisslicer +; 1 = enabled +; 0 = disabled + +build_percent=1 + +; RIGHT EXTRUDER + +[a] + +; override gcode for the right filament diameter +; 1.75 = default +; 0 = disabled + +actual_filament_diameter=0 + +; override gcode for the right nozzle temperature +; 0 = disabled + +nozzle_temperature=0 + +; override the gcode build plate temperature +; 0 = disabled + +build_platform_temperature=0 + +; LEFT EXTRUDER + +[b] + +; override gcode for the right filament diameter +; 1.75 = default +; 0 = disabled + +actual_filament_diameter=0 + +; override gcode for the right nozzle temperature +; 0 = disabled + +nozzle_temperature=0 + + +[machine] + +; set this to the filament diameter setting used in the slicer +; 1.75 = default + +nominal_filament_diameter=1.75