Control Air Purifier, Lights, and Machine via PrusaSlicer

Hi,

on Friday I installed my air purifier and was surprised how loud (and strong) it is.
Because I’m afraid it would be too loud, I try to search how to switch it on only, when needed. And I don’t want to tinker every time with the g-code. Therefore I try to find a smart solution.
And in best case it is only switched on at a suitable daytime.

My solution is based on placeholders in the gcodes defined within PrusaSlicer and the function “physical printer” in PrusaSlicer. In the “End G-code” I added the following lines:

;{if physical_printer_preset=~/.*LIGHTS-OFF.*/}
;M1010 S3 P0 ;shut down lights (not used right now)
;{endif}

{if physical_printer_preset=~/.*FILTER-ON-PLANNED.*/}
;
;REPLACEDHEREFILTER
;
{endif}

{if physical_printer_preset=~/.*FILTER-ON.*/}
M1011 F1 S1 ;Purifier 1 gear working. Use S1 to force power up and run in this gear.
M1010 S4 P100 ;set exhaust fan to 100%
G4 S180 ;180sec filtering
M1010 S4 P0 ;set exhaust fan to 0%
M1011 F0 ;Purifier 1 gear working. Use S1 to force power up and run in this gear.
{endif}

{if physical_printer_preset=~/.*SHUTDOWN-ON.*/}
M107 ; turn off the fan
M1010 S3 P0 ;shut down lights
M1010 S4 P0 ;shut down exhaust fan
M1011 ; turn off air purifier
M81 ;power off printer after print (not working with SM2)
M112 ;emergency shutdown
{endif}

;End of Gcode

PrusaSlicer checks now for the name of the chosen physical printer and modifies the g-code. E.g. if the Name of the physical printer includes “FILTER-ON” the gcode snippet is added that turns on the Air purifier for 90 seconds. I hope you got the idea.

Afterwards you just have to add physical printers (Hint: Don’t use “:” in the Name!). My physical printers look now (Oh, I see there are still some errors :hushed: )

The blue arrow marks the button to add physicals printer. You see also I have combined versions with filter and shutdown.

The last (and biggest) challenge was to start it only at certain time.
My solution is partly already shown above. If there is “FILTER-ON-PLANNED” in the name an additional placeholder (“;REPLACEDHEREFILTER”) is added. This placeholder is modified via a external python script to add several G04 (dwell) commands before the air purifier is switched on.

The python script has to be added here and is used automatically:

You have to link to python and tell python where the script is:
C:\Users\Sightz\AppData\Local\Programs\Python\Python310\python.exe D:\stefan\1030_Bastelprojekte\Snapmaker\sleep_filter_until_defined_clocktime.py;

And of course you need to have the script there :wink:

#!/usr/bin/env python3

import re, sys
import datetime as dt

script_filename = sys.argv[0]
gcode_filename = sys.argv[1]

#Nur zum Debuggen
#script_filename = "script"
#gcode_filename = "X:\\test.gcode"

print("Script:")
print(script_filename)
print("GCode:")
print(gcode_filename)
print("\n")

waitintervall = 3600;

totaltime_regex = r'estimated printing time \(normal mode\) = (\d+)h (\d+)m (\d+)s'
replacer_regex = ';REPLACEDHEREFILTER'
notreplacer_regex = '(end_gcode = .*)(;REPLACEDHEREFILTER)(.*)'

gcode_file = open(gcode_filename, 'r')
gcode = gcode_file.read()
gcode_file.close()

group = re.findall(totaltime_regex, gcode)
stunden = int(group[0][0])
minuten = int(group[0][1])
sekunden = int(group[0][2])

print("Stunden:")
print(stunden)
print("Minuten:")
print(minuten)
print("Sekunden:")
print(sekunden)
print("\n")

startdatum = dt.datetime.now()
dauer = dt.timedelta(days=0, seconds=sekunden, microseconds=0, milliseconds=0, minutes=minuten, hours=stunden, weeks=0)
enddatum = startdatum + dauer
earliestfilter = dt.datetime.combine(dt.date.today(), dt.time(9, 00, 0))
sleeptime = earliestfilter - enddatum

if sleeptime <= dt.timedelta(0,0,0,0,0,0,0): 
    sleeptime = earliestfilter + dt.timedelta(days=1, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) - enddatum

waitseconds = int(sleeptime.total_seconds())

waitintervalls_num = int(round(waitseconds / waitintervall, 0))
waitintervallrest = int(waitseconds % waitintervall)

print("Startdatum:")
print(startdatum)
print("Enddatum:")
print(enddatum)
print("Filter startet um:")
print(earliestfilter)
print("Sleeptime:")
print(sleeptime)
print("\n")
print("Sleeptime:")
print(sleeptime)
print("\n")

print("Neues Startdatum:")
print(enddatum + sleeptime)
print("Wartesekunden:")
print(waitseconds)
print("In " + str(waitintervalls_num) + " Intervallen a " + str(waitintervall) + " Sekunden und einer Restzeit von " + str(waitintervallrest) + " Sekunden.")
print("\n")

addgcode = ""
for x in range(waitintervalls_num):
	addgcode = addgcode + 'G4 S' + str(waitintervall) + " ; " + str(x+1) + ". Stunde gewartet" + '\n'
addgcode = addgcode + 'G4 S' + str(waitintervallrest) + '\n'

#notreplacer_regex

with open(gcode_filename, 'w') as gcode_file:
	gcode_file.write('; post-processed by ' + script_filename + ' to append wait time for filter (start not at night)\n')
	new_gcode = re.sub(notreplacer_regex, '\\1\\3', gcode, 1)
	gcode = new_gcode
	new_gcode = re.sub(replacer_regex, addgcode, new_gcode, 1)
	gcode_file.write(new_gcode)
gcode_file.close()

print("GCode added:")
print(addgcode)
print("\n")

I have to admit this is still work in progress. But it should work so far. No warranty!

A solution to switch off the printer completely would be welcome(?)

Greetings
Stefan

You can edit your own post only some time, or?
Yesterday I was able, but today I don’t find the button ^^

I had to correct the python-script a little bit, but it should now work a little bit better.

#!/usr/bin/env python3

import re, sys
import datetime as dt

debug = 0

#Nur zum Debuggen
script_filename = "script"
gcode_filename = "X:\\test.gcode"

if debug == 0:
	script_filename = sys.argv[0]
	gcode_filename = sys.argv[1]


print("Script:")
print(script_filename)
print("GCode:")
print(gcode_filename)
print("\n")

waitintervall = 3600;

totaltime_regex = r'estimated printing time \(normal mode\) = (\d+)h (\d+)m (\d+)s'
replacer_regex = ';REPLACEDHEREFILTER'
notreplacer_regex = '(end_gcode = .*)(;REPLACEDHEREFILTER)(.*)'

gcode_file = open(gcode_filename, 'r')
gcode = gcode_file.read()
gcode_file.close()

group = re.findall(totaltime_regex, gcode)
stunden = int(group[0][0])
minuten = int(group[0][1])
sekunden = int(group[0][2])

print("Stunden:")
print(stunden)
print("Minuten:")
print(minuten)
print("Sekunden:")
print(sekunden)
print("\n")

startdatum = dt.datetime.now()
dauer = dt.timedelta(days=0, seconds=sekunden, microseconds=0, milliseconds=0, minutes=minuten, hours=stunden, weeks=0)
enddatum = startdatum + dauer

earliestfilter = dt.datetime.combine(enddatum.date(), dt.time(9, 00, 0))
sleeptime = earliestfilter - enddatum

if sleeptime <= dt.timedelta(0,0,0,0,0,0,0): 
	sys.exit()

waitseconds = int(sleeptime.total_seconds())

waitintervalls_num = int(round(waitseconds / waitintervall, 0))
waitintervallrest = int(waitseconds % waitintervall)

print("Startdatum:")
print(startdatum)
print("Enddatum:")
print(enddatum)
print("Filter startet um:")
print(earliestfilter)
print("Sleeptime:")
print(sleeptime)
print("\n")
print("Sleeptime:")
print(sleeptime)
print("\n")

print("Neues Startdatum:")
print(enddatum + sleeptime)
print("Wartesekunden:")
print(waitseconds)
print("In " + str(waitintervalls_num) + " Intervallen a " + str(waitintervall) + " Sekunden und einer Restzeit von " + str(waitintervallrest) + " Sekunden.")
print("\n")

addgcode = ""
for x in range(waitintervalls_num):
	addgcode = addgcode + 'G4 S' + str(waitintervall) + " ; " + str(x+1) + ". Stunde gewartet" + '\n'
addgcode = addgcode + 'G4 S' + str(waitintervallrest) + '\n'

if debug == 0:
	with open(gcode_filename, 'w') as gcode_file:
		gcode_file.write('; post-processed by ' + script_filename + ' to append wait time for filter (start not at night)\n')
		new_gcode = re.sub(notreplacer_regex, '\\1\\3', gcode, 1)
		gcode = new_gcode
		new_gcode = re.sub(replacer_regex, addgcode, new_gcode, 1)
		gcode_file.write(new_gcode)
	gcode_file.close()

print("GCode added:")
print(addgcode)
print("\n")

Who could edit the original post? (Or tell me how to do it on my own)

Maybe because you are a basic user, but it should be possible to edit endless.

Nice work!
Prusa edits the gcode also with your python script? So it doesnt matter when i start my print, correct?

1 Like

I needed the edit button for my reply too. And it was there still available. Perhaps you’re right: Insufficient rights to edit after 24h, because I’m only a basic user.

Regarding your question: the python code is only necessary if the start of the air purifier shall be delayed beyond 9:00 o’clock. (Everything else is already possible with prusa slicer alone). But I assume the print is started immediately after gcode generation.
Only in this case the (via the python script) added delay seconds are correct. E.g. If I start the gcode 12 hours after generation, the air purifier will start at roundabout 21:00 (09:00 +12h). The gcode can’t check for the actual time(?).

Btw this is a future improvement. Right now only the time between 00:00 and 09:00 is prohibited. But it should be easily possible to change this. :slightly_smiling_face:

1 Like