Skip to content

Commit

Permalink
Implement cycle time estimation
Browse files Browse the repository at this point in the history
  • Loading branch information
jes committed Apr 17, 2022
1 parent 9660658 commit f8c4dcc
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 24 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ If you want to improve Meshmill but don't know where to start, you could look at
* implement Ramp entry
* make Pngcam multi-threaded, or otherwise improve performance
* draw diagrams to put in the tooltips to explain concepts like step over, step down, nominal deviation, etc.
* implement cycle time calculation
* implement support for rotary carving

## Contact me
Expand Down
41 changes: 41 additions & 0 deletions bin/pngcam
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ sub one_pass {
y => 0,
z => 0,
};
my $cycletime = 100;
for my $p (@path) {
# calculate the maximum feed rate that will not cause movement in either the XY plane or the Z axis to exceed their configured feed rates
my $dx = $p->{x} - $last->{x};
Expand Down Expand Up @@ -279,6 +280,8 @@ sub one_pass {
$feed_rate = $self->{xy_feedrate} if $feed_rate > $self->{xy_feedrate}; # XXX: can this happen?
}

$cycletime += $self->movetime($last->{x},$last->{y},$last->{z}, $p->{x},$p->{y},$p->{z}, $feed_rate);

print sprintf("$p->{G} X%.4f Y%.4f Z%.4f F%.1f\n", $p->{x}+$self->{x_offset}, $p->{y}+$self->{y_offset}, $p->{z}+$self->{z_offset}, $feed_rate);
$last = $p;
}
Expand All @@ -287,6 +290,8 @@ sub one_pass {
print "G1 Z$self->{rapid_clearance} F$self->{rapid_feedrate}\n";

print STDERR "\nDone.\n" if !$self->{quiet};

print STDERR "Cycle time estimate: $cycletime secs\n";
}

# return 1 if the 2 points are orthogonal and 1 stepover apart
Expand Down Expand Up @@ -422,6 +427,23 @@ sub get_brightness {
}
}

# calculate time to move from ($x1,$y1,$z1) to ($x2,$y2,$z2) at $feedrate mm/min, in seconds
sub movetime {
my ($self, $x1,$y1,$z1, $x2,$y2,$z2, $feedrate) = @_;

# TODO: take into account max. acceleration

$feedrate = $self->{maxvel} if !$feedrate || $feedrate > $self->{maxvel};

my $dx = abs($x2-$x1);
my $dy = abs($y2-$y1);
my $dz = abs($z2-$z1);
my $dist = sqrt($dx*$dx + $dy*$dy + $dz*$dz);
my $mins = $dist / $feedrate;
my $secs = $mins * 60;
return $secs;
}

1;
#!/usr/bin/perl

Expand Down Expand Up @@ -462,6 +484,9 @@ my $normalise;
my $normalise_ignore_black;
my $imperial;

my $maxvel = 4000;
my $maxaccel = 50;

my $quiet;

GetOptions(
Expand Down Expand Up @@ -495,6 +520,9 @@ GetOptions(
'normalise-ignore-black' => \$normalise_ignore_black,
'imperial' => \$imperial,

'max-vel=f' => \$maxvel,
'max-accel=f' => \$maxaccel,

'quiet' => \$quiet,

'help' => sub { help() },
Expand Down Expand Up @@ -541,6 +569,9 @@ my $pngcam = Pngcam->new(
normalise_ignore_black => $normalise_ignore_black,
imperial => $imperial,

maxvel => $maxvel,
maxaccel => $maxaccel,

quiet => $quiet,

image_file => $image_file,
Expand Down Expand Up @@ -665,6 +696,16 @@ Heightmap options:
All units are inches instead of mm, and inches/min instead of mm/min. G-code output has G20 instead of G21.
Default: not imperial.
Cycle time options:
--max-vel MM/MIN
Max. velocity in mm/min for cycle time calculation.
Default: 4000.
--max-accel MM/SEC^2
Max. acceleration in mm/sec^2 for cycle time calculation.
Default: 50.
Output options:
--quiet
Expand Down
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
<button id="toolpath-cancel">Stop</button> <progress max="100" id="toolpath-pct"></progress><br>
<span id="toolpath-eta"></span><br>
<button id="save-gcode">Save G-code</button><br>
Cycle time estimate: <span id="cycletime">45m23s</span><br>
<div class="has-tooltip"><div class="tooltip">Rough estimate of how long it will take for the job to complete.</div></div>Cycle time estimate: <span id="cycletime">?</span><br>
<small><button id="deletejob">Delete job</button></small><br>
</div>
</div>
Expand All @@ -118,6 +118,7 @@
<script src="js/lib/STLLoader.js"></script>
<script src="js/lib/OrbitControls.js"></script>
<script src="js/lib/jquery-3.6.0.min.js"></script>
<script src="js/fmt.js"></script>
<script src="js/project.js"></script>
<script src="js/settings.js"></script>
<script src="js/heightmap.js"></script>
Expand Down
27 changes: 27 additions & 0 deletions js/fmt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function timefmt(millis) {
let hours = Math.floor(millis/3600000);
millis -= hours*3600000;
let mins = Math.floor(millis/60000);
millis -= mins*60000;
let secs = Math.floor(millis/1000);
millis -= secs*1000;

if (hours) return hours + "h" + mins + "m";
if (mins) return mins + "m" + secs + "s";
return secs + "s";
}

function formatFloat(f) {
let dp = 2;
let n = 0.1;

if (f < 0) return "-" + formatFloat(-f);
if (f < 0.0000001) return "0.00";

while (f < n) {
n /= 10;
dp++;
}

return f.toFixed(dp);
}
7 changes: 1 addition & 6 deletions js/progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ var progresstarget;
var progressstarted;
var progressstate;

function timefmt(millis) {
// TODO: hours, minutes, etc.
return (1+Math.round(millis/1000)) + " secs";
}

function progress(pct) {
$(`#${progresstarget}-pct`).val(pct);
if (pct == null) {
Expand All @@ -28,7 +23,7 @@ function progressEta() {
let howmuch = pct/100;
let timefor100 = howlong/howmuch;
let remaining = timefor100 - howlong;
$(`#${progresstarget}-eta`).text("ETA: " + timefmt(remaining));
$(`#${progresstarget}-eta`).text("ETA: " + timefmt(1000+remaining));
} else {
$(`#${progresstarget}-eta`).text("ETA: ?");
}
Expand Down
20 changes: 4 additions & 16 deletions js/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ $('#generate-toolpath').click(function() {
progressEnd();
updateJob();
drawJob();
// TODO: show cycle time estimate
});
});

Expand Down Expand Up @@ -315,6 +314,10 @@ $('#addjob-tab').click(function() {
showJob(id);
});

window.api.receive('cycle-time', function(t) {
$('#cycletime').text(timefmt(t*1000));
});

/* menu actions */

window.api.receive('new-project', function() {
Expand Down Expand Up @@ -372,21 +375,6 @@ function confirmDialog(msg, yes, no, cb) {
}, cb);
}

function formatFloat(f) {
let dp = 2;
let n = 0.1;

if (f < 0) return "-" + formatFloat(-f);
if (f < 0.0000001) return "0.00";

while (f < n) {
n /= 10;
dp++;
}

return f.toFixed(dp);
}

window.api.receive('want-close', function() {
if (project && project.dirty) {
confirmDialog("Project unsaved. Are you sure you want to quit?", "Quit", "Don't quit", function(confirmed) {
Expand Down
8 changes: 8 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,10 @@ ipcMain.on('generate-toolpath', (event,arg,replychan) => {
'--x-offset', arg.offset.x,
'--y-offset', arg.offset.y,
'--z-offset', arg.offset.z,
'--max-vel', settings.maxvel,
'--max-accel', settings.maxaccel,
];
console.log(opts);
if (arg.roughingonly) opts.push('--roughing-only');
if (arg.rampentry) opts.push('--ramp-entry');
if (arg.omittop) opts.push('--omit-top');
Expand All @@ -240,6 +243,11 @@ ipcMain.on('generate-toolpath', (event,arg,replychan) => {
if (match) {
win.webContents.send('progress', match[1]);
}

match = (""+data).match(/Cycle time estimate: ([0-9.]+) secs/);
if (match) {
win.webContents.send('cycle-time', parseFloat(match[1]));
}
});

pngcam.on('close', (code) => {
Expand Down

0 comments on commit f8c4dcc

Please sign in to comment.