UC2-REST 0.2.0.27__tar.gz → 0.2.0.29__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.
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/PKG-INFO +1 -1
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/UC2_REST.egg-info/PKG-INFO +1 -1
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/UC2_REST.egg-info/SOURCES.txt +2 -2
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/UC2Client.py +13 -22
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/__init__.py +0 -1
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/__version__.py +1 -1
- uc2_rest-0.2.0.29/uc2rest/can.py +33 -0
- uc2_rest-0.2.0.29/uc2rest/lcddisplay.py +59 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/motor.py +79 -3
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/mserial.py +15 -13
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/objective.py +1 -0
- uc2_rest-0.2.0.27/uc2rest/config.py +0 -164
- uc2_rest-0.2.0.27/uc2rest/config_.py +0 -104
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/LICENSE +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/README.md +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/UC2_REST.egg-info/dependency_links.txt +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/UC2_REST.egg-info/not-zip-safe +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/UC2_REST.egg-info/requires.txt +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/UC2_REST.egg-info/top_level.txt +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/setup.cfg +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/setup.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/MockSerial.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/analog.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/camera.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/cmdrecorder.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/digitalout.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/galvo.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/gripper.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/home.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/laser.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/ledmatrix.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/logger.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/message.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/modules.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/pid.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/rotator.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/slm.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/state.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/temperature.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/utils.py +0 -0
- {uc2_rest-0.2.0.27 → uc2_rest-0.2.0.29}/uc2rest/wifi.py +0 -0
|
@@ -13,14 +13,14 @@ uc2rest/__init__.py
|
|
|
13
13
|
uc2rest/__version__.py
|
|
14
14
|
uc2rest/analog.py
|
|
15
15
|
uc2rest/camera.py
|
|
16
|
+
uc2rest/can.py
|
|
16
17
|
uc2rest/cmdrecorder.py
|
|
17
|
-
uc2rest/config.py
|
|
18
|
-
uc2rest/config_.py
|
|
19
18
|
uc2rest/digitalout.py
|
|
20
19
|
uc2rest/galvo.py
|
|
21
20
|
uc2rest/gripper.py
|
|
22
21
|
uc2rest/home.py
|
|
23
22
|
uc2rest/laser.py
|
|
23
|
+
uc2rest/lcddisplay.py
|
|
24
24
|
uc2rest/ledmatrix.py
|
|
25
25
|
uc2rest/logger.py
|
|
26
26
|
uc2rest/message.py
|
|
@@ -8,8 +8,8 @@ Copyright 2021 Benedict Diederich, released under LGPL 3.0 or later
|
|
|
8
8
|
from .mserial import Serial
|
|
9
9
|
from .mserial import SerialManagerWrapper
|
|
10
10
|
from .galvo import Galvo
|
|
11
|
-
from .config import config
|
|
12
11
|
from .ledmatrix import LedMatrix
|
|
12
|
+
from .lcddisplay import LCDDisplay
|
|
13
13
|
from .motor import Motor
|
|
14
14
|
from .gripper import Gripper
|
|
15
15
|
from .home import Home
|
|
@@ -26,6 +26,7 @@ from .logger import Logger
|
|
|
26
26
|
from .cmdrecorder import cmdRecorder
|
|
27
27
|
from .temperature import Temperature
|
|
28
28
|
from .message import Message
|
|
29
|
+
from .can import CAN
|
|
29
30
|
try:
|
|
30
31
|
import requests
|
|
31
32
|
except:
|
|
@@ -39,11 +40,11 @@ class UC2Client(object):
|
|
|
39
40
|
|
|
40
41
|
is_wifi = False
|
|
41
42
|
is_serial = False
|
|
43
|
+
BAUDRATE = 115200
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def __init__(self, host=None, port=31950, serialport=None, identity="UC2_Feather", baudrate=BAUDRATE, NLeds=64, SerialManager=None, DEBUG=False, logger=None, skipFirmwareCheck=False):
|
|
45
|
+
def __init__(self, host=None, port=31950, serialport=None, identity="UC2_Feather", baudrate=BAUDRATE,
|
|
46
|
+
NLeds=64, SerialManager=None, DEBUG=False, logger=None, skipFirmwareCheck=False,
|
|
47
|
+
isPyScript=False):
|
|
47
48
|
'''
|
|
48
49
|
This client connects to the UC2-REST microcontroller that can be found here
|
|
49
50
|
https://github.com/openUC2/UC2-REST
|
|
@@ -61,7 +62,7 @@ class UC2Client(object):
|
|
|
61
62
|
self.logger = logger
|
|
62
63
|
|
|
63
64
|
# perhaps we are in the browser?
|
|
64
|
-
self.isPyScript =
|
|
65
|
+
self.isPyScript = isPyScript
|
|
65
66
|
|
|
66
67
|
# initialize communication channel (# connect to wifi or usb)
|
|
67
68
|
if serialport is not None:
|
|
@@ -90,17 +91,8 @@ class UC2Client(object):
|
|
|
90
91
|
# import libraries depending on API version
|
|
91
92
|
self.logger.debug("Using API version 2")
|
|
92
93
|
|
|
93
|
-
#FIXME
|
|
94
|
-
#self.set_state(debug=False)
|
|
95
|
-
|
|
96
94
|
# initialize state
|
|
97
95
|
self.state = State(self)
|
|
98
|
-
if not self.isPyScript:
|
|
99
|
-
state = self.state.get_state()
|
|
100
|
-
|
|
101
|
-
# initialize config
|
|
102
|
-
if not self.isPyScript:
|
|
103
|
-
self.config = config(self)
|
|
104
96
|
|
|
105
97
|
# initialize cmdRecorder
|
|
106
98
|
self.cmdRecorder = cmdRecorder(self)
|
|
@@ -108,9 +100,15 @@ class UC2Client(object):
|
|
|
108
100
|
# initialize LED matrix
|
|
109
101
|
self.led = LedMatrix(self, NLeds=NLeds)
|
|
110
102
|
|
|
103
|
+
# initialize LCD display
|
|
104
|
+
self.lcd = LCDDisplay(self)
|
|
105
|
+
|
|
111
106
|
# initilize motor
|
|
112
107
|
self.motor = Motor(self)
|
|
113
108
|
|
|
109
|
+
# initialize CAN
|
|
110
|
+
self.can = CAN(self)
|
|
111
|
+
|
|
114
112
|
# initialize gripper
|
|
115
113
|
self.gripper = Gripper(self)
|
|
116
114
|
|
|
@@ -149,13 +147,6 @@ class UC2Client(object):
|
|
|
149
147
|
|
|
150
148
|
# initialize messaging
|
|
151
149
|
self.message = Message(self)
|
|
152
|
-
|
|
153
|
-
# initialize config
|
|
154
|
-
if False: # not self.isPyScript:
|
|
155
|
-
self.config = config(self)
|
|
156
|
-
try: self.pinConfig = self.config.loadConfigDevice()
|
|
157
|
-
except: self.pinConfig = None
|
|
158
|
-
|
|
159
150
|
|
|
160
151
|
# initialize module controller
|
|
161
152
|
self.modules = Modules(parent=self)
|
|
@@ -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.
|
|
9
|
+
__version__ = "v0.2.0.29"
|
|
10
10
|
__author__ = 'Benedict Diederich'
|
|
11
11
|
__author_email__ = 'benedictdied@gmail.com'
|
|
12
12
|
__license__ = 'GPL v3'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class CAN(object):
|
|
2
|
+
def __init__(self, parent):
|
|
3
|
+
"""
|
|
4
|
+
CANController handles sending commands to a remote CAN device via the parent post_json interface.
|
|
5
|
+
|
|
6
|
+
:param parent: Parent object with post_json(path, payload, getReturn, timeout, nResponses)
|
|
7
|
+
"""
|
|
8
|
+
self._parent = parent
|
|
9
|
+
|
|
10
|
+
def reboot_remote(self, qid=1, can_address=0, isBlocking=False, timeout=2):
|
|
11
|
+
"""
|
|
12
|
+
Send a reboot signal to the remote CAN device.
|
|
13
|
+
|
|
14
|
+
:param qid: Query ID for the CAN command (default: 1)
|
|
15
|
+
:param isBlocking: If True, wait for response
|
|
16
|
+
:param timeout: Timeout for the command in seconds
|
|
17
|
+
:param can_address: Address of the CAN device to reboot (0 is master)
|
|
18
|
+
:return: Response from the device
|
|
19
|
+
"""
|
|
20
|
+
path = "/can_act"
|
|
21
|
+
payload = {
|
|
22
|
+
"task": path,
|
|
23
|
+
"restart": int(can_address)
|
|
24
|
+
}
|
|
25
|
+
nResponses = 1 if isBlocking else 0
|
|
26
|
+
# Send the payload to the parent, which handles the actual communication
|
|
27
|
+
return self._parent.post_json(
|
|
28
|
+
path,
|
|
29
|
+
payload,
|
|
30
|
+
getReturn=isBlocking,
|
|
31
|
+
timeout=timeout if isBlocking else 0,
|
|
32
|
+
nResponses=nResponses
|
|
33
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class LCDDisplay:
|
|
2
|
+
def __init__(self, parent):
|
|
3
|
+
"""
|
|
4
|
+
LCD controller interface.
|
|
5
|
+
Sends JSON commands to draw on the LCD via the parent object.
|
|
6
|
+
"""
|
|
7
|
+
self._parent = parent
|
|
8
|
+
self.path = "/lcd_act"
|
|
9
|
+
self.timeout = 10
|
|
10
|
+
self.color = (255, 255, 255) # Default color
|
|
11
|
+
|
|
12
|
+
def _send(self, action, isBlocking=True, **kwargs):
|
|
13
|
+
payload = {
|
|
14
|
+
"task": self.path,
|
|
15
|
+
"action": action,
|
|
16
|
+
**kwargs
|
|
17
|
+
}
|
|
18
|
+
return self._parent.post_json(self.path, payload, getReturn=isBlocking, nResponses=1, timeout=self.timeout)
|
|
19
|
+
|
|
20
|
+
def set_grating(self, perdiod, r=255, g=255, b=255, horizontal=True):
|
|
21
|
+
# {"task":"/lcd_act", "action":"gratingh","period":3,"r":255,"g":255,"b":255}
|
|
22
|
+
if horizontal:
|
|
23
|
+
return self._send("gratingh", period=perdiod, r=r, g=g, b=b)
|
|
24
|
+
else:
|
|
25
|
+
return self._send("gratingv", period=perdiod, r=r, g=g, b=b)
|
|
26
|
+
|
|
27
|
+
def set_timeout(self, timeout=5):
|
|
28
|
+
"""
|
|
29
|
+
Set the timeout for the LCD display.
|
|
30
|
+
:param timeout: Timeout in seconds.
|
|
31
|
+
"""
|
|
32
|
+
self.timeout = timeout
|
|
33
|
+
|
|
34
|
+
def set_color(self, r=255, g=255, b=255):
|
|
35
|
+
self.color = (r, g, b)
|
|
36
|
+
|
|
37
|
+
def clear(self, r=0, g=0, b=0):
|
|
38
|
+
return self._send("clear", r=r, g=g, b=b)
|
|
39
|
+
|
|
40
|
+
def hline(self, x, y, length, width=1):
|
|
41
|
+
r, g, b = self.color
|
|
42
|
+
# {"task":"/lcd_act","action":"hline","x":0,"y":10,"len":800,"width":1,"r":255,"g":255,"b":0}
|
|
43
|
+
return self._send("hline", x=x, y=y, len=length, width=width, r=r, g=g, b=b)
|
|
44
|
+
|
|
45
|
+
def vline(self, x, y, length, width=1):
|
|
46
|
+
r, g, b = self.color
|
|
47
|
+
return self._send("vline", x=x, y=y, len=length, width=width, r=r, g=g, b=b)
|
|
48
|
+
|
|
49
|
+
def point(self, x, y, diam=1):
|
|
50
|
+
r, g, b = self.color
|
|
51
|
+
return self._send("point", x=x, y=y, diam=diam, r=r, g=g, b=b)
|
|
52
|
+
|
|
53
|
+
def rect(self, x, y, len, width):
|
|
54
|
+
r, g, b = self.color
|
|
55
|
+
return self._send("rect", x=x, y=y, len=len, width=width, r=r, g=g, b=b)
|
|
56
|
+
|
|
57
|
+
def fill(self, x, y, len, width):
|
|
58
|
+
r, g, b = self.color
|
|
59
|
+
return self._send("fill", x=x, y=y, len=len, width=width, r=r, g=g, b=b)
|
|
@@ -42,7 +42,7 @@ class Motor(object):
|
|
|
42
42
|
self.offsetY = 0
|
|
43
43
|
self.offsetZ = 0
|
|
44
44
|
|
|
45
|
-
self.DEFAULT_ACCELERATION =
|
|
45
|
+
self.DEFAULT_ACCELERATION = 1000000
|
|
46
46
|
|
|
47
47
|
self.motorAxisOrder = [0,1,2,3] # motor axis is 1,2,3,0 => X,Y,Z,T # FIXME: Hardcoded
|
|
48
48
|
|
|
@@ -142,6 +142,38 @@ class Motor(object):
|
|
|
142
142
|
def setMotorAxisOrder(self, order=[0,1,2,3]):
|
|
143
143
|
self.motorAxisOrder = order
|
|
144
144
|
|
|
145
|
+
# { "task": "/motor_act", "focusscan": { "zStart": 0, "zStep": 50, "nZ": 20, "tPre": 80, "tTrig": 20, "tPost": 0, "led": 0, "illumination": [0, 255, 0, 0], "speed": 20000, "acceleration": 1000000, "qid": 42 }}
|
|
146
|
+
def startFocusScanning(self, zStart=0, zStep=50, nZ=20, tPre=80, tTrig=20, tPost=0, led=0, illumination=[0, 255, 0, 0], speed=20000, acceleration=1000000, qid=42):
|
|
147
|
+
path = "/motor_act"
|
|
148
|
+
payload = {
|
|
149
|
+
"task": path,
|
|
150
|
+
"focusscan": {
|
|
151
|
+
"zStart": zStart,
|
|
152
|
+
"zStep": zStep,
|
|
153
|
+
"nZ": nZ,
|
|
154
|
+
"tPre": tPre,
|
|
155
|
+
"tTrig": tTrig,
|
|
156
|
+
"tPost": tPost,
|
|
157
|
+
"led": led,
|
|
158
|
+
"illumination": illumination,
|
|
159
|
+
"speed": speed,
|
|
160
|
+
"acceleration": acceleration,
|
|
161
|
+
"qid": qid
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
r = self._parent.post_json(path, payload)
|
|
165
|
+
return r
|
|
166
|
+
|
|
167
|
+
def stopFocusScanning(self):
|
|
168
|
+
path = "/motor_act"
|
|
169
|
+
payload = {
|
|
170
|
+
"task": path,
|
|
171
|
+
"focusscan": {
|
|
172
|
+
"stopped": 1
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
r = self._parent.post_json(path, payload)
|
|
176
|
+
return r
|
|
145
177
|
'''################################################################################################################################################
|
|
146
178
|
HIGH-LEVEL Functions that rely on basic REST-API functions
|
|
147
179
|
################################################################################################################################################'''
|
|
@@ -423,7 +455,7 @@ class Motor(object):
|
|
|
423
455
|
self.currentDirection[iMotor] = np.sign(steps[iMotor])
|
|
424
456
|
if self.lastDirection[iMotor] != self.currentDirection[iMotor]:
|
|
425
457
|
# we want to overshoot a bit
|
|
426
|
-
steps[iMotor] = steps[iMotor] +
|
|
458
|
+
steps[iMotor] = steps[iMotor] + self.currentDirection[iMotor]*self.backlash[iMotor]
|
|
427
459
|
|
|
428
460
|
|
|
429
461
|
if isAbsoluteArray[iMotor]:
|
|
@@ -459,6 +491,10 @@ class Motor(object):
|
|
|
459
491
|
motorPropList = []
|
|
460
492
|
for iMotor in range(4):
|
|
461
493
|
if isAbsoluteArray[iMotor] or abs(steps[iMotor])>0:
|
|
494
|
+
# if we are absolute and the last target position is the same as the current one, we don't need to move
|
|
495
|
+
if isAbsoluteArray[iMotor] and abs(steps[iMotor] - self.currentPosition[iMotor])<1:
|
|
496
|
+
if self._parent.serial.DEBUG: self._parent.logger.debug(f"Motor {iMotor} is already at target position {steps[iMotor]}")
|
|
497
|
+
continue
|
|
462
498
|
motorProp = { "stepperid": int(self.motorAxisOrder[iMotor]),
|
|
463
499
|
"position": int(steps[iMotor]),
|
|
464
500
|
"speed": int(speed[iMotor]),
|
|
@@ -471,7 +507,8 @@ class Motor(object):
|
|
|
471
507
|
else:
|
|
472
508
|
motorProp["accel"] = self.DEFAULT_ACCELERATION
|
|
473
509
|
motorPropList.append(motorProp)
|
|
474
|
-
|
|
510
|
+
if len(motorPropList)==0:
|
|
511
|
+
return "{'return':-1}"
|
|
475
512
|
path = "/motor_act"
|
|
476
513
|
payload = {
|
|
477
514
|
"task":path,
|
|
@@ -698,7 +735,46 @@ class Motor(object):
|
|
|
698
735
|
|
|
699
736
|
def set_direction(self, axis=1, sign=1, timeout=1):
|
|
700
737
|
return False
|
|
738
|
+
|
|
739
|
+
def stop_stage_scanning(self):
|
|
740
|
+
# {"task":"/motor_act", "stagescan":{ "stopped":1 }}
|
|
741
|
+
path = "/motor_act"
|
|
742
|
+
payload = {
|
|
743
|
+
"task": path,
|
|
744
|
+
"stagescan": {
|
|
745
|
+
"stopped": 1
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
r = self._parent.post_json(path, payload)
|
|
749
|
+
return r
|
|
750
|
+
|
|
751
|
+
|
|
701
752
|
|
|
753
|
+
def start_stage_scanning(self, xstart=0, xstep=1000, nx=20, ystart=0, ystep=1000, ny=10, tsettle=5, tExposure=50, illumination=(0,0,0,0), led=0, speed=20000, acceleration=None):
|
|
754
|
+
# {"task": "/motor_act", "stagescan": {"xStart": 0, "yStart": 0, "xStep": 500, "yStep": 500, "nX": 10, "nY": 10, "tPre": 50, "tPost": 50, "illumination": [0, 1, 0, 0], "led": 255}}
|
|
755
|
+
if acceleration is None:
|
|
756
|
+
acceleration = self.DEFAULT_ACCELERATION
|
|
757
|
+
path = "/motor_act"
|
|
758
|
+
payload = {
|
|
759
|
+
"task": path,
|
|
760
|
+
"stagescan": {
|
|
761
|
+
"xStart": xstart / self.stepSizeX,
|
|
762
|
+
"xStep": xstep / self.stepSizeX,
|
|
763
|
+
"nX": nx,
|
|
764
|
+
"yStart": ystart / self.stepSizeY,
|
|
765
|
+
"yStep": ystep / self.stepSizeY,
|
|
766
|
+
"nY": ny,
|
|
767
|
+
"tPre": tsettle,
|
|
768
|
+
"tPost": tExposure,
|
|
769
|
+
"illumination": illumination,
|
|
770
|
+
"led": led,
|
|
771
|
+
"accel": self.DEFAULT_ACCELERATION, # default acceleration
|
|
772
|
+
"speed": speed, # default speed
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
r = self._parent.post_json(path, payload)
|
|
776
|
+
return r
|
|
777
|
+
|
|
702
778
|
def set_tmc_parameters(self, axis=0, msteps=None, rms_current=None, stall_value=None, sgthrs=None, semin=None, semax=None, blank_time=None, toff=None, timeout=1):
|
|
703
779
|
''' set the TMC parameters for a specific axis
|
|
704
780
|
msteps: microsteps
|
|
@@ -33,7 +33,7 @@ class Serial:
|
|
|
33
33
|
self._logger.addHandler(logging.StreamHandler())
|
|
34
34
|
else:
|
|
35
35
|
self._logger = self._parent.logger
|
|
36
|
-
|
|
36
|
+
self.identifier_counter = 0
|
|
37
37
|
self.identity = identity
|
|
38
38
|
self.DEBUG = DEBUG
|
|
39
39
|
self.is_connected = False
|
|
@@ -228,7 +228,8 @@ class Serial:
|
|
|
228
228
|
try:
|
|
229
229
|
mLine = serialdevice.readline()
|
|
230
230
|
if self.cmdReadCallBackFct is not None and mLine!=b'' and mLine != b'\n' :
|
|
231
|
-
self.cmdReadCallBackFct(mLine)
|
|
231
|
+
try:self.cmdReadCallBackFct(mLine)
|
|
232
|
+
except:pass
|
|
232
233
|
return mLine
|
|
233
234
|
except SerialException as e:
|
|
234
235
|
self._logger.error("Failed to read the line in serial: "+str(e))
|
|
@@ -305,7 +306,7 @@ class Serial:
|
|
|
305
306
|
def _process_commands(self):
|
|
306
307
|
buffer = ""
|
|
307
308
|
reading_json = False
|
|
308
|
-
currentIdentifier =
|
|
309
|
+
currentIdentifier = 0
|
|
309
310
|
nLineCountTimeout = 50 # maximum number of lines read before timeout
|
|
310
311
|
lineCounter = 0
|
|
311
312
|
nFailedCommands = 0
|
|
@@ -339,19 +340,20 @@ class Serial:
|
|
|
339
340
|
line = ""
|
|
340
341
|
|
|
341
342
|
# if we have a problem with the serial connection, we need to reconnect
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
self.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
343
|
+
if nFailedCommands>5:
|
|
344
|
+
for i in range(4):
|
|
345
|
+
nFailedCommands=0
|
|
346
|
+
if self.reconnect():
|
|
347
|
+
self._logger.debug("Reconnected to the serial device")
|
|
348
|
+
break
|
|
349
|
+
else:
|
|
350
|
+
self._logger.debug("Failed to reconnect to the serial device")
|
|
351
|
+
time.sleep(1)
|
|
350
352
|
|
|
351
353
|
if line == "++":
|
|
352
354
|
reading_json = True
|
|
353
355
|
continue
|
|
354
|
-
elif line.find("error") != -1:
|
|
356
|
+
elif line.find("error") != -1 and currentIdentifier is not None:
|
|
355
357
|
# if we have an error, we need to reset the last command
|
|
356
358
|
self._logger.debug("Error - last command did not match the firmware: "+str(self.commands[currentIdentifier]))
|
|
357
359
|
self.resetLastCommand = True
|
|
@@ -365,7 +367,7 @@ class Serial:
|
|
|
365
367
|
reading_json = False
|
|
366
368
|
try:
|
|
367
369
|
json_response = json.loads(buffer)
|
|
368
|
-
self._logger.debug("[ProcessCommands]: "+str(json_response))
|
|
370
|
+
if self.DEBUG: self._logger.debug("[ProcessCommands]: "+str(json_response))
|
|
369
371
|
if len(self.callBackList) > 0:
|
|
370
372
|
for callback in self.callBackList:
|
|
371
373
|
# check if json has key
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class config(object):
|
|
5
|
-
def __init__(self, parent, configFilePath=None):
|
|
6
|
-
self._parent = parent
|
|
7
|
-
self.configFilePath = configFilePath
|
|
8
|
-
|
|
9
|
-
if self.configFilePath is not None:
|
|
10
|
-
self.configFilePath = "./config.json"
|
|
11
|
-
#TODO: read file and load
|
|
12
|
-
|
|
13
|
-
self.configFile = self.loadDefaultConfig()
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'''
|
|
17
|
-
default Configuration
|
|
18
|
-
'''
|
|
19
|
-
|
|
20
|
-
def loadDefaultConfig(self):
|
|
21
|
-
self.defaultConfig = {"motorconfig":
|
|
22
|
-
[{"stepperid": 0, "dir": 18, "step": 19, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000},
|
|
23
|
-
{"stepperid": 1, "dir": 16, "step": 26, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000},
|
|
24
|
-
{"stepperid": 2, "dir": 27, "step": 25, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000},
|
|
25
|
-
{"stepperid": 3, "dir": 14, "step": 17, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000}],
|
|
26
|
-
"ledconfig": {"ledArrNum": 0, "ledArrPin": 0, "LEDArrMode": [0, 1, 2, 3, 4, 5, 6, 7], "led_ison": False},
|
|
27
|
-
"stateconfig": {"identifier_name": "UC2_Feather", "identifier_id": "V1.2", "identifier_date": "Nov 7 202212:52:14", "identifier_author": "BD", "IDENTIFIER_NAME": ""},
|
|
28
|
-
"laserconfig": {"LASER1pin": 0, "LASER2pin": 0, "LASER3pin": 0}}
|
|
29
|
-
return self.defaultConfig
|
|
30
|
-
|
|
31
|
-
def setDefaultConfig(self, configDict=None, configFile=None):
|
|
32
|
-
if configDict is not None:
|
|
33
|
-
self.defaultConfig = configDict
|
|
34
|
-
if configFile is not None:
|
|
35
|
-
self.defaultConfig = self.json2dict(configFile)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def checkIfInitializedConfig(self, currentConfig, defaultConfig):
|
|
39
|
-
''' This should check if the different components were initialized with the config file
|
|
40
|
-
Otherwise we won't be able to retrieve any signals from the device
|
|
41
|
-
'''
|
|
42
|
-
# TODO: Not implemented yet!
|
|
43
|
-
if currentConfig['motorconfig'] == defaultConfig['motorconfig']:
|
|
44
|
-
print("motorconfig not initialized")
|
|
45
|
-
return False
|
|
46
|
-
|
|
47
|
-
def json2dict(self, jsonFile):
|
|
48
|
-
with open(jsonFile) as f:
|
|
49
|
-
data = json.load(f)
|
|
50
|
-
return data
|
|
51
|
-
|
|
52
|
-
def checkConfig(self, configfile):
|
|
53
|
-
# check if config is valid
|
|
54
|
-
if type(configfile['motorconfig'])==list and len(configfile['motorconfig'])==4:
|
|
55
|
-
print("loaded config is valid")
|
|
56
|
-
return True
|
|
57
|
-
else:
|
|
58
|
-
print("config is not valid")
|
|
59
|
-
return False
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'''
|
|
63
|
-
send configuration to device
|
|
64
|
-
'''
|
|
65
|
-
|
|
66
|
-
'''################################################################################################################################################
|
|
67
|
-
Set Configurations
|
|
68
|
-
################################################################################################################################################'''
|
|
69
|
-
|
|
70
|
-
def loadConfigDevice(self, timeout=1):
|
|
71
|
-
# load current configuration from device
|
|
72
|
-
if 0:
|
|
73
|
-
path = '/config_get'
|
|
74
|
-
payload = {
|
|
75
|
-
}
|
|
76
|
-
r = self._parent.post_json(path, payload, timeout=timeout)
|
|
77
|
-
|
|
78
|
-
if type(r) != dict:
|
|
79
|
-
r = self.loadDefaultConfig()
|
|
80
|
-
else:
|
|
81
|
-
self.setDefaultConfig(r)
|
|
82
|
-
return r
|
|
83
|
-
|
|
84
|
-
else:
|
|
85
|
-
motorconfig = self._parent.motor.get_motors()
|
|
86
|
-
ledconfig = self._parent.led.get_ledpin()
|
|
87
|
-
laserconfig = self._parent.laser.get_laserpins()
|
|
88
|
-
stateconfig = self._parent.state.get_state()
|
|
89
|
-
self.configfile = {"motorconfig": motorconfig,
|
|
90
|
-
"ledconfig": ledconfig,
|
|
91
|
-
"laserconfig": laserconfig,
|
|
92
|
-
"stateconfig": stateconfig}
|
|
93
|
-
|
|
94
|
-
# check if config is valid
|
|
95
|
-
isValidConfig = self.checkConfig(self.configfile)
|
|
96
|
-
|
|
97
|
-
if isValidConfig:
|
|
98
|
-
return self.configfile
|
|
99
|
-
else:
|
|
100
|
-
return self.loadDefaultConfig()
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def setConfigDevice(self, configfile, timeout=1):
|
|
105
|
-
# push changes back to device
|
|
106
|
-
if 0:
|
|
107
|
-
path = '/config_set'
|
|
108
|
-
if type(configfile)==dict:
|
|
109
|
-
payload = configfile
|
|
110
|
-
else:
|
|
111
|
-
return None
|
|
112
|
-
r = self._parent.post_json(path, payload, timeout=timeout)
|
|
113
|
-
return r
|
|
114
|
-
else:
|
|
115
|
-
# set all lasers
|
|
116
|
-
notAllowedPins = (1,2,3,5)
|
|
117
|
-
if configfile["laserconfig"]["LASER1pin"] in notAllowedPins:
|
|
118
|
-
self._parent.laser.set_laserpin(1, configfile["laserconfig"]["LASER1pin"])
|
|
119
|
-
if configfile["laserconfig"]["LASER2pin"] in notAllowedPins:
|
|
120
|
-
self._parent.laser.set_laserpin(2, configfile["laserconfig"]["LASER2pin"])
|
|
121
|
-
if configfile["laserconfig"]["LASER3pin"] in notAllowedPins:
|
|
122
|
-
self._parent.laser.set_laserpin(3, configfile["laserconfig"]["LASER3pin"])
|
|
123
|
-
self._parent.laser.set_laserpin(laserid=1, laserpin=configfile["laserconfig"]["LASER1pin"])
|
|
124
|
-
self._parent.laser.set_laserpin(laserid=2, laserpin=configfile["laserconfig"]["LASER2pin"])
|
|
125
|
-
self._parent.laser.set_laserpin(laserid=3, laserpin=configfile["laserconfig"]["LASER3pin"])
|
|
126
|
-
|
|
127
|
-
# set led
|
|
128
|
-
if configfile["ledconfig"]["ledArrPin"] in notAllowedPins:
|
|
129
|
-
self._parent.led.set_ledpin(ledArrPin=configfile["ledconfig"]["ledArrPin"], ledArrNum=configfile["ledconfig"]["ledArrNum"])
|
|
130
|
-
self._parent.led.set_ledpin(ledArrPin=configfile["ledconfig"]["ledArrPin"], ledArrNum=configfile["ledconfig"]["ledArrNum"])
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# set motors
|
|
134
|
-
if configfile["motorconfig"][0]["dir"] in notAllowedPins:
|
|
135
|
-
configfile["motorconfig"][0]["dir"] = 0
|
|
136
|
-
if configfile["motorconfig"][0]["step"] in notAllowedPins:
|
|
137
|
-
configfile["motorconfig"][0]["step"] = 0
|
|
138
|
-
if configfile["motorconfig"][1]["dir"] in notAllowedPins:
|
|
139
|
-
configfile["motorconfig"][1]["dir"] = 0
|
|
140
|
-
if configfile["motorconfig"][1]["step"] in notAllowedPins:
|
|
141
|
-
configfile["motorconfig"][1]["step"] = 0
|
|
142
|
-
if configfile["motorconfig"][2]["dir"] in notAllowedPins:
|
|
143
|
-
configfile["motorconfig"][2]["dir"] = 0
|
|
144
|
-
if configfile["motorconfig"][2]["step"] in notAllowedPins:
|
|
145
|
-
configfile["motorconfig"][2]["step"] = 0
|
|
146
|
-
if configfile["motorconfig"][3]["dir"] in notAllowedPins:
|
|
147
|
-
configfile["motorconfig"][3]["dir"] = 0
|
|
148
|
-
if configfile["motorconfig"][3]["step"] in notAllowedPins:
|
|
149
|
-
configfile["motorconfig"][3]["step"] = 0
|
|
150
|
-
if configfile["motorconfig"][0]["enable"] in notAllowedPins:
|
|
151
|
-
configfile["motorconfig"][0]["enable"] = 0
|
|
152
|
-
configfile["motorconfig"][1]["enable"] = 0
|
|
153
|
-
configfile["motorconfig"][2]["enable"] = 0
|
|
154
|
-
configfile["motorconfig"][3]["enable"] = 0
|
|
155
|
-
|
|
156
|
-
motorconfig = {
|
|
157
|
-
"motor":{
|
|
158
|
-
"steppers":
|
|
159
|
-
configfile["motorconfig"]}}
|
|
160
|
-
# check if pins are valid
|
|
161
|
-
|
|
162
|
-
self._parent.motor.set_motors(settingsdict=motorconfig)
|
|
163
|
-
|
|
164
|
-
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class config(object):
|
|
5
|
-
def __init__(self, parent, configFilePath=None):
|
|
6
|
-
self._parent = parent
|
|
7
|
-
self.configFilePath = configFilePath
|
|
8
|
-
|
|
9
|
-
if self.configFilePath is not None:
|
|
10
|
-
self.configFilePath = "./config.json"
|
|
11
|
-
#TODO: read file and load
|
|
12
|
-
|
|
13
|
-
self.configFile = self.loadDefaultConfig()
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'''
|
|
17
|
-
default Configuration
|
|
18
|
-
'''
|
|
19
|
-
|
|
20
|
-
def loadDefaultConfig(self):
|
|
21
|
-
self.defaultConfig = {"motorconfig":
|
|
22
|
-
[{"stepperid": 0, "dir": 18, "step": 19, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000},
|
|
23
|
-
{"stepperid": 1, "dir": 16, "step": 26, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000},
|
|
24
|
-
{"stepperid": 2, "dir": 27, "step": 25, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000},
|
|
25
|
-
{"stepperid": 3, "dir": 14, "step": 17, "enable": 12, "dir_inverted": False, "step_inverted": False, "enable_inverted": False, "speed": 0, "speedmax": 200000, "max_pos": 100000, "min_pos": -100000}],
|
|
26
|
-
"ledconfig": {"ledArrNum": 0, "ledArrPin": 0, "LEDArrMode": [0, 1, 2, 3, 4, 5, 6, 7], "led_ison": False},
|
|
27
|
-
"stateconfig": {"identifier_name": "UC2_Feather", "identifier_id": "V1.2", "identifier_date": "Nov 7 202212:52:14", "identifier_author": "BD", "IDENTIFIER_NAME": ""}}
|
|
28
|
-
return self.defaultConfig
|
|
29
|
-
|
|
30
|
-
def setDefaultConfig(self, configDict=None, configFile=None):
|
|
31
|
-
if configDict is not None:
|
|
32
|
-
self.defaultConfig = configDict
|
|
33
|
-
if configFile is not None:
|
|
34
|
-
self.defaultConfig = self.json2dict(configFile)
|
|
35
|
-
|
|
36
|
-
# importing the module
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def json2dict(self, jsonFile):
|
|
40
|
-
with open(jsonFile) as f:
|
|
41
|
-
data = json.load(f)
|
|
42
|
-
return data
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
'''
|
|
46
|
-
send configuration to device
|
|
47
|
-
'''
|
|
48
|
-
|
|
49
|
-
'''################################################################################################################################################
|
|
50
|
-
Set Configurations
|
|
51
|
-
################################################################################################################################################'''
|
|
52
|
-
|
|
53
|
-
def loadConfigDevice(self, timeout=1):
|
|
54
|
-
# load current configuration from device
|
|
55
|
-
if 0:
|
|
56
|
-
path = '/config_get'
|
|
57
|
-
payload = {
|
|
58
|
-
}
|
|
59
|
-
r = self._parent.post_json(path, payload, timeout=timeout)
|
|
60
|
-
|
|
61
|
-
self.setDefaultConfig(r)
|
|
62
|
-
|
|
63
|
-
if type(r) != dict:
|
|
64
|
-
r = self.loadDefaultConfig()
|
|
65
|
-
return r
|
|
66
|
-
|
|
67
|
-
else:
|
|
68
|
-
motorconfig = self._parent.motor.get_motors()
|
|
69
|
-
ledconfig = self._parent.led.get_ledpin()
|
|
70
|
-
laserconfig = self._parent.laser.get_laserpins()
|
|
71
|
-
stateconfig = self._parent.state.get_state()
|
|
72
|
-
self.configfile = {"motorconfig": motorconfig,
|
|
73
|
-
"ledconfig": ledconfig,
|
|
74
|
-
"laserconfig": laserconfig,
|
|
75
|
-
"stateconfig": stateconfig}
|
|
76
|
-
return self.configfile
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def setConfigDevice(self, configfile, timeout=1):
|
|
80
|
-
# push changes back to device
|
|
81
|
-
if 0:
|
|
82
|
-
path = '/config_set'
|
|
83
|
-
if type(configfile)==dict:
|
|
84
|
-
payload = configfile
|
|
85
|
-
else:
|
|
86
|
-
return None
|
|
87
|
-
r = self._parent.post_json(path, payload, timeout=timeout)
|
|
88
|
-
return r
|
|
89
|
-
else:
|
|
90
|
-
# set all lasers
|
|
91
|
-
self._parent.laser.set_laserpin(laserid=1, laserpin=configfile["laserconfig"]["LASER1pin"])
|
|
92
|
-
self._parent.laser.set_laserpin(laserid=2, laserpin=configfile["laserconfig"]["LASER2pin"])
|
|
93
|
-
self._parent.laser.set_laserpin(laserid=3, laserpin=configfile["laserconfig"]["LASER3pin"])
|
|
94
|
-
# set led
|
|
95
|
-
self._parent.led.set_ledpin(ledArrPin=configfile["ledconfig"]["ledArrPin"], ledArrNum=configfile["ledconfig"]["ledArrNum"])
|
|
96
|
-
# set motors
|
|
97
|
-
|
|
98
|
-
motorconfig = {
|
|
99
|
-
"motor":{
|
|
100
|
-
"steppers":
|
|
101
|
-
configfile["motorconfig"]}}
|
|
102
|
-
self._parent.motor.set_motors(settingsdict=motorconfig)
|
|
103
|
-
|
|
104
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|