moons-motor 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl
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.
- moons_motor/motor.py +107 -26
- {moons_motor-0.1.2.dist-info → moons_motor-0.1.4.dist-info}/METADATA +5 -5
- {moons_motor-0.1.2.dist-info → moons_motor-0.1.4.dist-info}/RECORD +6 -6
- {moons_motor-0.1.2.dist-info → moons_motor-0.1.4.dist-info}/WHEEL +1 -1
- {moons_motor-0.1.2.dist-info → moons_motor-0.1.4.dist-info}/licenses/LICENSE +0 -0
- {moons_motor-0.1.2.dist-info → moons_motor-0.1.4.dist-info}/top_level.txt +0 -0
moons_motor/motor.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import serial
|
2
|
+
import serial.rs485
|
2
3
|
from serial.tools import list_ports
|
3
4
|
import re
|
4
5
|
import threading
|
@@ -51,6 +52,7 @@ class StepperCommand:
|
|
51
52
|
SET_RETURN_FORMAT_HEXADECIMAL: str = "IFH" # Set return format to hexadecimal
|
52
53
|
|
53
54
|
SET_TRANSMIT_DELAY: str = "TD" # Set transmit delay
|
55
|
+
REQUEST_STATUS: str = "RS" # Request status
|
54
56
|
|
55
57
|
|
56
58
|
class MoonsStepper(Subject):
|
@@ -110,9 +112,10 @@ class MoonsStepper(Subject):
|
|
110
112
|
self.Opened = False
|
111
113
|
self.recvQueue = queue.Queue()
|
112
114
|
self.sendQueue = queue.Queue()
|
113
|
-
self.pending_callbacks =
|
115
|
+
self.pending_callbacks = queue.Queue()
|
114
116
|
self.update_thread = None
|
115
117
|
self.is_updating = False
|
118
|
+
self.readBuffer = ""
|
116
119
|
|
117
120
|
self.console = Console()
|
118
121
|
|
@@ -183,7 +186,22 @@ class MoonsStepper(Subject):
|
|
183
186
|
|
184
187
|
def attempt_connect(COM, baudrate):
|
185
188
|
try:
|
186
|
-
self.ser = serial.Serial(
|
189
|
+
# self.ser = serial.Serial(
|
190
|
+
# port=COM,
|
191
|
+
# baudrate=baudrate,
|
192
|
+
# bytesize=serial.EIGHTBITS,
|
193
|
+
# parity=serial.PARITY_NONE,
|
194
|
+
# stopbits=serial.STOPBITS_ONE,
|
195
|
+
# timeout=0.5,
|
196
|
+
# )
|
197
|
+
self.ser = serial.rs485.RS485(port=COM, baudrate=baudrate)
|
198
|
+
self.ser.rs485_mode = serial.rs485.RS485Settings(
|
199
|
+
rts_level_for_tx=True,
|
200
|
+
rts_level_for_rx=False,
|
201
|
+
loopback=False,
|
202
|
+
delay_before_tx=0.02,
|
203
|
+
delay_before_rx=0.02,
|
204
|
+
)
|
187
205
|
if self.ser is None:
|
188
206
|
self.Opened = False
|
189
207
|
if self.ser.is_open:
|
@@ -236,6 +254,8 @@ class MoonsStepper(Subject):
|
|
236
254
|
callback(self.device, self.Opened)
|
237
255
|
|
238
256
|
def disconnect(self):
|
257
|
+
self.send_command(command=StepperCommand.STOP_KILL)
|
258
|
+
time.sleep(0.5)
|
239
259
|
self.sendQueue.queue.clear()
|
240
260
|
self.recvQueue.queue.clear()
|
241
261
|
self.is_updating = False
|
@@ -259,7 +279,6 @@ class MoonsStepper(Subject):
|
|
259
279
|
self.temp_cmd = command + "\r"
|
260
280
|
|
261
281
|
if self.ser is not None or not self.only_simulate:
|
262
|
-
self.temp_cmd += "\r"
|
263
282
|
self.ser.write(self.temp_cmd.encode("ascii"))
|
264
283
|
if self.is_log_message:
|
265
284
|
print(
|
@@ -287,20 +306,28 @@ class MoonsStepper(Subject):
|
|
287
306
|
if self.ser.in_waiting > 0:
|
288
307
|
response = self.ser.read(self.ser.in_waiting)
|
289
308
|
response = response.decode("ascii", errors="ignore").strip()
|
290
|
-
|
291
|
-
|
309
|
+
response = response.split("\r")
|
310
|
+
|
311
|
+
for r in response:
|
312
|
+
if r != "":
|
313
|
+
self.readBuffer += r
|
314
|
+
self.handle_recv(r)
|
315
|
+
|
292
316
|
if self.sendQueue.empty() != True:
|
317
|
+
# time.sleep(
|
318
|
+
# 0.02
|
319
|
+
# ) # Time for RS485 converter to switch between Transmit and Receive mode
|
293
320
|
while not self.sendQueue.empty():
|
321
|
+
# time.sleep(
|
322
|
+
# 0.05
|
323
|
+
# ) # Time for RS485 converter to switch between Transmit and Receive mode
|
294
324
|
cmd = self.sendQueue.get_nowait()
|
295
325
|
self.send(cmd)
|
296
326
|
self.sendQueue.task_done()
|
297
|
-
time.sleep(
|
298
|
-
0.01
|
299
|
-
) # Time for RS485 converter to switch between Transmit and Receive mode
|
300
327
|
|
301
328
|
def handle_recv(self, response):
|
302
329
|
if "*" in response:
|
303
|
-
print("buffered_ack")
|
330
|
+
print(f"[bold green](o)buffered_ack[/bold green]")
|
304
331
|
elif "%" in response:
|
305
332
|
print(f"[bold green](v)success_ack[/bold green]")
|
306
333
|
elif "?" in response:
|
@@ -309,24 +336,54 @@ class MoonsStepper(Subject):
|
|
309
336
|
print(f"[bold blue]Received from {self.device}: [/bold blue]", response)
|
310
337
|
self.recvQueue.put_nowait(response)
|
311
338
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
339
|
+
if "=" in response:
|
340
|
+
callback = self.pending_callbacks.get_nowait()
|
341
|
+
if callback:
|
342
|
+
callback(response)
|
343
|
+
# for command, callback in list(self.pending_callbacks.items()):
|
344
|
+
# if command in response:
|
345
|
+
# if callback:
|
346
|
+
# callback(response)
|
347
|
+
# del self.pending_callbacks[command]
|
348
|
+
# break
|
318
349
|
|
319
350
|
# endregion
|
320
351
|
|
321
352
|
# region motor motion functions
|
322
353
|
|
323
|
-
def setup_motor(self, motor_address="", kill=False):
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
354
|
+
# def setup_motor(self, motor_address="", kill=False):
|
355
|
+
# if kill:
|
356
|
+
# self.stop_and_kill(motor_address)
|
357
|
+
# self.set_transmit_delay(motor_address, 25)
|
358
|
+
# self.set_return_format_dexcimal(motor_address)
|
328
359
|
|
329
360
|
def home(self, motor_address="", speed=0.3, onComplete=None):
|
361
|
+
homing_complete = threading.Event() # Shared event to signal completion
|
362
|
+
|
363
|
+
def check_status(response):
|
364
|
+
result = MoonsStepper.process_response(response)
|
365
|
+
print(f"[bold blue]Status check result:[/bold blue] {result}")
|
366
|
+
if "H" not in result["value"]:
|
367
|
+
print("[bold green]Motor is homed.[/bold green]")
|
368
|
+
if onComplete: # Call the onComplete callback if provided
|
369
|
+
onComplete(result)
|
370
|
+
homing_complete.set() # Signal that homing is complete
|
371
|
+
else:
|
372
|
+
print("[bold yellow]Motor is not homed yet.[/bold yellow]")
|
373
|
+
|
374
|
+
def check_homing_complete():
|
375
|
+
while not homing_complete.is_set(): # Loop until homing is complete
|
376
|
+
self.get_status(
|
377
|
+
motor_address=motor_address,
|
378
|
+
command=StepperCommand.REQUEST_STATUS,
|
379
|
+
callback=check_status,
|
380
|
+
)
|
381
|
+
time.sleep(0.3)
|
382
|
+
|
383
|
+
home_thread = threading.Thread(
|
384
|
+
target=check_homing_complete,
|
385
|
+
daemon=True,
|
386
|
+
)
|
330
387
|
self.send_command(
|
331
388
|
address=motor_address, command=StepperCommand.VELOCITY, value=speed
|
332
389
|
)
|
@@ -334,23 +391,47 @@ class MoonsStepper(Subject):
|
|
334
391
|
address=motor_address, command=StepperCommand.HOME, value="3F"
|
335
392
|
)
|
336
393
|
self.send_command(
|
337
|
-
address=motor_address, command=StepperCommand.ENCODER_POSITION
|
394
|
+
address=motor_address, command=StepperCommand.ENCODER_POSITION, value=0
|
338
395
|
)
|
339
396
|
self.send_command(
|
340
397
|
address=motor_address, command=StepperCommand.SET_POSITION, value=0
|
341
398
|
)
|
342
|
-
|
343
|
-
self.get_status(
|
344
|
-
motor_address, StepperCommand.SET_POSITION, callback=onComplete
|
345
|
-
)
|
399
|
+
home_thread.start()
|
346
400
|
|
347
401
|
# endregion
|
348
402
|
def get_status(self, motor_address, command: StepperCommand, callback=None):
|
349
403
|
command = self.addressed_cmd(motor_address, command)
|
350
404
|
if callback:
|
351
|
-
self.pending_callbacks
|
405
|
+
self.pending_callbacks.put_nowait(callback)
|
352
406
|
self.sendQueue.put_nowait(command)
|
353
407
|
|
408
|
+
def decode_status(status_code):
|
409
|
+
"""
|
410
|
+
Decode the status code from the motor.
|
411
|
+
"""
|
412
|
+
status = {
|
413
|
+
"A": "An Alarm code is present (use AL command to see code, AR command to clear code)",
|
414
|
+
"D": "Disabled (the drive is disabled)",
|
415
|
+
"E": "Drive Fault (drive must be reset by AR command to clear this fault)",
|
416
|
+
"F": "Motor moving",
|
417
|
+
"H": "Homing (SH in progress)",
|
418
|
+
"J": "Jogging (CJ in progress)",
|
419
|
+
"M": "Motion in progress (Feed & Jog Commands)",
|
420
|
+
"P": "In position",
|
421
|
+
"R": "Ready (Drive is enabled and ready)",
|
422
|
+
"S": "Stopping a motion (ST or SK command executing)",
|
423
|
+
"T": "Wait Time (WT command executing)",
|
424
|
+
"W": "Wait Input (WI command executing)",
|
425
|
+
}
|
426
|
+
status_string = ""
|
427
|
+
for char in status_code:
|
428
|
+
if char in status:
|
429
|
+
status_string += status[char]
|
430
|
+
status_string += "\n"
|
431
|
+
else:
|
432
|
+
status_string += f"Unknown status code: {char}"
|
433
|
+
return status_string
|
434
|
+
|
354
435
|
# endregion
|
355
436
|
|
356
437
|
# region utility functions
|
@@ -1,10 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: moons_motor
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.4
|
4
4
|
Summary: This is a python library for controlling the Moons' motor through the serial port.
|
5
5
|
Author-email: miroc <mike8503111@gmail.com>
|
6
6
|
Project-URL: Repository, https://github.com/miroc99/moons_motor.git
|
7
|
-
Classifier: Development Status ::
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
8
8
|
Classifier: Intended Audience :: Developers
|
9
9
|
Classifier: Topic :: Terminals :: Serial
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
@@ -38,7 +38,7 @@ python -m pip install moons_motor
|
|
38
38
|
## Usage
|
39
39
|
|
40
40
|
```python
|
41
|
-
from motor import MoonsStepper, StepperModules
|
41
|
+
from motor import MoonsStepper, StepperModules, StepperCommand
|
42
42
|
import simulate
|
43
43
|
from time import sleep
|
44
44
|
|
@@ -47,9 +47,9 @@ motor = MoonsStepper(StepperModules.STM17S_3RN, "0403", "6001", "TESTA")
|
|
47
47
|
MoonsStepper.list_all_ports()
|
48
48
|
motor.connect()
|
49
49
|
|
50
|
-
motor.
|
50
|
+
motor.send_command(address="@", command=StepperCommand.JOG)
|
51
51
|
sleep(5)
|
52
|
-
motor.
|
52
|
+
motor.send_command(address="@", command=StepperCommand.STOP_JOG)
|
53
53
|
|
54
54
|
```
|
55
55
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
moons_motor/__init__.py,sha256=qOpsRwizV-DpKSvNzyvj8ju3cs6vwgIICur1Oe6sxOA,27
|
2
|
-
moons_motor/motor.py,sha256=
|
2
|
+
moons_motor/motor.py,sha256=ZXXX6Ie-PL5QN8O-JpMVGh9xgYSsQpJM0BsqiVbtdns,15521
|
3
3
|
moons_motor/observer.py,sha256=PXzuPYKRb2HpjArJcD8HakYIPfFGAs1uBDIL8PSizgA,124
|
4
4
|
moons_motor/simulate.py,sha256=J0y1fZhoOim9i-BAkprxnPern1SAdkDfKPqT2MWyDwU,2561
|
5
5
|
moons_motor/status.py,sha256=jXQZFZTt9ugHktkWKLII8MpEQQaeO-UjlwTrrP4LJNE,2872
|
6
6
|
moons_motor/subject.py,sha256=L_GS6fvJTeX7X23o3T92oiZ4rtLVKA2OEd9GpHn_Dz4,445
|
7
|
-
moons_motor-0.1.
|
8
|
-
moons_motor-0.1.
|
9
|
-
moons_motor-0.1.
|
10
|
-
moons_motor-0.1.
|
11
|
-
moons_motor-0.1.
|
7
|
+
moons_motor-0.1.4.dist-info/licenses/LICENSE,sha256=nsYjO800SjIjI85y2kVHR5mC3tca2vs4kK_BhNe89bM,1074
|
8
|
+
moons_motor-0.1.4.dist-info/METADATA,sha256=OfYNsukji4MOjMxTBk87GHo1Y4GH5eQFkfpLY8czulE,1403
|
9
|
+
moons_motor-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
10
|
+
moons_motor-0.1.4.dist-info/top_level.txt,sha256=0dE-CR5_NYBw34jHIDGQNWpMllzO6mtUIuKyRv_rJLg,12
|
11
|
+
moons_motor-0.1.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|