Scribbler Wire Protocol

From IPRE Wiki
Jump to: navigation, search

This documentation is based upon the contents of the scribbler server code located here.


Messages to the Scribbler are a constant 9 bytes long. Messages from the Scribbler are variable length depending on the message type. See below for details.

On startup, the robot repeatedly sends its name preceded by "IPRE" every 'TIMEOUT milliseconds. This allows the PC to find it and connect. After the Scribbler receives a command, this name broadcasting stops.

All "SET" messages have a return type of "GET_ALL".

Messages TO robot:

  • The first byte is the message type
  • The next bytes are the command data (if any)
  • The rest of the message is filled with null characters until a total of 9 bytes.

Messages FROM robot:

  • The first bytes are the message data
  • The last byte is the message type
  • If the message is a GET type message, just the requested data is sent
  • If the message is a SET type message, the binary state of the robot is sent


name values notes
SOFT_RESET 33 Format: 33 0 0 0 0 0 0 0 0, Notes: Performs a software reset of robot. (turns name broadcast back on)

GET Commands

name values notes
GET_ALL 65 leftIR rightIR LeftLightHighyte LeftLightLowByte CenterLightHighByte CenterLightLowByte RightLightHighByte RightLightLowByte LineLeft LineRight Stall 65
GET_ALL_BINARY 66 BinaryData 66, Notes: where the individual bits of BinaryData are: 0x000 IRLeft IRRight Stall LineLeft LineRight
GET_LIGHT_LEFT 67 HighByte LowByte 67
GET_LIGHT_CENTER 68 HighByte LowByte 68
GET_LIGHT_RIGHT 69 HighByte LowByte 69
GET_LIGHT_ALL 70 LeftHighyte LeftLowByte CenterHighByte CenterLowByte RightHighByte RightLowByte 70
GET_IR_LEFT 71 leftIR 71, Notes: IR is 1 when there is no obstacle to the left of robot
GET_IR_RIGHT 72 rightIR 72, Notes: IR is 1 when there is no obstacle to the left of robot
GET_IR_ALL 73 LeftIR RightIR 73, Notes: IR is 1 when there is no obstacle to the left of robot
GET_LINE_LEFT 74 lineLeft 74
GET_LINE_RIGHT 75 lineRight 75
GET_LINE_ALL 76 LineLeft LineRight 76
GET_STATE 77 inPins outPins 77, Notes: inPins is the state of all the input pins (0-7), and outPins is the state of all the output pins (8-15) as defined in the I/O Pin Declarations.
GET_NAME1 78 char1 char2 char3 char4 char5 char6 char7 char8 78
GET_NAME2 64 char9 char10 char11 char12 char13 char14 char15 char16 87
GET_STALL 79 stall 79
GET_INFO 80 "information on version robot, etc" 10 80
GET_DATA 81 data from flash memory 81
GET_PASS1 50 16 bytes from flash memory
GET_PASS2 51 16 bytes from flash memory

SET Commands

name values notes
SET_SINGLE_DATA 96 Sets a single byte of data in flash memory'
SET_DATA 97 Sets 8 bytes of data in flash memory
SET_ECHO_MODE 98 Set the echo mode on or off; if off, no echo is made after command
SET_LED_ALL 107 107 LeftLEDstate CenterLEDstate RightLEDstate 0 0 0 0 0
SET_MOTORS_OFF 108 108 0 0 0 0 0 0 0 0
SET_MOTORS 109 109 rightmotor leftmotor 0 0 0 0 0 0, Notes: 0 = full speed backwards, 100 = stop, 200 = full speed forward
SET_NAME1 110 110 char1 char2 char3 char4 char5 char6 char7 char8
SET_NAME2 119 119 char9 char10 char11 char12 char13 char14 char15 char16
SET_SPEAKER 113 113 DurationHighByte DurationLowByte FreqHighByte FreqLowByte
SET_SPEAKER_2 114 114 DurationHighByte DurationLowByte Freq1HighByte Freq1LowByte Freq2HighByte Freq2LowByte
SET_PASS2 56 56 PASS9 PASS2 ... PASS16

Commands As Issued By Myro

When commands are issued via Myro, they are sent to the Fluke board, which in turn sends them to the Scribbler robot. Typical Myro commands send one or more sets of Scribbler wire commands to the Scribbler. For example the forward() function actually calls SET_MOTORS followed by SET_MOTORS_OFF. By turning on debugging within Myro, these bytes can be observed as follows:

>>> myro.globvars.robot.debug = 1
>>> forward(1, 1)
_write: mÈÈ 9 data: ['0x6d', '0xc8', '0xc8', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0']
_read (9)
['0x6d', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0']
_read (11)
['0x1', '0x1', '0x7', '0x3e', '0x12', '0x92', '0x3b', '0xa9', '0x0', '0x0', '0x0']
_write: l�������� 9 data: ['0x6c', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0']
_read (9)
['0x6c', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0']
_read (11)
['0x1', '0x1', '0xb', '0x13', '0xe', '0x8f', '0x39', '0xf3', '0x0', '0x0', '0x0']

From the output within IDLE, we can see that two sets of "write" commands are performed. The bytes written are in accordance with the previously listed byte layout. 0x6D = 109, which is SET_MOTORS, 0x6C = 108, which is SET_MOTORS_OFF. 0xC8 = 200 which is given as the 2nd and 3rd paramters to SET_MOTORS, which indicates full speed on both wheels.

We also see that for each set of bytes written out, two sets of reads are performed. This is due to the fact that the Fluke sits between Myro and the scribbler. The Fluke actually intercepts the commands are performs its communication with the Scribbler in addition to the bytes issued directly from Myro.

Response As Read By Myro

The latter of the two sets of "read" bytes are interpreted by the Myro framework and made available to the user. The 11 bytes returned are unpacked in getLastSensors:

  def getLastSensors(self):
      retval = self._lastSensors
      return {"light": [retval[2] << 8 | retval[3], retval[4] << 8 | retval[5], retval[6] << 8 | retval[7]],
              "ir": [retval[0], retval[1]], "line": [retval[8], retval[9]], "stall": retval[10]}

This method is called periodically and provides the latest values of various sensor values: light, ir, line, and stall.

In the code above, some sensor values are taken as two bytes. For example, the "light" sensor is computed as:

[retval[2] << 8 | retval[3]

Which bit shifts the 3rd byte to the left a whole byte taking the value from:




We then logically OR the 4th byte


Leaving us the 16-bit value