Definition of the SRV-1 Control Protocol (Blackfin Version) - as of 6 February 2009

All commands from the host to the SRV-1 robot are comprised of ASCII characters or ASCII followed by 8-binary or ASCII decimal characters. All commands receive an acknowledgment from the robot to the host, which is either a '#' character followed by the command, or '##' for variable length responses. Variable length commands which don't specify a return size append a newline ('\n') to their response.
Note that all of these commands can be executed via a terminal program with TCP / telnet capability. For example, you can connect using the 'netcat' command via
'nc robot-ip 10001'
When the robot first powers up, it will dump the 'V' Version command results ("##Version ...\n") so you can see what version of firmware is running. There is typically a 2 second delay after startup before the robot can accept any commands while the camera and other sensors are initialized - you should see the yellow LED's flash when the processor reboots. After startup, just to test that there is 2-way communication, send an 'V' to access the firmware version string. The only command that will produce strange results is the 'I' IMJ command, which grabs a JPEG frame - this will flood the screen with binary characters.
The firmware has two small interpreters - one is a prototype Lisp interpreter and the other is the Little C interpreter. The 'Q' command will execute the C program that has been stored in the robot's flash buffer. The 'P' command will run a Lisp program from the flash buffer, and the '!' command will run Lisp interactively, terminated with an ESC. The flash buffer can be set by the 'zr' command which transfers the contents of the user flash segment to the flash buffer, or via the 'X' command which transfers a file from the host via XMODEM protocol. Before executing a program, the contents of the flash buffer can be examined using 'zd'. When the program finishes (assuming the C program isn't running an infinite loop), control returns to the regular SRV-1 command processing loop.
If there are any questions about this protocol, send email to support@surveyor.com or check the Surveyor Robotics Forum.

CommandResponseDescription
Core Robot Commands
except for 'q' command, all parameters are sent as 8-bit binary characters (0x00 - 0xFF)
'7''#7'note that keypad commands ('1' - '9') don't become active until an 'Mxxx' motor control command has been received

robot drift left
'8''#8'robot drive forward
'9''#9'robot drift right
'4''#4'robot drive left
'5''#5'robot stop
'6''#6'robot drive right
'1''#1'robot back left
'2''#2'robot drive back
'3''#3'robot back right
'0''#0'robot rotate left 20-deg
'.''#.'robot rotate right 20-deg
'+''#+'increase motor/servo level
'-''#-'decrease motor/servo level
'<''#<'trim motor balance toward left
'>''#>'trim motor balance toward right
'a''#a'set capture resolution to 160x120
'b''#b'set capture resolution to 320x240
'c''#c'set capture resolution to 640x480
'd' or 'A''#A'set capture resolution to 1280x1024
'E'launches flash buffer line editor -
(T)op (B)ottom (P)reviouse (N)ext line (L)ist (I)nsert until ESC (D)elete (H)elp (X)exit
'Fab''#F'Enables Failsafe mode for motor control
'ab' parameters sent as 8-bit binary

a = left motor/servo failsafe level, b = right motor/servo failsafe level.

sets motor/servo levels for 'M' and 'S' commands in case no command is received via the radio link within 2 seconds.
'f''#f'disables Failsafe mode
'g0''##g0'grab reference frame and enable frame differencing
'g1''##g1'enable color segmentation
'g2''##g2'enable edge detection (threshold changed with 'T' command)
'G''#G'disable frame differencing / color segmentation / edge detection
'h''#h'switch serial channel to high baud rate (2500kbps)
'I''##IMJxs0s1s2s3....'grab JPEG compressed video frame

x = frame size in pixels:
1 = 80x64, 3 = 160x120, 5 = 320x240, 7 = 640x480, 9 = 1280x1024

s0s1s2s3=frame size in bytes (s0 * 256^0 + s1 * 256^1 + s2 * 256^2 + s3 * 256^3)
.... = full JPEG frame

Note that sometimes the 'I' command returns nothing if the robot camera is busy, so the 'I' command should be called as many times as needed until a frame is returned
'irab''##ir cc'I2C register read ('ab' parameters sent as 8-bit binary)
a is device id, b is register, cc is 8-bit return value from register displayed as decimal value
'iRab''##iR cc'I2C register read ('ab' parameters sent as 8-bit binary)
a is device id, b is register, cc is 16-bit return value from register displayed as decimal value
'iwabc''##iw'I2C register write ('abc' parameters sent as 8-bit binary)
a is device id, b is register, c is value written to register
'l''#l'turn on lasers
'L''#L'turn off lasers
'Mabc''#M'direct motor control
'abc' parameters sent as 8-bit binary

a=left speed, b=right speed, c=duration*10milliseconds

speeds are 2's complement 8-bit binary values - 0x00 through 0x7F is forward, 0xFF through 0x81 is reverse, e.g. the decimal equivalent of the 4-byte sequence 0x4D 0x32 0xCE 0x14 = 'M' 50 -50 20 (rotate right for 200ms)

duration of 00 is infinite, e.g. the 4-byte sequence 0x4D 0x32 0x32 0x00 = M 50 50 00 (drive forward at 50% indefinitely)
'o''#o'enable caption overlay
'O''#O'disable caption overlay
'p''##ping xxxx xxxx xxxx xxxx\n'ping ultrasonic ranging modules attached to pins 27, 28, 29, 30 with trigger on pin 18 - tested with Maxbotics EZ0 and EZ1 modules. xxxx return value is range in inches * 100 (2500 = 25 inches)
'qx''##quality x\n'sets JPEG quality between 1-8 ('x' is an ASCII decimal character). 1 is highest, 8 is lowest
'R''##Range(cm) = xxx'measure range to nearest obstacle using laser pointers
'r''##Range(cm)'same as 'R', but with lots of diagnostic output
'Sab''#S'direct servo control (TMR2 and TMR3)
'ab' parameters sent as 8-bit binary

a=left servo setting (0x00-0x64), b=right servo setting (0x00-0x64)

servo settings are 8-bit binary values, representing timing pulse widths ranging from 1ms to 2ms. 0x00 corresponds to a 1ms pulse, 0x64 corresponds to a 2ms pulse, and 0x32 is midrange with a 1.5ms pulse
'sab''#s'direct servo control of 2nd bank of servos (TMR6 and TMR7)
'ab' parameters sent as 8-bit binary

a=left servo setting (0x00-0x64), b=right servo setting (0x00-0x64)

servo settings are 8-bit binary values, representing timing pulse widths ranging from 1ms to 2ms. 0x00 corresponds to a 1ms pulse, 0x64 corresponds to a 2ms pulse, and 0x32 is midrange with a 1.5ms pulse
't''##time - millisecs: xxxx\n'outputs time in milliseconds since reset
'Tx''#T'changes threshold in 'g2' edge detection - T4 is default, range is T1 to T9
'V''##Version ...\n'read firmware version info
response is terminated by newline character
'X''#Xmodem transfer count: bytes'Xmodem-1K file transfer - receive file via xmodem protocol - store in flash buffer
'y''#y'flip video capture (for use with upside-down camera)
'Y''#Y'restore video capture to normal orientation
'zc''##zclear\n'clear contents of flash buffer
'zC''##zCRC xxxx\n'compute crc16_ccitt for flash buffer
'zd''##zd...\n'flash buffer dump - dump contents of flash memory buffer to console
'zr''##zr\n'flash memory read - read 65kb from user flash sector to flash buffer (e.g. read C program from flash sector before running C interpreter)
'zRxx''##zRead\n'flash memory read - read 65kb from specified flash sector xx (02 - 63) to flash buffer (e.g. read C program from flash sector before running C interpreter). Sectors 00 and 01 are off-limits.
'zw''##zw\n'flash memory write - write 65kb from flash buffer to user flash sector
'zWxx''##zWxx\n'flash memory write - write 65kb from flash buffer to specified flash sector 02-63 (sectors 00 and 01 are off-limits)
'zZ''##zZ\n'flash memory boot sector update - writes contents of flash buffer to boot sectors of flash memory - used to replace u-boot.ldr or srv1.ldr - checks first that a valid LDR format image is in the flash buffer
Special Commands
'$!'reset Blackfin
'$R'SVS command - configures slave Blackfin to receive SPI transfer to flash buffer
'$X'SVS command - configures master Blackfin to transfer contents of flash buffer via SPI
'C'play chess. before first use, save book.txt book openings to flash sector 5 with zW05 command
Vision Commands
all parameters are sent as ASCII decimal characters ('0' - '9')
'vbc''##vbc x1 x2 y1 y2 ssss...\n'the 'vb' command searches for blobs matching the colors in color bin #c, and returns coordinates of an x1, x2, y1, y2 rectangular region containing the matching pixels, along with a count of matching pixels in the blob. up to 16 blobs can be returned, and the blobs are sent in order of pixel count, though blobs smaller than MIN_BLOB_SIZE (currently set to 5 pixels) aren't shown.
'vccy1y2u1u2v1v2''##vcc\n'the 'vc' command directly sets the contents of color bin #c.
this command will return string with 'vc' followed by the color bin number.
for example, we could save a set of colors to color bin #3 corresponding to measurements taken at another time, such as the above mentioned orange golf ball color measurement, using 'vc3127176086111154200'. we could then confirm that the colors were properly stored by issuing the command 'vr3' to retrieve the contents of color bin #3.
'vh''##vhist y u v\n'computes and lists the distribution of Y, U and V pixels over the entire range of possible values, divided into bins of 0-3, 4-7, 8-11, ... 248-251, 252-255
'vm''##vmean yy uu vv\n'computes mean values for Y, U and V over the entire image.
'vpxxxxyyyy''##vp yyy uuu vvv\n'the 'vp' command samples a single pixel defined by coordinates xxxx (column 0000-0159, 0000-0319, 0000-0639, 0000-1279 depending on resolution) and yy (row 0000-0127, 0000-0255, 0000-0511, 0000-1023, where 0000 is top of image). 'vp01600128' will sample a pixel in the middle of the image at 320x256 resolution, 'vp01600000' will sample a pixel in the middle of the top row, etc...
'vrc''##vrc y1 y2 u1 u2 v1 v2\n'the 'vr' command retrieves the stored color info from color bin #c.
this command will return string with 'vr' followed by the color bin number, followed by y1=Ymin, y2=Ymax, u1=Umin, u2=Umax, v1=Vmin, v2=Vmax.
in the above example where colors for an orange golf ball were captured using the 'vg' command for color bin #0, issuing a 'vr0' command will return the colors stored in color bin #0 - e.g. '##vr0 127 176 86 111 154 200\n'.
'vzx''##vzero\n'vz0 zeros out all of the color bins, vz1 / vz2 / vz3 / vz4 segments colors into various color spaces which can be used by enabling 'g1' color segmentation function ('G' turns it off)
Neural Network Commands
all parameters are sent as ASCII hex characters ('0' - 'f')
'np'store a new pattern
'nd'display a stored pattern
'ni'initialize the network with random weights
'nt'train the network from stored patterns
'nx'test the network with sample pattern
'ng'grab a pattern using blob located by "vb"
'nb'match pattern against specific blob from "vb"
Lisp Commands
'P'execute Lisp from flash bufferruns Lisp program stored in flash buffer, which got there via the 'zr' command (which reads user flash sector into flash buffer), 'X' command (XMODEM file transfer), or 'E' line editor. The interpreter is based on the Scheme dialect of Lisp, using code from "Scheme In One Defun" (SIOD) by George J. Carrette.
'!'execute Lisp interactivelyruns Lisp interactively from console; ESC character (0x1B) terminates interpreter and returns to main firmware control loop

Lisp primitives
built-in functions + - * / = > < eq? eqv? null? pair? symbol? number? and or not
car cdr cons set-car! set-cdr! set! print eval define lambda
while quote if begin reverse
special functions (console) - pass interpreter control to console
(dump) - show current heap and stack pointers
(quit) - exit Lisp
(read) - input and process
(error) - throw error message
(oblist) - list all stored objects
robot functions (time) - returns time since last reset in milliseconds
(input) - reads from keyboard numbers 0-9 (blocking read)
(compass) - reads heading from HMC6352 compass (option)
(signal) - returns true on any input from console (non-blocking)
(rand x) - returns random value ranging from 0 to x
(range) - uses laser pointers to distance to nearest obstacle in cm's
(delay x) - wait x milliseconds
(lasers x) - non-zero value turns lasers on
(robot x) - move robot ... 2=back 5=stop 8=fwd 4=left 6=right
(ping x) - read from sonar module 1-4
(color x '(ymin ymax umin umax vmin vmax)) - set color bin 0-16
(blob x) - search on color bin x
; commentno processing of characters to end of line, e.g.
; this is a comment
C Language Commands
'Q'execute C programruns C program stored in flash buffer, which got there via the 'E' line editor, the 'zr' command (which reads user flash sector into flash buffer) or 'X' command (XMODEM file transfer)

C primitives
assignmentsa = b / 20;    a = a - 0x55;
operators+ - * / % & | ^ = ( ) > >= < <= == !=
int, char'int' is 32-bit signed integer, 'char' is 8 bit unsigned chars. variables declared locally or globally - variable names can be up to 31 characters in length
/* comment */no processing of characters, e.g.
/* this is a comment */
/* this is a
   two line comment */
for()for() loop, can be nested 15 deep, e.g.

main()
{
   int i, j, k;
   for(i = 0; i < 5; i = i + 1) {
     for(j = 0; j < 3; j = j + 1) {
       for(k = 3; k ; k = k - 1) {
         print(i);
         print(j);
         print(k);
       }
     }
   }
}
int|char|void function() ... returnup to 25 functions can be defined, function name length up to 25 characters, and functions can be called recursively e.g.

factr(int i)
{
   if (i < 2) {
     return 1;
   }
   else {
     return i * factr(i-1);
   }
}
if () ... else int x;
x = sonar(1);      /* read sonar range */
if (x < 500) {
  motors(50, -50);    /* if obstacle detected, turn right */
} else {
  motors(50, 50);
}
char input()checks the serial port (radio channel) for a single incoming character.

  ch = input() /* if no data is found, ch = 0 */
void print()prints a set of strings and variables, followed by a newline ('\n'), e.g.
  print("hello");
  print("test" x y z);
while()
while() ... do
do ... while()
  count = a;
   do {
     print(count);
   } while(count=count-1);
C - robot control/sense
void delay(milliseconds)program delay in milliseconds, e.g.

  delay(500);
int get(location)pointer operation - gets int data from memory location

   int S; S = get(0x00100000);    /* sets S from memory location 0x00100000 */
   int S; int T = 0x00100000; S = get(T);    /* sets S from memory location pointed to by T */
void laser(on/off)laser(1); turns on laser pointers, laser(0); turns them off
void motors(left, right)sets left and right motor output, e.g.

  motors(50, -50); /* spin right */
  motors(-50, 50); /* spin left */
  motors(-50, -50); /* go backwards */
  motors(50, 50); /* go forwards */
int rand()returns a pseudo-random number between 0 and 65535
int range()computes distance to nearest obstacle using laser pointers
int readi2c(channel, register)same as 'ir' command - returns 8-bit value
int readi2c2(channel, register)same as 'iR' command - returns 16-bit value
void servo(left, right)sets left and right servo output, e.g.

  servo(50, 50); /* stop */
  servo(25, 75); /* spin left */
  servo(25, 25); /* go backwards */
  servo(75, 75); /* go forward */
void servo2(left, right)same as servo() command, but supports a 2nd set of servos on timer ports 6 & 7
int sonar(channel)if sonar transducers are installed, returns measured range in channels 1-4. return value of 0 means there is no active transducer on that channel
void set(location, value)pointer operation - write int data to memory location

   set(0x00100000, 555);    /* writes 555 to memory location 0x00100000 */
   int S = 0x00100000; set(S, 555);    /* writes 555 to memory location pointed to by S */
   int T = 555; set(0x00100000, T);    /* writes value of T to memory 0x00100000 */
   int S=0x00100000; int T = 555; set(S, T);    /* writes value of T to memory location pointed to by S */
int time()get current time (milliseconds since startup) -

  int t1;
  t1 = time();
int writei2c(channel, register, value)same as 'iw' command
C - robot vision
int blob(color, num)size = blob(colorbin, blobnum); - similar to the "vb" Blob function above, but only returns the selected blob[blobnum] matching the specified color (0 - 9), using reserved variables x, y and z, where x = centroid x coordinate, y = centroid y coordinate, z = blob width. Note that calling blob() with blobnum=0 will compute a new blob search, but calling blob() with blobnum>0 will only retrieve previous located blobs rather than triggering a new search
e.g.

main() {
  int x, y, z;
  color(2, 100, 140, 90, 110, 130, 160);
  imgcap();
  if (blob(2, 0))
  {
    print("blob 0" x y z);   }
  if (blob(2, 1))
  {
    print("blob 1" x y z);   }
}

which might output
   blob 0 40 30 15
   blob 1 60 25 8
for one blob centered at (40,30) with a width of 15 pixels and another blob centered at (60,25) with a width of 8 pixels

a returned size of 0 would indicate that no matching blob was found
void color(bin, y0, y1, u0, u1, v0, v1)sets the y, u, v color range for a color bin, e.g.

    color(0, 100, 140, 90, 110, 130, 160);

would set color bin #0 with y ranging 100-140, u 90-110, v 130-160. functionally equivalent to 'vc' color set function, and results can be confirmed with 'vr' command
void imgcap()captures image at default resolution
void imgrcap()captures and stores reference frame at default resolution
void imgdiff(flag)enables image differencing on captured images at default resolution. imgdiff(1) causes imgcap() to compute difference between latest captured frame and reference frame, imgdiff(0) turns off frame differencing
void resolution('abcA')changes capture resolution 'a' = 160x128, 'b' = 320x256, 'c' = 640x512, 'A' = 1280x1024


last updated 27 February 2009 - 23:50 GMT