diff --git a/cli/axicli/axidraw_cli.py b/cli/axicli/axidraw_cli.py
index 0178e65..cdc4001 100644
--- a/cli/axicli/axidraw_cli.py
+++ b/cli/axicli/axidraw_cli.py
@@ -73,7 +73,7 @@
from plotink.plot_utils_import import from_dependency_import # plotink
exit_status = from_dependency_import("ink_extensions_utils.exit_status")
-cli_version = "AxiDraw Command Line Interface 3.1.0"
+cli_version = "AxiDraw Command Line Interface 3.2.0"
quick_help = '''
Basic syntax to plot a file: axicli svg_in [OPTIONS]
@@ -156,8 +156,9 @@ def axidraw_CLI(dev = False):
parser.add_argument("-M","--manual_cmd", \
metavar='COMMAND', type=str, \
help="Manual command. One of: [fw_version, lower_pen, raise_pen, "\
- + "walk_x, walk_y, enable_xy, disable_xy, bootload, strip_data, " \
- + "read_name, list_names, write_name]. Default: fw_version")
+ + "walk_x, walk_y, walk_mmx, walk_mmy, walk_home, enable_xy, disable_xy, "\
+ + "bootload, strip_data, read_name, list_names, write_name]. "\
+ + "Default: fw_version")
parser.add_argument("-w","--walk_dist", \
metavar='DISTANCE', type=float, \
@@ -197,8 +198,9 @@ def axidraw_CLI(dev = False):
parser.add_argument("-L","--model",\
metavar='MODELCODE', type=int,\
- help="AxiDraw Model (1-4). 1: AxiDraw V2 or V3. " \
- + "2: AxiDraw V3/A3. 3: AxiDraw V3 XLX. 4: AxiDraw MiniKit")
+ help="AxiDraw Model (1-6). 1: AxiDraw V2 or V3. " \
+ + "2:AxiDraw V3/A3 or SE/A3. 3: AxiDraw V3 XLX. " \
+ + "4:AxiDraw MiniKit. 5:AxiDraw SE/A1. 6: AxiDraw SE/A2.")
parser.add_argument("-p","--port",\
metavar='PORTNAME', type=str,\
diff --git a/cli/requirements/requirements.txt b/cli/requirements/requirements.txt
index a33bddd..6a10b11 100644
--- a/cli/requirements/requirements.txt
+++ b/cli/requirements/requirements.txt
@@ -5,8 +5,8 @@ charset-normalizer==2.0.7
future==0.18.2
idna==3.3
ink-extensions==1.1.0
-lxml==4.6.4
-plotink==1.4.0
+lxml==4.6.5
+plotink==1.5.0
pyserial==3.5
requests==2.26.0
urllib3==1.26.7
diff --git a/cli/setup.py b/cli/setup.py
index 587c4d5..ccf011c 100644
--- a/cli/setup.py
+++ b/cli/setup.py
@@ -57,7 +57,7 @@ def replacement_setup(*args, **kwargs):
replacement_setup(
name='axicli',
- version='3.1.0',
+ version='3.2.0',
python_requires='>=3.6.0',
long_description=long_description,
long_description_content_type='text/plain',
@@ -66,9 +66,10 @@ def replacement_setup(*args, **kwargs):
author_email='contact@evilmadscientist.com',
packages=setuptools.find_packages(exclude=['contrib', 'docs', 'test']),
install_requires=[
+ # this only includes publicly available dependencies
'ink_extensions>=1.1.0',
- 'lxml>=4.6.2',
- 'plotink>=1.4.0',
+ 'lxml>=4.6.5',
+ 'plotink>=1.5.0',
'pyserial>=3.5',
'requests', # just for the certificates for now
],
diff --git a/inkscape driver/axidraw.inx b/inkscape driver/axidraw.inx
index 616ab4e..2c19fee 100755
--- a/inkscape driver/axidraw.inx
+++ b/inkscape driver/axidraw.inx
@@ -143,6 +143,8 @@ _gui-text="Pen height: DOWN, (%):">30
<_option value="1">AxiDraw V2 or AxiDraw V3
<_option value="2">AxiDraw V3/A3 or SE/A3
<_option value="4">AxiDraw MiniKit
+<_option value="5">AxiDraw SE/A1
+<_option value="6">AxiDraw SE/A2
<_option value="3">AxiDraw V3 XLX
@@ -176,17 +178,18 @@ raise or lower the pen, or enable or disable the motors.
-<_option value="none" >- Select -
-<_option value="walk_x" >Walk Carriage (X, inches)
-<_option value="walk_y" >Walk Carriage (Y, inches)
+<_option value="none" >- Select -
+<_option value="walk_x" >Walk Carriage (X, inches)
+<_option value="walk_y" >Walk Carriage (Y, inches)
<_option value="walk_mmx" >Walk Carriage (X, mm)
<_option value="walk_mmy" >Walk Carriage (Y, mm)
-<_option value="raise_pen" >Raise the Pen
-<_option value="lower_pen" >Lower the Pen
+<_option value="walk_home" >Walk Home
+<_option value="raise_pen" >Raise the Pen
+<_option value="lower_pen" >Lower the Pen
<_option value="enable_xy" >Enable XY Motors
<_option value="disable_xy" >Disable XY Motors
-<_option value="bootload" >Enter Bootloader mode
-<_option value="strip_data" >Strip plotter data from file
+<_option value="bootload" >Enter Bootloader mode
+<_option value="strip_data" >Strip plotter data from file
1.000
@@ -256,7 +259,7 @@ the Return to Home Corner command.
<_param name="copyright" type="description" indent="5" xml:space="preserve"
->Version 3.1.0 — Copyright 2021 Evil Mad Scientist
+>Version 3.2.0 — Copyright 2022 Evil Mad Scientist
diff --git a/inkscape driver/axidraw.py b/inkscape driver/axidraw.py
index d34c740..0d65028 100644
--- a/inkscape driver/axidraw.py
+++ b/inkscape driver/axidraw.py
@@ -34,6 +34,7 @@
import math
import time
from array import array
+from multiprocessing import Event
from lxml import etree
@@ -87,6 +88,7 @@ def __init__(self, default_logging=True, user_message_fun=message.emit, params=N
self.pen_up = None # Initial state of pen is neither up nor down, but _unknown_.
self.virtual_pen_up = False # Pen state when stepping through plot before resuming
self.ebblv_set = False # EBBLV is not yet set.
+ self.connected = False # Variable for Python API to poll for connection status.
self.Secondary = False
self.user_message_fun = user_message_fun
@@ -99,7 +101,6 @@ def __init__(self, default_logging=True, user_message_fun=message.emit, params=N
self.start_y = None
self.end_x = None
self.end_y = None
-
self.pen_lifts = 0
# logging setup
@@ -110,6 +111,14 @@ def __init__(self, default_logging=True, user_message_fun=message.emit, params=N
if self.spew_debugdata:
logger.setLevel(logging.DEBUG) # by default level is INFO
+ def set_up_pause_receiver(self, software_pause_event):
+ """ use a multiprocessing.Event/threading.Event to communicate a
+ keyboard interrupt (ctrl-C) to pause the AxiDraw """
+ self._software_pause_event = software_pause_event
+
+ def receive_pause_request(self):
+ return hasattr(self, "_software_pause_event") and self._software_pause_event.is_set()
+
def set_secondary(self, suppress_standard_out=True):
""" Various things are slightly different if this is a "secondary"
AxiDraw called by axidraw_control """
@@ -183,6 +192,12 @@ def update_options(self):
elif self.options.model == 4:
self.x_bounds_max = self.params.x_travel_MiniKit
self.y_bounds_max = self.params.y_travel_MiniKit
+ elif self.options.model == 5:
+ self.x_bounds_max = self.params.x_travel_SEA1
+ self.y_bounds_max = self.params.y_travel_SEA1
+ elif self.options.model == 6:
+ self.x_bounds_max = self.params.x_travel_SEA2
+ self.y_bounds_max = self.params.y_travel_SEA2
else:
self.x_bounds_max = self.params.x_travel_default
self.y_bounds_max = self.params.y_travel_default
@@ -448,7 +463,7 @@ def effect(self):
time.sleep(0.100) # Use short intervals to improve responsiveness
self.pause_res_check() # Detect button press while paused between plots
- elif self.options.mode == "align" or self.options.mode == "toggle":
+ elif self.options.mode in ('align', 'toggle'):
self.setup_command()
elif self.options.mode == "manual":
@@ -459,7 +474,7 @@ def effect(self):
if self.serial_port is not None:
ebb_motion.doTimedPause(self.serial_port, 10) # Pause for motion commands to finish.
if self.options.port is None: # Do not close serial port if it was opened externally.
- ebb_serial.closePort(self.serial_port)
+ self.disconnect()
def resume_plot_setup(self):
""" Initialization for resuming plots """
@@ -591,8 +606,7 @@ def manual_command(self):
gettext.gettext("Entering bootloader mode for firmware programming.\n" +
"To resume normal operation, you will need to first\n" +
"disconnect the AxiDraw from both USB and power."))
- ebb_serial.closePort(self.serial_port) # Manually close port
- self.serial_port = None # Indicate that serial port is closed.
+ self.disconnect() # Disconnect from AxiDraw; end serial session
else:
logger.error('Failed while trying to enter bootloader.')
return
@@ -619,10 +633,9 @@ def manual_command(self):
else:
logger.error('Error encountered while writing nickname.')
ebb_serial.reboot(self.serial_port) # Reboot required after writing nickname
- ebb_serial.closePort(self.serial_port) # Manually close port
- self.serial_port = None # Indicate that serial port is closed.
+ self.disconnect() # Disconnect from AxiDraw; end serial session
else:
- logger.error("AxiDraw naming requires firmware version 2.5.5 or higher.")
+ logger.error("This function requires a newer firmware version. See: axidraw.com/fw")
return
# Next: Commands that require both power and serial connectivity:
@@ -639,8 +652,21 @@ def manual_command(self):
self.enable_motors()
elif self.options.manual_cmd == "disable_xy":
ebb_motion.sendDisableMotors(self.serial_port)
- else: # self.options.manual_cmd is walk motor:
- if self.options.manual_cmd == "walk_y":
+ else: # walk motors or move home cases:
+ self.servo_setup_wrapper()
+ self.enable_motors() # Set plotting resolution
+ if self.options.manual_cmd == "walk_home":
+ if ebb_serial.min_version(self.serial_port, "2.6.2"):
+ a_pos, b_pos = ebb_motion.query_steps(self.serial_port)
+ n_delta_x = -(a_pos + b_pos) / (4 * self.params.native_res_factor)
+ n_delta_y = -(a_pos - b_pos) / (4 * self.params.native_res_factor)
+ if self.options.resolution == 2: # Low-resolution mode
+ n_delta_x *= 2
+ n_delta_y *= 2
+ else:
+ logger.error("This function requires newer firmware. Update at: axidraw.com/fw")
+ return
+ elif self.options.manual_cmd == "walk_y":
n_delta_x = 0
n_delta_y = self.options.walk_dist
elif self.options.manual_cmd == "walk_x":
@@ -655,9 +681,6 @@ def manual_command(self):
else:
return
- self.servo_setup_wrapper()
-
- self.enable_motors() # Set plotting resolution
self.f_curr_x = self.svg_last_known_x_old + self.pt_first[0]
self.f_curr_y = self.svg_last_known_y_old + self.pt_first[1]
self.ignore_limits = True
@@ -665,6 +688,7 @@ def manual_command(self):
f_y = self.f_curr_y + n_delta_y # New position is not saved; use with care.
self.plot_seg_with_v(f_x, f_y, 0, 0)
+
def update_v_charts(self, v_1, v_2, v_total):
""" Update velocity charts, using some appropriate scaling for X and Y display."""
temp_time = self.vel_data_time / 1000.0
@@ -2183,6 +2207,8 @@ def pause_res_check(self):
# if (self.options.mode == "plot") and (self.node_count == 24):
# self.force_pause = True
+ self.force_pause |= self.receive_pause_request()
+
if self.force_pause:
pause_state = 1
elif self.serial_port is not None:
@@ -2190,6 +2216,7 @@ def pause_res_check(self):
pause_state = int(str_button[0])
except:
logger.error('\nUSB connection to AxiDraw lost.')
+ self.connected = False
pause_state = 2 # Pause the plot; we appear to have lost connectivity.
logger.debug('\n (Node # : ' + str(self.node_count) + ')')
@@ -2259,11 +2286,8 @@ def serial_connect(self):
self.serial_port = ebb_serial.testPort(the_port)
self.options.port = None # Clear this input, to ensure that we close the port later.
else:
- # This function may be passed a serial port object reference;
- # an instance of serial.serialposix.Serial.
- # In that case, we should interact with that given
- # port object, and leave it open at the end.
-
+ # self.options.port may be a serial port object of type serial.serialposix.Serial.
+ # In that case, interact with that given port object, and leave it open at the end.
self.serial_port = self.options.port
if self.serial_port is None:
if named_port:
@@ -2271,8 +2295,7 @@ def serial_connect(self):
else:
logger.error(gettext.gettext("Failed to connect to AxiDraw."))
return
-
- # Successfully connected
+ self.connected = True
if named_port:
logger.debug(gettext.gettext('Connected successfully to port: ' + str(named_port)))
else:
@@ -2281,14 +2304,9 @@ def serial_connect(self):
def enable_motors(self):
"""
Enable motors, set native motor resolution, and set speed scales.
-
- The "pen down" speed scale is adjusted with the following factors
- that make the controls more intuitive:
- * Reduce speed by factor of 2 when using 8X microstepping
- * Reduce speed by factor of 2 when disabling acceleration
-
- These factors prevent unexpected dramatic changes in speed when turning
- those two options on and off.
+ The "pen down" speed scale is adjusted by reducing speed when using 8X microstepping or
+ disabling aceleration. These factors prevent unexpected dramatic changes in speed when
+ turning those two options on and off.
"""
if self.use_layer_speed:
local_speed_pendown = self.layer_speed_pendown
@@ -2297,19 +2315,21 @@ def enable_motors(self):
if self.options.resolution == 1: # High-resolution ("Super") mode
if not self.options.preview:
- ebb_motion.sendEnableMotors(self.serial_port, 1) # 16X microstepping
+ res_1, res_2 = ebb_motion.query_enable_motors(self.serial_port)
+ if not (res_1 == 1 and res_2 == 1): # Do not re-enable if already enabled
+ ebb_motion.sendEnableMotors(self.serial_port, 1) # 16X microstepping
self.step_scale = 2.0 * self.params.native_res_factor
self.speed_pendown = local_speed_pendown * self.params.speed_lim_xy_hr / 110.0
self.speed_penup = self.options.speed_penup * self.params.speed_lim_xy_hr / 110.0
if self.options.const_speed:
self.speed_pendown = self.speed_pendown * self.params.const_speed_factor_hr
-
else: # i.e., self.options.resolution == 2; Low-resolution ("Normal") mode
if not self.options.preview:
- ebb_motion.sendEnableMotors(self.serial_port, 2) # 8X microstepping
+ res_1, res_2 = ebb_motion.query_enable_motors(self.serial_port)
+ if not (res_1 == 2 and res_2 == 2): # Do not re-enable if already enabled
+ ebb_motion.sendEnableMotors(self.serial_port, 2) # 8X microstepping
self.step_scale = self.params.native_res_factor
# Low-res mode: Allow faster pen-up moves. Keep maximum pen-down speed the same.
- # Speeds given as maximum inches/second in XY plane
self.speed_penup = self.options.speed_penup * self.params.speed_lim_xy_lr / 110.0
self.speed_pendown = local_speed_pendown * self.params.speed_lim_xy_lr / 110.0
if self.options.const_speed:
@@ -2352,9 +2372,8 @@ def pen_raise(self):
ebb_motion.sendPenUp(self.serial_port, v_time)
if self.params.use_b3_out:
ebb_motion.PBOutValue( self.serial_port, 3, 0 ) # I/O Pin B3 output: low
- if v_time > 50:
- if self.options.mode != "manual":
- time.sleep(float(v_time - 30) / 1000.0) # pause before issuing next command
+ if (v_time > 50) and (self.options.mode != "manual"):
+ time.sleep(float(v_time - 30) / 1000.0) # pause before issuing next command
self.pen_up = True
if not self.ebblv_set:
ebb_motion.setEBBLV(self.serial_port, self.options.pen_pos_up + 1)
@@ -2369,7 +2388,6 @@ def pen_lower(self):
if self.pen_up is not None:
if not self.pen_up:
return # skip if pen is state is _known_ and is down
-
if self.resume_mode or self.b_stopped: # skip if resuming or stopped
return
@@ -2379,9 +2397,7 @@ def pen_lower(self):
pen_down_pos = self.options.pen_pos_down
v_dist = abs(float(self.options.pen_pos_up - pen_down_pos))
- # Servo travel time is estimated as the 4th power average (a smooth blend between):
- # (A) Servo transit time for fast servo sweeps (t = slope * v_dist + min) and
- # (B) Sweep time for slow sweeps (t = v_dist * full_scale_sweep_time / sweep_rate)
+ # Timing uses the same transit time model detailed in pen_raise():
v_time = int(((self.params.servo_move_slope * v_dist + self.params.servo_move_min) ** 4 +
(self.params.servo_sweep_time * v_dist / self.options.pen_rate_raise) ** 4) ** 0.25)
if v_dist < 0.9: # If up and down positions are equal, no initial delay
@@ -2398,10 +2414,8 @@ def pen_lower(self):
ebb_motion.sendPenDown(self.serial_port, v_time)
if self.params.use_b3_out:
ebb_motion.PBOutValue( self.serial_port, 3, 1 ) # I/O Pin B3 output: high
- if v_time > 50:
- if self.options.mode != "manual":
- # pause before issuing next command
- time.sleep(float(v_time - 30) / 1000.0)
+ if (v_time > 50) and (self.options.mode != "manual"):
+ time.sleep(float(v_time - 30) / 1000.0) # pause before issuing next command
self.pen_up = False
def servo_setup_wrapper(self):
@@ -2460,7 +2474,7 @@ def servo_setup_wrapper(self):
self.virtual_pen_up = False
def servo_setup(self):
- """
+ """ Set servo up/down positions, raising/lowering rates, and power timeout
Pen position units range from 0% to 100%, which correspond to a typical timing range of
9855 - 27831 in units of 83.3 ns (1/(12 MHz)), giving a timing range of 0.82 - 2.32 ms.
"""
@@ -2477,11 +2491,10 @@ def servo_setup(self):
int_temp = int(round(self.params.servo_min + servo_slope * pen_down_pos))
ebb_motion.setPenDownPos(self.serial_port, int_temp)
- """
- Servo rate options (pen_rate_raise, pen_rate_lower) range from 1% to 100%.
- The EBB servo rate values are in units of 83.3 ns steps per 24 ms.
- Our servo sweep at 100% rate sweeps over 100% range in servo_sweep_time ms.
- """
+ # Servo rate options (pen_rate_raise, pen_rate_lower) range from 1% to 100%.
+ # The EBB servo rate values are in units of 83.3 ns steps per 24 ms.
+ # Our servo sweep at 100% rate sweeps over 100% range in servo_sweep_time ms.
+
servo_rate_scale = float(servo_range) * 0.24 / self.params.servo_sweep_time
int_temp = int(round(servo_rate_scale * self.options.pen_rate_raise))
ebb_motion.setPenUpRate(self.serial_port, int_temp)
@@ -2763,10 +2776,11 @@ def current_pen(self):
return self.pen_up
def disconnect(self):
- '''End interactive session; disconnect from AxiDraw '''
+ '''End serial session; disconnect from AxiDraw '''
if self.serial_port:
ebb_serial.closePort(self.serial_port)
self.serial_port = None
+ self.connected = False
class SecondaryLoggingHandler(logging.Handler):
'''To be used for logging to AxiDraw.text_out and AxiDraw.error_out.'''
diff --git a/inkscape driver/axidraw_conf.py b/inkscape driver/axidraw_conf.py
index f0a4a42..1353550 100644
--- a/inkscape driver/axidraw_conf.py
+++ b/inkscape driver/axidraw_conf.py
@@ -2,7 +2,7 @@
# Part of the AxiDraw driver software
#
# https://github.com/evil-mad/axidraw
-# Version 3.2.0, dated 2022-02-17.
+# Version 3.2.0, dated 2022-02-22.
#
# Copyright 2022 Windell H. Oskay, Evil Mad Scientist Laboratories
#
@@ -59,11 +59,10 @@
# 2: Render only pen-up movement
# 3: Render all movement (Default)
-model = 1 # AxiDraw Model (1-4)
- # 1: AxiDraw V2 or V3 (Default)
- # 2: AxiDraw V3/A3 or SE/A3
- # 3: AxiDraw V3 XLX
- # 4: AxiDraw MiniKit
+model = 1 # AxiDraw Model (1-6)
+ # 1: AxiDraw V2 or V3 (Default). 2: AxiDraw V3/A3 or SE/A3.
+ # 3: AxiDraw V3 XLX. 4: AxiDraw MiniKit.
+ # 5: AxiDraw SE/A1. 6: AxiDraw SE/A2.
port = None # Serial port or named AxiDraw to use
# None (Default) will plot to first unit located
@@ -154,20 +153,26 @@
# Page size values typically do not need to be changed. They primarily affect viewpoint and centering.
# Measured in page pixelssteps. Default printable area for AxiDraw is 300 x 218 mm
-x_travel_default = 11.81 # AxiDraw V2 and AxiDraw V3: X Carriage travel in inches. Default: 300 mm = about 11.81 inches
-y_travel_default = 8.58 # AxiDraw V2 and AxiDraw V3: Y Carriage travel in inches. Default: 218 mm = about 8.58 inches
+x_travel_default = 11.81 # AxiDraw V2, V3: X Carriage travel, inches. Default: 11.81 (300 mm)
+y_travel_default = 8.58 # AxiDraw V2, V3: Y Carriage travel, inches. Default: 8.58 (218 mm)
-x_travel_V3A3 = 16.93 # AxiDraw V3/A3: X Carriage travel in inches. Default: 430 mm = about 16.93 inches
-y_travel_V3A3 = 11.69 # AxiDraw V3/A3: Y Carriage travel in inches. Default: 297 mm = about 11.69 inches
+x_travel_V3A3 = 16.93 # V3/A3 and SE/A3: X Carriage travel, inches. Default: 16.93 (430 mm)
+y_travel_V3A3 = 11.69 # V3/A3 and SE/A3: Y Carriage travel, inches. Default: 11.69 (297 mm)
-x_travel_V3XLX = 23.42 # AxiDraw V3 XLX: X Carriage travel in inches. Default: 595 mm = about 23.42 inches
-y_travel_V3XLX = 8.58 # AxiDraw V3 XLX: Y Carriage travel in inches. Default: 218 mm = about 8.58 inches
+x_travel_V3XLX = 23.42 # AxiDraw V3 XLX: X Carriage travel, inches. Default: 23.42 (595 mm
+y_travel_V3XLX = 8.58 # AxiDraw V3 XLX: Y Carriage travel, inches. Default: 8.58 (218 mm)
-x_travel_MiniKit = 6.30 # AxiDraw MiniKit: X Carriage travel in inches. Default: 160 mm = about 6.30 inches
-y_travel_MiniKit = 4.00 # AxiDraw MiniKit: Y Carriage travel in inches. Default: 101.6 mm = 4.00 inches
+x_travel_MiniKit = 6.30 # AxiDraw MiniKit: X Carriage travel, inches. Default: 6.30 (160 mm)
+y_travel_MiniKit = 4.00 # AxiDraw MiniKit: Y Carriage travel, inches. Default: 4.00 (101.6 mm)
+x_travel_SEA1 = 34.02 # AxiDraw SE/A1: X Carriage travel, inches. Default: 34.02 (864 mm)
+y_travel_SEA1 = 23.39 # AxiDraw SE/A1: Y Carriage travel, inches. Default: 23.39 (594 mm)
-native_res_factor = 1016.0 # Motor resolution calculation factor, steps per inch, and used in conversions. Default: 1016.0
+x_travel_SEA2 = 23.39 # AxiDraw SE/A2: X Carriage travel, inches. Default: 23.39 (594 mm)
+y_travel_SEA2 = 17.01 # AxiDraw SE/A2: Y Carriage travel, inches. Default: 17.01 (432 mm )
+
+
+native_res_factor = 1016.0 # Motor resolution factor, steps per inch. Default: 1016.0
# Note that resolution is defined along native (not X or Y) axes.
# Resolution is native_res_factor * sqrt(2) steps per inch in Low Resolution (Approx 1437 steps per inch)
# and 2 * native_res_factor * sqrt(2) steps per inch in High Resolution (Approx 2874 steps per inch)
@@ -178,8 +183,8 @@
# We use a conservative value, to help prevent errors due to rounding.
# This value is normally used _for speed limit checking only_.
-speed_lim_xy_lr = 15.000 # Maximum XY speed allowed when in Low Resolution mode, in inches per second. Default: 15.000 Max: 17.3958
-speed_lim_xy_hr = 8.6979 # Maximum XY speed allowed when in High Resolution mode, in inches per second. Default: 8.6979, Max: 8.6979
+speed_lim_xy_lr = 15.000 # Maximum XY speed allowed when in Low Resolution mode, inches/second. Default: 15.000 Max: 17.3958
+speed_lim_xy_hr = 8.6979 # Maximum XY speed allowed when in High Resolution mode, inches/second. Default: 8.6979, Max: 8.6979
# Do not increase these values above Max; they are derived from max_step_rate and the resolution.
max_step_dist_lr = 0.000696 # Maximum distance covered by 1 step in Low Res mode, rounded up, in inches. ~1/(1016 sqrt(2))
diff --git a/inkscape driver/axidraw_control.py b/inkscape driver/axidraw_control.py
index 8f76682..2eac9a0 100644
--- a/inkscape driver/axidraw_control.py
+++ b/inkscape driver/axidraw_control.py
@@ -29,6 +29,7 @@
import logging
import threading
import time
+import signal
from axidrawinternal import axidraw # https://github.com/evil-mad/axidraw
from axidrawinternal.axidraw_options import common_options
@@ -47,6 +48,7 @@
else:
# Multiprocessing does not work on Windows; use multiple threads.
import threading
+from multiprocessing import Event
logger = logging.getLogger(__name__)
@@ -71,6 +73,17 @@ def __init__( self, default_logging = True, params = None ):
if default_logging:
logger.addHandler(self.default_handler)
+ self.set_up_pause_transmitter()
+
+ def set_up_pause_transmitter(self):
+ # intercept ctrl-C (keyboard interrupt) and redefine as "pause" command
+ signal.signal(signal.SIGINT, self.transmit_pause_request)
+ # one pause event for all axidraws
+ self.software_initiated_pause_event = Event()
+
+ def transmit_pause_request(self, *args):
+ self.software_initiated_pause_event.set()
+
def effect( self ):
'''
Main entry point
@@ -181,6 +194,7 @@ def plot_to_axidraw( self, port, primary):
# return # Skip secondary units, without opening class or serial connection
ad = axidraw.AxiDraw(params=self.params, default_logging=self.default_logging)
+ ad.set_up_pause_receiver(self.software_initiated_pause_event)
ad.getoptions([])
prim = "primary" if primary else "secondary"
diff --git a/inkscape driver/axidraw_options/common_options.py b/inkscape driver/axidraw_options/common_options.py
index 6391f60..29b22de 100644
--- a/inkscape driver/axidraw_options/common_options.py
+++ b/inkscape driver/axidraw_options/common_options.py
@@ -85,8 +85,9 @@ def core_options(parser, config):
options.add_option("--model",\
type="int", action="store", dest="model",\
default=config["model"],\
- help="AxiDraw Model (1-3). 1: AxiDraw V2 or V3. " \
- + "2:AxiDraw V3/A3 or SE/A3. 3: AxiDraw V3 XLX.")
+ help="AxiDraw Model (1-6). 1: AxiDraw V2 or V3. " \
+ + "2:AxiDraw V3/A3 or SE/A3. 3: AxiDraw V3 XLX. " \
+ + "4:AxiDraw MiniKit. 5:AxiDraw SE/A1. 6: AxiDraw SE/A2.")
options.add_option("--port_config",\
type="int", action="store", dest="port_config",\
@@ -172,9 +173,10 @@ def core_mode_options(parser, config):
options.add_option("--manual_cmd",\
type="string", action="store", dest="manual_cmd",\
default="fw_version",\
- help="Manual command. One of: [fw_version, raise_pen, lower_pen, " \
- + "walk_x, walk_y, enable_xy, disable_xy, bootload, strip_data, " \
- + "read_name, list_names, write_name]. Default: fw_version")
+ help="Manual command. One of: [fw_version, raise_pen, lower_pen, "\
+ + "walk_x, walk_y, walk_mmx, walk_mmy, walk_home, enable_xy, disable_xy, "\
+ + "bootload, strip_data, read_name, list_names, write_name]. "\
+ + "Default: fw_version")
options.add_option("--walk_dist",\
type="float", action="store", dest="walk_dist",\
diff --git a/inkscape driver/digest_svg.py b/inkscape driver/digest_svg.py
index f1a118d..2a8f9dd 100644
--- a/inkscape driver/digest_svg.py
+++ b/inkscape driver/digest_svg.py
@@ -1,6 +1,6 @@
# coding=utf-8
#
-# Copyright 2021 Windell H. Oskay, Evil Mad Scientist Laboratories
+# Copyright 2022 Windell H. Oskay, Evil Mad Scientist Laboratories
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -209,17 +209,21 @@ def traverse(self, node_list, mat_current=None,\
if str(str_layer_name)[0] == '%':
continue # Skip Documentation layer and its contents
- if self.layer_selection >= 0: # Check for selected layer name
+ if self.layer_selection >= 0 and len(str(str_layer_name)) > 0: # layers mode
layer_match = False
layer_name_int = -1
-
temp_num_string = 'x'
string_pos = 1
- max_length = len(str_layer_name)
+
+ layer_name_temp = str(str_layer_name) # Ignore leading '!' in layers mode
+ if str(str_layer_name)[0] == '!':
+ layer_name_temp = str_layer_name[1:]
+
+ max_length = len(layer_name_temp)
while string_pos <= max_length:
- layer_name_fragment = str_layer_name[:string_pos]
+ layer_name_fragment = layer_name_temp[:string_pos]
if layer_name_fragment.isdigit():
- temp_num_string = str_layer_name[:string_pos]
+ temp_num_string = layer_name_temp[:string_pos]
string_pos += 1
else:
break