UC2-REST 0.2.0.42__tar.gz → 0.2.0.43__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/PKG-INFO +1 -1
  2. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/UC2_REST.egg-info/PKG-INFO +1 -1
  3. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/UC2_REST.egg-info/SOURCES.txt +1 -0
  4. uc2_rest-0.2.0.43/tests/test_motor_axes.py +114 -0
  5. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/__version__.py +1 -1
  6. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/home.py +27 -99
  7. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/motor.py +228 -325
  8. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/LICENSE +0 -0
  9. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/README.md +0 -0
  10. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/UC2_REST.egg-info/dependency_links.txt +0 -0
  11. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/UC2_REST.egg-info/not-zip-safe +0 -0
  12. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/UC2_REST.egg-info/requires.txt +0 -0
  13. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/UC2_REST.egg-info/top_level.txt +0 -0
  14. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/setup.cfg +0 -0
  15. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/setup.py +0 -0
  16. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/tests/test_canota_reconnect.py +0 -0
  17. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/tests/test_stage_scan.py +0 -0
  18. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/MockSerial.py +0 -0
  19. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/UC2Client.py +0 -0
  20. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/__init__.py +0 -0
  21. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/aio.py +0 -0
  22. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/analog.py +0 -0
  23. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/camera.py +0 -0
  24. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/camera_trigger.py +0 -0
  25. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/can.py +0 -0
  26. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/canota.py +0 -0
  27. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/cmdrecorder.py +0 -0
  28. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/digitalin.py +0 -0
  29. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/digitalout.py +0 -0
  30. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/fan.py +0 -0
  31. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/galvo.py +0 -0
  32. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/gpio.py +0 -0
  33. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/gripper.py +0 -0
  34. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/i2c.py +0 -0
  35. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/laser.py +0 -0
  36. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/lcddisplay.py +0 -0
  37. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/ledmatrix.py +0 -0
  38. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/logger.py +0 -0
  39. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/message.py +0 -0
  40. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/modules.py +0 -0
  41. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/motor_config.py +0 -0
  42. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/mserial.py +0 -0
  43. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/objective.py +0 -0
  44. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/pid.py +0 -0
  45. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/ptz.py +0 -0
  46. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/rotator.py +0 -0
  47. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/slm.py +0 -0
  48. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/state.py +0 -0
  49. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/temperature.py +0 -0
  50. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/utils.py +0 -0
  51. {uc2_rest-0.2.0.42 → uc2_rest-0.2.0.43}/uc2rest/wifi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UC2-REST
3
- Version: 0.2.0.42
3
+ Version: 0.2.0.43
4
4
  Summary: This pacage will help you to drive the ESP32-driven microscopy control modules from UC2
5
5
  Home-page: https://github.com/openUC2/UC2-REST
6
6
  Author: Benedict Diederich
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UC2-REST
3
- Version: 0.2.0.42
3
+ Version: 0.2.0.43
4
4
  Summary: This pacage will help you to drive the ESP32-driven microscopy control modules from UC2
5
5
  Home-page: https://github.com/openUC2/UC2-REST
6
6
  Author: Benedict Diederich
@@ -8,6 +8,7 @@ UC2_REST.egg-info/not-zip-safe
8
8
  UC2_REST.egg-info/requires.txt
9
9
  UC2_REST.egg-info/top_level.txt
10
10
  tests/test_canota_reconnect.py
11
+ tests/test_motor_axes.py
11
12
  tests/test_stage_scan.py
12
13
  uc2rest/MockSerial.py
13
14
  uc2rest/UC2Client.py
@@ -0,0 +1,114 @@
1
+ """Generic motor axes (stepperid 0-9, named axes), without hardware.
2
+
3
+ Run: python -m unittest tests.test_motor_axes (from the repo root)
4
+ """
5
+ import unittest
6
+ from unittest import mock
7
+
8
+ from uc2rest.home import Home
9
+ from uc2rest.motor import Motor
10
+
11
+
12
+ class _Parent:
13
+ """Just enough of UC2Client: a serial with register_callback, post_json and a motor."""
14
+
15
+ def __init__(self):
16
+ self.serial = mock.Mock()
17
+ self.logger = mock.Mock()
18
+ self.sent = []
19
+ self.reply = {"qid": 1, "return": 1}
20
+
21
+ def post_json(self, path, payload, **kwargs):
22
+ self.sent.append((path, payload))
23
+ return self.reply
24
+
25
+
26
+ class MotorAxesTest(unittest.TestCase):
27
+ def setUp(self):
28
+ self.parent = _Parent()
29
+ self.motor = self.parent.motor = Motor(parent=self.parent)
30
+
31
+ def steppers(self):
32
+ return self.parent.sent[-1][1]["motor"]["steppers"]
33
+
34
+ def test_named_axis_beyond_xyza(self):
35
+ self.motor.setup_motor("C", minPos=0, maxPos=10, stepSize=0.5, backlash=0)
36
+ self.motor.move_axis_by_name("C", 10, speed=1000)
37
+ self.assertEqual([(s["stepperid"], s["position"]) for s in self.steppers()], [(5, 20)])
38
+ self.motor.move_axis_by_name(7, 3, speed=1000) # by stepperid
39
+ self.assertEqual(self.steppers()[0]["stepperid"], 7)
40
+
41
+ def test_move_axes_mixed_names(self):
42
+ self.motor.move_axes({"X": 100, "B": -50}, speed={"X": 2000, "B": 3000})
43
+ got = {s["stepperid"]: (s["position"], s["speed"]) for s in self.steppers()}
44
+ self.assertEqual(got, {1: (100, 2000), 4: (-50, 3000)})
45
+
46
+ def test_relative_zero_axes_are_not_sent(self):
47
+ self.motor.move_xyz((0, 5, 0), speed=1000)
48
+ self.assertEqual([s["stepperid"] for s in self.steppers()], [2])
49
+
50
+ def test_remapped_and_custom_names(self):
51
+ self.motor.setMotorAxisOrder([0, 2, 1, 3]) # legacy: X and Y swapped
52
+ self.motor.move_x(10, speed=1000)
53
+ self.assertEqual(self.steppers()[0]["stepperid"], 2)
54
+ self.motor.set_axis_ids({"T": 6})
55
+ self.motor.move_axis_by_name("t", 1, speed=1000)
56
+ self.assertEqual(self.steppers()[0]["stepperid"], 6)
57
+ with self.assertRaises(ValueError):
58
+ self.motor.axis_id("Q")
59
+ with self.assertRaises(ValueError):
60
+ self.motor.axis_id(10)
61
+
62
+ def test_feedback_reaches_every_callback(self):
63
+ seen = {}
64
+ self.motor.register_callback("stage1", lambda p: seen.setdefault("a", p[6]))
65
+ self.motor.register_callback("stage2", lambda p: seen.setdefault("b", p[6]))
66
+ self.motor.setup_motor("D", 0, 0, stepSize=2, backlash=0, direction=-1)
67
+ self.motor._callback_motor_status(
68
+ {"steppers": [{"stepperid": 6, "position": 10}, {"stepperid": 42, "position": 1}]})
69
+ self.assertEqual(seen, {"a": -20, "b": -20})
70
+
71
+ def test_stop_all_sends_only_known_ids(self):
72
+ self.motor.move_axis_by_name("E", 5, speed=1000)
73
+ self.motor.stop()
74
+ self.assertEqual([s["stepperid"] for s in self.steppers()], [0, 1, 2, 3, 7])
75
+
76
+ def test_move_forever_only_given_axes(self):
77
+ self.motor.move_forever({"C": 500})
78
+ self.assertEqual(self.steppers(), [{"stepperid": 5, "isforever": 1, "speed": 500}])
79
+
80
+ def test_get_position_filtered(self):
81
+ self.parent.reply = [{"steppers": [{"stepperid": 4, "position": 8}, {"stepperid": 5, "isDone": -1}]}]
82
+ self.motor.setup_motor("B", 0, 0, stepSize=0.25, backlash=0)
83
+ pos = self.motor.get_position(axis=["B", "C"])
84
+ self.assertEqual(self.parent.sent[-1][1]["motor"], {"steppers": [{"stepperid": 4}, {"stepperid": 5}]})
85
+ self.assertEqual((len(pos), pos[4], pos[5]), (10, 2, 0))
86
+
87
+ def test_legacy_step_size_attributes(self):
88
+ self.motor.stepSizeX = 2.0
89
+ self.assertEqual((self.motor.stepSize[1], self.motor.stepSizeX), (2.0, 2.0))
90
+
91
+ def test_backlash_only_on_reversal(self):
92
+ self.motor.set_backlash("X", 10)
93
+ self.motor.move_x(100, speed=1000) # first move counts as a reversal
94
+ self.assertEqual(self.steppers()[0]["position"], 110)
95
+ self.motor.move_y(5, speed=1000) # another axis must not reset X's direction
96
+ self.motor.move_x(100, speed=1000)
97
+ self.assertEqual(self.steppers()[0]["position"], 100)
98
+ self.motor.move_x(-100, speed=1000)
99
+ self.assertEqual(self.steppers()[0]["position"], -110)
100
+ self.motor.move_x(0, speed=1000, is_absolute=True) # still moving down
101
+ self.assertEqual(self.steppers()[0]["position"], 0)
102
+ self.motor.move_x(50, speed=1000, is_absolute=True) # up again: overshoot upwards
103
+ self.assertEqual(self.steppers()[0]["position"], 60)
104
+
105
+ def test_home_named_axis(self):
106
+ home = Home(self.parent)
107
+ home.home(axis="C", speed=1000)
108
+ self.assertEqual(self.parent.sent[-1][1]["home"]["steppers"][0]["stepperid"], 5)
109
+ home.home_x()
110
+ self.assertEqual(self.parent.sent[-1][1]["home"]["steppers"][0]["stepperid"], 1)
111
+
112
+
113
+ if __name__ == "__main__":
114
+ unittest.main()
@@ -6,7 +6,7 @@ __version__.py
6
6
 
7
7
  __title__ = 'UC2-REST'
8
8
  __description__ = 'This pacage will help you to drive the ESP32-driven microscopy control modules from UC2'
9
- __version__ = "v0.2.0.42"
9
+ __version__ = "v0.2.0.43"
10
10
  __author__ = 'Benedict Diederich'
11
11
  __author_email__ = 'benedictdied@gmail.com'
12
12
  __license__ = 'GPL v3'
@@ -1,6 +1,7 @@
1
1
  import time
2
2
  import json
3
3
  import numpy as np
4
+ from .motor import AXIS_NAMES
4
5
 
5
6
  class Home(object):
6
7
  ## Laser
@@ -12,8 +13,8 @@ class Home(object):
12
13
  self.timeout = 20000
13
14
  self.endstoppolarity = 1
14
15
 
15
- self.nMotors = 4
16
- self.isHomed = np.zeros((self.nMotors))
16
+ self.nMotors = len(AXIS_NAMES)
17
+ self.isHomed = np.zeros((self.nMotors)) # indexed by stepperid
17
18
 
18
19
 
19
20
  # register a callback function for the motor status on the serial loop
@@ -43,15 +44,10 @@ class Home(object):
43
44
  into the position array of the motors '''
44
45
  try:
45
46
  steppers = data["home"]["steppers"]
46
- # Handle both single stepper and multiple steppers
47
- if isinstance(steppers, dict):
48
- # Single stepper format: {"axis":1,"pos":0,"isDone":1}
49
- stepperID = steppers["axis"]
50
- self.isHomed[stepperID] = steppers["isDone"]
51
- elif isinstance(steppers, list):
52
- # Multiple steppers format: [{"axis":1,"pos":0,"isDone":1}, ...]
53
- for stepper in steppers:
54
- stepperID = stepper["axis"]
47
+ # Single stepper {"axis":1,"pos":0,"isDone":1} or a list of them
48
+ for stepper in ([steppers] if isinstance(steppers, dict) else steppers):
49
+ stepperID = stepper["axis"]
50
+ if 0 <= stepperID < self.nMotors:
55
51
  self.isHomed[stepperID] = stepper["isDone"]
56
52
 
57
53
  if callable(self._callbackPerKey[0]):
@@ -65,49 +61,21 @@ class Home(object):
65
61
 
66
62
 
67
63
  def home_x(self, speed = None, direction = None, endposrelease = None, endstoppolarity=None, timeout=None, isBlocking=False):
68
- # axis = 1 corresponds to 'X'
69
- axis = 1
70
- self.home(axis=axis,
71
- endstoptimeout=timeout,
72
- speed = speed,
73
- direction = direction,
74
- endposrelease=endposrelease,
75
- endstoppolarity=endstoppolarity,
76
- isBlocking=isBlocking)
64
+ return self.home(axis="X", endstoptimeout=timeout, speed=speed, direction=direction,
65
+ endposrelease=endposrelease, endstoppolarity=endstoppolarity, isBlocking=isBlocking)
77
66
 
78
67
  def home_y(self, speed = None, direction = None, endposrelease = None, endstoppolarity=None, timeout=None, isBlocking=False):
79
- # axis = 2 corresponds to 'Y'
80
- axis = 2
81
- self.home(axis=axis,
82
- endstoptimeout=timeout,
83
- speed = speed,
84
- direction = direction,
85
- endposrelease=endposrelease,
86
- endstoppolarity=endstoppolarity,
87
- isBlocking=isBlocking)
88
-
68
+ return self.home(axis="Y", endstoptimeout=timeout, speed=speed, direction=direction,
69
+ endposrelease=endposrelease, endstoppolarity=endstoppolarity, isBlocking=isBlocking)
70
+
89
71
  def home_z(self, speed = None, direction = None, endposrelease = None, endstoppolarity=None, timeout=None, isBlocking=False, hardhome=False):
90
- # axisa = 3 corresponds to 'Z'
91
- axis = 3
92
- self.home(axis=axis,
93
- endstoptimeout=timeout,
94
- speed = speed,
95
- direction = direction,
96
- endposrelease=endposrelease,
97
- endstoppolarity=endstoppolarity,
98
- isBlocking=isBlocking,
99
- hardhome=hardhome)
100
-
72
+ return self.home(axis="Z", endstoptimeout=timeout, speed=speed, direction=direction,
73
+ endposrelease=endposrelease, endstoppolarity=endstoppolarity, isBlocking=isBlocking,
74
+ hardhome=hardhome)
75
+
101
76
  def home_a(self, speed = None, direction = None, endposrelease = None, endstoppolarity=None, timeout=None, isBlocking=False):
102
- # axis = 0 corresponds to 'A'
103
- axis = 0
104
- self.home(axis=axis,
105
- endstoptimeout=timeout,
106
- speed = speed,
107
- direction = direction,
108
- endposrelease=endposrelease,
109
- endstoppolarity=endstoppolarity,
110
- isBlocking=isBlocking)
77
+ return self.home(axis="A", endstoptimeout=timeout, speed=speed, direction=direction,
78
+ endposrelease=endposrelease, endstoppolarity=endstoppolarity, isBlocking=isBlocking)
111
79
 
112
80
  def home_xy(self, axes=["X", "Y"], speeds=None, directions=None, endposreleases=None,
113
81
  endstoppolarities=None, timeouts=None, isBlocking=False, preMove=True):
@@ -133,18 +101,8 @@ class Home(object):
133
101
  timeouts=[400, 200]
134
102
  )
135
103
  """
136
- # Convert axes to stepper IDs
137
- # First get logical motor index, then map through motorAxisOrder to get physical stepper ID
138
- stepper_ids = []
139
- motorAxisOrder = self._parent.motor.motorAxisOrder if hasattr(self._parent.motor , 'motorAxisOrder') else [0, 1, 2, 3]
140
- for axis in axes:
141
- if isinstance(axis, str):
142
- logical_motor_index = self.xyztTo1230(axis)
143
- else:
144
- logical_motor_index = axis
145
- # Map logical motor index to physical stepper ID
146
- stepper_id = motorAxisOrder[logical_motor_index]
147
- stepper_ids.append(stepper_id)
104
+ # axis names or stepperids -> stepperids
105
+ stepper_ids = [self.xyztTo1230(axis) for axis in axes]
148
106
 
149
107
  num_motors = len(stepper_ids)
150
108
 
@@ -180,18 +138,8 @@ class Home(object):
180
138
  preMoveDistanceSteps = 100 # steps to move away from endstop
181
139
 
182
140
  # Move away from endstop using the motor controller
183
- if stepper_id == 1: # X
184
- self._parent.motor.move_x(steps=preMoveDirection*preMoveDistanceSteps,
185
- speed=speeds[i], is_blocking=True, is_absolute=False, is_enabled=True)
186
- elif stepper_id == 2: # Y
187
- self._parent.motor.move_y(steps=preMoveDirection*preMoveDistanceSteps,
188
- speed=speeds[i], is_blocking=True, is_absolute=False, is_enabled=True)
189
- elif stepper_id == 3: # Z
190
- self._parent.motor.move_z(steps=preMoveDirection*preMoveDistanceSteps,
191
- speed=speeds[i], is_blocking=True, is_absolute=False, is_enabled=True)
192
- elif stepper_id == 0: # A
193
- self._parent.motor.move_a(steps=preMoveDirection*preMoveDistanceSteps,
194
- speed=speeds[i], is_blocking=True, is_absolute=False, is_enabled=True)
141
+ self._parent.motor.move_axis_by_name(axis=stepper_id, steps=preMoveDirection*preMoveDistanceSteps,
142
+ speed=speeds[i], is_blocking=True, is_absolute=False, is_enabled=True)
195
143
  time.sleep(0.5)
196
144
 
197
145
  # Build the steppers list for the JSON payload
@@ -227,22 +175,12 @@ class Home(object):
227
175
  return r
228
176
 
229
177
  def xyztTo1230(self, axis):
230
- """Convert axis string to stepper ID number."""
231
- if isinstance(axis, str):
232
- axis = axis.upper()
233
- if axis == "X":
234
- return 1
235
- elif axis == "Y":
236
- return 2
237
- elif axis == "Z":
238
- return 3
239
- elif axis == "A":
240
- return 0
241
- return axis
178
+ """Axis name ("X", "B", ...) or stepperid -> stepperid, see Motor.axis_id."""
179
+ return self._parent.motor.axis_id(axis)
242
180
 
243
181
  def home(self, axis=None, timeout=None, speed=None, direction=None, endposrelease=None, endstoppolarity=None, endstoptimeout=10000, isBlocking=False, preMove=False, hardhome=False):
244
182
  '''
245
- axis = 0,1,2,3 or 'A, 'X','Y','Z'
183
+ axis = stepperid (A=0, X=1, Y=2, Z=3, B..G=4..9) or axis name ('X', 'B', ...)
246
184
  timeout => when to stop homing (it's a while loop on the MCU)
247
185
  speed => speed of homing (0...15000)
248
186
  direction => 1,-1 (left/right)
@@ -275,20 +213,10 @@ class Home(object):
275
213
  preMoveDistanceSteps = 100 # steps to move away from endstop
276
214
 
277
215
  # move away from endstop
278
- if axis == 1 or axis == "X":
279
- self._parent.motor.move_x(steps=preMoveDirection*preMoveDistanceSteps, speed=self.speed, is_blocking=True, is_absolute=False, is_enabled=True)
280
- elif axis == 2 or axis == "Y":
281
- self._parent.motor.move_y(steps=preMoveDirection*preMoveDistanceSteps, speed=self.speed, is_blocking=True, is_absolute=False, is_enabled=True)
282
- elif axis == 3 or axis == "Z":
283
- self._parent.motor.move_z(steps=preMoveDirection*preMoveDistanceSteps, speed=self.speed, is_blocking=True, is_absolute=False, is_enabled=True)
284
- elif axis == 0 or axis == "A":
285
- self._parent.motor.move_a(steps=preMoveDirection*preMoveDistanceSteps, speed=self.speed, is_blocking=True, is_absolute=False, is_enabled=True)
286
- else:
287
- raise ValueError("Invalid axis. Use 'X', 'Y', 'Z', or 'A'.")
216
+ self._parent.motor.move_axis_by_name(axis=axis, steps=preMoveDirection*preMoveDistanceSteps, speed=self.speed, is_blocking=True, is_absolute=False, is_enabled=True)
288
217
  time.sleep(0.5)
289
218
 
290
- # Map logical motor index to physical stepper ID through motorAxisOrder
291
- stepper_id = self._parent.motor.motorAxisOrder[axis]
219
+ stepper_id = self.xyztTo1230(axis)
292
220
 
293
221
  # construct json string
294
222
  path = "/home_act"