Motoron Motor Controller library for Raspberry Pi
Loading...
Searching...
No Matches
serial_setup_example.py
1#!/usr/bin/env python3
2
3# This example code provides an interactive utility you can use to set the
4# device number, baud rate, and all the other settings in the EEPROM of a
5# a Motoron with a UART serial interface.
6#
7# For this code to work the Motoron must be wired properly to your
8# computer so it can receive serial commands. It must also be operating
9# at a known baud rate, and the baud rate must be one that your serial
10# hardware can generate accurately. If you are not sure what baud
11# rate your Motoron is using or whether your hardware can generate it
12# accurately, you can short JMP1 to GND and then power cycle or reset the
13# Motoron to ensure it uses 9600 baud.
14
15help_message = """
16Command | Summary
17-----------------|----------------------------------------------------------
18a [NUM] [ALTNUM] | Write all settings to EEPROM (JMP1 must be low).
19r | Reset devices.
20i | Identify devices.
21b BAUD | Use a different baud rate to communicate.
22o [OPTS] | Use different communication options.
23n | Use 115200 baud, 8-bit responses, 7-bit device number.
24j | Use 9600 baud, 8-bit responses, 7-bit device number.
25k | Use the options & baud rate we're assigning to devices.
26
27For more information about each command, see the comments in the
28source code.
29"""
30
31start_message = """
32Motoron Serial Setup Utility
33
34Type "h" for help.
35"""
36
37import readline
38import sys
39import time
40import serial
41import motoron
42
43# The serial parameters below are assigned to a device when you use the "a"
44# command. You can modify these lines to assign different parameters.
45assign_baud_rate = 115200
46assign_7bit_responses = False
47assign_14bit_device_number = False
48assign_err_is_de = False
49assign_response_delay = 0
50
51if assign_baud_rate < motoron.MIN_BAUD_RATE or \
52 assign_baud_rate > motoron.MAX_BAUD_RATE:
53 raise RuntimeError("Invalid baud rate.")
54
55assign_communication_options = \
56 (assign_7bit_responses << motoron.COMMUNICATION_OPTION_7BIT_RESPONSES) | \
57 (assign_14bit_device_number << motoron.COMMUNICATION_OPTION_14BIT_DEVICE_NUMBER) | \
58 (assign_err_is_de << motoron.COMMUNICATION_OPTION_ERR_IS_DE)
59
60port = serial.Serial("/dev/serial0", 115200, timeout=0.01, write_timeout=0.1)
61
62mc = motoron.MotoronSerial(port=port)
63
64last_device_number = 16
65
66# Command syntax: a [NUM] [ALTNUM]
67#
68# This command sends a series of "Write EEPROM" commands using the
69# compact protocol to set all the settings in Motoron's EEPROM.
70# For this command to work, the Motoron must be using the same baud rate as
71# the Arduino and the Motoron's JMP1 line must be low.
72#
73# NUM should be the desired device number for the Motoron.
74# If NUM is omitted or equal to "-1", the program will automatically pick a
75# device number.
76#
77# ALTNUM should be the desired *alternative* device number for the Motoron.
78# If ALTNUM is omitted or equal to "-1", the feature is disabled.
79#
80# The other settings are set according to the constants above
81# (e.g. assignBaudRate).
82#
83# Settings written to the Motoron's EEPROM do not have an immediate affect,
84# but you can use the "r" command to reset the Motoron and make the new
85# settings take effect.
86#
87# Examples:
88# a
89# a 17
90# a -1 0
91# a 0x123 0x456
92def assign_all_settings(line):
93 global last_device_number
94 max_device_number = 0x3FFF if assign_14bit_device_number else 0x7F
95
96 device_number = -1
97 alt_device_number = -1
98
99 parts = line[1:].split()
100 if len(parts) >= 1:
101 try:
102 device_number = int(parts[0])
103 except ValueError:
104 print("Invalid device number argument.")
105 return
106 if len(parts) >= 2:
107 try:
108 alt_device_number = int(parts[1])
109 except ValueError:
110 print("Invalid alternative device number argument.")
111 return
112
113 if device_number == -1:
114 # The user did not specify a device number, so pick one.
115 device_number = (last_device_number + 1) & max_device_number
116
117 if not device_number in range(0, max_device_number + 1):
118 print("Invalid device number.")
119 return
120
121 if not alt_device_number in range(-1, max_device_number + 1):
122 print("Invalid alternative device number.")
123 return
124
125 mc.enable_crc()
126 mc.write_eeprom_device_number(device_number)
127 if alt_device_number == -1:
128 mc.write_eeprom_disable_alternative_device_number()
129 else:
130 mc.write_eeprom_alternative_device_number(alt_device_number)
131 mc.write_eeprom_baud_rate(assign_baud_rate)
132 mc.write_eeprom_communication_options(assign_communication_options)
133 mc.write_eeprom_response_delay(assign_response_delay)
134
135 print("Assigned device number", device_number, end='')
136
137 if alt_device_number != -1:
138 print(" and", alt_device_number, end='')
139 print(",", assign_baud_rate, "baud", end='')
140
141 if assign_14bit_device_number:
142 print(", 14-bit device number", end='')
143 else:
144 print(", 7-bit device number", end='')
145
146 if assign_7bit_responses:
147 print(", 7-bit responses", end='')
148 else:
149 print(", 8-bit responses", end='')
150
151 if assign_err_is_de:
152 print(", ERR is DE", end='')
153 else:
154 print(", ERR is normal", end='')
155
156 print(".")
157
158 last_device_number = device_number
159
160def print_communication_settings():
161 print(port.baudrate, 'baud', end='')
162 if mc.communication_options & (1 << motoron.COMMUNICATION_OPTION_14BIT_DEVICE_NUMBER):
163 print(', 14-bit device number', end='')
164 else:
165 print(', 7-bit device number', end='')
166 if mc.communication_options & (1 << motoron.COMMUNICATION_OPTION_7BIT_RESPONSES):
167 print(', 7-bit responses', end='')
168 else:
169 print(', 8-bit responses', end='')
170
171def print_communication_settings_line():
172 print("Using ", end='')
173 print_communication_settings();
174 print(".")
175
176def print_device_info_if_possible():
177 firmware = mc.get_firmware_version()
178 product_id = firmware['product_id']
179 firmware_version = firmware['firmware_version']
180
181 jumper_state = mc.get_jumper_state() & 3
182 if jumper_state == 0b10: jumper_string = 'off'
183 elif jumper_state == 0b01: jumper_string = 'on'
184 else: jumper_string = 'err'
185
186 # We fetch EEPROM with two requests because the maximum payload size in
187 # 7-bit response mode is 7 bytes.
188 eeprom = mc.read_eeprom(1, 4) + mc.read_eeprom(5, 4)
189
190 print("%3d: product=0x%04X version=%x.%02x JMP1=%s EEPROM=%s" % (
191 mc.device_number, product_id,
192 firmware_version['major'], firmware_version['minor'], jumper_string,
193 ' '.join(('%02X' % b for b in eeprom))))
194
195# Command syntax: i
196#
197# This command tries to communicate with every possible device number using
198# the current communication settings and the Pololu protocol. If it finds a
199# Motoron it prints out some information about it.
200#
201# Note: When using 14-bit device numbers, this command might take several minutes.
202def identify_devices():
203 if mc.communication_options & (1 << motoron.COMMUNICATION_OPTION_14BIT_DEVICE_NUMBER):
204 max_device_number = 0x3FFF
205 else:
206 max_device_number = 0x7F
207
208 print("Identifying Motoron controllers (", end='')
209 print_communication_settings()
210 print(")...")
211 for i in range(max_device_number + 1):
212 port.reset_input_buffer()
213 mc.device_number = i
214 try:
215 mc.enable_crc()
216 print_device_info_if_possible()
217 except RuntimeError:
218 pass
219 print("Done.")
220 mc.device_number = None
221
222# Command syntax: b BAUD
223#
224# This command configures the Arduino to use a different baud rate when
225# communicating with the Motoron.
226#
227# Example: b 38600
228def command_set_baud_rate(line):
229 try:
230 baud_rate = int(line[1:])
231 except ValueError:
232 print("Invalid baud rate.")
233 return
234 if baud_rate < motoron.MIN_BAUD_RATE or baud_rate > motoron.MAX_BAUD_RATE:
235 print("Invalid baud rate.")
236 return
237 print(baud_rate)
238 port.baudrate = baud_rate
239 print_communication_settings_line()
240
241# Command syntax: o [OPTS]
242#
243# This command configures the Arduino to use different serial options when
244# communicating with the Motoron.
245#
246# If OPTS is omitted, this command cycles through the four different possible
247# sets of serial options.
248#
249# Otherwise, OPTS should be a number between 0 and 3:
250# 0 = 8-bit responses, 7-bit device numbers
251# 1 = 7-bit responses, 7-bit device numbers
252# 2 = 8-bit responses, 14-bit device numbers
253# 3 = 7-bit responses, 14-bit device numbers
254def command_set_communication_options(line):
255 try:
256 mc.communication_options = int(line[1:])
257 except ValueError:
258 mc.communication_options = (mc.communication_options + 1) & 3
259 pass
260 print_communication_settings_line()
261
262def process_command(line):
263 if not line: return
264 elif line[0] == 'a': assign_all_settings(line)
265 elif line[0] == 'r':
266 print("Reset")
267 mc.reset()
268 elif line[0] == 'i': identify_devices()
269 elif line[0] == 'b': command_set_baud_rate(line)
270 elif line[0] == 'o': command_set_communication_options(line)
271 elif line[0] == 'n':
272 port.baudrate = 115200
273 mc.communication_options = 0
274 print_communication_settings_line()
275 elif line[0] == 'j':
276 port.baudrate = 9600
277 mc.communication_options = 0
278 print_communication_settings_line()
279 elif line[0] == 'k':
280 port.baudrate = assign_baud_rate
281 mc.communication_options = assign_communication_options
282 print_communication_settings_line()
283 elif line[0] == 'h' or line[0] == 'H' or line[0] == '?': print(help_message)
284 elif line == 'q' or line == 'quit': sys.exit(0)
285 else: print("Error: Unreocgnized command. Type h for help.")
286
287print(start_message)
288try:
289 while True:
290 process_command(input("Enter command: "))
291except (KeyboardInterrupt, EOFError):
292 print()
293
Represents a serial connection to a Pololu Motoron Motor Controller.
Definition: motoron.py:1761