luc-github / ESP3D-WEBUI

A Web UI for ESP8266 or ESP32 based boards connected to 3D printers / CNC
GNU General Public License v3.0
747 stars 305 forks source link

[FEATURE REQUEST] [Print Status Panel] Idea for better "Left"/"Remaining" Time calculation #271

Closed microlomaniac closed 1 year ago

microlomaniac commented 1 year ago

Is your feature request related to a problem? Please describe. The "Left" time calculation is based on total print time reported by the printer and is not accurate, especially in the early minutes of the print, because the printer does not start printing the code right away. This leads to the Print Status Panel reporting an initial remaining print time of several days for a 90-minute print.

Describe the solution you'd like Since the current calculation seems to be remaining = elapsed * (100 - progress) / progress (Originally posted by @olivierbarriere in https://github.com/luc-github/ESP3D-WEBUI/issues/239#issuecomment-1151066960) Maybe it would be helpful to check when the print REALLY starts (i.e. when the nozzle starts printing onto the bed). Maybe measure the time at which "SD Card printing byte" (M27) crosses a threshold (I haven't checked if this threshold can be 0) and adjust the calculation as follows: remaining = (elapsed - elapsed_when_m27_crossed_threshold) * (100 - progress) / progress

Describe alternatives you've considered No alternatives, just this idea.

Additional context I did not find the according bits in the code, otherwise I would have tried to implement it myself.

github-actions[bot] commented 1 year ago

Thank your for submiting, please be sure you followed template or your issue may be dismissed.

luc-github commented 1 year ago

the time is based on M31 and progress on M27.so everything is coming from Marlin, it is updated at each call of both commands, so accuracy should be fixed on Marlin side not webui I think

luc-github commented 1 year ago

@microlomaniac any feedback on this ?

olivierbarriere commented 1 year ago

I modified Marlin and added this to cardreader.h / cpp duration_t CardReader::init_duration; uint32_t CardReader::init_size;

init_duration = duration_t(0); init_size = 600;

void CardReader::report_status() { SERIAL_ECHOPGM(STR_SD_PRINTING_BYTE, (sdpos > init_size) ? sdpos - init_size : 0); SERIAL_CHAR('/'); SERIAL_ECHOLN(filesize - init_size); }

static uint8_t percentDone() { if ((sdpos > init_size) && (init_duration.second() == 0)) { init_duration = print_job_timer.duration(); } if (flag.sdprintdone) return 100; if (isFileOpen() && filesize && (sdpos > init_size)) return (sdpos - init_size) / ((filesize - init_size) / 100); return 0; }

and this to M31.cpp duration_t elapsed = print_job_timer.duration(); duration_t init = card.getInitDuration(); duration_t((init.second() > 0) ? (elapsed.second() - init.second()) : 0).toString(buffer); SERIAL_ECHO_MSG("Print time: ", buffer);

and it does work as expected. I also modified the code for my LCD screen so that it prints the corrected remaining time too. Position 600 in my gcode (sliced with Cura) corresponds roughly to the first layer, after heating and G28 / G29 which can take a lot of time.

Would it be possible, in WebUI, to save the time (from M31 output) at which sdpos is above 600 (from M27 output) and use it to recompute the duration left based on that new reference point? It may be tricky since it needs two commands, that may not be run at the same time.

luc-github commented 1 year ago

Sorry I am not sure what you expect from webui, webui already catch all M31 and M27 output and calcul time left according these output

Also position 600 is valid only for your gcode, not everyone use cura and not everyone had same starting gcode

microlomaniac commented 1 year ago

Merci Olivier, I'll try this out on my next print (haven't figured out how to simulate prints without actually extruding anything yet).

After having thought about this a little bit more, I guess it's more complicated than figuring out the start time only. After all, not every command in the Gcode takes the same amount of time (or, as it were, is proportional to its length in bytes). So if we really want to calculate a precise time estimation, the whole .gcode file should be parsed with every line attributed a time in ms. Maybe a bit overkill. (maybe ESP3D could "learn" the speed of the 3D printer. again, overkill.)

Also I know this is a very low priority issue :)

luc-github commented 1 year ago

the issue is that esp3d does not know what printer is currently doing and what command is currently read - it only knows the progress of file read in bytes (M27) and since when Print started (M31) - so it only rely on these informations to give an estimated time - the heat time can depend if preheat is done already , if have a bed, if have one extruder , or 2 extruders, or more, if do bed leveling, etc... Nothing is simple when informations are unknown ^_^ So my suggestion is still valid - and as @olivierbarriere showed, need some modifications in Marlin itself if you want to improve situation. another solution is to apply a magic number , correction factor, based on experiments, it is what Repetier host do I think, but results can also be random IMHO, and I do not know this factor and conditions...

luc-github commented 1 year ago

And the best would be M31 has a flag giving the estimated time directly, it would avoid to rely on 2 differents commands and time delay between them, but that is a dream I think ;)

olivierbarriere commented 1 year ago

Merci Olivier, I'll try this out on my next print (haven't figured out how to simulate prints without actually extruding anything yet).

Just run the print without filament :) That's what I did for my tests with a small 5 min print job.

After having thought about this a little bit more, I guess it's more complicated than figuring out the start time only. After all, not every command in the Gcode takes the same amount of time (or, as it were, is proportional to its length in bytes). So if we really want to calculate a precise time estimation, the whole .gcode file should be parsed with every line attributed a time in ms. Maybe a bit overkill. (maybe ESP3D could "learn" the speed of the 3D printer. again, overkill.)

Indeed, it is very unlinear, and the remaining time based on the percentage of lines done (including comments!) can be very innacurate I think the proper way to have an accurate estimate is that it is computed by the slicer and added as M73 commands https://marlinfw.org/docs/gcode/M073.html I'm using Cura which does not do that, and I haven't found any plugin to do so (only some old references on google, but nothing in the current marketplace)

Also, while the estimate based on lines may be not be precise, it has the benefit to be always available and agnostic of the slicer, printer, CNC, etc.

And the best would be M31 has a flag giving the estimated time directly, it would avoid to rely on 2 differents commands and time delay between them, but that is a dream I think ;)

It would be quite easy to add such a flag to M31.cpp, but if it is still based on percentage of lines done, it has the same issues.

Another option would be M73, but it needs:

  1. a slicer that generates it in the gcode
  2. a modification to Marlin (again) in order to echo it on the serial output, because for now it's only used internally to show on the LCD screen
luc-github commented 1 year ago

So I close issue if actions need to be done Marlin side

github-actions[bot] commented 1 year ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.