#!/usr/bin/php -q // Description: this script will parse a G-Code file and reformat it to work with the newer RepRap G-Code interpreter firmware. // Licence: GPLv3 or later // Documentation can be found at: // http://objects.reprap.org/wiki/3D-to-5D-Gcode.php // /* Changelog: * 0.5 Erik 14/07/09 Software anti-backlash (TODO: differentiate between dynamic and static friction) * 0.6 Erik 15/07/09 Output to file --output_file filename.gcode Default: out-5D.gcode * 0.7 Erik 19/07/09 Condition based actions (change lines based on a list of criteria). * 0.8 Erik 20/07/09 Added start and stop conditions in addition to 'while'. * 0.9 Erik 11/08/09 Possibly fixed non-incremental extrusion mode. Needs testing though. Siert, tnx for bug report. * 0.10 Erik 11/08/09 Several bugfixes. Of course I shouldn't use str_replace this much... * 0.11 Erik 17/09/09 Bugfix: order of processing improved. Anti-backlash is applied first, then better distances will be measured * 0.12 Erik 17/09/09 Softener of Z-moves was relative and for EVERY Z move, also those that were already slow. This is not based * on the maximum speed the Z-axis should move and if it's high the feedrate is adjusted so that it effectively moves * at this maximum speed along the Z-axis. * 0.13 Erik 17/09/09 Bugfix: dZ is used absolute for softening. This is what caused towering to go bad, the printhead has to move down * (negative Z) but it tends to skip steps when movement speed is not capped to a sensible max. * 0.14 Erik 17/09/09 Bugfix: minor problem in anti-backlash. Would sometimes match and replace too many values. * 0.15 Erik 17/09/09 Feature: added anti-ooze system for Bowden extruder. Still experimental, stops pullback after a while, WHY?! * 0.16 Erik 21/11/09 Feature: status line with progress indication. * 0.17 Erik 28/12/09 Feature: can perform a search for the input file in varous directories * 0.18 Erik 09/01/10 Feature: can rescale and offset g-code * 0.19 Erik 28/02/10 Feature: can put the output on an SD card and safely unmounts it. * 0.20 Erik 19/07/10 Feature: preliminary functionality for multiple extruders and device profiles. Upcoming: * ... Erik ../../.. Feature: can remove the raft if --noraft is set */ ini_set('memory_limit','128M'); $version = 0.21; out("\n( Modified by 3D-to-5D-Gcode v$version on ".date("c").')'); $uTime=microtime(true); // Settings: $setting['prepend_gcode'] = "G1 E250 F6000\nG1 Z0.3 F140\n"; // begin with this Gcode //$setting['append_gcode'] = "G91\nG1 Z4 F40\nG90\nM104 S200"; // add this Gcode at the end $setting['append_gcode'] = "G91\nG1 Z4 F140\nG90\nM104 S150"; // add this Gcode at the end $setting['extrusion_adjust'] = 1.5; // factor to adjust extruded distances with //$setting['extruder_backlash_fwd']=402.0; // manages tension in the Bowden extruder or for other more flexible material feedstock. Extrusion adjust NOT factored in. //$setting['extruder_backlash_rev']=400.0; // The amount to pull it back (see prev, comment) $setting['reversing_minimum_distance'] = 5; // minimum amount of travel milimeters to reverse extruder for (smaller is slower builds) $setting['reversing_minimum_extrusion'] = $setting['extruder_backlash_fwd']*.75; // if litle material is extruded, many reverses (pumping action) without much extrusion will transfer heat higher up the heater barrel. The extruder should reverse only when about 75% of the 'backlash' is extruded again. $setting['extrude_incremental'] = 1; // E values are incremental. Better for making small adjustments //$setting['replace_ereg'] = array('F330.0[^0-9]'=>'F1320.0'); // $setting['replace_strings'] = array( 'Z1.2 F960.0 '=>'Z1.2 F500.0 ', // hugely speed up the raft-making //'Z0.9 F1320.0 '=>'Z0.9 F1320.0 ', // hugely speed up the raft-making //'F330.0'=>'F1320.0', // hugely speed up the raft-making //'F330.0'=>'F430.0', // moderately speed up the raft-making ); // $setting['accelerated_travel'] = false; //false = off, 1.0 is base speed, 2.0 is two times faster. $setting['repeat_M103-M101'] = false; // a workaround for BfB v3.1 beta firmware $setting['switch_extruders'] = false; // replace M101 with M201 and vice versa $setting['accelerated_travel_mindist'] = 7; // the minimum distance in milimeters $setting['accelerated_travel_segments'] = 7; // should always be an ODD number! $setting['remove_redundant_Gcodes'] = true; // save bandwidth and processing power on sanguino/arduino. Set to false to disable. $setting['actions'] = array( //array('while'=>array('match','F330.0'),'actions'=>array('E_mul'=>6,'F_mul'=>0.7)), // raft making: slow down XY-moves, speed up extrusion. //Z0.39 F330.0 array('while'=>array('match','Z0.61'),'actions'=>array('E_mul'=>6,'F_mul'=>0.7)), // raft making: slow down XY-moves, speed up extrusion. array('while'=>array('match','Z1.05'),'actions'=>array('E_mul'=>1.7,'F_mul'=>1/2.1)), // raft making: slow down XY-moves, speed up extrusion. array('while'=>array('match','Z1.16 F1320.0 '),'actions'=>array('E_mul'=>1.7,'F_mul'=>1/2.1)), // raft making: slow down XY-moves, speed up extrusion. // .22 layer height array('while'=>array('match','Z0.44 '),'actions'=>array('E_mul'=>6,'F_mul'=>0.7)), // raft making: slow down XY-moves, speed up extrusion. //array('while'=>array('match','F1320.0'),'actions'=>array('E_mul'=>2.2,'F_mul'=>0.8)), // raft making: slow down XY-moves, speed up extrusion. /* array( // raft making: slow down XY-moves, speed up extrusion. Does the same as the above if the raft is set for feedrate 330.0 in skeinforge. This might be more reliable though... 'condition_start'=>array('match',' 0.5'), // set it to match the foundation layer of your raft. 'condition_stop'=>array('match',''), 'actions'=>array('E_mul'=>15,'F_mul'=>0.75) ), array( // raft making: the same, but now for interface layer 'condition_start'=>array('match',' 0.86'), // set it to match the foundation layer of your raft. 'condition_stop'=>array('match',''), 'actions'=>array('E_mul'=>4,'F_mul'=>0.8) ), */ ); $setting['machine'] = 'charles'; $setting['extension'] = 'gcode'; $setting['add_E_codes'] = true; $setting['F_max'] = 6000; $setting['remove_comments'] = true; // Set true/false to remove comments from input file or not. $setting['remove_M108s'] = true; $setting['scale'] = 1; $setting['offset_x'] = 0; $setting['offset_y'] = 0; $setting['remove_M101-M103'] = true; //$setting['soften_z_move_factor'] = .5; // this slows down the move in the Z direction to this speed $setting['anti-backlash'] = array( // 'X'=>array('fwd_dynamic'=>0.0/*mm*/, 'rev_dynamic'=>0.0/*mm*/,'fwd_static'=>0.20/*mm*/, 'rev_static'=>0.20/*mm*/ ), // Backlash on X-axis //'Y'=>array('fwd_dynamic'=>0.00/*mm*/, 'rev_dynamic'=>0.00/*mm*/,'fwd_static'=>0.25/*mm*/, 'rev_static'=>0.25/*mm*/ ), // Backlash on Y-axis // Y backlash was .30 //'Y'=>array('fwd_dynamic'=>0.45/*mm*/, 'rev_dynamic'=>0.45/*mm*/,'fwd_static'=>0.1/*mm*/, 'rev_static'=>0.1/*mm*/ ), // Backlash on Y-axis ); if(my_ereg("^(.+)_export\.".$setting['extension']."$",basename($argv[1]),$regs)) $setting['output_file'] = $regs[1].'.'.$setting['extension']; elseif(my_ereg("^(.+)\.".$setting['extension']."$",basename($argv[1]),$regs)) $setting['output_file'] = $regs[1].'.'.$setting['extension']; elseif(my_ereg("^([^\.]+)$",basename($argv[1]),$regs)) $setting['output_file'] = $regs[1].'.'.$setting['extension']; else $setting['output_file'] = 'out-5D.'.$setting['extension']; // null = output directly. $setting['default_output_path'] = '/home/erik/RepRap/gcode/'; $setting_file = $_SERVER['HOME']."/.reprap/3D-to-5D.settings"; if(file_exists($setting_file)) $setting = ini_get($setting_file); else out("\n( Warning: no settings file found in $setting_file using only defaults.)"); // explain defaults foreach($setting as $sName => $sVal) { $sVal = str_replace("\n"," \\n ",$sVal); out("\n( $sName = $sVal )"); if($aKey = array_search("--".$sName,$argv)) { out("\n( Cmdline override of setting: $sName ".$argv[($aKey+1)].')'); $setting[$sName] = $argv[$aKey+1]; } } if(isset($setting['machine']) && ($setting['machine'] == 'leo')) { $setting['remove_M101-M103'] = false; $setting['prepend_gcode'] = "G90\nG21\nM108 S10.0\nM227 S1000 P800\n"; //\n";// HOME: "G28\n"; //M227 S1000 P800 on extruder stop (M103) reverse the extruder stepper for S turns and on extruder start (M101) prepare (push) filament P steps (available from firmware 1.0.8) #$setting['extrusion_adjust'] = 0.13; $setting['add_E_codes'] = false; $setting['scale'] = array(); #$setting['scale']['X'] = 0.77; #$setting['scale']['Y'] = 0.77; #$setting['scale']['Z'] = 1.0; #$setting['scale']['F'] = 0.77; #$setting['offset_x'] = 120; #$setting['offset_y'] = -60; $setting['F_max'] = 1900; //maximum feedrate $setting['extension']='bfb'; $setting['output_file'] = str_replace('.gcode','.bfb',$setting['output_file']); $setting['remove_redundant_Gcodes'] = false; $setting['remove_M108s'] = false; $setting['M108factor'] = 0.14; init_sd(&$setting); } if(isset($setting['machine']) && ($setting['machine'] == 'mini')) { $setting['scale']=array(); $setting['scale']['X'] = 0.9; $setting['scale']['Y'] = 0.9; $setting['scale']['Z'] = 2.5; // 8 teeth / 20 teeth = 0.4 $setting['scale']['F'] = 1.30; $setting['offset_x'] = -180; $setting['offset_y'] = 150; $setting['remove_M101-M103'] = false; $setting['prepend_gcode'] = "G90\nG21\nG28\nM221\nM225\nM108 S11.0\n";//\nM227 S1000 P800 $setting['extension']='bfb'; $setting['output_file'] = str_replace('.gcode','.bfb',$setting['output_file']); $setting['remove_redundant_Gcodes'] = false; $setting['remove_M108s'] = false; $setting['M108factor'] = 0.15; $setting['repeat_M103-M101'] = true; // a workaround for BfB v3.1 beta firmware $setting['switch_extruders'] = true; // replace M101 with M201 and vice versa init_sd(&$setting); } if(isset($setting['scale'])&&(!is_array($setting['scale']))) // doesn't scale Z by default { $scale = $setting['scale']; $setting['scale']=array(); $setting['scale']['X'] = $scale; $setting['scale']['Y'] = $scale; } if(isset($setting['scale_z'])) $setting['scale']['Z'] = $setting['scale_z']; echo "============="; print_r($setting['scale']); echo "============="; if(!strstr($setting['output_file'],'/')) $setting['output_file'] = $setting['default_output_path'].$setting['output_file']; $conditionOk = false; // Accell configuration check: if(isset($setting['accelerated_travel_segments'])) $segs = $setting['accelerated_travel_segments']; else $segs = 3; if($segs < 3) echo "Error: travel feedrate accelleration is misconfigured, accelerated_travel_segments should be at minimum 3."; echo "\nOutput file is: ".$setting['output_file']."\n"; @unlink($setting['output_file']); // The *OLD*, 3D (lame!) way: // M108 S200 ; extruder motor speed at 200 PWM // M101 ; extruder motor forward // G1 ... ; make your moves... // *NEW*, Now 5 Dimensionally! // G1 X0.0 Y0.0 Z0.0 // G1 X1.0 Y1.0 E1.4142 ; Extrude the pythagorian distance (X^2+Y^2)^.5. Assuming just XY plain (2D) moves... // $fName = determine_input_file($argv[1]); bcscale(4); $lines = file($fName); // ugly mem-sucker... I know. When I have files that are too big I'll improve this ;) // if you fix it, please e-mail the update. // Defaults: (check your firmware!) $abs = false; $X = $Y = $Z = "0.0"; $lastX = $lastY = $lastZ = "0.0"; $dist = 0; $extruder_starting = false; $hist = -1; // a counter used to keep history of movements $line_count = count($lines); $line_nr=0; out($setting['prepend_gcode']); foreach($lines as $line) { $line_nr++; // keep track of the line_nr // Remove original comments if(!($line_nr % 1000)) // every 1000 lines { echo statusLine(); } // Remove original comments if($setting['remove_comments']==true) { if($line{0}==';') continue; if($line{0}=='\'') continue; if($line{0}=='(') continue; } #my_ereg("[GMEXYZFS]{1 $comment = ''; if(my_ereg("M[ ]*108[ ]S([0-9.]+)",$line,$regs)) { $line = trim($line)." ; fw/bck/off"; $speed = $regs[1]; if(isset($setting['remove_M108s']) && ($setting['remove_M108s']==false)) { if(isset($setting['M108factor'])) out("M108 S".trim($regs[1]*$setting['M108factor'])."\n"); } continue; } // Store previous coordinates $lastX = $X; $lastY = $Y; $lastZ = $Z; if(my_ereg("X[ ]*(-?[0-9.]+)",$line,$regs)) $X = $regs[1]; if(my_ereg("Y[ ]*(-?[0-9.]+)",$line,$regs)) $Y = $regs[1]; if(my_ereg("Z[ ]*(-?[0-9.]+)",$line,$regs)) $Z = $regs[1]; if(my_ereg("F[ ]*(-?[0-9.]+)",$line,$regs)) $F = $regs[1]; if(isset($setting['scale']['X'])) $line = str_replace("X$X","X".(($X+$setting['offset_x'])*$setting['scale']['X']),$line); if(isset($setting['scale']['Y'])) $line = str_replace("Y$Y","Y".(($Y+$setting['offset_y'])*$setting['scale']['Y']),$line); if(isset($setting['scale']['Z'])) $line = str_replace("Z$Z","Z".($Z*$setting['scale']['Z']),$line); if(isset($setting['scale']['F'])) { $F_replace = $F*$setting['scale']['F']; if($F_replace > $setting['F_max']) $F_replace = $setting['F_max']; $line = str_replace("F$F","F".$F_replace,$line); } if(my_ereg("M[ ]*10([123])",$line,$regs)) { $last_dir = $dir;//Anti-Ooze switch($regs[1]) { case "1": $dir = 1; $extruder_starting = true; if(isset($extrusion_has_started)) { if(isset($setting['extruder_backlash_fwd'])) { //out("(dist_trav=$distance_traveled)\n"); if(($distance_traveled >= $setting['reversing_minimum_distance']) && ($amount_extruded > ($setting['extrusion_adjust']*$setting['reversing_minimum_extrusion']))) { ////////////////////////////////////////////////// // Go forward (usually as much as was pulled back) ////////////////////////////////////////////////// out("G1 E".(0.8*$setting['extruder_backlash_fwd']).".0 F19000.0\n"); out("G1 E".(0.2*$setting['extruder_backlash_fwd']).".0 F14000.0\n"); out("G1 F".($F*1.0)."\n"); // restore previous F out('','flush'); }else { $buffer = out('','get'); //echo $buffer; $buffer_new = ereg_replace('buffstart_reverse(.*)reverse_end','skipped_reversing',$buffer); //if($buffer != $buffer_new) echo "\nBefore: ======== $buffer ===== \nAfter: ========== $buffer_new\n"; //else echo "\n========".$buffer; out($buffer_new,'put'); out('','flush'); } } } $extrusion_has_started = true; // When starting extrusion, E = 0? break; case "2"; $dir = -1; break; case "3": $dir = 0; if(isset($setting['extruder_backlash_rev'])) { // start buffered output, reversing is conditional, based on distance we will travel before turning it on again! if($last_dir != $dir) { //////////////////////////////////////////////////////////////////////// // Pull back! First start buffering to be able to revert these added codes, then add them. ////////////////////////////////////////////////// out("(buffstart_reverse)\n",'on');// buffering on #$dist -= $setting['extruder_backlash_rev'];// Needs testing #$line .= "E-".(1.0*$setting['extruder_backlash_rev']); out("G1 E-".(1.0*$setting['extruder_backlash_rev']).".0 F19000.0\n"); #out("(Turning extruder off. $E)\n"); out("G1 F".($F*1.0)."\n"); // restore previous F out("(reverse_end)\n"); $distance_traveled = 0; // Reset this var $amount_extruded = 0; //Reset this var } } break; } //$comment .= " dir $dir"; //out("(".trim($line).")\n"); if(($setting['remove_M101-M103']==false) && ($setting['repeat_M103-M101']!=true)) out("$line"); continue; // Assuming that M codes are always on a single line... skip this } if($setting['repeat_M103-M101']==true) // BfB bug workaround { if($dir == 1) #out("M103\nM101\n"); { $line = str_replace("\n","\nM103\nM101\n",$line); #$line = str_replace("\n","\nM103\nM101\n",$line); } } if(my_ereg("G[ ]*90",$line,$_dummy)) $abs = true; if(my_ereg("G[ ]*91",$line,$_dummy)) $abs = false; // G20 - inches, G21 - mm unset($E); $comment .= sprintf("dXY=%.2f,%.2f ",$dX,$dY)." lastXY= ".sprintf("%.2f,%.2f",$lastX,$lastY); $prev_delta['X']=$dX; $prev_delta['Y']=$dY; $prev_delta['Z']=$dZ; if($abs) { /* $dX=bcsub($X,$lastX); $dY=bcsub($Y,$lastY); $dZ=bcsub($Z,$lastZ); */ $dX=(1.0*$X-$lastX); $dY=(1.0*$Y-$lastY); $dZ=(1.0*$Z-$lastZ); } else { $dX=$X; $dY=$Y; $dZ=$Z; } $hist++; if($hist>9) $hist=0; // keep 9 segments in history $moveHist['X'][$hist]=$dX; $moveHist['Y'][$hist]=$dY; $dist2 = bcsqrt(bcadd(bcpow($dX,2),bcpow($dY,2))); $distance_traveled += $dist2; if($setting['extrude_incremental'] != 1) $dist = bcadd($dist,$dist2); else $dist = $dist2; $comment .= "( dist=sqrt($dX^2+$dY^2)=".bcpow($dX,2).'+'.bcpow($dY,2).'= '.sprintf("%.2f",$dist).')'; if($dir!=0) $E = bcmul($setting['extrusion_adjust'],$dist); $amount_extruded += $E; // Only when cartesian coordinates are used??? //if(my_ereg("[^;(].*[XYZ])",$line,$regs)) //{} $line = trim($line); if(false && ($extruder_starting) && ($setting['extrude_incremental'] == 1)) // FIXME: Needs testing. Does the non-incremental work now? { //$line .= " E0";// Causes multiple E's! //out ("(starting extruder \$E=$E)\n"); $dist = 0; #echo "\n$E was... now making it ".$setting['extruder_backlash_fwd']; //$E += $setting['extruder_backlash_fwd']; $extruder_starting = false; } // LET OP, moet misschien IF zijn!??! //elseif($E) if($E && ($setting['add_E_codes'])) { $line .= " E".sprintf("%.2f",bcmul($E,$dir)); // number w/ four decimals } // Anti-backlash: if(is_array($setting['anti-backlash'])) { foreach($setting['anti-backlash'] as $thisAxis => $backlash) { //'Y'=>array('fwd_dynamic'=>0.1/*mm*/, 'rev_dynamic'=>0.1/*mm*/,'fwd_static'=>0.1/*mm*/, 'rev_static'=>0.1/*mm*/ ), // Backlash on Y-axis // Dynamic or static? //$vibration = 0; //$vibration += ($moveHist['X'][$hist])/$dist; //$vibration += -($moveHist['X'][($hist-1)%10])/$dist; //$vibration += (1/$moveHist['X'][($hist-2)%10])/$dist*.8; //$vibration += -(1/$moveHist['X'][($hist-3)%10])/$dist*.6; //$vibration += (1/$moveHist['X'][($hist-4)%10])/$dist*.4; extract($backlash); if($thisAxis == 'X') { $axisPos = $X; $axisDelta = $dX; } if($thisAxis == 'Y') { $axisPos = $Y; $axisDelta = $dY; } $newAxisPos = $axisPos; if($axisDelta > 0) { if($lastDelta[$thisAxis]<0) // if previous move was in the other direction, dynamic friction applies? $newAxisPos = bcadd($axisPos,$fwd_dynamic); else $newAxisPos = bcadd($axisPos,$fwd_static);//otherwise, static friction } elseif($axisDelta < 0) { if($lastDelta[$thisAxis]>0) $newAxisPos = bcsub($axisPos,$rev_dynamic); else $newAxisPos = bcsub($axisPos,$rev_static); } // maintain once previous backlash compensation if axis didn't move. After that compensation will be removed (!?) //elseif($lastDelta[$thisAxis] > 0) // $newAxisPos = bcadd($axisPos,$fwd_static); //elseif($lastDelta[$thisAxis] < 0) // $newAxisPos = bcsub($axisPos,$rev_static); //if(($axisDelta < 0) && ($lastDelta[$thisAxis]>0)) $line .= " Dyn"; //if(($axisDelta > 0) && ($lastDelta[$thisAxis]<0)) $line .= " Dyn"; //$line .= "\td$axisDelta"; $lastDelta[$thisAxis] = $axisDelta; //not used??? $line = str_replace("$thisAxis$axisPos","$thisAxis$newAxisPos",$line); //$line.="\tAcc$thisAxis=".($accelleration[$thisAxis]/$axisDelta); //if($thisAxis=='X') $line.="\td$thisAxis=".$dX." Vib=".($vibration); //if($thisAxis=='X') $line.="\td$thisAxis=".$dX." Vib=".($vibration); //out("(AntiBacklash d$thisAxis=$axisDelta: $thisAxis$axisPos now $newAxisPos)\n"); } } // Replace feedrate: foreach($setting['replace_strings'] as $oldRate=>$newRate) { $line = str_replace("$oldRate","$newRate",$line); } // Accelleration when traveling (not extruding) if(isset($setting['accelerated_travel']) && ($setting['accelerated_travel']!=false)) { if( ($E==0) // extruder should be OFF && ($dist > $setting['accelerated_travel_mindist']) // not for very small distances ) { //out("\n(Dist: $dist F=$F. Line:\t".$line.")"); // Segments are spread evenly, but could be improved. e.g. 111222333222111, could be 123333333333321 //out("\n (dX=$dX, dY=$dY, dZ=$dZ)"); $segX = $lastX; $segY = $lastY; $segZ = $lastZ; $segspeedfactor=0; $segs = 7; if($dist > 10) $segs = 15; for($segnr=1;$segnr<($segs);$segnr++) // normal line will be added below { if($segnr<=(($segs+1)/2)) $segspeedfactor+=$setting['accelerated_travel']; else $segspeedfactor-=$setting['accelerated_travel']; $newF = bcmul($F,$segspeedfactor); if($newF > 4500) { $newF = 4500; continue; } // do not output the line out("G1"); $segX = bcadd($segX,bcdiv($dX,$segs)); $segY = bcadd($segY,bcdiv($dY,$segs)); $segZ = bcadd($segZ,bcdiv($dZ,$segs)); if($dX) out(" X".$segX); if($dY) out(" Y".$segY); if($dZ) out(" Z".$segZ); out(" F".intval($newF).".0\n"); //out(" ($segspeedfactor speed @ seg$segnr/$segs)\n"); } } } // Actions: $orrigLine = $line; foreach($setting['actions'] as $action) { //array('condition'=>array('match','F330.0'),'actions'=>array('E_mul'=>2,'F_mul'=>0.5)), // raft making: slow down XY-moves, speed up extrusion. // conditions: // Implemented: match a string. To implement: match a Z-layer, < > or =.? if($action['while'][0]=='match') { if(isset($action['while'])) $conditionOk = false; if(strpos($orrigLine,$action['while'][1])) { //echo "(line matches $action[condition]"; $conditionOk = true; } } // I know, this is not coded in a very elegant way... EdB if(($action['condition_start'][0]=='match') && (strpos($orrigLine,$action['condition_start'][1]))) $conditionOk = true; if(($action['condition_stop'][0]=='match') && (strpos($orrigLine,$action['condition_stop'][1]))) $conditionOk = false; if($conditionOk) { foreach($action['actions'] as $actParam => $actVal) {// Todo: eval expressions? //echo "Condit: $conditionOk"; if(my_ereg('([XYZFE])_mul',$actParam,$regs)) { $actOnAxis=$regs[1]; if(my_ereg("$actOnAxis([0-9\.]+)",$orrigLine,$regs2)) // eval action against original line? { $newRate = bcmul($regs2[1],$actVal); $line = str_replace("$actOnAxis$regs2[1]","$actOnAxis$newRate",$line); } } } } } if(abs($dZ)>0.1) { // Smooth-Z: WARNING, is buggy! /*G1 X23.1300 Y-18.8500 Z22.4 F1080.0 E1.63 G1 X23.0900 Y-18.9200 Z22.51 F73.2727 (smthd) E0.12 G1 X23.5000 Y-18.2900 Z22.64 F24.3076 (smthd) <--- WAY too low! .25 + .25 + .10 G1 X23.5700 Y-18.1700 Z22.75 F126.2727 (smthd) */ if($setting['soften_z_move_factor']) { // F =mm/s // (mm/s)/mm = /s // mm/(mm/s) = s // dZmm/s = ... //out("(dist=$dist, dZ=$dZ, F=$regs[1], time=".($dist/$regs[1])."s Z-speed=".($dZ/($dist/$regs[1])).")"); if(my_ereg("F([0-9\.]+)",$line,$regs)) { //out("(dist=$dist,F=$regs[1])"); $Zspeed = (abs($dZ)/($dist/$regs[1])); if($Zspeed>100)//if($dZ/($dist/$regs[1])>500.0) { #$newF = bcmul($setting['soften_z_move_factor'],$regs[1]); #EXPERIMENTAL: reduce speed so that effective Zspeed is at most 100. $newF = bcmul(100/$Zspeed,$regs[1]); $Znewspeed = (abs($dZ)/($dist/$newF)); //if($setting['debug']) $oldlline= $line; $line = ereg_replace("F[0-9\.]+","F$newF (smthd)",$line); //out("(f was SLOWeD DOWN, dist=$dist f/dist=".($regs[1]/$dist)." oldLine: $oldlline, new $line)\n"); } //else out("(f was slow enough, not softened, dist=$dist f/dist=".($regs[1]/$dist).")\n"); //out("(Smooth-Z dZ > 0.1 F=$regs[1], newF=$newF. $Zspeed=$Zspeed, now: $Znewspeed )\n"); } }//end if smooth } out($line); if($E > 999) { out("\nG92 E0 ( set extruder home )"); $dist = 0; } //out(" ; ".$comment); out("\n"); // } // end foreach line out($setting['append_gcode']); echo "\n(Gcode processing took: ".number_format((microtime(true)-$uTime),2,'.','')." seconds)"; if($setting['sd_mount']) { echo "Backing up SD card contents to ".$setting['sdbak_dir']."\n"; echo "Copying to SD card... "; if(!copy($setting['output_file'],$setting['sd_mount']."/".basename($setting['output_file']))) die("Copying ".$setting['output_file']." to ".$setting['sd_mount']." failed."); echo "done\n"; echo "Syncing filesystem and unmounting..."; `sync`; echo shell_exec("umount ".escapeshellarg($setting['sd_mount'])); echo "done\n"; } /* $fp = fopen($fName,'r'); if(!$fp) die("File $argv[0] could not be opened."); $go = true; while($go) { if(!strpos($str,"\n")) { $str .= fgets($fp,128); } else { $lines = split("\n",$str); out($str); } } */ function out($str,$buffered = 'nochange') // TODO: writer class { global $setting,$out_buffer,$buffer_status; if($buffered == 'flush') { $tmpvar = out($out_buffer.$str,'off'); $out_buffer = ''; $buffer_status = false; return $tmpvar; } if($buffered == 'get') { return $out_buffer; } if($buffered == 'put') { $out_buffer = $str; return true; } if($buffered == 'on') { $buffer_status = true; } if($buffered == 'off')// turn off buffering { #echo $str.'turning off buffering\n'; $buffer_status = false; } if($buffer_status == true) { $out_buffer .= $str; return; } if(isset($setting['remove_redundant_Gcodes']) && $setting['remove_redundant_Gcodes']) { if(my_ereg("G([0-9]+)[^0-9]",$str,$regs)) { if($setting['last_gcode']==$regs[1]) $str = str_replace("G".$regs[1].' ','',$str); $setting['last_gcode'] = $regs[1]; } if(my_ereg("Z([0-9\.]+)[^0-9]",$str,$regs)) { if($setting['last_Z']==$regs[1]) $str = str_replace("Z".$regs[1],'',$str); $setting['last_Z'] = $regs[1]; } if(my_ereg("F([0-9\.]+)[^0-9]",$str,$regs)) { if($setting['last_F']==$regs[1]) $str = str_replace("F".$regs[1],'',$str); $setting['last_F'] = $regs[1]; } //$str = ereg_replace("[XYZFE]([0-9]+\.[1-9]*)0+ ","\\1 ",$str); // remove unneeded spaces //$str = ereg_replace("([XYZFE]^ *)[0]+ ","\\1 ",$str); // remove unneeded spaces //$str = ereg_replace(" +","\t",$str); // remove unneeded spaces } if($setting['switch_extruders']) { $str = ereg_replace("M10([12348])","m20\\1",$str); $str = ereg_replace("M20([12348])","M10\\1",$str); $str = ereg_replace("m20([12348])","M20\\1",$str); } if($setting['output_file'] == null) { echo($str); } else { if(!isset($setting['firstline'])) { file_put_contents($setting['output_file'],$str); $setting['firstline'] = false; } else file_put_contents($setting['output_file'],$str,FILE_APPEND); } } function statusLine() { global $line_nr,$line_count,$uTime; $lines_left = $line_count - $line_nr; $lines_per_second = $line_nr / (microtime(true)-$uTime); $seconds_left = $lines_left / $lines_per_second; $percent = intval($line_nr/$line_count*100); $str = "".chr(0x1B)."\r ".intval($percent)."% done. $lines_left lines or ".Sec2Time($seconds_left)." remaining. "; return $str; } function Sec2Time($time){ if(is_numeric($time)){ $value = array( "years" => 0, "days" => 0, "hours" => 0, "minutes" => 0, "seconds" => 0, ); if($time >= 31556926){ $str .= $value["years"] = floor($time/31556926); $time = ($time%31556926); $str .= " years, "; } if($time >= 86400){ $str .= $value["days"] = floor($time/86400); $time = ($time%86400); $str .= " days, "; } if($time >= 3600){ $str .= $value["hours"] = floor($time/3600); $time = ($time%3600); $str .= " hours, "; } if($time >= 60){ $str .= $value["minutes"] = floor($time/60); $time = ($time%60); $str .= " minutes, "; } $str .= $value["seconds"] = floor($time); $str .= " seconds"; return $str; #return (array) $value; }else{ return (bool) FALSE; } } function determine_input_file($fName='') { if(!$fName) die("\nUsage: ".basename($argv[0])." foo.".$setting['extension']." [--setting-name setting-value] [--output_file filename.".$settings['extension']."]\n"); if(!file_exists($fName)) { echo "Warning, $fName not found. Looking in search paths...\n"; $tryFile = array( "/home/erik/RepRap/obj/$fName", "/home/erik/RepRap/obj/${fName}_export.".$setting['extension'], "/home/erik/RepRap/obj/$fName*.".$setting['extension'], "/home/erik/RepRap/obj/${fName}*_export.".$setting['extension'], ); $fName = ''; foreach($tryFile as $try) { $results = glob($try); if(count($results)==1) { $fName = $results[0]; echo "Notice: found unambiguous matching filename: $fName\n"; break; } } if($fName=='') die("\nNo input file found in search paths:\n".print_r($tryFile,true)); } return $fName; } function init_sd($setting) { $sd_mounted = glob("/media/disk*/RR_SD"); if($nr_SDs = count($sd_mounted)) { if($nr_SDs > 1) { echo "Multiple ($nr_SDs) SD cards found. Please mount only one at a time..."; } $setting['sd_mount'] = dirname($sd_mounted[0]); echo "Notice: SD mounted on ".dirname($setting['sd_mount'])."\n"; } } function my_ereg($reg,$str,&$regs) { return @ereg($reg,$str,$regs); } ?>