Serial Communication between 3pi robots using Xbee!

I need to do a project where 3 robots move in a grid to six stations which is shown below. The robots need to go to the stations for 18 times(3 times each station), each time returning to the starting point.(As if collecting 3 packages from each station) as fast as possible. The problem i am facing is that the robots need to communicate among each other serially so that they don’t collide(robot needs to detect another robot nearing it and stop).

I have been thinking about using the master and slave serial program given by you to make them communicate! Like set one robot as the the master other as the slave, but i am confused how i am gonna differentiate between the two slaves(thought about using different delays on slaves). I am using a basic grid program for the movement to the stations using co-ordinates of the points.

/*

*/
#include <iostream>
#include <stdio.h>
#include <windows.h>
/*
*This code came directly from http://www.robbayer.com/files/serial-win.pdf
*Minor modifications for output and 3pi connections by Drew Mangus
*/
using namespace std;

int main()
{

string com;
cout << "Enter COM port using 'COM#' as the format: ";
cin >> com;

HANDLE hSerial;

hSerial = CreateFile(com.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);

if(hSerial==INVALID_HANDLE_VALUE){
    if(GetLastError()==ERROR_FILE_NOT_FOUND){
        //serial port does not exist. Inform user.
        cout << "Serial port number doesn't exist";
    }
    //some other error occurred. Inform user.
    cout << "Error of some sort, check the settings (1)";
}

DCB dcbSerialParams = {0};
//dcbSerial.DCBlength=sizeof(dcbSerialParams);

if (!GetCommState(hSerial, &dcbSerialParams)) {
    //error getting state
    cout << "Error getting the state";
}

dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;

if(!SetCommState(hSerial, &dcbSerialParams)){
    //error setting serial port state
    cout << "Error setting the port state";
}

COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;

if(!SetCommTimeouts(hSerial, &timeouts)){
    //error occureed. Inform user
    cout << "Error of some sort, check the settings (2)";
}

/************************************************************/
/************************************************************/
/****************Code for 3pi begins here********************/
char tempbuff[10];//for use in input
char UI;
char forward[5] = {0x02,0x00,0x00,0x01,0x03};
char backward[5] = {0x02,0x00,0x00,0x02,0x03};
char left[5] = {0x02,0x00,0x00,0x03,0x03};
char right[5] = {0x02,0x00,0x00,0x04,0x03};
char point[7] = {0x02,0x00,0x02,0x05,0x00,0x00,0x03};

//int i = 0;
//char szBuff[4] = {0x01,0x80,0x01,0x81}; //Command that you wish to send
DWORD dwBytesRead = 0;

while(UI != 'e'){
    printf("Type WASD followed by Enter to move the robot. p to use coordinate positions or type e to exit\r\nCommand: ");
    gets(tempbuff);
    sscanf(tempbuff,"%c",&UI);

    switch(UI){
        case 'W':
            if(!WriteFile(hSerial, forward, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'A':
            if(!WriteFile(hSerial, left, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'S':
            if(!WriteFile(hSerial, backward, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'D':
            if(!WriteFile(hSerial, right, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'w':
            if(!WriteFile(hSerial, forward, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'a':
            if(!WriteFile(hSerial, left, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 's':
            if(!WriteFile(hSerial, backward, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'd':
            if(!WriteFile(hSerial, right, 5, &dwBytesRead, NULL))
                printf("Write failed"); //error occurred. Report to user.
        break;
        case 'p':
            int xcor[10], ycor[10];
            int w, m, n;
            printf("Enter the number of waypoints you want: \r\n");
            gets(tempbuff);
            sscanf(tempbuff,"%i", &w);
            printf("Enter the point X Y hitting enter in between each number: \n");
            for(m=0;m<w;++m)
            {
                gets(tempbuff);
                sscanf(tempbuff,"%i", &xcor[m]);
                gets(tempbuff);
                sscanf(tempbuff,"%i", &ycor[m]);
            }
            for(n=0;n<w;++n)
            {
                point[4] = (char)xcor[n];
                point[5] = (char)ycor[n];
                if(!WriteFile(hSerial, point, 7, &dwBytesRead, NULL))
                    printf("Write failed"); //error occurred. Report to user
            }

        break;
        default:
            //Chances are if it got this and you didn't enter an incorrect value it picked up a \n (carriage return) in the buffer.
            printf("Error, input did not match a correct value\r\n");
        break;
    }

}
}

Could you please advise how i should approach this project…and how should i get a start!

Hi,

You might be interested in my own project, which is similar, here. Note that it uses Wixels instead of XBees. I’ve had to jump through a few hoops to make multi-agent communication work, though. The use of XBees may (or may not) enable easier approaches…

A good starting point for you would be to establish the ability to wirelessly target specific robot(s) and have only that/those robot(s) respond to/receive wireless information, while the others do not. Keep the commands and the robots’ behaviours simple at first - this incremental development will allow you to more easily test and debug your system as a whole.

From that point on, it’s a simple matter of developing your own protocol to distribute information among them as desired. For example, you might consider using a sort of check-point system, where each robot says to the others, “I’m at station x, heading in direction y” (or even “I’m on the main middle roadway, heading north up to station z”), and the other robots will then navigate around it or avoid it as necessary. This describes how my own multi-agent project works, at a very high level.

As a side note, I’ve observed that there are some redundant lines on the grid you have, which creates certain advantages. For example, next to a station, you can now have a robot move aside to make room for another who wishes to approach that station (or a robot could be made to enter and exit a station’s grid area in a clockwise fashion, as an example). Additionally, the use of these extra lines (ie, the ones that run perpendicular to a given path) gives you more precision in determining a robot’s exact location. Taking advantage of these facts can help you to create a really robust system.

Hope that helps.

Geoff

OP, I didn’t read your program, but if you have “3” robots and you’re using
series 1 XBees, then you will need to use the broadcast mode, rather than
point-to-point mode, unless you want to change DL addresses before every
transmission. I believe broadcast uses DL=0xFF.

All you need to do is send an address in software to select between slave
devices. Each slave will monitor all transmissions, and only respond to
its own address. As simple as beginning each message with something
like “Q2” or “Q3”.