ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Problems with Serial port code for Ros

asked 2014-08-19 14:46:20 -0500

sumanth gravatar image

I wanted the ROS pc to communicate over the UART with a microcontroller on mobile robot, I canot use ros serial as on the controller I canot use C++ code, so I have used a wrapper code for serial port in linux following the example code from this link: https://code.google.com/p/team-diana/...

My code is as follows:

#define DEFAULT_BAUDRATE 115200
#define DEFAULT_SERIALPORT "/dev/ttyUSB0"

//Global data
FILE *fpSerial = NULL;   //serial port file pointer
ros::Publisher ucResponseMsg;
ros::Subscriber ucCommandMsg;
int ucIndex;          //ucontroller index number

int FileDesc;

unsigned char crc_sum=0;

//Initialize serial port, return file descriptor
FILE *serialInit(char * port, int baud)
{
  int BAUD = 0;
  int fd = -1;
  struct termios newtio, oldtio;
  FILE *fp = NULL;

 //Open the serial port as a file descriptor for low level configuration
 // read/write, not controlling terminal for process,
  fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);

  ROS_INFO("FileDesc : %d",fd);

 if ( fd<0 )
  {
    ROS_ERROR("serialInit: Could not open serial device %s",port);
   return fp;
  }

  // save current serial port settings
  tcgetattr(fd,&oldtio);

  // clear the struct for new port settings
  bzero(&newtio, sizeof(newtio));

  //Look up appropriate baud rate constant
  switch (baud)
  {
     case 38400:
     default:
        BAUD = B38400;
        break;
     case 19200:
        BAUD  = B19200;
        break;
    case 115200:
        BAUD  = B115200;
        break;
     case 9600:
       BAUD  = B9600;
        break;
     case 4800:
        BAUD  = B4800;
        break;
     case 2400:
        BAUD  = B2400;
        break;
     case 1800:
        BAUD  = B1800;
        break;
     case 1200:
        BAUD  = B1200;
        break;
  }  //end of switch baud_rate

  if (cfsetispeed(&newtio, BAUD) < 0 || cfsetospeed(&newtio, BAUD) < 0)
  {
    ROS_ERROR("serialInit: Failed to set serial baud rate: %d", baud);
    close(fd);
    return NULL;
  }

  // set baud rate, (8bit,noparity, 1 stopbit), local control, enable receiving characters.
  newtio.c_cflag  = BAUD | CRTSCTS | CS8 | CLOCAL | CREAD;

  // ignore bytes with parity errors
  newtio.c_iflag =  IGNPAR;

  // raw output
  newtio.c_oflag = 0;

  // set input mode to non - canonical
  newtio.c_lflag = 0;

  // inter-charcter timer 
  newtio.c_cc[VTIME] = 0;

  // blocking read (blocks the read until the no.of charcters are read
  newtio.c_cc[VMIN] = 0;

  // clean the line and activate the settings for the port
  tcflush(fd, TCIFLUSH);
  tcsetattr (fd, TCSANOW,&newtio);

  //Open file as a standard I/O stream
  fp = fdopen(fd, "r+");

 if (!fp) {
    ROS_ERROR("serialInit: Failed to open serial stream %s", port);
    fp = NULL;
  }

ROS_INFO("FileStandard I/O stream: %d",fp);

  return fp;
} //serialInit


//Process ROS command message, send to uController
void ucCommandCallback(const geometry_msgs::TwistConstPtr& cmd_vel)
{
  unsigned char msg[14];
  float test1,test2;
  unsigned long i;

 // build the message packet to be sent
 msg = packet to be sent;
 msg[13] = crc_sum;

   for (i=0;i<14;i++)
   {
     fprintf(fpSerial, "%c", msg[i]);
   }

tcflush(FileDesc, TCOFLUSH); 

} //ucCommandCallback


//Receive command responses from robot uController
//and publish as a ROS message
void *rcvThread(void *arg)
{
  int rcvBufSize = 200;
  char ucResponse[10];//[rcvBufSize];   //response string from uController
  char *bufPos;
  std_msgs::String msg;
  std::stringstream ss;
  int BufPos,i;
  unsigned char crc_rx_sum =0;

  while (ros::ok()) {

     BufPos = fread((void*)ucResponse,1,10,fpSerial);

for (i=0;i<10;i++)
{
 ROS_INFO("T: %x ",(unsigned char)ucResponse[i]);
 ROS_INFO("NT: %x ",ucResponse[i]);
}

          msg.data = ucResponse;
          ucResponseMsg.publish(msg ...
(more)
edit retag flag offensive close merge delete

3 Answers

Sort by » oldest newest most voted
2

answered 2014-08-19 15:08:16 -0500

William gravatar image

Not sure that this has anything to do with the ROS component of this program. It seems like it is just an issue with your serial implementation. I don't have time to dig into your code, but my serial library is available in ROS and is known to work in many existing robots, so you might try that:

http://wjwwood.io/serial/doc/1.1.0/in...

edit flag offensive delete link more

Comments

Oh that's great, How can I use this library in ROS. Do I need to create a package with some dependencies and copy the library into that or how is it done exactly.?

sumanth gravatar image sumanth  ( 2014-08-20 01:30:59 -0500 )edit

I have used the library as it is with out changing anything, then I tried to run the serial_example.cc it is running fine. I have modified the code of the example (added some ROS publisher's subscribers), but it gives "Invoking "make failed". Do I need to change CMakeLists.txt

sumanth gravatar image sumanth  ( 2014-08-20 02:42:04 -0500 )edit

It is a ROS package itself, you can just install it with sudo apt-get install ros-indigo-serial. Then you can write a new ROS package with a new ROS node which uses it (see the example for how to use it).

William gravatar image William  ( 2014-08-20 13:28:28 -0500 )edit

Thanks a lot william . I have tried to use the library and the communication is working fine, there is some problem in transmitting the data from ROS to micro controller (The data gets drifted), this I guess is a problem on uC side. I will check this part.

sumanth gravatar image sumanth  ( 2014-08-20 14:30:27 -0500 )edit
0

answered 2014-08-19 16:57:44 -0500

Andromeda gravatar image

updated 2014-08-19 16:58:16 -0500

Not sure, but I had lots of problem with USB Serial and Ubuntu/Debian (the problem is to configure the serial port to work correctly in C/C++). Could you try with a simple python script that reads from the serial port the same datas from the micro and see it the same problem happens?

edit flag offensive delete link more
0

answered 2015-05-06 16:33:35 -0500

I think the problem is very simple: you don't need to set CTSRTS handshake here

// set baud rate, (8bit,noparity, 1 stopbit), local control, enable receiving characters.
  newtio.c_cflag  = BAUD | CRTSCTS | CS8 | CLOCAL | CREAD;

Use CLOCAL instead CTSRTS

With Best regards, Wagan Sarukhanov

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2014-08-19 14:46:20 -0500

Seen: 2,700 times

Last updated: Aug 19 '14