36 from __future__
import print_function
45 g_version =
"20190703" 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 thread.start_new_thread(keyboard_thread, (keyBuf,))
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 thread.start_new_thread(keyboard_thread, (intKeys,))
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(
" q - Query a 16 bit word value from register. Q - Query 32 bit register value")
304 logAlways(
" S - Set a word value from for any register. Enter reg as hex and value as decimal")
305 logAlways(
" 21 = Hardware Rev (50 = 5.0) 22 = Firmware version")
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)
341 ser = serial.Serial(serialDev, 38400, 8,
'N', 1, timeout=1)
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 thread.start_new_thread(keyboard_thread, (intKeys,))
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(
"Enable firmware ESET stop safety feature")
488 queryBytes = [ 0x7e, 0x3a, 0x33, 0, 0, 0, 0 ]
490 queryBytes.append(pktCksum)
492 ser.write(queryBytes)
494 print(
"Prior ESTOP enable setting was ", estopEnableState)
498 logAlways(
"Enabled firmware ESET stop safety feature")
502 queryBytes = [ 0x7e, 0x3a, 0x31, 0, 0, 0, 0 ]
504 queryBytes.append(pktCksum)
506 ser.write(queryBytes)
508 print(
"Robot type ID is ", robotTypeId)
518 logAlways(
"Fetch motor controller motor power state")
519 queryBytes = [ 0x7e, 0x3a, 0x32, 0, 0, 0, 0 ]
521 queryBytes.append(pktCksum)
523 ser.write(queryBytes)
525 print(
"Motor controller things motor power state is ", motPowState)
535 logAlways(
"Query any control register to any value up to one word size")
536 cmdRegAsHex = raw_input(
"Enter control register number in hex: ")
537 cmdRegNumber = int(cmdRegAsHex,16)
538 queryBytes = [ 0x7e, 0x3a, 0x34, 0, 0, 0, 0 ]
539 queryBytes[2] = cmdRegNumber
541 queryBytes.append(pktCksum)
543 ser.write(queryBytes)
545 print(
"Register was set to ", int(registerValue,16),
" decimal", registerValue,
" hex")
549 logAlways(
"Query any control register to any value up to one long word size")
550 cmdRegAsHex = raw_input(
"Enter control register number in hex: ")
551 cmdRegNumber = int(cmdRegAsHex,16)
552 queryBytes = [ 0x7e, 0x3a, 0x34, 0, 0, 0, 0 ]
553 queryBytes[2] = cmdRegNumber
555 queryBytes.append(pktCksum)
557 ser.write(queryBytes)
559 print(
"Register was set to ", int(registerValue,16),
" decimal", registerValue,
" hex")
563 logAlways(
"Set any control register to any value up to one word size")
564 cmdRegAsHex = raw_input(
"Enter control register number in as hex digits: ")
565 cmdRegValue = raw_input(
"Enter control register value to be set in decimal: ")
566 cmdRegNumber = int(cmdRegAsHex,16)
573 logAlways(
"Exit after sending stop command")
582 logAlways(
"Query hardware version from I2C interface on motor controller board")
583 i2cbus = smbus.SMBus(1)
584 print (
"Setup 8-bit I2C port to set as inputs. Also detect if port is present")
587 i2cbus.write_byte(PCF8574,0xff)
591 print (
"Did not detect 8-bit port which is only on rev 5.0 and later boards OR I2C failure")
593 if (portPresent == 1):
594 inputPortBits = i2cbus.read_byte(PCF8574)
596 if ((inputPortBits & 0x80) == 0):
597 print (
"Motor power is OFF")
599 print (
"Motor power is ON")
603 boardRev = 49 + (15 - (inputPortBits & 0x0f))
604 print (
"Motor Controller Board Revision is: ", boardRev)
605 optionBits = (inputPortBits & 0x70) >> 4
606 print (
"Option jumper block is set to: (install a jumper sets a bit to 0)", optionBits)
610 logAlways(
"Fetch software and hardware version information")
612 queryVersion = [ 0x7e, 0x3a, 0x22, 0, 0, 0, 0 ]
614 queryVersion.append(pktCksum)
616 ser.write(queryVersion)
618 fwRevInt = int(fwRev,16)
619 print(
"fw revision ", fwRevInt)
622 queryVersion = [ 0x7e, 0x3a, 0x3a, 0, 0, 0, 0 ]
624 queryVersion.append(pktCksum)
626 ser.write(queryVersion)
628 print(
"fw daycode ", registerValue)
631 queryVersion = [ 0x7e, 0x3a, 0x21, 0, 0, 0, 0 ]
633 queryVersion.append(pktCksum)
635 ser.write(queryVersion)
637 boardRev = int(fwRev,16) / 10.0
638 print(
"hw revision ", boardRev)
641 except RuntimeError,e:
642 logAlways(
"Exception in magni_cmd: " + e.message)
643 except KeyboardInterrupt:
644 logAlways(
"terminated by keyboard interrupt! Zero the motor speed and exit")
651 logAlways(
"NOTE: Program requires prior use of: sudo systemctl stop magni-base")
654 if __name__ ==
'__main__':
655 print(
"Running with script version: " + g_version)
657 if str(len(sys.argv)) ==
"3":
658 if str(sys.argv[1]) ==
"--dev":
659 g_serialDev = str(sys.argv[2])
660 print(
"Using serial device file: " + g_serialDev)
664 except RuntimeError,e:
665 logAlways(
"Exception in magni_cmd: " + e.message)
def formMagniParamSetMessage(registerNumber, paramValue)
def keyboard_thread(intKeys)
def setSpeedTillKeypress(ser, speed1, speed2)
def runTillKeypress(speed)
def fetchReplyByte(ser, cmdHex, regHex)
def formMagniSpeedMessage(rightSpeed, leftSpeed)
def fetchReplyLongWord(ser, cmdHex, regHex)
def fetchReplyWord(ser, cmdHex, regHex)
def calcPacketCksum(msgBytes)