Microsoft Robotics Developer Studio 2008 July CTP, bluetooth
RogueSeven
Posts: 5
Windows XP Pro, SP3
Microsoft Robotics Developer Studio 2008 July CTP
MSRS-Bluetooth_Boe_bot_v1.5_PDF
EB500_Ser_D
Board of Education_Rev_C
Used each Parallax code for MSRS:
1a. BoeBotControlForMSRS (See below)
2a. BoeBotControlForMSRSCtp2 (see below)
I am following the pdf on MSRS-Bluetooth_Boe_bot_v1.5.
I am currently stuck on page 11. "Parallax.Boe.Bot.config.xml", "Parallax.MotorIrBumper.config.xml".
This file is nowhere to be found.
Any & all help would be greatly appreciated.
Thank you in advance,
RogueSeven
Used each Parallax code for MSRS:
1b.
'
[noparse][[/noparse] Title ]
' File: BoeBotControlForMsrs.bs2
' {$STAMP BS2}
' {$PBASIC 2.5}
' Updated version for ProMSRS by Trevor Taylor
' October 2007 -
' Added new functionality
' January 2008 -
' Fix bug with Message Index reaching 255 that caused Boe-Bot to "twitch"
' every so often apparently at random
' Add a version number into the protocol
'
'
[noparse][[/noparse] DATA ]
' TT - Insert version info into commands 1, 2 and 3 as last two bytes:
' major version, minor version
ResetOnOff DATA 0 ' On/off toggle w/ Reset button
RequestConnect DATA $FF, 0, 1, 1, 0
ConnectionGranted DATA $FF, 0, 2, 1, 0
RequestCommand DATA $FF, 0, 3, 1, 0
ServoSpeeds DATA $FF, 0, 4, 0, 0
'
[noparse][[/noparse] Variables ]
tLeft VAR Word ' Servo control pulse durations
tRight VAR Word
temp VAR Word ' Temp variable
' Buffer array not declared as buffer VAR Word(5) for SERIN functionality.
' It can still be accessed as buffer(0), buffer(1), etc. However,
' buffer0, buffer1, etc. should be used in SERIN commands with variations
' of WAIT.
buffer0 VAR Byte ' Buffer - Start char = $ff
buffer1 VAR Byte ' Message Index value
buffer2 VAR Byte ' Command
buffer3 VAR Byte ' Argument 1 (return data 1)
buffer4 VAR Byte ' Argument 2 (return data 2)
buffer VAR buffer0 ' For standard array indexing
duration VAR Byte ' 50ths of ms duration
frequency VAR Byte ' 50ths of frequency
pointer VAR Byte ' EEPROM pointer
msgIndex VAR Byte ' EEPROM message index
routine VAR Nib ' Routine selector
counter VAR Nib
index VAR Nib
flagWhiskers VAR Bit ' Act on Whisker values
flagDigSens VAR Bit ' Send back digital sensors 1/0s
' with every reply
flagIr VAR Bit '
tempBit VAR Bit
'
[noparse][[/noparse] Initialization ]
' This code makes it possible to toggle the Boe-Bot on/off by pressing and
' releasing the Board of Education's Reset button.
Program_Start:
' For on/off toggle with Reset
' READ ResetOnOff, temp
' temp = temp + 1
' WRITE ResetOnOff, temp
' IF temp.BIT0 = 0 THEN
' FREQOUT 4, 1000, 2000 - Indicate inactive
' END
' ENDIF
HIGH 15
FREQOUT 4, 75, 4500
LOW 15
Reset:
DEBUG CLS
'Wait for the eb500 radio to be ready.
PAUSE 1000
'Wait for the EB500 Bluetooth connection to be established.
DO UNTIL IN5 = 1: LOOP
GOSUB Ram_Clear
Request_Connect:
pointer = RequestConnect
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
Confirm_Connect:
pointer = ConnectionGranted
GOSUB Get_Packet
Wait_For_Confirm:
' TT - This is hard-coded here, so add version number (last two bytes)
SEROUT 1, 84, [noparse][[/noparse]255, 0, 1, 1, 0]
SERIN 0, 84, 20, Wait_For_Confirm, [noparse][[/noparse]WAITSTR buffer \ 2,
buffer2, buffer3,
buffer4]
Request_Packet:
msgIndex = msgIndex + 1
' TT - The protocol does not allow 255 in any other byte other than
' the very first one
IF msgIndex = 255 THEN
msgIndex = 0
ENDIF
pointer = RequestCommand
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
'
[noparse][[/noparse] Main Routine ]
DO
Resume: ' If Message not rcvd, try again
IF IN5 = 0 THEN Reset ' EB500 disconnected?
PULSOUT 13, tLeft ' Servo control pulses
PULSOUT 12, tRight
SERIN 0, 84, 5, Resume, ' Get next command
[noparse][[/noparse]WAITSTR buffer \ 2, buffer2,
buffer3, buffer4]
PULSOUT 13, tLeft ' Servo control pulses again
PULSOUT 12, tRight
' Just in case the 192 is missed, check for 2 also
' because the host PC sends these continuously
' TT - MSRS service seems to send a 2 instead of 192
IF buffer2 = 192 OR buffer2 = 2 THEN ' Handle restart req from PC
msgIndex = 0
GOTO Request_Connect
ENDIF
LOOKDOWN buffer2,[noparse][[/noparse]32, 33,
64, 65,
96, 97, 98,
128, 129, 130,
160, 161, 162], routine
ON routine GOSUB Set_Servo_Speed, Maneuver,
Get_Ir, Get_Whiskers,
Speaker_Tone, Set_Pins, Delay,
Enable_Digital_Sensors, Enable_Ir, Enable_Whiskers,
Disable_Digital_Sensors, Disable_Ir, Disable_Whiskers
' Load digital sensor values into buffer byte 3 for return message.
IF flagDigSens = 1 THEN GOSUB Digital_Sensors
' Increment message index for reply. Next message from PC has to use
' reply's buf.
msgIndex = msgIndex + 1
' TT - Protocol does not allow 255!
IF msgIndex = 255 THEN
msgIndex = 0
ENDIF
buffer1 = msgIndex
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
LOOP
'
[noparse][[/noparse] Subroutine Digital_Sensors ]
' This subroutine is used by the main routine to return digital sensor values
' with each reply.
Digital_Sensors:
buffer3 = 0
GOSUB Get_Ir
GOSUB Get_Whiskers
IF ((buffer3.BIT2 = 0 OR buffer3.BIT3 = 0) AND (flagWhiskers = 1)) THEN
tLeft = tLeft MAX 750
tRight = tRight MIN 750
ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Set_Servo_Speed ]
' Range of 0 to 200 with 100 = stopped maps to 650 to 850 with 750 stopped.
Set_Servo_Speed:
tLeft = buffer3 + 650 ' Decode servo speed.
tRight = buffer4 + 650
RETURN
'
[noparse][[/noparse] Subroutine Speaker_Tone ]
Speaker_Tone:
duration = buffer3 ' Decode speaker tone
frequency = buffer4
FREQOUT 4, duration * 50, frequency * 50 ' Transmit tone
RETURN ' Go to resume routine
'
[noparse][[/noparse] Subroutine Get_Ir ]
' IR object detection for buf bits 1 (left) and 0 (right).
Get_Ir:
' IF flagIr THEN
FREQOUT 9, 1, 38500 ' IR headlight
tempBit = IN10 ' IR receiver
buffer3.BIT1 = tempBit ' Left IR reply bit
FREQOUT 3, 1, 38500
tempBit = IN2
buffer3.BIT0 = tempBit
' ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Get_Packet ]
' Loads packet into buffer for transmitting. Used by initialization.
Get_Packet:
FOR index = 0 TO 4
READ pointer + index, buffer(index)
NEXT
buffer(1) = msgIndex
RETURN
'
[noparse][[/noparse] Subroutine Display_Command ]
' For debugging.
Display_Command:
' FOR index = 0 TO 4
' DEBUG DEC buffer(index), CR
' NEXT
RETURN
'
[noparse][[/noparse] Subroutine - Check_Whiskers ]
' Stores left and right wiskers (contact switches) for buf bit 3 (left) and
' 2 (right).
Get_Whiskers:
'IF FlagWhiskers THEN
buffer3.BIT3 = IN7 ' Left whisker
buffer3.BIT2 = IN8 ' Right whisker
'ENDIF
RETURN
'
[noparse][[/noparse] Subroutine - Set_Pins ]
' Sets up to two pins. buf high nibble specifies the operation, and the
' low nibble specifies the pin. The same applies to buf.
' High nibble:
' 0 - no action
' 1 - set to output
' 2 - set to input
' 3 - set to (output-high)
' 4 - set to (output-low)
' Low Nibble:
' 0 to 15 - Specifies I/O pin.
' DO NOT try to set 0, 1, 5, or 6.
Set_Pins:
temp.NIB1 = buffer3.HIGHNIB
temp.NIB0 = buffer3.LOWNIB
GOSUB Op_Pins
temp.NIB1 = buffer4.HIGHNIB
temp.NIB0 = buffer4.LOWNIB
GOSUB Op_Pins
RETURN
Op_pins:
SELECT temp.NIB1
CASE 1
OUTPUT temp.NIB0
CASE 2
INPUT temp.NIB0
CASE 3
HIGH temp.NIB0
CASE 4
LOW temp.NIB0
ENDSELECT
RETURN
'
[noparse][[/noparse] Subroutine - Delay ]
' Specify delay in ms.
Delay:
temp.LOWBYTE = buffer3
temp.HIGHBYTE = buffer4
PAUSE temp
RETURN
'
[noparse][[/noparse] Subroutine - Enable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Enable_Digital_Sensors:
FlagDigSens = 1
RETURN
'
[noparse][[/noparse] Subroutine - Disable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Disable_Digital_Sensors:
FlagDigSens = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Causes program to stop the Boe-Bot if Whisker contact is sensed. This gives
' the PC bluetooth system time to reply.
Enable_Whiskers:
flagWhiskers = 1
RETURN
'
[noparse][[/noparse] Subroutine Disable_Whiskers ]
' Causes program to ignore the whisker contact. Also ignores when they are
' not connected.
Disable_Whiskers:
flagWhiskers = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Ir ]
' Not implemented.
Enable_Ir:
flagIr = 1
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Not implemented.
Disable_Ir:
flagIr = 0
RETURN
'
[noparse][[/noparse] Subroutine - Maneuver ]
' Preprogrammed maneuver example. Current setup allows:
' "U" - Back up then U-turn
' "R" - Back up then right turn
' "L" - Back up then left turn
'
' TT - Added Oct-2007
' Additional behaviours for better control.
' All of these take a parameter which is a counter
' that effectively controls the time duration.
' The counter is roughly in increments of 23ms.
' "F" - Move Forward
' "B" - Move Backward
' "A" - Move Anti-Clockwise (Rotate Left)
' "C" - Move Clockwise (Rotate Right)
'
' The changes to the code also allow the duration
' of the "back up" to be altered independently
' for each of the behaviors. It could be specified
' as a parameter, but this seems unnecessary.
'
' IMPORTANT NOTE: While a behavior is being executed,
' the robot is effectively operating blind! It does
' not send back any sensor information or even look
' at the sensors itself.
Maneuver:
SELECT buffer3
CASE "U"
GOSUB BackUp
FOR temp = 0 TO 40
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "R"
GOSUB BackUp
FOR temp = 0 TO 20
PULSOUT 13, 850
PULSOUT 12, 850
PAUSE 20
NEXT
CASE "L"
GOSUB BackUp
FOR temp = 0 TO 20
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
' New behaviors
CASE "F" ' Forward
FOR temp = 0 TO buffer4
PULSOUT 13, 850
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "B" ' Backward
FOR temp = 0 TO buffer4
PULSOUT 13, 650
PULSOUT 12, 850
PAUSE 20
NEXT
CASE "A" ' Anti-Clockwise
FOR temp = 0 TO buffer4
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "C" ' Clockwise
FOR temp = 0 TO buffer4
PULSOUT 13, 850
PULSOUT 12, 850
PAUSE 20
NEXT
ENDSELECT
RETURN
BackUp:
FOR temp = 0 TO 35
PULSOUT 13, 650
PULSOUT 12, 850
PAUSE 20
NEXT
RETURN
'
[noparse][[/noparse] Subroutine Ram_Clear ]
' Clears ram for reset from PC. This prevents retaining the msgIndex and
' pulseLeft/right variable values, which would otherwise cause problems.
Ram_Clear:
W0 = 0
W1 = 0
W2 = 0
W3 = 0
W4 = 0
W5 = 0
W6 = 0
W7 = 0
W8 = 0
W9 = 0
W10 = 0
W11 = 0
W12 = 0
RETURN
2b.
'
[noparse][[/noparse] Title ]
' File: BoeBotControlForMsrsCtp2.bs2
' {$STAMP BS2}
' {$PBASIC 2.5}
'
[noparse][[/noparse] DATA ]
ResetOnOff DATA 0 ' On/off toggle w/ Reset button
RequestConnect DATA $FF, 0, 1, 0, 0
ConnectionGranted DATA $FF, 0, 2, 0, 0
RequestCommand DATA $FF, 0, 3, 0, 0
ServoSpeeds DATA $FF, 0, 4, 0, 0
'
[noparse][[/noparse] Variables ]
tLeft VAR Word ' Servo control pulse durations
tRight VAR Word
temp VAR Word ' Temp variable
' Buffer array not declared as buffer VAR Word(5) for SERIN functionality.
' It can still be accessed as buffer(0), buffer(1), etc. However,
' buffer0, buffer1, etc. should be used in SERIN commands with variations
' of WAIT.
buffer0 VAR Byte ' Buffer - Start char = $ff
buffer1 VAR Byte ' Message Index value
buffer2 VAR Byte ' Command
buffer3 VAR Byte ' Argument 1 (return data 1)
buffer4 VAR Byte ' Argument 2 (return data 2)
buffer VAR buffer0 ' For standard array indexing
duration VAR Byte ' 50ths of ms duration
frequency VAR Byte ' 50ths of frequency
pointer VAR Byte ' EEPROM pointer
msgIndex VAR Byte ' EEPROM message index
routine VAR Nib ' Routine selector
counter VAR Nib
index VAR Nib
flagWhiskers VAR Bit ' Act on Whisker values
flagDigSens VAR Bit ' Send back digital sensors 1/0s
' with every reply
flagIr VAR Bit '
tempBit VAR Bit
'
[noparse][[/noparse] Initialization ]
' This code makes it possible to toggle the Boe-Bot on/off by pressing and
' releasing the Board of Education's Reset button.
Program_Start:
' For on/off toggle with Reset
' READ ResetOnOff, temp
' temp = temp + 1
' WRITE ResetOnOff, temp
' IF temp.BIT0 = 0 THEN
' FREQOUT 4, 1000, 2000 - Indicate inactive
' END
' ENDIF
HIGH 15
FREQOUT 4, 75, 4500
LOW 15
Reset:
DEBUG CLS
'Wait for the eb500 radio to be ready.
PAUSE 1000
'Wait for the EB500 Bluetooth connection to be established.
DO UNTIL IN5 = 1: LOOP
GOSUB Ram_Clear
Request_Connect:
pointer = RequestConnect
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
Confirm_Connect:
pointer = ConnectionGranted
GOSUB Get_Packet
Wait_For_Confirm:
SEROUT 1, 84, [noparse][[/noparse]255, 0, 1, 0, 0]
SERIN 0, 84, 20, Wait_For_Confirm, [noparse][[/noparse]WAITSTR buffer \ 2,
buffer2, buffer3,
buffer4]
Request_Packet:
msgIndex = msgIndex + 1
pointer = RequestCommand
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
'
[noparse][[/noparse] Main Routine ]
DO
Resume: ' If Message not rcvd, try again
IF IN5 = 0 THEN Reset ' EB500 disconnected?
PULSOUT 13, tLeft ' Servo control pulses
PULSOUT 12, tRight
SERIN 0, 84, 5, Resume, ' Get next command
[noparse][[/noparse]WAITSTR buffer \ 2, buffer2,
buffer3, buffer4]
PULSOUT 13, tLeft ' Servo control pulses again
PULSOUT 12, tRight
IF buffer2 = 192 THEN ' Handle restart req from PC
msgIndex = 0
GOTO Request_Connect
ENDIF
LOOKDOWN buffer2,[noparse][[/noparse]32, 33,
64, 65,
96, 97, 98,
128, 129, 130,
160, 161, 162], routine
ON routine GOSUB Set_Servo_Speed, Maneuver,
Get_Ir, Get_Whiskers,
Speaker_Tone, Set_Pins, Delay,
Enable_Digital_Sensors, Enable_Ir, Enable_Whiskers,
Disable_Digital_Sensors, Disable_Ir, Disable_Whiskers
' Load digital sensor values into buffer byte 3 for return message.
IF flagDigSens = 1 THEN GOSUB Digital_Sensors
' Increment message index for reply. Next message from PC has to use
' reply's buf.
msgIndex = msgIndex + 1
buffer1 = msgIndex
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
LOOP
'
[noparse][[/noparse] Subroutine Digital_Sensors ]
' This subroutine is used by the main routine to return digital sensor values
' with each reply.
Digital_Sensors:
buffer3 = 0
GOSUB Get_Ir
GOSUB Get_Whiskers
IF ((buffer3.BIT2 = 0 OR buffer3.BIT3 = 0) AND (flagWhiskers = 1)) THEN
tLeft = tLeft MAX 750
tRight = tRight MIN 750
ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Set_Servo_Speed ]
' Range of 0 to 200 with 100 = stopped maps to 650 to 850 with 750 stopped.
Set_Servo_Speed:
tLeft = buffer3 + 650 ' Decode servo speed.
tRight = buffer4 + 650
RETURN
'
[noparse][[/noparse] Subroutine Speaker_Tone ]
Speaker_Tone:
duration = buffer3 ' Decode speaker tone
frequency = buffer4
FREQOUT 4, duration * 50, frequency * 50 ' Transmit tone
RETURN ' Go to resume routine
'
[noparse][[/noparse] Subroutine Get_Ir ]
' IR object detection for buf bits 1 (left) and 0 (right).
Get_Ir:
' IF flagIr THEN
FREQOUT 9, 1, 38500 ' IR headlight
tempBit = IN10 ' IR receiver
buffer3.BIT1 = tempBit ' Left IR reply bit
FREQOUT 3, 1, 38500
tempBit = IN2
buffer3.BIT0 = tempBit
' ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Get_Packet ]
' Loads packet into buffer for transmitting. Used by initialization.
Get_Packet:
FOR index = 0 TO 4
READ pointer + index, buffer(index)
NEXT
buffer(1) = msgIndex
RETURN
'
[noparse][[/noparse] Subroutine Display_Command ]
' For debugging.
Display_Command:
' FOR index = 0 TO 4
' DEBUG DEC buffer(index), CR
' NEXT
RETURN
'
[noparse][[/noparse] Subroutine - Check_Whiskers ]
' Stores left and right wiskers (contact switches) for buf bit 3 (left) and
' 2 (right).
Get_Whiskers:
'IF FlagWhiskers THEN
buffer3.BIT3 = IN7 ' Left whisker
buffer3.BIT2 = IN8 ' Right whisker
'ENDIF
RETURN
'
[noparse][[/noparse] Subroutine - Set_Pins ]
' Sets up to two pins. buf high nibble specifies the operation, and the
' low nibble specifies the pin. The same applies to buf.
' High nibble:
' 0 - no action
' 1 - set to output
' 2 - set to input
' 3 - set to (output-high)
' 4 - set to (output-low)
' Low Nibble:
' 0 to 15 - Specifies I/O pin.
' DO NOT try to set 0, 1, 5, or 6.
Set_Pins:
temp.NIB1 = buffer3.HIGHNIB
temp.NIB0 = buffer3.LOWNIB
GOSUB Op_Pins
temp.NIB1 = buffer4.HIGHNIB
temp.NIB0 = buffer4.LOWNIB
GOSUB Op_Pins
RETURN
Op_pins:
SELECT temp.NIB1
CASE 1
OUTPUT temp.NIB0
CASE 2
INPUT temp.NIB0
CASE 3
HIGH temp.NIB0
CASE 4
LOW temp.NIB0
ENDSELECT
RETURN
'
[noparse][[/noparse] Subroutine - Delay ]
' Specify delay in ms.
Delay:
temp.LOWBYTE = buffer3
temp.HIGHBYTE = buffer4
PAUSE temp
RETURN
'
[noparse][[/noparse] Subroutine - Enable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Enable_Digital_Sensors:
FlagDigSens = 1
RETURN
'
[noparse][[/noparse] Subroutine - Disable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Disable_Digital_Sensors:
FlagDigSens = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Causes program to stop the Boe-Bot if Whisker contact is sensed. This gives
' the PC bluetooth system time to reply.
Enable_Whiskers:
flagWhiskers = 1
RETURN
'
[noparse][[/noparse] Subroutine Disable_Whiskers ]
' Causes program to ignore the whisker contact. Also ignores when they are
' not connected.
Disable_Whiskers:
flagWhiskers = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Ir ]
' Not implemented.
Enable_Ir:
flagIr = 1
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Not implemented.
Disable_Ir:
flagIr = 0
RETURN
'
[noparse][[/noparse] Subroutine - Maneuver ]
' Preprogrammed maneuver example. Current setup allows:
' "U" - Back up then U-turn
' "R" - Back up then right turn
' "L" - Back up then left turn
Maneuver:
FOR temp = 0 TO 35
PULSOUT 13, 650
PULSOUT 12, 850
PAUSE 20
NEXT
SELECT buffer3
CASE "U"
FOR temp = 0 TO 40
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "R"
FOR temp = 0 TO 20
PULSOUT 13, 850
PULSOUT 12, 850
PAUSE 20
NEXT
CASE "L"
FOR temp = 0 TO 20
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
ENDSELECT
RETURN
'
[noparse][[/noparse] Subroutine Ram_Clear ]
' Clears ram for reset from PC. This prevents retaining the msgIndex and
' pulseLeft/right variable values, which would otherwise cause problems.
Ram_Clear:
W0 = 0
W1 = 0
W2 = 0
W3 = 0
W4 = 0
W5 = 0
W6 = 0
W7 = 0
W8 = 0
W9 = 0
W10 = 0
W11 = 0
W12 = 0
RETURN
Microsoft Robotics Developer Studio 2008 July CTP
MSRS-Bluetooth_Boe_bot_v1.5_PDF
EB500_Ser_D
Board of Education_Rev_C
Used each Parallax code for MSRS:
1a. BoeBotControlForMSRS (See below)
2a. BoeBotControlForMSRSCtp2 (see below)
I am following the pdf on MSRS-Bluetooth_Boe_bot_v1.5.
I am currently stuck on page 11. "Parallax.Boe.Bot.config.xml", "Parallax.MotorIrBumper.config.xml".
This file is nowhere to be found.
Any & all help would be greatly appreciated.
Thank you in advance,
RogueSeven
Used each Parallax code for MSRS:
1b.
'
[noparse][[/noparse] Title ]
' File: BoeBotControlForMsrs.bs2
' {$STAMP BS2}
' {$PBASIC 2.5}
' Updated version for ProMSRS by Trevor Taylor
' October 2007 -
' Added new functionality
' January 2008 -
' Fix bug with Message Index reaching 255 that caused Boe-Bot to "twitch"
' every so often apparently at random
' Add a version number into the protocol
'
'
[noparse][[/noparse] DATA ]
' TT - Insert version info into commands 1, 2 and 3 as last two bytes:
' major version, minor version
ResetOnOff DATA 0 ' On/off toggle w/ Reset button
RequestConnect DATA $FF, 0, 1, 1, 0
ConnectionGranted DATA $FF, 0, 2, 1, 0
RequestCommand DATA $FF, 0, 3, 1, 0
ServoSpeeds DATA $FF, 0, 4, 0, 0
'
[noparse][[/noparse] Variables ]
tLeft VAR Word ' Servo control pulse durations
tRight VAR Word
temp VAR Word ' Temp variable
' Buffer array not declared as buffer VAR Word(5) for SERIN functionality.
' It can still be accessed as buffer(0), buffer(1), etc. However,
' buffer0, buffer1, etc. should be used in SERIN commands with variations
' of WAIT.
buffer0 VAR Byte ' Buffer - Start char = $ff
buffer1 VAR Byte ' Message Index value
buffer2 VAR Byte ' Command
buffer3 VAR Byte ' Argument 1 (return data 1)
buffer4 VAR Byte ' Argument 2 (return data 2)
buffer VAR buffer0 ' For standard array indexing
duration VAR Byte ' 50ths of ms duration
frequency VAR Byte ' 50ths of frequency
pointer VAR Byte ' EEPROM pointer
msgIndex VAR Byte ' EEPROM message index
routine VAR Nib ' Routine selector
counter VAR Nib
index VAR Nib
flagWhiskers VAR Bit ' Act on Whisker values
flagDigSens VAR Bit ' Send back digital sensors 1/0s
' with every reply
flagIr VAR Bit '
tempBit VAR Bit
'
[noparse][[/noparse] Initialization ]
' This code makes it possible to toggle the Boe-Bot on/off by pressing and
' releasing the Board of Education's Reset button.
Program_Start:
' For on/off toggle with Reset
' READ ResetOnOff, temp
' temp = temp + 1
' WRITE ResetOnOff, temp
' IF temp.BIT0 = 0 THEN
' FREQOUT 4, 1000, 2000 - Indicate inactive
' END
' ENDIF
HIGH 15
FREQOUT 4, 75, 4500
LOW 15
Reset:
DEBUG CLS
'Wait for the eb500 radio to be ready.
PAUSE 1000
'Wait for the EB500 Bluetooth connection to be established.
DO UNTIL IN5 = 1: LOOP
GOSUB Ram_Clear
Request_Connect:
pointer = RequestConnect
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
Confirm_Connect:
pointer = ConnectionGranted
GOSUB Get_Packet
Wait_For_Confirm:
' TT - This is hard-coded here, so add version number (last two bytes)
SEROUT 1, 84, [noparse][[/noparse]255, 0, 1, 1, 0]
SERIN 0, 84, 20, Wait_For_Confirm, [noparse][[/noparse]WAITSTR buffer \ 2,
buffer2, buffer3,
buffer4]
Request_Packet:
msgIndex = msgIndex + 1
' TT - The protocol does not allow 255 in any other byte other than
' the very first one
IF msgIndex = 255 THEN
msgIndex = 0
ENDIF
pointer = RequestCommand
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
'
[noparse][[/noparse] Main Routine ]
DO
Resume: ' If Message not rcvd, try again
IF IN5 = 0 THEN Reset ' EB500 disconnected?
PULSOUT 13, tLeft ' Servo control pulses
PULSOUT 12, tRight
SERIN 0, 84, 5, Resume, ' Get next command
[noparse][[/noparse]WAITSTR buffer \ 2, buffer2,
buffer3, buffer4]
PULSOUT 13, tLeft ' Servo control pulses again
PULSOUT 12, tRight
' Just in case the 192 is missed, check for 2 also
' because the host PC sends these continuously
' TT - MSRS service seems to send a 2 instead of 192
IF buffer2 = 192 OR buffer2 = 2 THEN ' Handle restart req from PC
msgIndex = 0
GOTO Request_Connect
ENDIF
LOOKDOWN buffer2,[noparse][[/noparse]32, 33,
64, 65,
96, 97, 98,
128, 129, 130,
160, 161, 162], routine
ON routine GOSUB Set_Servo_Speed, Maneuver,
Get_Ir, Get_Whiskers,
Speaker_Tone, Set_Pins, Delay,
Enable_Digital_Sensors, Enable_Ir, Enable_Whiskers,
Disable_Digital_Sensors, Disable_Ir, Disable_Whiskers
' Load digital sensor values into buffer byte 3 for return message.
IF flagDigSens = 1 THEN GOSUB Digital_Sensors
' Increment message index for reply. Next message from PC has to use
' reply's buf.
msgIndex = msgIndex + 1
' TT - Protocol does not allow 255!
IF msgIndex = 255 THEN
msgIndex = 0
ENDIF
buffer1 = msgIndex
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
LOOP
'
[noparse][[/noparse] Subroutine Digital_Sensors ]
' This subroutine is used by the main routine to return digital sensor values
' with each reply.
Digital_Sensors:
buffer3 = 0
GOSUB Get_Ir
GOSUB Get_Whiskers
IF ((buffer3.BIT2 = 0 OR buffer3.BIT3 = 0) AND (flagWhiskers = 1)) THEN
tLeft = tLeft MAX 750
tRight = tRight MIN 750
ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Set_Servo_Speed ]
' Range of 0 to 200 with 100 = stopped maps to 650 to 850 with 750 stopped.
Set_Servo_Speed:
tLeft = buffer3 + 650 ' Decode servo speed.
tRight = buffer4 + 650
RETURN
'
[noparse][[/noparse] Subroutine Speaker_Tone ]
Speaker_Tone:
duration = buffer3 ' Decode speaker tone
frequency = buffer4
FREQOUT 4, duration * 50, frequency * 50 ' Transmit tone
RETURN ' Go to resume routine
'
[noparse][[/noparse] Subroutine Get_Ir ]
' IR object detection for buf bits 1 (left) and 0 (right).
Get_Ir:
' IF flagIr THEN
FREQOUT 9, 1, 38500 ' IR headlight
tempBit = IN10 ' IR receiver
buffer3.BIT1 = tempBit ' Left IR reply bit
FREQOUT 3, 1, 38500
tempBit = IN2
buffer3.BIT0 = tempBit
' ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Get_Packet ]
' Loads packet into buffer for transmitting. Used by initialization.
Get_Packet:
FOR index = 0 TO 4
READ pointer + index, buffer(index)
NEXT
buffer(1) = msgIndex
RETURN
'
[noparse][[/noparse] Subroutine Display_Command ]
' For debugging.
Display_Command:
' FOR index = 0 TO 4
' DEBUG DEC buffer(index), CR
' NEXT
RETURN
'
[noparse][[/noparse] Subroutine - Check_Whiskers ]
' Stores left and right wiskers (contact switches) for buf bit 3 (left) and
' 2 (right).
Get_Whiskers:
'IF FlagWhiskers THEN
buffer3.BIT3 = IN7 ' Left whisker
buffer3.BIT2 = IN8 ' Right whisker
'ENDIF
RETURN
'
[noparse][[/noparse] Subroutine - Set_Pins ]
' Sets up to two pins. buf high nibble specifies the operation, and the
' low nibble specifies the pin. The same applies to buf.
' High nibble:
' 0 - no action
' 1 - set to output
' 2 - set to input
' 3 - set to (output-high)
' 4 - set to (output-low)
' Low Nibble:
' 0 to 15 - Specifies I/O pin.
' DO NOT try to set 0, 1, 5, or 6.
Set_Pins:
temp.NIB1 = buffer3.HIGHNIB
temp.NIB0 = buffer3.LOWNIB
GOSUB Op_Pins
temp.NIB1 = buffer4.HIGHNIB
temp.NIB0 = buffer4.LOWNIB
GOSUB Op_Pins
RETURN
Op_pins:
SELECT temp.NIB1
CASE 1
OUTPUT temp.NIB0
CASE 2
INPUT temp.NIB0
CASE 3
HIGH temp.NIB0
CASE 4
LOW temp.NIB0
ENDSELECT
RETURN
'
[noparse][[/noparse] Subroutine - Delay ]
' Specify delay in ms.
Delay:
temp.LOWBYTE = buffer3
temp.HIGHBYTE = buffer4
PAUSE temp
RETURN
'
[noparse][[/noparse] Subroutine - Enable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Enable_Digital_Sensors:
FlagDigSens = 1
RETURN
'
[noparse][[/noparse] Subroutine - Disable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Disable_Digital_Sensors:
FlagDigSens = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Causes program to stop the Boe-Bot if Whisker contact is sensed. This gives
' the PC bluetooth system time to reply.
Enable_Whiskers:
flagWhiskers = 1
RETURN
'
[noparse][[/noparse] Subroutine Disable_Whiskers ]
' Causes program to ignore the whisker contact. Also ignores when they are
' not connected.
Disable_Whiskers:
flagWhiskers = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Ir ]
' Not implemented.
Enable_Ir:
flagIr = 1
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Not implemented.
Disable_Ir:
flagIr = 0
RETURN
'
[noparse][[/noparse] Subroutine - Maneuver ]
' Preprogrammed maneuver example. Current setup allows:
' "U" - Back up then U-turn
' "R" - Back up then right turn
' "L" - Back up then left turn
'
' TT - Added Oct-2007
' Additional behaviours for better control.
' All of these take a parameter which is a counter
' that effectively controls the time duration.
' The counter is roughly in increments of 23ms.
' "F" - Move Forward
' "B" - Move Backward
' "A" - Move Anti-Clockwise (Rotate Left)
' "C" - Move Clockwise (Rotate Right)
'
' The changes to the code also allow the duration
' of the "back up" to be altered independently
' for each of the behaviors. It could be specified
' as a parameter, but this seems unnecessary.
'
' IMPORTANT NOTE: While a behavior is being executed,
' the robot is effectively operating blind! It does
' not send back any sensor information or even look
' at the sensors itself.
Maneuver:
SELECT buffer3
CASE "U"
GOSUB BackUp
FOR temp = 0 TO 40
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "R"
GOSUB BackUp
FOR temp = 0 TO 20
PULSOUT 13, 850
PULSOUT 12, 850
PAUSE 20
NEXT
CASE "L"
GOSUB BackUp
FOR temp = 0 TO 20
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
' New behaviors
CASE "F" ' Forward
FOR temp = 0 TO buffer4
PULSOUT 13, 850
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "B" ' Backward
FOR temp = 0 TO buffer4
PULSOUT 13, 650
PULSOUT 12, 850
PAUSE 20
NEXT
CASE "A" ' Anti-Clockwise
FOR temp = 0 TO buffer4
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "C" ' Clockwise
FOR temp = 0 TO buffer4
PULSOUT 13, 850
PULSOUT 12, 850
PAUSE 20
NEXT
ENDSELECT
RETURN
BackUp:
FOR temp = 0 TO 35
PULSOUT 13, 650
PULSOUT 12, 850
PAUSE 20
NEXT
RETURN
'
[noparse][[/noparse] Subroutine Ram_Clear ]
' Clears ram for reset from PC. This prevents retaining the msgIndex and
' pulseLeft/right variable values, which would otherwise cause problems.
Ram_Clear:
W0 = 0
W1 = 0
W2 = 0
W3 = 0
W4 = 0
W5 = 0
W6 = 0
W7 = 0
W8 = 0
W9 = 0
W10 = 0
W11 = 0
W12 = 0
RETURN
2b.
'
[noparse][[/noparse] Title ]
' File: BoeBotControlForMsrsCtp2.bs2
' {$STAMP BS2}
' {$PBASIC 2.5}
'
[noparse][[/noparse] DATA ]
ResetOnOff DATA 0 ' On/off toggle w/ Reset button
RequestConnect DATA $FF, 0, 1, 0, 0
ConnectionGranted DATA $FF, 0, 2, 0, 0
RequestCommand DATA $FF, 0, 3, 0, 0
ServoSpeeds DATA $FF, 0, 4, 0, 0
'
[noparse][[/noparse] Variables ]
tLeft VAR Word ' Servo control pulse durations
tRight VAR Word
temp VAR Word ' Temp variable
' Buffer array not declared as buffer VAR Word(5) for SERIN functionality.
' It can still be accessed as buffer(0), buffer(1), etc. However,
' buffer0, buffer1, etc. should be used in SERIN commands with variations
' of WAIT.
buffer0 VAR Byte ' Buffer - Start char = $ff
buffer1 VAR Byte ' Message Index value
buffer2 VAR Byte ' Command
buffer3 VAR Byte ' Argument 1 (return data 1)
buffer4 VAR Byte ' Argument 2 (return data 2)
buffer VAR buffer0 ' For standard array indexing
duration VAR Byte ' 50ths of ms duration
frequency VAR Byte ' 50ths of frequency
pointer VAR Byte ' EEPROM pointer
msgIndex VAR Byte ' EEPROM message index
routine VAR Nib ' Routine selector
counter VAR Nib
index VAR Nib
flagWhiskers VAR Bit ' Act on Whisker values
flagDigSens VAR Bit ' Send back digital sensors 1/0s
' with every reply
flagIr VAR Bit '
tempBit VAR Bit
'
[noparse][[/noparse] Initialization ]
' This code makes it possible to toggle the Boe-Bot on/off by pressing and
' releasing the Board of Education's Reset button.
Program_Start:
' For on/off toggle with Reset
' READ ResetOnOff, temp
' temp = temp + 1
' WRITE ResetOnOff, temp
' IF temp.BIT0 = 0 THEN
' FREQOUT 4, 1000, 2000 - Indicate inactive
' END
' ENDIF
HIGH 15
FREQOUT 4, 75, 4500
LOW 15
Reset:
DEBUG CLS
'Wait for the eb500 radio to be ready.
PAUSE 1000
'Wait for the EB500 Bluetooth connection to be established.
DO UNTIL IN5 = 1: LOOP
GOSUB Ram_Clear
Request_Connect:
pointer = RequestConnect
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
Confirm_Connect:
pointer = ConnectionGranted
GOSUB Get_Packet
Wait_For_Confirm:
SEROUT 1, 84, [noparse][[/noparse]255, 0, 1, 0, 0]
SERIN 0, 84, 20, Wait_For_Confirm, [noparse][[/noparse]WAITSTR buffer \ 2,
buffer2, buffer3,
buffer4]
Request_Packet:
msgIndex = msgIndex + 1
pointer = RequestCommand
GOSUB Get_Packet
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
'
[noparse][[/noparse] Main Routine ]
DO
Resume: ' If Message not rcvd, try again
IF IN5 = 0 THEN Reset ' EB500 disconnected?
PULSOUT 13, tLeft ' Servo control pulses
PULSOUT 12, tRight
SERIN 0, 84, 5, Resume, ' Get next command
[noparse][[/noparse]WAITSTR buffer \ 2, buffer2,
buffer3, buffer4]
PULSOUT 13, tLeft ' Servo control pulses again
PULSOUT 12, tRight
IF buffer2 = 192 THEN ' Handle restart req from PC
msgIndex = 0
GOTO Request_Connect
ENDIF
LOOKDOWN buffer2,[noparse][[/noparse]32, 33,
64, 65,
96, 97, 98,
128, 129, 130,
160, 161, 162], routine
ON routine GOSUB Set_Servo_Speed, Maneuver,
Get_Ir, Get_Whiskers,
Speaker_Tone, Set_Pins, Delay,
Enable_Digital_Sensors, Enable_Ir, Enable_Whiskers,
Disable_Digital_Sensors, Disable_Ir, Disable_Whiskers
' Load digital sensor values into buffer byte 3 for return message.
IF flagDigSens = 1 THEN GOSUB Digital_Sensors
' Increment message index for reply. Next message from PC has to use
' reply's buf.
msgIndex = msgIndex + 1
buffer1 = msgIndex
SEROUT 1, 84, [noparse][[/noparse]STR buffer \5]
LOOP
'
[noparse][[/noparse] Subroutine Digital_Sensors ]
' This subroutine is used by the main routine to return digital sensor values
' with each reply.
Digital_Sensors:
buffer3 = 0
GOSUB Get_Ir
GOSUB Get_Whiskers
IF ((buffer3.BIT2 = 0 OR buffer3.BIT3 = 0) AND (flagWhiskers = 1)) THEN
tLeft = tLeft MAX 750
tRight = tRight MIN 750
ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Set_Servo_Speed ]
' Range of 0 to 200 with 100 = stopped maps to 650 to 850 with 750 stopped.
Set_Servo_Speed:
tLeft = buffer3 + 650 ' Decode servo speed.
tRight = buffer4 + 650
RETURN
'
[noparse][[/noparse] Subroutine Speaker_Tone ]
Speaker_Tone:
duration = buffer3 ' Decode speaker tone
frequency = buffer4
FREQOUT 4, duration * 50, frequency * 50 ' Transmit tone
RETURN ' Go to resume routine
'
[noparse][[/noparse] Subroutine Get_Ir ]
' IR object detection for buf bits 1 (left) and 0 (right).
Get_Ir:
' IF flagIr THEN
FREQOUT 9, 1, 38500 ' IR headlight
tempBit = IN10 ' IR receiver
buffer3.BIT1 = tempBit ' Left IR reply bit
FREQOUT 3, 1, 38500
tempBit = IN2
buffer3.BIT0 = tempBit
' ENDIF
RETURN
'
[noparse][[/noparse] Subroutine Get_Packet ]
' Loads packet into buffer for transmitting. Used by initialization.
Get_Packet:
FOR index = 0 TO 4
READ pointer + index, buffer(index)
NEXT
buffer(1) = msgIndex
RETURN
'
[noparse][[/noparse] Subroutine Display_Command ]
' For debugging.
Display_Command:
' FOR index = 0 TO 4
' DEBUG DEC buffer(index), CR
' NEXT
RETURN
'
[noparse][[/noparse] Subroutine - Check_Whiskers ]
' Stores left and right wiskers (contact switches) for buf bit 3 (left) and
' 2 (right).
Get_Whiskers:
'IF FlagWhiskers THEN
buffer3.BIT3 = IN7 ' Left whisker
buffer3.BIT2 = IN8 ' Right whisker
'ENDIF
RETURN
'
[noparse][[/noparse] Subroutine - Set_Pins ]
' Sets up to two pins. buf high nibble specifies the operation, and the
' low nibble specifies the pin. The same applies to buf.
' High nibble:
' 0 - no action
' 1 - set to output
' 2 - set to input
' 3 - set to (output-high)
' 4 - set to (output-low)
' Low Nibble:
' 0 to 15 - Specifies I/O pin.
' DO NOT try to set 0, 1, 5, or 6.
Set_Pins:
temp.NIB1 = buffer3.HIGHNIB
temp.NIB0 = buffer3.LOWNIB
GOSUB Op_Pins
temp.NIB1 = buffer4.HIGHNIB
temp.NIB0 = buffer4.LOWNIB
GOSUB Op_Pins
RETURN
Op_pins:
SELECT temp.NIB1
CASE 1
OUTPUT temp.NIB0
CASE 2
INPUT temp.NIB0
CASE 3
HIGH temp.NIB0
CASE 4
LOW temp.NIB0
ENDSELECT
RETURN
'
[noparse][[/noparse] Subroutine - Delay ]
' Specify delay in ms.
Delay:
temp.LOWBYTE = buffer3
temp.HIGHBYTE = buffer4
PAUSE temp
RETURN
'
[noparse][[/noparse] Subroutine - Enable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Enable_Digital_Sensors:
FlagDigSens = 1
RETURN
'
[noparse][[/noparse] Subroutine - Disable_Digital_Sensors ]
' Causes program to put digital sensor values in buf of the reply packet.
Disable_Digital_Sensors:
FlagDigSens = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Causes program to stop the Boe-Bot if Whisker contact is sensed. This gives
' the PC bluetooth system time to reply.
Enable_Whiskers:
flagWhiskers = 1
RETURN
'
[noparse][[/noparse] Subroutine Disable_Whiskers ]
' Causes program to ignore the whisker contact. Also ignores when they are
' not connected.
Disable_Whiskers:
flagWhiskers = 0
RETURN
'
[noparse][[/noparse] Subroutine Enable_Ir ]
' Not implemented.
Enable_Ir:
flagIr = 1
RETURN
'
[noparse][[/noparse] Subroutine Enable_Whiskers ]
' Not implemented.
Disable_Ir:
flagIr = 0
RETURN
'
[noparse][[/noparse] Subroutine - Maneuver ]
' Preprogrammed maneuver example. Current setup allows:
' "U" - Back up then U-turn
' "R" - Back up then right turn
' "L" - Back up then left turn
Maneuver:
FOR temp = 0 TO 35
PULSOUT 13, 650
PULSOUT 12, 850
PAUSE 20
NEXT
SELECT buffer3
CASE "U"
FOR temp = 0 TO 40
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
CASE "R"
FOR temp = 0 TO 20
PULSOUT 13, 850
PULSOUT 12, 850
PAUSE 20
NEXT
CASE "L"
FOR temp = 0 TO 20
PULSOUT 13, 650
PULSOUT 12, 650
PAUSE 20
NEXT
ENDSELECT
RETURN
'
[noparse][[/noparse] Subroutine Ram_Clear ]
' Clears ram for reset from PC. This prevents retaining the msgIndex and
' pulseLeft/right variable values, which would otherwise cause problems.
Ram_Clear:
W0 = 0
W1 = 0
W2 = 0
W3 = 0
W4 = 0
W5 = 0
W6 = 0
W7 = 0
W8 = 0
W9 = 0
W10 = 0
W11 = 0
W12 = 0
RETURN
Comments
Ok, I found something to help.
http://www.promrds.com/Downloads.htm
"The Samples Package for July CTP is a DssDeploy package. It will only install into the July CTP."
It has the updated files needed for Boe Bot.
Hooray!!!
When I posted that I was at my witts end, stressed!
I'm sure you know the feeling.
AAaaarrrrrrrr, why won't this work right.
Anyone else,
I will post any new info as it comes up.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Skroeder: What the hell does it need input for?
Newton Crosby: I don't know; I guess it can't triangulate its position.
Howard Marner: That's a simple function.
Newton Crosby: Can you triangulate YOUR position, Howard?
Howard Marner: No.
Newton Crosby: Well, then - there you go!
I am also stuck at this point. I don't know how to proceed with it.
I have gotten no where with this software. Very frustrating.
I have tried with the Lego NXT and the Boebot but always the documentation and files provided was not enough.
So with this in mind I have moved on to C++ with the Lego NXT.
If you find anything please post.
Rogue7
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Skroeder: What the hell does it need input for?
Newton Crosby: I don't know; I guess it can't triangulate its position.
Howard Marner: That's a simple function.
Newton Crosby: Can you triangulate YOUR position, Howard?
Howard Marner: No.
Newton Crosby: Well, then - there you go!