1
2
3
4
5
6 import os
7 import unittest
8 import time
9 import logging
10
11 from pololu.motors import Qik2s9v1
12
13
14 BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
15 '..', '..', '..', 'logs'))
18 FORMAT = ("%(asctime)s %(levelname)s %(module)s %(funcName)s "
19 "[line:%(lineno)d] %(message)s")
20 logging.basicConfig(filename=fullpath, format=FORMAT, level=level)
21 return logging.getLogger()
22
25 """
26 Unit tests for the Qik 2s9v1 motor controller.
27
28 Most tests have a for loop which first tests the pololu protocol then tests
29 the compact protocol.
30 """
31 _DEFAULT_TTY = '/dev/ttyUSB0'
32 _PROTOCOL_MAP = {0: "Pololu Protocol", 1: "Compact Protocol"}
33
39
41 self._log.debug("Processing")
42 self._qik = Qik2s9v1(self._DEFAULT_TTY, readTimeout=5, log=self._log)
43
63
65 self._log.debug("Processing")
66
67 for device in self._qik._deviceConfig:
68 config = self._qik.getConfigForDevice(device)
69 self.assertTrue(config['version'] in (1, 2))
70 self.assertTrue(config['pwm'] == 0)
71 self.assertTrue(config['shutdown'] == 1)
72 self.assertTrue(config['timeout'] == 0)
73
75 self._log.debug("Processing")
76 self.assertTrue(self._qik.isOpen() == True)
77 self._qik.close()
78 self.assertTrue(self._qik.isOpen() == False)
79
88
97
103
104 @unittest.skip("Temporarily skipped")
106 self._log.debug("Processing")
107
108 @unittest.skip("Temporarily skipped")
110 self._log.debug("Processing")
111
112 @unittest.skip("Temporarily skipped")
114 self._log.debug("Processing")
115
135
137 self._log.debug("Processing")
138 timeout = 0.262
139 num = 128
140 error = self._qik._ERRORS.get(num)
141
142 for i in range(2):
143 protocol = self._PROTOCOL_MAP.get(i)
144 self._qik.setSerialTimeout(timeout)
145 time.sleep(0.275)
146 result = self._qik.getError(message=False)
147 msg = "{}: Invalid error '{}' should be '{}'.".format(
148 protocol, result, [num])
149 self.assertTrue(num in result and len(result) == 1, msg=msg)
150 self._qik.setSerialTimeout(timeout)
151 time.sleep(0.275)
152 result = self._qik.getError()
153 msg = "{}: Invalid error '{}' should be '{}'.".format(
154 protocol, result, [error])
155 self.assertTrue(error in result and len(result) == 1, msg=msg)
156 self._qik.setCompactProtocol()
157
159 """
160 Only test Pololu protocol, it's the only protocol that uses the device
161 ID.
162 """
163 protocol = self._PROTOCOL_MAP.get(0)
164 self._log.debug("Processing")
165 devices = (self._qik.DEFAULT_DEVICE_ID, 127)
166
167 result = self._qik.getDeviceID(device=devices[0])
168 msg = "Invalid device '{}' should be '{}'.".format(
169 protocol, result, devices[0])
170 self.assertTrue(result == devices[0], msg=msg)
171
172 self._qik.setDeviceID(devices[1], device=devices[0])
173 result = self._qik.getDeviceID(device=devices[1])
174 msg = "{}: Invalid device '{}' should be '{}'.".format(
175 protocol, result, devices[1])
176 self.assertTrue(result == devices[1], msg=msg)
177
179 self._log.debug("Processing")
180
181 for i in range(2):
182 protocol = self._PROTOCOL_MAP.get(i)
183 result = self._qik.getPWMFrequency()
184 msg = "{}: Invalid PWM frequency '{}' should be '{}'.".format(
185 protocol, result, self._qik._CONFIG_PWM.get(0)[1])
186 self.assertTrue(result == self._qik._CONFIG_PWM.get(0)[1], msg=msg)
187 result = self._qik.getPWMFrequency(message=False)
188 msg = "{}: Invalid PWM frequency '{}' should be '{}'.".format(
189 protocol, result, self._qik._CONFIG_PWM.get(0)[0])
190 self.assertTrue(result == self._qik._CONFIG_PWM.get(0)[0], msg=msg)
191 self._qik.setCompactProtocol()
192
194 self._log.debug("Processing")
195
196 for i in range(2):
197 protocol = self._PROTOCOL_MAP.get(i)
198 tf = self._qik.getMotorShutdown()
199 msg = ("{}: Invalid motor shutdown value '{}' should be '{}'."
200 ).format(protocol, tf, True)
201 self.assertTrue(tf == True, msg=msg)
202 self._qik.setCompactProtocol()
203
205 self._log.debug("Processing")
206
207 for i in range(2):
208 protocol = self._PROTOCOL_MAP.get(i)
209 result = self._qik.getSerialTimeout()
210 timeout = self._qik._valueToTimeout.get(0)
211 msg = ("{}: Invalid serial timeout value '{}' should be '{}'."
212 ).format(protocol, result, timeout)
213 self.assertTrue(result == timeout, msg=msg)
214 self._qik.setSerialTimeout(200.0)
215 result = self._qik.getSerialTimeout()
216 timeout = self._qik._valueToTimeout.get(108)
217 msg = ("{}: Invalid serial timeout value '{}' should be '{}'."
218 ).format(protocol, result, timeout)
219 self.assertTrue(result == timeout, msg=msg)
220 self._qik.setCompactProtocol()
221 self._qik.setSerialTimeout(0.0)
222
224 self._log.debug("Processing")
225 devices = (self._qik.DEFAULT_DEVICE_ID, 127)
226
227 for i in range(2):
228 protocol = self._PROTOCOL_MAP.get(i)
229 result = self._qik.setDeviceID(devices[1], devices[0])
230 msg = ("{}: Invalid device ID '{}' should be '{}'.").format(
231 protocol, result, 'OK')
232 self.assertTrue(result == 'OK', msg=msg)
233 result = self._qik.setDeviceID(devices[0], devices[1],
234 message=False)
235 msg = ("{}: Invalid device ID '{}' should be '{}'.").format(
236 protocol, result, devices[0])
237 self.assertTrue(result == 0, msg=msg)
238
239 msg = ("{}: Set device '{}' is not in stored device config "
240 ).format(protocol, result)
241 self.assertTrue(devices[0] in self._qik._deviceConfig, msg=msg)
242 self._qik.setCompactProtocol()
243
245 self._log.debug("Processing")
246 pwms = [v[0] for v in self._qik._CONFIG_PWM.values()]
247 nums = dict([(v[0], k) for k, v in self._qik._CONFIG_PWM.items()])
248
249 for i in range(2):
250 protocol = self._PROTOCOL_MAP.get(i)
251
252 for pwm in pwms:
253 result = self._qik.setPWMFrequency(pwm)
254 rtn = self._qik._CONFIG_RETURN.get(0)
255 msg = ("{}: Invalid PM return text '{}' for PWM '{}', "
256 "should be '{}'.").format(protocol, result, pwm, rtn)
257 self.assertTrue(result == rtn, msg=msg)
258 num = self._qik.setPWMFrequency(pwm, message=False)
259 msg = ("{}: Invalid PWM number '{}' for PWM '{}', "
260 "should be '{}'.").format(protocol, num, pwm, 0)
261 self.assertTrue(num == 0, msg=msg)
262
263 freq = self._qik.getPWMFrequency(message=False)
264 num = self._qik._CONFIG_PWM_TO_VALUE.get(freq)
265 config = self._qik.getConfigForDevice(
266 self._qik.DEFAULT_DEVICE_ID)
267 cnum = config.get('pwm')
268 msg = ("{}: Invalid PWM number '{}' for PWM '{}', "
269 "in stored config, should be '{}'").format(
270 protocol, num, pwm, cnum)
271 self.assertTrue(num == cnum, msg=msg)
272
273 self._qik.setCompactProtocol()
274
276 self._log.debug("Processing")
277 command = 0x70
278 error = self._qik._ERRORS.get(64)
279 rtn = self._qik._CONFIG_RETURN.get(0)
280
281 for i in range(2):
282 protocol = self._PROTOCOL_MAP.get(i)
283
284
285 self._qik.setM0Speed(50)
286 tf = self._qik.getMotorShutdown()
287 msg = ("{}: Invalid motor shutdown value '{}' should be '{}'."
288 ).format(protocol, tf, True)
289 self.assertTrue(tf == True, msg=msg)
290 time.sleep(0.5)
291
292 self._qik._writeData(command, self._qik.DEFAULT_DEVICE_ID)
293 result = self._qik.getError()
294 msg = ("{}: Invalid response error text '{}' should be '{}'."
295 ).format(protocol, result, [error])
296 self.assertTrue(error in result and len(result) == 1, msg=msg)
297
298
299 text = self._qik.setMotorShutdown(False)
300 msg = "{}: Invalid response '{}' should be '{}'.".format(
301 protocol, text, rtn)
302 self.assertTrue(text == rtn, msg=msg)
303 tf = self._qik.getMotorShutdown()
304 msg = ("{}: Invalid motor shutdown value '{}' should be '{}'."
305 ).format(protocol, text, False)
306 self.assertTrue(text == rtn, msg=msg)
307
308
309 config = self._qik.getConfigForDevice(self._qik.DEFAULT_DEVICE_ID)
310 shutdown = config.get('shutdown')
311 msg = ("{}: Invalid motor shutdown value '{}' in stored config, "
312 "should be '{}'.").format(protocol, tf, bool(shutdown))
313 self.assertTrue(tf == bool(shutdown), msg=msg)
314
315
316
317 self._qik.setM0Speed(0)
318 self._qik.setM0Speed(-50)
319 tf = self._qik.getMotorShutdown()
320 msg = ("{}: Invalid motor shutdown value '{}' should be '{}'."
321 ).format(protocol, tf, False)
322 self.assertTrue(tf == False, msg=msg)
323 time.sleep(0.5)
324
325 self._qik._writeData(command, self._qik.DEFAULT_DEVICE_ID)
326 result = self._qik.getError()
327 msg = ("{}: Invalid response error text '{}' should be '{}'."
328 ).format(protocol, result, [error])
329 self.assertTrue(error in result and len(result) == 1, msg=msg)
330 self._qik.setM0Speed(0)
331 self._qik.setM0Coast()
332
333
334 config = self._qik.getConfigForDevice(self._qik.DEFAULT_DEVICE_ID)
335 shutdown = config.get('shutdown')
336 msg = ("{}: Invalid motor shutdown value '{}' in stored config, "
337 "should be '{}'.").format(protocol, bool(shutdown), tf)
338 self.assertTrue(tf == bool(shutdown), msg=msg)
339
340
341 result = self._qik.setMotorShutdown(True)
342 msg = "{}: Invalid response '{}' should be '{}'.".format(
343 protocol, result, rtn)
344 self.assertTrue(result == rtn, msg=msg)
345 self._qik.setCompactProtocol()
346
348 self._log.debug("Processing")
349 rtn = self._qik._CONFIG_RETURN.get(0)
350 shortDelay = self._qik._valueToTimeout.get(1)
351 longDelay = self._qik._valueToTimeout.get(127)
352
353 for i in range(2):
354 protocol = self._PROTOCOL_MAP.get(i)
355
356 result = self._qik.setSerialTimeout(0.3)
357 msg = ("{}: Invalid serial timeout '{}' should be '{}'."
358 ).format(protocol, result, rtn)
359 self.assertTrue(result == rtn, msg=msg)
360 result = self._qik.getSerialTimeout()
361 msg = ("{}: Invalid serial timeout value '{}' should be '{}'."
362 ).format(protocol, result, shortDelay)
363 self.assertTrue(result == shortDelay, msg=msg)
364
365
366 config = self._qik.getConfigForDevice(self._qik.DEFAULT_DEVICE_ID)
367 timeout = config.get('timeout')
368 msg = ("{}: Invalid motor timeout value '{}' in stored config, "
369 "should be '{}'.").format(protocol, result, timeout)
370 self.assertTrue(result == timeout, msg=msg)
371
372
373 result = self._qik.setSerialTimeout(500.0)
374 msg = ("{}: Invalid serial timeout '{}' should be '{}'."
375 ).format(protocol, result, rtn)
376 self.assertTrue(result == rtn, msg=msg)
377 result = self._qik.getSerialTimeout()
378 msg = ("{}: Invalid serial timeout value '{}' should be '{}'."
379 ).format(protocol, result, longDelay)
380 self.assertTrue(result == longDelay, msg=msg)
381
382
383 config = self._qik.getConfigForDevice(self._qik.DEFAULT_DEVICE_ID)
384 timeout = config.get('timeout')
385 msg = ("{}: Invalid motor timeout value '{}' in stored config, "
386 "should be '{}'.").format(protocol, result, timeout)
387 self.assertTrue(result == timeout, msg=msg)
388
389 self._qik.setCompactProtocol()
390
391 @unittest.skip("Skipped, no return values.")
393 self._log.debug("Processing")
394
395 for i in range(2):
396 self._qik.setM0Speed(50)
397 time.sleep(0.5)
398 self._qik.setM0Coast()
399
400 @unittest.skip("Skipped, no return values.")
402 self._log.debug("Processing")
403
404 for i in range(2):
405 self._qik.setM1Speed(50)
406 time.sleep(0.5)
407 self._qik.setM1Coast()
408
409 @unittest.skip("Skipped, no return values and no get speed command.")
411 self._log.debug("Processing")
412
413 for i in range(2):
414 self._qik.setM0Speed(50)
415 time.sleep(0.5)
416
417 @unittest.skip("Skipped, no return values and no get speed command.")
419 self._log.debug("Processing")
420
421 for i in range(2):
422 self._qik.setM1Speed(50)
423 time.sleep(0.5)
424
425
426 if __name__ == '__main__':
427 unittest.main()
428