Skip to content

Commit

Permalink
Miscellanous updates and updates to documentation
Browse files Browse the repository at this point in the history
- Added ability to set tmc current between printing and loading
- Added helper function to sync and unsync to extruder
- Changing sync and unsync to use stepper helper functions
- AFC-29 Adding check to make sure printer is not moving when loading filament, displays error message to user
- AFC-25 Added a boolean flag so that TCMD macros don't try to get reassigned when users manually run prep after prep has automatically ran
- Added comments for each variable that can be configured
- Added features document to cover misc features found in AFC
- Added trsync commented out to default config file
  • Loading branch information
jimmyjon711 committed Dec 23, 2024
1 parent ac8e390 commit c958222
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 92 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,13 @@ file as the code now generates them automatically.
- More error printouts to aid users

### Fixes
- Misc error fixes
- Misc error fixes

## [2024-12-23]
### Added
- Added ability to set lower stepper current when printing to help reduce how hot steppers can get.
To enable this feature set `global_print_current` in AFC.cfg or `print_current` for each AFC_stepper
During testing it was found that 0.6 was optimal, going lower than this may result in buffer not working as intended

- Added check to make sure printer is not printing or homing when trying to load a spool. Doing so before would
result in klipper crashing.
10 changes: 10 additions & 0 deletions config/AFC.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ short_moves_speed: 50 # mm/s. Default value is 50mm/s.
short_moves_accel: 300 # mm/s². Default value is 300mm/s².
short_move_dis: 10 # Move distance for failsafe moves. Default is 10mm.

# global_print_current: 0.6 # Uncomment to set stepper motors to a lower current while printing
# This value can also be set per stepper with print_current: 0.6

#--=================================================================================-
#------- TRSYNC Values --------------------------------------------------------------
#--=================================================================================-
# trsync_update: True # Uncomment this value to update klippers trsync value
# trsync_timeout: 0.05 # Uncomment this value if timeout needs to be greater than the default of 0.05
# trsync_single_timeout: 0.250 # Uncomment this value if single_timeout needs to be greater than the default of 0.250

#--=================================================================================-
#------- Pause/Resume ---------------------------------------------------------------
#--=================================================================================-
Expand Down
24 changes: 24 additions & 0 deletions docs/Features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Overview of features

This file goes over the features that can be found in Armored Turtle Automated Filament Changer (AFC) Software

## TurtleNeck Buffer Ram Sensor
AFC allows the use of using the TurtleNeck Buffers as a ram sensor for detecting when filament is loaded to the toolhead extruder. This can be used inplace of a toolhead filament sensor. To learn more about this feature please see [Buffer Ram Sensor](Buffer_Ram_Sensor.md) document

## Bypass
You can enable AFC bypass by printing out [bypass](https://github.com/ArmoredTurtle/AFC-Accessories/tree/main/AFC_Bypass) accessory, connecting inline after your buffer and adding a bypass filament sensor to klipper config like below. Once filament is inserted into the bypass side, the switch disables AFC functionality so you can print like normal.

```
[filament_switch_sensor bypass]
switch_pin: <replace with MCU pin that switch is connected to>
pause_on_runout: False
```

## Lower stepper current when printing
For longer prints you may want to have the ability to lower BoxTurtles steppers current as they can get hot when engaged for a long period of time.

Enabling lower current during printing can be enabled two ways:
1. Set `global_print_current` in AFC.cfg file
2. Set `print_current` for each AFC_stepper, this will override `global_print_current` in AFC.cfg

During testing it was found that 0.6A worked well during printing and kept the steppers warms to the touch. Would not suggest going lower than this or the TurtleNeck buffers may not work as intended.
108 changes: 57 additions & 51 deletions extras/AFC.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,58 +46,61 @@ def __init__(self, config):
self.absolute_coord = True

# SPOOLMAN
self.spoolman_ip = config.get('spoolman_ip', None)
self.spoolman_port = config.get('spoolman_port', None)
self.spoolman_ip = config.get('spoolman_ip', None) # To utilize spoolman enter spoolmans IP address
self.spoolman_port = config.get('spoolman_port', None) # To utilize spoolman enter spoolmans port

#LED SETTINGS
self.ind_lights = None
self.led_name = config.get('led_name')
self.led_fault =config.get('led_fault','1,0,0,0')
self.led_ready = config.get('led_ready','1,1,1,1')
self.led_not_ready = config.get('led_not_ready','1,1,0,0')
self.led_loading = config.get('led_loading','1,0,0,0')
self.led_prep_loaded = config.get('led_loading','1,1,0,0')
self.led_unloading = config.get('led_unloading','1,1,.5,0')
self.led_tool_loaded = config.get('led_tool_loaded','1,1,0,0')
self.led_advancing = config.get('led_buffer_advancing','0,0,1,0')
self.led_trailing = config.get('led_buffer_trailing','0,1,0,0')
self.led_buffer_disabled = config.get('led_buffer_disable', '0,0,0,0.25')
self.led_name = config.get('led_name') # Not used removed?
self.led_fault =config.get('led_fault','1,0,0,0') # LED color to set when faults occur in lane (R,G,B,W) 0 = off, 1 = full brightness.
self.led_ready = config.get('led_ready','1,1,1,1') # LED color to set when lane is ready (R,G,B,W) 0 = off, 1 = full brightness.
self.led_not_ready = config.get('led_not_ready','1,1,0,0') # LED color to set when lane not ready (R,G,B,W) 0 = off, 1 = full brightness.
self.led_loading = config.get('led_loading','1,0,0,0') # LED color to set when lane is loading (R,G,B,W) 0 = off, 1 = full brightness.
self.led_prep_loaded = config.get('led_loading','1,1,0,0') # LED color to set when lane is loaded (R,G,B,W) 0 = off, 1 = full brightness.
self.led_unloading = config.get('led_unloading','1,1,.5,0') # LED color to set when lane is unloading (R,G,B,W) 0 = off, 1 = full brightness.
self.led_tool_loaded = config.get('led_tool_loaded','1,1,0,0') # LED color to set when lane is loaded into tool (R,G,B,W) 0 = off, 1 = full brightness.
self.led_advancing = config.get('led_buffer_advancing','0,0,1,0') # LED color to set when buffer is advancing (R,G,B,W) 0 = off, 1 = full brightness.
self.led_trailing = config.get('led_buffer_trailing','0,1,0,0') # LED color to set when buffer is trailing (R,G,B,W) 0 = off, 1 = full brightness.
self.led_buffer_disabled = config.get('led_buffer_disable', '0,0,0,0.25') # LED color to set when buffer is disabled (R,G,B,W) 0 = off, 1 = full brightness.

# TOOL Cutting Settings
self.tool = ''
self.tool_cut = config.getboolean("tool_cut", False)
self.tool_cut_cmd = config.get('tool_cut_cmd', None)
self.tool_cut = config.getboolean("tool_cut", False) # Set to True to enable toolhead cutting
self.tool_cut_cmd = config.get('tool_cut_cmd', None) # Macro to use when doing toolhead cutting. Change macro name if you would like to use your own cutting macro

# CHOICES
self.park = config.getboolean("park", False)
self.park_cmd = config.get('park_cmd', None)
self.kick = config.getboolean("kick", False)
self.kick_cmd = config.get('kick_cmd', None)
self.wipe = config.getboolean("wipe", False)
self.wipe_cmd = config.get('wipe_cmd', None)
self.poop = config.getboolean("poop", False)
self.poop_cmd = config.get('poop_cmd', None)

self.form_tip = config.getboolean("form_tip", False)
self.form_tip_cmd = config.get('form_tip_cmd', None)
self.park = config.getboolean("park", False) # Set to True to enable parking during unload
self.park_cmd = config.get('park_cmd', None) # Macro to use when parking. Change macro name if you would like to use your own park macro
self.kick = config.getboolean("kick", False) # Set to True to enable poop kicking after lane loads
self.kick_cmd = config.get('kick_cmd', None) # Macro to use when kicking. Change macro name if you would like to use your own kick macro
self.wipe = config.getboolean("wipe", False) # Set to True to enable nozzle wipeing after lane loads
self.wipe_cmd = config.get('wipe_cmd', None) # Macro to use when nozzle wipeing. Change macro name if you would like to use your own wipe macro
self.poop = config.getboolean("poop", False) # Set to True to enable pooping(purging color) after lane loads
self.poop_cmd = config.get('poop_cmd', None) # Macro to use when pooping. Change macro name if you would like to use your own poop/purge macro

self.form_tip = config.getboolean("form_tip", False) # Set to True to tip forming when unloading lanes
self.form_tip_cmd = config.get('form_tip_cmd', None) # Macro to use when tip forming. Change macro name if you would like to use your own tip forming macro

# MOVE SETTINGS
self.tool_sensor_after_extruder = config.getfloat("tool_sensor_after_extruder", 0)
self.long_moves_speed = config.getfloat("long_moves_speed", 100)
self.long_moves_accel = config.getfloat("long_moves_accel", 400)
self.short_moves_speed = config.getfloat("short_moves_speed", 25)
self.short_moves_accel = config.getfloat("short_moves_accel", 400)
self.short_move_dis = config.getfloat("short_move_dis", 10)
self.tool_max_unload_attempts = config.getint('tool_max_unload_attempts', 2)
self.tool_max_load_checks = config.getint('tool_max_load_checks', 4)
self.z_hop =config.getfloat("z_hop", 0)
self.xy_resume =config.getboolean("xy_resume", False)
self.resume_speed =config.getfloat("resume_speed", 0)
self.resume_z_speed = config.getfloat("resume_z_speed", 0)
self.tool_sensor_after_extruder = config.getfloat("tool_sensor_after_extruder", 0) # Currently unused
self.long_moves_speed = config.getfloat("long_moves_speed", 100) # Speed in mm/s to move filament when doing long moves
self.long_moves_accel = config.getfloat("long_moves_accel", 400) # Acceleration in mm/s squared when doing long moves
self.short_moves_speed = config.getfloat("short_moves_speed", 25) # Speed in mm/s to move filament when doing short moves
self.short_moves_accel = config.getfloat("short_moves_accel", 400) # Acceleration in mm/s squared when doing short moves
self.short_move_dis = config.getfloat("short_move_dis", 10) # Move distance in mm for failsafe moves.
self.tool_max_unload_attempts = config.getint('tool_max_unload_attempts', 2)# Max number of attempts to unload filament from toolhead when using buffer as ramming sensor
self.tool_max_load_checks = config.getint('tool_max_load_checks', 4) # Max number of attempts to check to make sure filament is loaded into toolhead extruder when using buffer as ramming sensor

self.z_hop =config.getfloat("z_hop", 0) # Height to move up before and after a tool change completes
self.xy_resume =config.getboolean("xy_resume", False) # Need description or remove as this is currently an unused variable
self.resume_speed =config.getfloat("resume_speed", 0) # Speed mm/s of resume move. Set to 0 to use gcode speed
self.resume_z_speed = config.getfloat("resume_z_speed", 0) # Speed mm/s of resume move in Z. Set to 0 to use gcode speed

self.global_print_current = config.getfloat("global_print_current", None) # Global variable to set steppers current to a specified current when printing. Going lower than 0.6 may result in TurtleNeck buffer's not working correctly

self._update_trsync(config)

self.VarFile = config.get('VarFile')
self.VarFile = config.get('VarFile') # Path to the variables file for AFC configuration.

# Get debug and cast to boolean
#self.debug = True == config.get('debug', 0)
Expand All @@ -108,12 +111,12 @@ def __init__(self, config):

def _update_trsync(self, config):
# Logic to update trsync values
update_trsync = config.getboolean("trsync_update", False)
update_trsync = config.getboolean("trsync_update", False) # Set to true to enable updating trsync value in klipper mcu. Enabling this and updating the timeouts can help with Timer Too Close(TTC) errors
if update_trsync:
try:
import mcu
trsync_value = config.getfloat("trsync_timeout", 0.05)
trsync_single_value = config.getfloat("trsync_single_timeout", 0.5)
trsync_value = config.getfloat("trsync_timeout", 0.05) # Timeout value to update in klipper mcu. Klippers default value is 0.025
trsync_single_value = config.getfloat("trsync_single_timeout", 0.5) # Single timeout value to update in klipper mcu. Klippers default value is 0.250
self.gcode.respond_info("Applying TRSYNC update")

# Making sure value exists as kalico(danger klipper) does not have TRSYNC_TIMEOUT value
Expand Down Expand Up @@ -295,7 +298,10 @@ def cmd_LANE_MOVE(self, gcmd):
self.gcode.respond_info('{} Unknown'.format(lane.upper()))
return
CUR_LANE = self.stepper[lane]
CUR_LANE.set_load_current() # Making current is set correctly when doing lane moves
CUR_LANE.do_enable(True)
CUR_LANE.move(distance, self.short_moves_speed, self.short_moves_accel, True)
CUR_LANE.do_enable(False)

def save_pos(self):
# Only save previous location on the first toolchange call to keep an error state from overwriting the location
Expand Down Expand Up @@ -351,7 +357,7 @@ def save_vars(self):
status = self.get_status(0)
f.write(json.dumps(status, indent=4))
with open(self.VarFile+ '.tool', 'w') as f:
f.write(json.dumps(self.extruders, indent=4))
f.write(json.dumps(status['system']['extruders'], indent=4))

cmd_HUB_CUT_TEST_help = "Test the cutting sequence of the hub cutter, expects LANE=legN"
def cmd_HUB_CUT_TEST(self, gcmd):
Expand Down Expand Up @@ -640,7 +646,7 @@ def TOOL_LOAD(self, CUR_LANE):
# Synchronize lane's extruder stepper and finalize tool loading.
CUR_LANE.status = 'Tooled'
self.save_vars()
CUR_LANE.extruder_stepper.sync_to_extruder(CUR_LANE.extruder_name)
CUR_LANE.sync_to_extruder()

# Adjust tool position for loading.
pos = self.toolhead.get_position()
Expand All @@ -652,7 +658,7 @@ def TOOL_LOAD(self, CUR_LANE):
# Lane will load until Advance sensor is True
# After the tool_stn distance the lane will retract off the sensor to confirm load and reset buffer
if CUR_EXTRUDER.tool_start == "buffer":
CUR_LANE.extruder_stepper.sync_to_extruder(None)
CUR_LANE.unsync_to_extruder()
load_checks = 0
while CUR_EXTRUDER.tool_start_state == True:
CUR_LANE.move( self.short_move_dis * -1, self.short_moves_speed, self.short_moves_accel )
Expand All @@ -664,7 +670,7 @@ def TOOL_LOAD(self, CUR_LANE):
msg += "Tool may not be loaded"
self.gcode.respond_info("<span class=warning--text>{}</span>".format(msg))
break
CUR_LANE.extruder_stepper.sync_to_extruder(CUR_LANE.extruder_name)
CUR_LANE.sync_to_extruder()
# Update tool and lane status.
CUR_LANE.status = 'Tooled'
CUR_LANE.tool_loaded = True
Expand Down Expand Up @@ -780,7 +786,7 @@ def TOOL_UNLOAD(self, CUR_LANE):

if CUR_LANE.extruder_stepper.motion_queue != CUR_LANE.extruder_name:
# Synchronize the extruder stepper with the lane.
CUR_LANE.extruder_stepper.sync_to_extruder(CUR_LANE.extruder_name)
CUR_LANE.sync_to_extruder()

# Check and set the extruder temperature if below the minimum.
wait = True
Expand Down Expand Up @@ -812,7 +818,7 @@ def TOOL_UNLOAD(self, CUR_LANE):
num_tries = 0
if CUR_EXTRUDER.tool_start == "buffer":
# if ramming is enabled, AFC will retract to collapse buffer before unloading
CUR_LANE.extruder_stepper.sync_to_extruder(None)
CUR_LANE.unsync_to_extruder()
while CUR_EXTRUDER.buffer_trailing == False:
# attempt to return buffer to trailng pin
CUR_LANE.move( self.short_move_dis * -1, self.short_moves_speed, self.short_moves_accel )
Expand All @@ -824,7 +830,7 @@ def TOOL_UNLOAD(self, CUR_LANE):
msg += "Increasing 'tool_max_unload_attempts' may improve loading reliablity"
self.gcode.respond_info("<span class=warning--text>{}</span>".format(msg))
break
CUR_LANE.extruder_stepper.sync_to_extruder(CUR_LANE.extruder_name)
CUR_LANE.sync_to_extruder(False)
pos = self.toolhead.get_position()
pos[3] -= CUR_EXTRUDER.tool_stn_unload
self.toolhead.manual_move(pos, CUR_EXTRUDER.tool_unload_speed)
Expand All @@ -837,7 +843,7 @@ def TOOL_UNLOAD(self, CUR_LANE):
message = ('FAILED TO UNLOAD. FILAMENT STUCK IN TOOLHEAD.')
self.ERROR.handle_lane_failure(CUR_LANE, message)
return False
CUR_LANE.extruder_stepper.sync_to_extruder(CUR_LANE.extruder_name)
CUR_LANE.sync_to_extruder()
pos = self.toolhead.get_position()
pos[3] -= CUR_EXTRUDER.tool_stn_unload
self.toolhead.manual_move(pos, CUR_EXTRUDER.tool_unload_speed)
Expand All @@ -851,7 +857,7 @@ def TOOL_UNLOAD(self, CUR_LANE):
self.toolhead.wait_moves()

# Synchronize and move filament out of the hub.
CUR_LANE.extruder_stepper.sync_to_extruder(None)
CUR_LANE.unsync_to_extruder()
CUR_LANE.move(CUR_HUB.afc_bowden_length * -1, self.long_moves_speed, self.long_moves_accel, True)

# Clear toolhead's loaded state for easier error handling later.
Expand Down
Loading

0 comments on commit c958222

Please sign in to comment.