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

Unreliable UART communication in C++

asked 2019-04-26 03:21:26 -0600

EdwardNur gravatar image

I have written a small code in C++ that reads the data in serial port and sometimes writes to the serial port when the callback is being called. I am using this library in C++ for the serial communication:

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

The problem I have is that sometimes the serial port stops writing to the data (does not happen often but happens) and also I need to write twice to the serial port in order for the data to be changed in the serial. For debugging purposes, I have added outputs that shows the data that has been read and the data that has been written.

Here is my code:

void UART::run()
    {

        while(ros::ok())
        {
            _letter = _serial.read();
            if (_serial.available() > 0)
            {
                _line.clear();
                _line = _serial.readline(65536, "!");
                _words.clear();
                std::istringstream f(_line);
                std::string s;
                while (getline(f,s,'\t'))
                {
                    _words.push_back(s);
                }
                this->fillVars();
                _msg.velocity = _velocity;
                _msg.position = _position;
                _pub.publish(_msg);
                ros::spinOnce();
            }
            _serial.flush();
        }
    }

    void UART::fillVars()
    {
        if (_words[0] == "u")
        {
            _ultrasonic = std::stoi(_words[1]);
        }
        else if (_words[0] == "s")
        {
            std::cout << "reading " << _words[1] << std::endl;
        }

    }


    void UART::callback(const std_msgs::Int32::ConstPtr& speed)
    {
        // Convert m/s and serial write
        _effort = speed->data - 32;
        std::string toWrite = std::to_string(_effort);
        size_t temp = _serial.write(toWrite);
        std::cout << "Writing :" << toWrite << std::endl;
    }

The code always runs in the run() function and pauses when the callback happens.

The only data in the serial for now is: !s 23 where 23 is any integer and I am simply writing to change the integer when callback is being called.

So what can be wrong with my code? Why do I need to call the callback twice in order to change the data in the serial and why does sometime the writing does not happen (my assumption is that the while loop gets stuck)? Is it due to the subscriber issue? Cannot figure out

edit retag flag offensive close merge delete

Comments

This is probably not the cause, but I'd move the ros::spinOnce() out of the if (so always run it, not only when there is data).

Additionally: unless _serial.read() is blocking, I'd add a ros::Rate or some other type of delay to moderate the rate at which this loop is running. And even if read() is blocking it might still be an idea to include a ros::Rate (but that depends on whether you want the control flow to be dependent on IO events or periodic).

gvdhoorn gravatar image gvdhoorn  ( 2019-04-26 03:49:55 -0600 )edit

@gvdhoorn thanks for the advice. Regarding the rate, that is a good idea

EdwardNur gravatar image EdwardNur  ( 2019-04-26 04:44:56 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2019-07-12 12:11:08 -0600

duck-development gravatar image

you may put the ros::spinOnce() after the flush what it the purpuse of the var letter does it destry you logic? you should use lees global / objeckt vars. could put the var words as reference, and define it in the function run

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2019-04-26 03:21:26 -0600

Seen: 891 times

Last updated: Jul 12 '19