36 from __future__
import print_function
45 g_version =
"20210215"
48 g_serialDev =
'/dev/ttyAMA0'
68 intKeys.append(inChar)
76 cksum = cksum + int(c)
78 cksum = 0xff - (cksum & 0xff)
84 paramSetCmd = [ 0x7e, 0x3b, 0x32, 0, 0, 0, 0 ]
88 paramSetCmd[2] = registerNumber
91 msByte = (int(paramValue)/int(256))
92 paramSetCmd[5] = msByte & 0xff
93 paramSetCmd[6] = int(paramValue) & 0xff
97 paramSetCmd.append(pktCksum)
104 speedCmd = [ 0x7e, 0x3b, 0x2a, 0, 0, 0, 0 ]
108 speedCmd[4] = 0xff - ((-1 * rightSpeed) & 0xff)
110 speedCmd[4] = rightSpeed & 0xff
114 speedCmd[6] = 0xff - ((-1 * leftSpeed) & 0xff)
116 speedCmd[6] = leftSpeed & 0xff
118 speedCmd.append(pktCksum)
124 print(
"runTillKeypress starting using speed ", int(speed))
126 threading.Thread(target=keyboard_thread, args=(keyBuf,)).start()
127 logAlways(
"runTillKeypress drop into loop")
129 logAlways(
"runTillKeypress do the speed command")
133 logAlways(
"runTillKeypress do the delay")
156 read_byte = ser.read()
157 while read_byte
is not None:
160 print(
"fetchReplyByte: Too many reply chars ")
162 hexData = read_byte.encode(
'hex')
174 if (hexData == regHex):
179 if (hexData == cmdHex):
183 if (charState == 0)
and (hexData ==
'7e'):
185 read_byte = ser.read()
199 read_byte = ser.read()
200 while read_byte
is not None:
203 print(
"fetchReplyWord: Too many reply chars ")
205 hexData = read_byte.encode(
'hex')
208 replyWord = replyMsb + hexData
219 if (hexData == regHex):
224 if (hexData == cmdHex):
228 if (charState == 0)
and (hexData ==
'7e'):
230 read_byte = ser.read()
245 replyLongWord =
'0000'
246 read_byte = ser.read()
247 while read_byte
is not None:
250 print(
"fetchReplyWord: Too many reply chars ")
252 hexData = read_byte.encode(
'hex')
255 replyLongWord = reply24 + reply16 + reply08 + hexData
268 if (hexData == regHex):
273 if (hexData == cmdHex):
277 if (charState == 0)
and (hexData ==
'7e'):
279 read_byte = ser.read()
286 threading.Thread(target=keyboard_thread, args=(intKeys,)).start()
294 keyInput = intKeys[0]
298 logAlways(
"ONLY USE THIS LOW LEVEL UTILITY WITH EXPLICIT HELP FROM Ubiquity Robotics SUPPORT!")
299 logAlways(
"ONLY RUN WHEN MAGNI IS STOPPED!. Use sudo systemctl stop magni-base.service")
300 logAlways(
"Commands: h or ? for help. v for versions of firmware and hardware. Use Control-C to quit or E")
301 logAlways(
"Speeds: Enter 0 - 9 fwd speed. n,N slow/fast reverse. s for 'any speed' or c cycle last fwd/reverse")
302 logAlways(
" v - Query firmware and hw version setting o - Query 8-bit hardware option port with real board rev")
303 logAlways(
" p - Query PID control loop parameters O - Query firmware hw options")
304 logAlways(
" D - Query range of registers for 32bit vals. S - Set word value for any register. Reg in hex, value as decimal")
305 logAlways(
" q - Query a 16 bit word value from register. Q - Query 32 bit register value")
306 logAlways(
" 32 = Query if firmware thinks motors active 33 = Set to 1 to enable any exit of ESTOP feature")
307 logAlways(
" 34 = Set to max PID threshold where pre rev 5.0 boards did a safer ESTOP release. 0 to disable")
308 logAlways(
" 35 = Set to the max forward limit speed 36 - Set to a max negative reverse limit speed")
309 logAlways(
" 37 = Set max PWM setting [250] ")
319 serialDev = g_serialDev
339 print(
"Start Serial port using device ", serialDev)
343 logAlways(
"Unable to open serial port. Verify correct port was specified")
349 logAlways(
"Set motors to run at 0.0 MPs")
356 logAlways(
"Unable to properly send the command to Magni. This pregram canno run with Magni running.")
357 logAlways(
"Did you stop main software using sudo systemctl stop magni-base.service")
373 input = raw_input(
">> ")
387 logAlways(
"Run at 0.0 MPs till a key is pressed")
392 logAlways(
"Run at 0.1 MPs till a key is pressed")
397 logAlways(
"Run at 0.2 MPs till a key is pressed")
402 logAlways(
"Run at 0.3 MPs till a key is pressed")
407 logAlways(
"Run at 0.4 MPs till a key is pressed")
412 logAlways(
"Run at 0.5 MPs till a key is pressed")
417 logAlways(
"Run at 0.65 MPS or 1 rev per second")
422 logAlways(
"Run at 0.5 MPs till a key is pressed")
427 logAlways(
"Run at 0.5 MPs till a key is pressed")
432 logAlways(
"Run FAST till a key is pressed")
438 lastSpeed = int(raw_input(
"Enter peed value 0-255 max integer: "))
442 logAlways(
"Run reverse using slow negative speed")
443 lastNegativeSpeed = -10
447 logAlways(
"Run reverse using fast negative speed")
448 lastNegativeSpeed = -95
452 logAlways(
"Cycle between last speed that was set to zero and back over and over")
453 threading.Thread(target=keyboard_thread, args=(intKeys,)).start()
456 print(
"Cycle to the ON speed for ", cycleOnPeriod,
" cycles")
457 while not intKeys
and loops < cycleOnPeriod:
463 print(
"Cycle to the OFF speed for ", cycleOffPeriod,
" cycles")
464 while not intKeys
and loops < cycleOffPeriod:
472 nextInput = intKeys[0]
477 logAlways(
"Forced Board Revision to rev 5.0")
483 logAlways(
"Forced Board Revision to rev 4.9")
487 logAlways(
"Query any control register to any value up to one long word size")
488 cmdFirstRegAsHex = raw_input(
"Enter first control register number in hex: ")
489 cmdFirstRegNumber = int(cmdFirstRegAsHex,16)
490 cmdLastRegAsHex = raw_input(
"Enter last control register number in hex: ")
491 cmdLastRegNumber = int(cmdLastRegAsHex,16)
492 print(
"Dump MCB from hex Reg ", cmdFirstRegAsHex,
"[",cmdFirstRegNumber,
"] to hex Reg ", cmdLastRegAsHex,
"[",cmdLastRegNumber,
"]")
493 for reg
in range(cmdFirstRegNumber, cmdLastRegNumber, 1):
494 queryBytes = [ 0x7e, 0x3a, 0x34, 0, 0, 0, 0 ]
497 queryBytes.append(pktCksum)
499 ser.write(queryBytes)
500 hexRegValue =
'{:02x}'.format(reg)
502 integerValue = int(registerValue,16)
503 if integerValue > 2147483647:
504 integerValue = (4294967296 - integerValue) * -1
505 print(
"Reg ", hexRegValue,
" value = ", registerValue,
" hex : or dec ", integerValue)
510 logAlways(
"Enable firmware ESET stop safety feature")
511 queryBytes = [ 0x7e, 0x3a, 0x33, 0, 0, 0, 0 ]
513 queryBytes.append(pktCksum)
515 ser.write(queryBytes)
517 print(
"Prior ESTOP enable setting was ", estopEnableState)
521 logAlways(
"Enabled firmware ESET stop safety feature")
525 queryBytes = [ 0x7e, 0x3a, 0x31, 0, 0, 0, 0 ]
527 queryBytes.append(pktCksum)
529 ser.write(queryBytes)
531 print(
"Robot type ID is ", robotTypeId)
541 logAlways(
"Fetch motor controller motor power state")
542 queryBytes = [ 0x7e, 0x3a, 0x32, 0, 0, 0, 0 ]
544 queryBytes.append(pktCksum)
546 ser.write(queryBytes)
548 print(
"Motor controller things motor power state is ", motPowState)
558 logAlways(
"Query any control register to any value up to one word size")
559 cmdRegAsHex = raw_input(
"Enter control register number in hex: ")
560 cmdRegNumber = int(cmdRegAsHex,16)
561 queryBytes = [ 0x7e, 0x3a, 0x34, 0, 0, 0, 0 ]
562 queryBytes[2] = cmdRegNumber
564 queryBytes.append(pktCksum)
566 ser.write(queryBytes)
568 print(
"Register was set to ", int(registerValue,16),
" decimal", registerValue,
" hex")
572 logAlways(
"Query the current hardware option bit settings")
574 cmdRegNumber = int(cmdRegAsHex,16)
575 queryBytes = [ 0x7e, 0x3a, 0x34, 0, 0, 0, 0 ]
576 queryBytes[2] = cmdRegNumber
578 queryBytes.append(pktCksum)
580 ser.write(queryBytes)
584 print(
"Hardware option bits are set to ", int(registerValue,16),
" decimal", registerValue,
" hex")
585 if ((int(registerValue,16) & 0x01) != 0):
586 print (
" High resolution encoders")
588 print (
" Standard resolution encoders")
589 if ((int(registerValue,16) & 0x02) != 0):
590 print (
" Thin gearless wheels")
592 print (
" Standard wheels")
593 if ((int(registerValue,16) & 0x04) != 0):
594 print (
" Reverse the wheel direction")
598 logAlways(
"Query any control register to any value up to one long word size")
599 cmdRegAsHex = raw_input(
"Enter control register number in hex: ")
600 cmdRegNumber = int(cmdRegAsHex,16)
601 queryBytes = [ 0x7e, 0x3a, 0x34, 0, 0, 0, 0 ]
602 queryBytes[2] = cmdRegNumber
604 queryBytes.append(pktCksum)
606 ser.write(queryBytes)
608 integerValue = int(registerValue,16)
609 if integerValue > 2147483647:
610 integerValue = (4294967296 - integerValue) * -1
611 print(
"Reg ", cmdRegAsHex,
" value = ", registerValue,
" hex : or dec ", integerValue)
615 logAlways(
"Set any control register to any value up to one word size")
616 cmdRegAsHex = raw_input(
"Enter control register number in as hex digits: ")
617 cmdRegValue = raw_input(
"Enter control register value to be set in decimal: ")
618 cmdRegNumber = int(cmdRegAsHex,16)
625 logAlways(
"Exit after sending stop command")
634 logAlways(
"Query hardware version from I2C interface on motor controller board")
635 i2cbus = smbus.SMBus(1)
636 print (
"Setup 8-bit I2C port to set as inputs. Also detect if port is present")
639 i2cbus.write_byte(PCF8574,0xff)
643 print (
"Did not detect 8-bit port which is only on rev 5.0 and later boards OR I2C failure")
645 if (portPresent == 1):
646 inputPortBits = i2cbus.read_byte(PCF8574)
648 if ((inputPortBits & 0x80) == 0):
649 print (
"Motor power is OFF")
651 print (
"Motor power is ON")
655 boardRev = 49 + (15 - (inputPortBits & 0x0f))
656 print (
"Motor Controller Board Revision is: ", boardRev)
657 optionBits = (inputPortBits & 0x70) >> 4
658 print (
"Option jumper block is set to: (install a jumper sets a bit to 0)", optionBits)
663 queryPid = [ 0x7e, 0x3a, 0x1b, 0, 0, 0, 0 ]
665 queryPid.append(pktCksum)
669 print(
" P (1b) = ", int(pidReg,16),
" [", pidReg,
" hex]")
670 queryPid = [ 0x7e, 0x3a, 0x1c, 0, 0, 0, 0 ]
672 queryPid.append(pktCksum)
676 print(
" I (1c) = ", int(pidReg,16),
" [", pidReg,
" hex]")
677 queryPid = [ 0x7e, 0x3a, 0x1d, 0, 0, 0, 0 ]
679 queryPid.append(pktCksum)
683 print(
" D (1d) = ", int(pidReg,16),
" [", pidReg,
" hex]")
684 queryPid = [ 0x7e, 0x3a, 0x37, 0, 0, 0, 0 ]
686 queryPid.append(pktCksum)
690 print(
" MaxPWM (37)= ", int(pidReg,16),
" [", pidReg,
" hex]")
694 logAlways(
"Fetch software and hardware version information")
696 queryVersion = [ 0x7e, 0x3a, 0x22, 0, 0, 0, 0 ]
698 queryVersion.append(pktCksum)
700 ser.write(queryVersion)
702 fwRevInt = int(fwRev,16)
703 print(
"fw revision ", fwRevInt)
706 queryVersion = [ 0x7e, 0x3a, 0x3a, 0, 0, 0, 0 ]
708 queryVersion.append(pktCksum)
710 ser.write(queryVersion)
712 print(
"fw daycode ", registerValue)
715 queryVersion = [ 0x7e, 0x3a, 0x21, 0, 0, 0, 0 ]
717 queryVersion.append(pktCksum)
719 ser.write(queryVersion)
721 boardRev = int(fwRev,16) / 10.0
722 print(
"hw revision ", boardRev)
725 except RuntimeError
as e:
726 logAlways(
"Exception in magni_cmd: " + e.message)
727 except KeyboardInterrupt:
728 logAlways(
"terminated by keyboard interrupt! Zero the motor speed and exit")
735 logAlways(
"NOTE: Program requires prior use of: sudo systemctl stop magni-base")
738 if __name__ ==
'__main__':
739 print(
"Running with script version: " + g_version)
741 if str(len(sys.argv)) ==
"3":
742 if str(sys.argv[1]) ==
"--dev" or str(sys.argv[1]) ==
"--device":
743 g_serialDev = str(sys.argv[2])
744 print(
"Using serial device file: " + g_serialDev)
748 except RuntimeError
as e:
749 logAlways(
"Exception in magni_cmd: " + e.message)