Skip to content

Commit 96033d5

Browse files
committed
added error codes for PosConCM
1 parent 4d0c93b commit 96033d5

File tree

1 file changed

+75
-27
lines changed

1 file changed

+75
-27
lines changed

src/compas_fab/sensors/baumer.py

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,6 @@
44
from compas_fab.sensors.exceptions import ProtocolError
55
from compas_fab.sensors.exceptions import SensorTimeoutError
66

7-
ERROR_CODES = {
8-
'000': 'No error',
9-
'001': 'False checksum',
10-
'002': 'False command',
11-
'003': 'False frame',
12-
'004': 'False value or parameter',
13-
'005': 'Missed command 000 to begin RS-485 control',
14-
'006': 'Out of range',
15-
'007': 'Buffer overflow',
16-
'010': 'All outputs Off',
17-
'020': 'Display Off',
18-
'99': 'Argument out of Range',
19-
'100': 'Distance out of Range (see FSP)',
20-
'101': 'Angle out of Range (see FSP)',
21-
'102': 'Flatness out of Range (see FSP)',
22-
'103': 'Length out of Range (see FSP)',
23-
'200': 'Fatal Error (Reset sensor, Power Off / On)'
24-
}
25-
267
__all__ = ['PosCon3D', 'PosConCM']
278

289
class PosCon3D(SerialSensor):
@@ -71,20 +52,39 @@ class is a context manager type, so it's best used in combination
7152
1: 'Low signal',
7253
2: 'No edge',
7354
3: 'Low signal, no edge',
74-
4: 'No signal'
75-
}
55+
4: 'No signal'}
56+
ERROR_CODES = {
57+
'000': 'No error',
58+
'001': 'False checksum',
59+
'002': 'False command',
60+
'003': 'False frame',
61+
'004': 'False value or parameter',
62+
'005': 'Missed command 000 to begin RS-485 control',
63+
'006': 'Out of range',
64+
'007': 'Buffer overflow',
65+
'010': 'All outputs Off',
66+
'020': 'Display Off',
67+
'99': 'Argument out of Range',
68+
'100': 'Distance out of Range (see FSP)',
69+
'101': 'Angle out of Range (see FSP)',
70+
'102': 'Flatness out of Range (see FSP)',
71+
'103': 'Length out of Range (see FSP)',
72+
'200': 'Fatal Error (Reset sensor, Power Off / On)'}
7673

7774
def __init__(self, serial, address):
7875
super(PosCon3D, self).__init__(serial)
7976
self.address = address
8077

78+
8179
def __enter__(self):
8280
self.begin()
8381
return self
8482

83+
8584
def __exit__(self, *args):
8685
self.end()
8786

87+
8888
def begin(self):
8989
"""Locks the sensor to start RS-485 communication.
9090
@@ -95,6 +95,7 @@ def begin(self):
9595
"""
9696
return self.send_command(self.address, '000', '1')
9797

98+
9899
def end(self):
99100
"""Unlocks the sensor from RS-485 communication.
100101
@@ -105,6 +106,7 @@ def end(self):
105106
"""
106107
return self.send_command(self.address, '000', '0')
107108

109+
108110
def send_command(self, address, command, data=None):
109111
"""Sends a command to the sensor's address specified. The command
110112
can optionally contain a data string.
@@ -156,12 +158,14 @@ def send_command(self, address, command, data=None):
156158

157159
return None
158160

161+
159162
def format_command(self, address, command, data=None):
160163
"""Formats the command."""
161164
data = data + ',' if data else ''
162165
frame = self.FRAME_HEAD % (address, command, data)
163166
return self.FRAME_TAIL % (frame, self.calculate_checksum(frame))
164167

168+
165169
def calculate_checksum(self, command):
166170
"""Checks that message is complete."""
167171
code_points = [ord(c) for c in list(command)]
@@ -171,6 +175,7 @@ def calculate_checksum(self, command):
171175

172176
return str(checksum).zfill(3)
173177

178+
174179
def get_payload(self, result):
175180
"""Gets payload."""
176181
data = result.split(',')[2:-1]
@@ -180,10 +185,11 @@ def get_payload(self, result):
180185
return data[0]
181186
else:
182187
if data[0] == 'E':
183-
raise ProtocolError(ERROR_CODES[str(data[1])])
188+
raise ProtocolError(self.ERROR_CODES[str(data[1])])
184189

185190
return data
186191

192+
187193
def get_address(self):
188194
"""Gets the address of the RS-485 sensors currently connected to the bus. This command
189195
is only really useful when this class is initialized with the broadcast address,
@@ -200,6 +206,7 @@ def get_address(self):
200206
"""
201207
return int(self.send_command(self.address, '013'))
202208

209+
203210
def set_measurement_type(self, measurement_type):
204211
"""Defines the measurement type to use.
205212
@@ -227,6 +234,7 @@ def set_measurement_type(self, measurement_type):
227234

228235
return self.send_command(self.address, '020', str(self.MEASUREMENT_TYPES.index(measurement_type)))
229236

237+
230238
def set_precision(self, precision):
231239
"""Defines the precision the sensor will use to determine edges:
232240
@@ -251,6 +259,7 @@ def set_precision(self, precision):
251259
raise ProtocolError('Precision must be 0 (standard), 1 (high) or 2 (very high)')
252260
return self.send_command(self.address, '040', str(precision))
253261

262+
254263
def set_edge_height(self, height):
255264
"""Defines the minimum height of an edge to be detected.
256265
@@ -261,6 +270,7 @@ def set_edge_height(self, height):
261270
"""
262271
return self.send_command(self.address, '042', str(height))
263272

273+
264274
def get_measurement(self):
265275
"""Retrieves the current measurement of the sensor according to the current settings.
266276
@@ -283,6 +293,7 @@ def get_measurement(self):
283293

284294
return (value, self.QUALITY[quality])
285295

296+
286297
def get_live_monitor_data(self):
287298
"""Retrieves the distance to the surface in the center of the laser beam and the
288299
angle at which it's found.
@@ -302,26 +313,31 @@ def get_live_monitor_data(self):
302313

303314
return map(float, result)
304315

316+
305317
def reset(self):
306318
"""Resets the sensor to factory settings."""
307319
self.send_command(self.address, '003')
308320

321+
309322
def activate_flex_mount(self, reference_thickness):
310323
"""Activates the FLEX Mount feature of the sensor to allow positioning it on an
311324
angled installation. The reference thickness is only required if the surface is
312325
uneven and an additional leveling auxiliary plate as been added."""
313326
result = self.send_command(self.address, '062', str(reference_thickness))
314327
return map(float, result)
315328

329+
316330
def deactivate_flex_mount(self):
317331
"""Deactivates the FLEX Mount feature."""
318332
self.send_command(self.address, '063')
319333

334+
320335
def set_flex_mount(self, angle, distance):
321336
"""Sets the FLEX Mount feature to a specific angle and distance."""
322337
result = self.send_command(self.address, '060', '%.2f,%.2f' % (angle, distance))
323338
return map(float, result)
324339

340+
325341
def adjust_to_dark_object(self, is_dark_object):
326342
"""Adjusts the sensor to detect darker or lighter surfaces."""
327343
data = '1' if is_dark_object else '0'
@@ -374,27 +390,41 @@ class provides access to the serial interface (RS-485).
374390
'Z_center' : 30,
375391
'X_left' : 31,
376392
'X_right' : 32,
377-
'Z_top' : 33
378-
}
393+
'Z_top' : 33}
379394
QUALITY = {
380395
0: 'Valid',
381396
1: 'Low signal',
382397
2: 'No edge',
383398
3: 'Low signal, no edge',
384-
4: 'No signal'
385-
}
399+
4: 'No signal'}
400+
ERROR_CODES = {
401+
'1': 'Wrong message type',
402+
'2': 'Wrong payload format',
403+
'3': 'Wrong argument',
404+
'4': 'Wrong argument count',
405+
'5': 'Not enough data',
406+
'6': 'Index do not exist',
407+
'7': 'Index locked',
408+
'8': 'Access not allowed',
409+
'9': 'Not enough memory for encoding',
410+
'10': 'Not possible to encode argument',
411+
'11': 'Application specific error',
412+
'12': 'Wrong state'}
386413

387414
def __init__(self, serial, address):
388415
super(PosConCM, self).__init__(serial)
389416
self.address = address
390417

418+
391419
def __enter__(self):
392420
self.begin()
393421
return self
394422

423+
395424
def __exit__(self, *args):
396425
self.end()
397426

427+
398428
def begin(self):
399429
"""Locks the sensor to start RS-485 communication.
400430
@@ -405,6 +435,7 @@ def begin(self):
405435
"""
406436
return self.send_command(self.address, 'W010', '0')
407437

438+
408439
def end(self):
409440
"""Unlocks the sensor from RS-485 communication.
410441
@@ -415,12 +446,14 @@ def end(self):
415446
"""
416447
return self.send_command(self.address, 'W010', '1')
417448

449+
418450
def format_command(self, address, command, data=None):
419451
"""Formats the command."""
420452
data = data or ''
421453
frame = self.FRAME_HEAD % (str(address).zfill(2), command, data)
422454
return self.FRAME_TAIL % (frame, self.calculate_checksum(frame))
423455

456+
424457
def calculate_checksum(self, command):
425458
"""Checks that message is complete.
426459
@@ -430,22 +463,27 @@ def calculate_checksum(self, command):
430463
"""
431464
return '****'
432465

466+
433467
def get_payload(self, result):
434468
"""Gets payload."""
435469
frame_head = result[:-6]
436470
result_type = frame_head[3]
437471

472+
print(frame_head)
473+
438474
if result_type == 'a':
439475
raise SensorTimeoutError('Sensor has not completed reading')
440476

441477
if result_type == 'E':
442-
raise ProtocolError('Application error, Result=%s' % frame_head)
478+
error_index = frame_head.split(';')
479+
raise ProtocolError('Application error, Result=%s' % frame_head + 'Error type: ' + str(self.ERROR_CODES[str(error_index[1])]))
443480

444481
if result_type == 'B':
445482
raise ProtocolError('Sensor is busy, Result=%s' % frame_head)
446483

447484
return result[5:-6].split(';')
448485

486+
449487
def send_command(self, address, command, data=None):
450488
"""Sends a command to the sensor's address specified. The command
451489
can optionally contain a data string.
@@ -491,6 +529,7 @@ def send_command(self, address, command, data=None):
491529

492530
return None
493531

532+
494533
def get_address(self):
495534
"""Gets the address of the RS-485 sensors currently connected to the bus. This command
496535
is only really useful when this class is initialized with the broadcast address,
@@ -508,6 +547,7 @@ def get_address(self):
508547
result = self.send_command(self.address, 'R005')
509548
return int(result[0])
510549

550+
511551
def set_measurement_type(self, measurement_type):
512552
"""Defines the measurement type to use.
513553
@@ -532,6 +572,7 @@ def set_measurement_type(self, measurement_type):
532572

533573
return self.send_command(self.address, 'W020', str(self.MEASUREMENT_TYPES[measurement_type]))
534574

575+
535576
def set_precision(self, precision):
536577
"""Defines the precision the sensor will use to determine edges:
537578
@@ -556,6 +597,7 @@ def set_precision(self, precision):
556597
raise ProtocolError('Precision must be 0 (standard), 1 (high) or 2 (very high)')
557598
return self.send_command(self.address, 'W033', str(precision))
558599

600+
559601
def get_measurement(self):
560602
"""Retrieves the current measurement of the sensor according to the current settings.
561603
@@ -578,33 +620,39 @@ def get_measurement(self):
578620

579621
return (value, self.QUALITY[quality])
580622

623+
581624
def activate_flex_mount(self):
582625
"""Activates the FLEX Mount feature of the sensor to allow positioning it on an
583626
angled installation. The reference thickness is only required if the surface is
584627
uneven and an additional leveling auxiliary plate as been added."""
585628
result = self.send_command(self.address, 'W035', '1')
586629
return map(float, result)
587630

631+
588632
def deactivate_flex_mount(self):
589633
"""Deactivates the FLEX Mount feature."""
590634
result = self.send_command(self.address, 'W035', '0')
591635
return map(float, result)
592636

637+
593638
def set_flex_mount(self, angle, distance):
594639
"""Sets the FLEX Mount feature to a specific angle and distance."""
595640
data='{:.2f};{:.2f}'.format(angle, distance)
596641
return self.send_command(self.address, 'W036', data)
597642

643+
598644
def teach_flex_mount(self, reference_thickness):
599645
"""Sets the FLEX Mount feature to a specific angle and distance."""
600646
return self.send_command(self.address, 'W037', str(reference_thickness))
601647

648+
602649
def adjust_to_dark_object(self, is_dark_object):
603650
"""Adjusts the sensor to detect darker or lighter surfaces."""
604651
data = '1' if is_dark_object else '0'
605652
result = self.send_command(self.address, 'W032', data)
606653
return map(float, result)
607654

655+
608656
def reset(self):
609657
"""Resets the sensor to factory settings."""
610658
self.send_command(self.address, 'W202', '0')

0 commit comments

Comments
 (0)