Monday, April 30, 2012

Controlling an iRobot Create over serial

Controlling an iRobot device is remarkably easy. If done over the receive and transmit pins on the db-25 connector, no connection configuration is needed and you can simply push messages over a GPIO. For us, it was easier to open and connect a USB-serial cable than build connections from the Beagleboard to the create ourselves. Driving and retrieving information from the create is simple once you've opened and configured the serial port properly, and here's a code snippet of how to do so:

In the beginning of the file:

/* Define the serial port path */
#define CREATE_SERIAL_PORT "/dev/ttyUSB0"
/* Define baudrate */
#define CREATE_SERIAL_BRATE B57600

Somewhere else in the file (such as a function):

fd = open(CREATE_SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY );


// can't open port
if (fd == -1) {
  printf("Error opening port\n");
  return -1;
}
// open successful
else {
  printf("Serial port opened with status: %d\n", fd);
  fcntl(fd, F_SETFL, 0);
}
// configure port
struct termios portSettings;
tcgetattr(fd, &portSettings);


if(cfsetispeed(&portSettings, CREATE_SERIAL_BRATE) != 0)
  printf("Failed setting baud rate for input");
if(cfsetospeed(&portSettings, CREATE_SERIAL_BRATE) != 0)
  printf("Failed setting baud rate for output");


//set parity bits
portSettings.c_cflag &= ~PARENB;
portSettings.c_cflag &= ~CSTOPB;
portSettings.c_cflag &= ~CSIZE;
portSettings.c_cflag |= CS8;
cfmakeraw(&portSettings);


if(tcsetattr(fd, TCSANOW, &portSettings) != 0) {
  printf("Failed pushing port settings.\n");
  return fd;
}


Since there is no actual support for serial communication in C, they work around it by treating the connection as a file with the fopen and fclose commands. After opening the port, various checks need to be done to make sure that it was open properly, set the proper configuration, and then make sure that those settings were pushed properly.

After this, communication is very simple and well explained in the iRobot Create manual, found here:
http://www.irobot.com/filelibrary/pdfs/hrd/create/Create%20Open%20Interface_v2.pdf

There are messages intended for you to be able to drive the Create a specific distance or rotate a certain amount, but for our application we found it easier to just sleep for a specified time and then stop after it has completed. Such that:


wd = write(fd, initsafe, 8);
wd = write(fd, forward, 8);
sleep(1);
wd = write(fd, initsafe, 8);
wd = write(fd, stop, 8);


Where those messages were specified by:

char initsafe[] = {128, 131};
char forward[] = {137, 0, 100, 128, 0 };
char stop[] = {137, 0, 0, 0, 0 }; 

Other similar and useful messages are:

char init[] = {128};
char initfull[] = {128, 132};  
char LED[] = {139, 8, 0, 128 };
char beep[] = {141, 1 };
char reverse[] = {137, 255, 100, 128, 0 };
char left[] = {137, 0, 100, 0, 1 };
char right[] = {137, 0, 100, 255, 255 }; 

Next, we wanted to be able to read the sensor data from all of the available sensors on the Create.

char packet[] = {142, 6};


wd = write(fd, initfull , 8);
wd = write(fd, packet, 8);


read(fd, &a, sizeof(unsigned char));
read(fd, &b, sizeof(unsigned char));
read(fd, &c, sizeof(unsigned char));
read(fd, &d, sizeof(unsigned char));
read(fd, &e, sizeof(unsigned char));
read(fd, &f, sizeof(unsigned char));
read(fd, extras, sizeof(extras));


Packet was a Create command that allowed you to specify a group of sensor and data packets that are available, and from that you can read them in whatever method you prefer. From this we created a set of cases to allow the robot to move if that action was available, and not move if something happened that could possibly damage the device, such as falling down a flight of stairs.




No comments:

Post a Comment