-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtmcl.py
More file actions
99 lines (80 loc) · 2.63 KB
/
tmcl.py
File metadata and controls
99 lines (80 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import struct
# Status code to string mapping
status_string = {
100: "Successfully executed, no error",
101: "Command loaded into TMCL program EEPROM",
1: "Wrong checksum",
2: "Invalid command",
3: "Wrong type",
4: "Invalid value",
5: "Configuration EEPROM locked",
6: "Command not available"
}
class TMCLError(Exception):
pass
def _calculate_checksum(data):
""" Calculate checksum.
Input: Bytes object
Output: Integer
"""
return (sum(b for b in data))%256
def send_command(handle, address, command, type, motor, value):
""" Send a command to a Trinamic controller.
handle is a file or stream object, basically anything that
implements write and read methods.
"""
data=struct.pack('>BBBBi', address, command, type, motor, value)
data+=struct.pack('>B',_calculate_checksum(data))
handle.write(data)
def get_result(handle):
""" Read a result from a Trinamic controller.
handle is a file or stream object, basically anything that
implements write and read methods.
Returns a tuple with controller address, status code and
value.
Raises TMCLError with appropriate error message on error.
"""
data=handle.read(9)
address,module,status,command,value,checksum=struct.unpack('>BBBBiB', data)
if not checksum==_calculate_checksum(data[:-1]):
# Checksum error
raise TMCLError(status_string[1])
if not status==100:
# Error from motor controller
raise TMCLError(
'Error {}: {}'.format(
status, status_string.get(status,'Unknown error')
))
return address, value
class TMCL:
def __init__(self, address=1, port=None):
self.address=address
self.port=port
def send(self, instruction, type, motor, value):
values=[int(x) for x in
[self.address, instruction, type, motor, value]
]
send_command(self.port, *values)
return get_result(self.port)
if __name__=='__main__':
import sys
import serial
def print_usage():
print('Usage: {} <instruction> <type> <motor> <value> <port>'.format(sys.argv[0]))
if not len(sys.argv) == 6:
print_usage()
sys.exit(-1)
port=serial.Serial(sys.argv[5], 9600)
try:
port.open()
except OSError as e:
print('Error opening serial port: '+str(e))
sys.exit(-1)
address=1
instruction=int(sys.argv[1])
type=int(sys.argv[2])
motor=int(sys.argv[3])
value=int(sys.argv[4])
send_command(port, address, instruction, type, motor, value)
result=get_result(port)
print('Result: '+str(result))