Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time until M600 feature? #115

Closed
brandonscholet opened this issue Feb 3, 2020 · 17 comments
Closed

Time until M600 feature? #115

brandonscholet opened this issue Feb 3, 2020 · 17 comments
Labels
status: markedForAutoClose Issue will be closed automatically status: waitingForTestFeedback type: enhancement New feature or request

Comments

@brandonscholet
Copy link

I may try and write my first plugin to see how long until an M600. I'd probably try to display it in Dashboard.

Do you have any advice how where I should start? I know that you have where it can estimate how long until the end, but how hard would it be to find the M600's and use that layer for the estimate?

@brandonscholet
Copy link
Author

image

So I've been working on this. I've got a standalone python script that works pulling from your api endpoint.

Below is my code (sorry if it is so shabby.)

if I'm able to figure out how to parse for the M600 in the files on octoprint, then I think I could somehow make this plugin

import requests
import json
import pprint
import sys

#layerChange=sys.argv[1]
pp = pprint.PrettyPrinter(indent=4)
global data

def secondsToText(secs):
days = secs//86400
hours = (secs - days86400)//3600
minutes = (secs - days
86400 - hours3600)//60
seconds = secs - days
86400 - hours3600 - minutes60
result = ("{0} day{1}, ".format(days, "s" if days!=1 else "") if days else "") +
("{0} hour{1}, ".format(hours, "s" if hours!=1 else "") if hours else "") +
("{0} minute{1}, ".format(minutes, "s" if minutes!=1 else "") if minutes else "") +
("{0} second{1}, ".format(seconds, "s" if seconds!=1 else "") if seconds else "")
return result

def getData():
url = 'http://pi.hole:5000/plugin/DisplayLayerProgress/values'
headers = {'X-Api-Key': '30181C03E72440EBB0096D9A0A0830BA'}
response=requests.get(url, headers=headers)
data=json.loads(response.text)
calculateAndPrint(data)
#pp.pprint(data)

def calculateAndPrint(data):
layerChange=sys.argv[1]

layersleft=int(data["layer"]["total"])-int(data["layer"]["current"])
averageSecondsPerLeftLayer=int(data["print"]["timeLeftInSeconds"])/layersleft
pp.pprint("Current Layer is: "+str(data["layer"]["current"]))
pp.pprint("total layers left "+str(layersleft))
pp.pprint("seconds per layer left: "+str(averageSecondsPerLeftLayer))

for x in range(1,len(sys.argv)):
    layerChange=sys.argv[x]
    pp.pprint("--------------")
    pp.pprint("Layer Change at Layer: "+layerChange)
    layerstochange=int(layerChange)-int(data["layer"]["current"])
    answer=layerstochange * averageSecondsPerLeftLayer 

    pp.pprint("layers left to change: "+str(layerstochange))
    pp.pprint("Estimated Time to Layer: "+str(secondsToText(answer)))

getData()

@brandonscholet
Copy link
Author

'Current Layer is: 408'
'total layers left 823'
'seconds per layer left: 91'
'--------------'
'Layer Change at Layer: 409'
'layers left to change: 1'
'Estimated Time to Layer: 1 minute, 31 seconds, '
'Estimated Change Time: 2020-02-03 23:03:44'
'--------------'
'Layer Change at Layer: 819'
'layers left to change: 411'
'Estimated Time to Layer: 10 hours, 23 minutes, 21 seconds, '
'Estimated Change Time: 2020-02-04 09:25:34'

I added a time to change it for QOL.

I would love to make this a thing

@OllisGit
Copy link
Owner

OllisGit commented Feb 4, 2020

Hi,

nice idea! This function is still missing in OctoPrint!

so if I would start to write a plugin that predict the filament change times. My plugin will look like this:

Use the event-bus instead of the api, because I need a push-notification if a layer is changed instead of polling each second about the current layer-number.

Use the on_event function and listen on "fileSelected" and "DisplayLayerProgress_layerChanged".

  • fileSelected:
    parse the selected file line by line and identify in which layers (could be multiple times) is a M600 included.

  • layerChanged:
    grab the attribute "lastLayerDurationInSeconds" (or maybe better "averageLayerDurationInSeconds") and calculate the difference between next M600-layer and current layer, multiply durationsInSeconds. The result should be added to current time -> predicted time for the next change.

Look into my sourcecode, there you can find the event-handling and also the line by line parsing after selecting the file.

...maybe I can include your idea into my plugin....or maybe even better you want to contribute and add that feature to my plugin....what do you think?

BR
Olli

@OllisGit OllisGit added type: question Further information is requested status: waitingForFeedback Wating for Customers feedback labels Feb 4, 2020
@OllisGit
Copy link
Owner

OllisGit commented Feb 4, 2020

Hi @brandonscholet,

I like the idea so much that I already started the implementation ;-)
Unfortunately I am currently at my 9-5 Job and don't have much time. The implementation is almost done. I just added some if-statements and a time calculation, thats it.
But I need to test the implementation...so I am looking for a free time slot in my spare time to test it. Maybe on the next weekend.

@brandonscholet
Copy link
Author

I've been looking through your source code and started the tutorial, but as I'm more of a bash guy and not python it's hard to give up grep. I was trying to figure out the best way to parse for the m600's and then look for the layer number in the next line.

I totally get the 9-5, I'm at my 8-4 :)

I feel like it would be easier to add in line with your script and extend your json API. I wonder if the printtimegenius and dashboard peeps would be interested in this too.

It's cool to see that you like my idea.

Let me know what I can test or what I can help with.

@brandonscholet
Copy link
Author

@StefanCohen @eyal0

Do you thing that this would be a great addition to the dashboard? Would PrintTimeGenius be able to calculate something like this?

@eyal0
Copy link

eyal0 commented Feb 4, 2020

I've already got that request here: eyal0/OctoPrint-PrintTimeGenius#150

I have a good idea about how to do it, I just need to find the time to do it. :-)

@StefanCohen
Copy link

Sure, It sounds great but I have a couple of problems. My father in law recently passed away so I'm quite busy atm. I've also re-purposed my dev RPi to monitor his old house and I haven't had the time to set up a new dev env yet.

@OllisGit
Copy link
Owner

OllisGit commented Feb 5, 2020

Btw. the implementation is done.
Now I do some testing...but to be honest: my printer doesn't support M600-command.
So, currently I am playing around with faked/dummy gcode.

Hopefully I can cleanup some code today and push my implementation as a dev-release to github.
So you can test the stuff with your printer (maybe with my dry-run-plugin ;-)

@eyal0
Copy link

eyal0 commented Feb 5, 2020

@OllisGit Funny, I just made the same thing! I wonder if we used the same techniques. https://github.com/eyal0/OctoPrint-TimeToFilament

OllisGit added a commit that referenced this issue Feb 5, 2020
- PR #114 Total Height Calculation for PrusaSlicer
- #115 detection of M600 filament change
@OllisGit
Copy link
Owner

OllisGit commented Feb 5, 2020

Hi,
new Version is pushed to git.
See release notes for details:
https://github.com/OllisGit/OctoPrint-DisplayLayerProgress/releases/tag/1.18.0dev

You can download it via:
https://github.com/OllisGit/OctoPrint-DisplayLayerProgress/releases/download/1.18.0dev/master.zip

@eyal0 I looked into your implementation and it looks totally different.
I am working with layers and layer durations, because I already have this information.

My Plugin:

  • after selecting the file, all M600 occurencies will be identified and stored together with the layer number.
  • during print the filament change time is calculated with the layer difference between current and next m600 layer, multiplied with average layer duration
  • Only on layer-change event the time is recalculated. For ChangeFilamentTime is it okay, but for changeFilamentTimeLeft it looks a little bit weird, because a better "refresh" is maybe expected.

Please test and give me a feedback!
Thx, in advance
Olli

@OllisGit OllisGit added status: waitingForTestFeedback and removed status: waitingForFeedback Wating for Customers feedback labels Feb 5, 2020
@brandonscholet
Copy link
Author

The data structure looks nice.

The first issue I see is that the average layer duration is zero, so the whole first layerit thinks the change is this minute. This average will always be wild until the first few solid layers are done.

When I wrote my proof of concept, I took remaining time / remaining layers and that gave me a pretty good result. It even helped estimate when the second layer change was.

Maybe there is a good middle ground for this?

Otherwise I love it. Thanks for keeping the dream alive.

@OllisGit
Copy link
Owner

Hi @brandonscholet ,
thanks for the feedback!

To be honest I didn't thought a lot about a good prediction time.
Currently the "average layer duration" is only take after the average value is available (default: after 5 layers), before that the last layer duration is taken. Maybe there is the issue.
So, I will take a deeper look into that to improve the values.

OllisGit added a commit that referenced this issue Feb 17, 2020
…Python3 bug

- #115 optimize the first output of the filamentchangetime
@OllisGit
Copy link
Owner

Hi @brandonscholet,
in the new Version 1.18.0 I changed the behaviour about calculating the change filament time. Now it starts calculating after the first layer is printed.

@OllisGit OllisGit added status: waitingForTestFeedback type: enhancement New feature or request and removed status: inNextRelease Will be implemented/fixed in next release type: question Further information is requested labels Feb 17, 2020
@brandonscholet
Copy link
Author

I'll need to see if the update changes from the dev one you gave me,

the issue with calculating by average layer time is still an issue. Sometimes it can take hours to get back to change the filament out and that can rapidly balloon the avg layer time I waited 20 minutes and did the change.

It was then showing that the 2nd filament change is 1.5 days passed the estimated time of completion of the print, which should be fairly accurate at this point. it took around 70 layers for it to catch up to where the filament change was less than the print time. The change was at an even third of the print lightweight.

I love the display for the update and when this print is done, I'll be able to check it out.

This is why when I did the POC I divided estimated time remaining by layer count left until change.
I am a fan of this as it would be scalable.

I thought about it a bit today and there could be a best solution, but returns vs amount or work ight not be worth it. This could be done by parsing the TimeElapsed before the layer numbers, subtracting it from the total estimated print time and then counting back. Maybe by averaging that with the POC result it could yield a fairly accurate result.

Let me know what you think. Below are some screenshots with the estimates

Screenshot_20200218_173242
Screenshot_20200218_200807

@OllisGit
Copy link
Owner

Hi @brandonscholet , I see the issue...

  • to reduce the inaccuracy you can reduce the average layer cont from 5 to 1. Then only the last layer-duration will be used. So after the next two layer is printed the value must be fit again (instead of 5 layers). The duration of the filament change is only included in one layer-duration
  • the "time elapsed" approach could be an option...the value is still on my list, see [Enhancement] New Value: time elapsed #116.
  • an other option could be to stop the timer during M600 and resume

Because I don't have a printer that support M600, how often do you need a change? It's depending on the model I know, but is it more layer based or also in a current layer-print?

@stale
Copy link

stale bot commented Aug 30, 2020

This issue has been automatically marked for closing, because it has not had activity in 30 days. It will be closed if no further activity occurs in 10 days.

@stale stale bot added the status: markedForAutoClose Issue will be closed automatically label Aug 30, 2020
@stale stale bot closed this as completed Sep 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: markedForAutoClose Issue will be closed automatically status: waitingForTestFeedback type: enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants