Anson Liu 836a7cc2d1
Add Anneal After Print PostProcessingPlugin
This new plugin generates annealing gcode with the following features:
- Bed and chamber heating options
- Provides progress bar and time remaining feedback
- Beep on annealing start
- Gradual annealing cooldown to desired temperature
2022-04-20 16:02:28 -04:00

160 lines
7.0 KiB
Python

# Copyright (c) 2021 Anson Liu
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
from ..Script import Script
class AnnealAfterPrint(Script):
"""Adds timed annealing GCODE after objects finish printing.
Bed annealing works best with a glass bed and a plastic container placed on top of the object during annealing.
"""
def getSettingDataString(self):
return """{
"name": "Anneal After Print",
"key": "AnnealAfterPrint",
"metadata": {},
"version": 2,
"settings":
{
"heatingElement":
{
"label": "Heating Element",
"description": "Printer heating element to use for annealing.",
"type": "enum",
"options":
{
"bed": "Bed",
"chamber": "Chamber",
"all": "Bed and Chamber"
},
"default_value": "bed"
},
"annealBedTemp":
{
"label": "Bed Temperature",
"description": "Bed temperature annealing. Recommended bed temperature is greater of build plate printing or vendor specified annealing temperature for material. E.g. PC 90-110 C, PLA 60-90 C",
"unit": "C",
"type": "float",
"default_value": 0,
"minimum_value": 0,
"enabled": "heatingElement == \\\"bed\\\" or heatingElement == \\\"all\\\""
},
"annealChamberTemp":
{
"label": "Chamber Temperature",
"description": "Chamber temperature for annealing.",
"unit": "C",
"type": "float",
"default_value": 0,
"minimum_value": 0,
"enabled": "heatingElement == \\\"chamber\\\" or heatingElement == \\\"all\\\""
},
"annealMinutes":
{
"label": "Annealing Target Temperature Duration",
"description": "Duration in minutes to anneal at target temperature. After duration ends gradually cool down to End Cooling Temperature.",
"unit": "min",
"type": "int",
"default_value": 120,
"minimum_value": 0
},
"reminderBeep":
{
"label": "Beep on annealing start",
"description": "",
"type": "bool",
"default_value": false
},
"endCoolingTemp":
{
"label": "End Cooling Temperature",
"description": "Temperature to end gradual cooling at. After annealing at target temperature for specified duration temperature decreases by 1 degree after 1 minute at each step.",
"unit": "C",
"type": "float",
"default_value": 50,
"minimum_value": 0
}
}
}"""
def generateAnnealCode(self, annealBedTemp, annealChamberTemp, annealMinutes, initialBeep, endCoolingTemp):
anneal_code = ';Generated Annealing GCODE by Anson Liu'
if initialBeep:
anneal_code += '\nM300 ;play beep for plastic container placement reminder'
anneal_code += '\nM117 '
if annealBedTemp:
anneal_code += 'Place plastic container over objects on bed now! '
anneal_code += 'Waiting until annealing temp reached...'
anneal_code += '\nM73 P00 ;reset progress bar to 0'
if annealBedTemp:
anneal_code += '\nM190 R{} ;wait for buildplate to reach temp in C even if cooling'.format(annealBedTemp)
if annealChamberTemp:
anneal_code += '\nM191 R{} ;wait for chamber to reach temp in C even if cooling'.format(annealChamberTemp)
anneal_code += '\nM117 '
if annealBedTemp:
anneal_code += 'Keep plastic container over objects. '
anneal_code += 'Annealing...'
anneal_code += '\nM73 P00' # reset progress bar to 0
def generateDwellAndProgressCode(minutes): # Update progress bar and time every minute
dp_code = 'M73 P0 R{}'.format(minutes)
for x in range(1, minutes+1):
dwellWaitSeconds = 60
dp_code += '\nG4 S{}'.format(dwellWaitSeconds)
progress = round(x/minutes * 100, 2)
remainingMinutes = minutes - x
dp_code += '\nM73 P{} R{}'.format(progress, remainingMinutes)
return dp_code
anneal_code += '\n' + generateDwellAndProgressCode(int(annealMinutes))
anneal_code += '\nM117 Annealing complete. Gradually lowering bed temperature...'
for x in reversed(range(endCoolingTemp, max(annealBedTemp, annealChamberTemp))):
if annealBedTemp and annealBedTemp > x:
anneal_code += '\nM190 S{}'.format(x) # Wait for buildplate only if heating
if annealChamberTemp and annealChamberTemp > x:
anneal_code += '\nM191 S{}'.format(x)
anneal_code += '\nG4 S60' # Wait 60 seconds after reaching each cooldown temperature
if annealBedTemp:
anneal_code += '\nM140 S0'
if annealChamberTemp:
anneal_code += '\nM141 S0'
anneal_code += '\nM117 Annealing complete.'
return anneal_code
def execute(self, data):
heating_element = self.getSettingValueByKey("heatingElement")
# Set bed and chamber temp to true/false value based on heating element selection
anneal_bed_temp = 0
anneal_chamber_temp = 0
if heating_element == "bed" or heating_element == "all":
anneal_bed_temp = self.getSettingValueByKey("annealBedTemp")
if heating_element == "chamber" or heating_element == "all":
anneal_chamber_temp = self.getSettingValueByKey("annealChamberTemp")
anneal_minutes = self.getSettingValueByKey("annealMinutes")
initial_beep = self.getSettingValueByKey("firmware_config")
final_cooling_temp = self.getSettingValueByKey("endCoolingTemp")
# Test printing the generated anneal code
#print(self.generateAnnealCode(110, 120, False, 50))
anneal_code = self.generateAnnealCode(anneal_bed_temp, anneal_chamber_temp, anneal_minutes, initial_beep, final_cooling_temp)
try:
end_of_gcode_index = data[-1].index(';End sof Gcode')
except ValueError:
data[-1] += anneal_code + '\n'
else:
data[-1] = data[-1][:end_of_gcode_index] + anneal_code + '\n' + data[-1][end_of_gcode_index:]
return data