Raspberry pi2串口通信

安装pyserial的串口库,$ wget  http://downloads.sourceforge.net/project/pyserial/pyserial/2.7/pyserial-2.7.tar.gz

下载后,对压缩文件解压:

$ tar zxvf  ./pyserial-2.7.tar.gz

$ cd pyserial

$ sudo python setup.py  install

用命令查找串口设备

$ dmesg | grep tty*

打开python交互运行环境

 $ python

>>> import serial

>>> ser = serial.Serial('/dev/ttyUSB0',115200)

>>> while 1:

.... ser.readlin()


>>>ser.write('this is string')


连接到PC端串口调试助手,打印

Communication with ROS through USART Serial Port   

$ cd ~/catkin_ws/src
$ catkin_create_pkg r2SerialDriver std_msgs rospy roscpp
$ cd ~/catkin_ws
$ catkin_make

To add the workspace to your ROS environment you need to source the generated setup file:

$ . ~/catkin_ws/devel/setup.bash
$ cd ~/catkin_ws/src/r2SerialDriver/src

Add a file: "r2Serial.cpp", Source code:



  1. /*                                                                                                                       
     * Copyright (c) 2010, Willow Garage, Inc.                                                                               
     * All rights reserved.                                                                                                  
     *                                                                                                                       
     * Redistribution and use in source and binary forms, with or without                                                    
     * modification, are permitted provided that the following conditions are met:                                           
     *                                                                                                                       
     *     * Redistributions of source code must retain the above copyright                                                  
     *       notice, this list of conditions and the following disclaimer.                                                   
     *     * Redistributions in binary form must reproduce the above copyright                                               
     *       notice, this list of conditions and the following disclaimer in the                                             
     *       documentation and/or other materials provided with the distribution.                                            
     *     * Neither the name of the Willow Garage, Inc. nor the names of its                                                
     *       contributors may be used to endorse or promote products derived from                                            
     *       this software without specific prior written permission.                                                        
     *                                                                                                                       
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"                                           
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE                                             
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE                                            
     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE                                              
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR                                                   
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF                                                  
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS                                              
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN                                               
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)                                               
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE                                            
     * POSSIBILITY OF SUCH DAMAGE.                                                                                           
     */
    
    //r2Serial.cpp
    
    // communicate via RS232 serial with a remote uController. 
    // communicate with ROS using String type messages.
    // subscribe to command messages from ROS
    // publish command responses to ROS
    
    // program parameters - ucontroller# (0,1), serial port, baud rate
    
    //Thread main
    //  Subscribe to ROS String messages and send as commands to uController
    //Thread receive
    //  Wait for responses from uController and publish as a ROS messages
    
    
    #include "ros/ros.h"
    #include "std_msgs/String.h"
    #include <sstream>
    #include <pthread.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/time.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define DEFAULT_BAUDRATE 19200
    #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
    
    
    //Initialize serial port, return file descriptor
    FILE *serialInit(char * port, int baud)
    {
      int BAUD = 0;
      int fd = -1;
      struct termios newtio;
      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 );
      if ( fd<0 )
      {
        ROS_ERROR("serialInit: Could not open serial device %s",port);
        return fp;
      }
    
      // set up new settings
      memset(&newtio, 0,sizeof(newtio));
      newtio.c_cflag =  CS8 | CLOCAL | CREAD;  //no parity, 1 stop bit
    
      newtio.c_iflag = IGNCR;    //ignore CR, other options off
      newtio.c_iflag |= IGNBRK;  //ignore break condition
    
      newtio.c_oflag = 0;        //all options off
    
      newtio.c_lflag = ICANON;     //process input as lines
    
      // activate new settings
      tcflush(fd, TCIFLUSH);
      //Look up appropriate baud rate constant
      switch (baud)
      {
         case 38400:
         default:
            BAUD = B38400;
            break;
         case 19200:
            BAUD  = B19200;
            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;
      }
      tcsetattr(fd, TCSANOW, &newtio);
      tcflush(fd, TCIOFLUSH);
    
      //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;
      }
      return fp;
    } //serialInit
    
    
    //Process ROS command message, send to uController
    void ucCommandCallback(const std_msgs::String::ConstPtr& msg)
    {
      ROS_DEBUG("uc%dCommand: %s", ucIndex, msg->data.c_str());
      fprintf(fpSerial, "%s", msg->data.c_str()); //appends newline
    } //ucCommandCallback
    
    
    //Receive command responses from robot uController
    //and publish as a ROS message
    void *rcvThread(void *arg)
    {
      int rcvBufSize = 200;
      char ucResponse[rcvBufSize];   //response string from uController
      char *bufPos;
      std_msgs::String msg;
      std::stringstream ss;
    
      ROS_INFO("rcvThread: receive thread running");
    
      while (ros::ok()) {
        bufPos = fgets(ucResponse, rcvBufSize, fpSerial);
        if (bufPos != NULL) {
          ROS_DEBUG("uc%dResponse: %s", ucIndex, ucResponse);
          msg.data = ucResponse;
          ucResponseMsg.publish(msg);
        }
      }
      return NULL;
    } //rcvThread
    
    
    int main(int argc, char **argv)
    {
      char port[20];    //port name
      int baud;     //baud rate 
    
      char topicSubscribe[20];
      char topicPublish[20];
    
      pthread_t rcvThrID;   //receive thread ID
      int err;
    
      //Initialize ROS
      ros::init(argc, argv, "r2SerialDriver");
      ros::NodeHandle rosNode;
      ROS_INFO("r2Serial starting");
    
      //Open and initialize the serial port to the uController
      if (argc > 1) {
        if(sscanf(argv[1],"%d", &ucIndex)==1) {
          sprintf(topicSubscribe, "uc%dCommand",ucIndex);
          sprintf(topicPublish, "uc%dResponse",ucIndex);
        }
        else {
          ROS_ERROR("ucontroller index parameter invalid");
          return 1;
        }
      }
      else {
        strcpy(topicSubscribe, "uc0Command");
        strcpy(topicPublish, "uc0Response");
      }
    
      strcpy(port, DEFAULT_SERIALPORT);
      if (argc > 2)
         strcpy(port, argv[2]);
    
      baud = DEFAULT_BAUDRATE;
      if (argc > 3) {
        if(sscanf(argv[3],"%d", &baud)!=1) {
          ROS_ERROR("ucontroller baud rate parameter invalid");
          return 1;
        }
      }
    
      ROS_INFO("connection initializing (%s) at %d baud", port, baud);
       fpSerial = serialInit(port, baud);
      if (!fpSerial )
      {
        ROS_ERROR("unable to create a new serial port");
        return 1;
      }
      ROS_INFO("serial connection successful");
    
      //Subscribe to ROS messages
      ucCommandMsg = rosNode.subscribe(topicSubscribe, 100, ucCommandCallback);
    
      //Setup to publish ROS messages
      ucResponseMsg = rosNode.advertise<std_msgs::String>(topicPublish, 100);
    
      //Create receive thread
      err = pthread_create(&rcvThrID, NULL, rcvThread, NULL);
      if (err != 0) {
        ROS_ERROR("unable to create receive thread");
        return 1;
      }
    
      //Process ROS messages and send serial commands to uController
      ros::spin();
    
      fclose(fpSerial);
      ROS_INFO("r2Serial stopping");
      return 0;
    }

Modify the CMakeList.txt file:

$ cd ~/catkin_ws/src/r2SerialDriver
$ gedit CMakeList.txt

add/modify these lines as below:

  1. find_package(catkin REQUIRED COMPONENTS  
  2.   roscpp  
  3.   rospy  
  4.   std_msgs  
  5. )  
  6.   
  7. include_directories(  
  8.   ${catkin_INCLUDE_DIRS}  
  9. )  
  10.   
  11. add_executable(r2SerialDriver src/r2Serial.cpp)  
  12.   
  13. add_dependencies(r2SerialDriver ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})  
  14.   
  15. target_link_libraries(r2SerialDriver  
  16.    ${catkin_LIBRARIES}  
  17.  )  

Save and Build the package again:

$ cd ~/catkin_ws
$ catkin_make -DCMAKE_BUILD_TYPE=Release 

He also offered a simple launch file that interfaces to two microcontrollers using two serial connections, put the code into
  "~/catkin_ws/src/r2SerialDriver/launch/r2SerialDriver.launch" file:

  1. <launch>  
  2.   <node pkg="r2SerialDriver" type="r2SerialDriver" name="r2Serial0" args="0 /dev/ttyUSB0 9600" output="screen" >  
  3.   <remap from="ucCommand" to="uc0Command" />  
  4.   <remap from="ucResponse" to="uc0Response" />  
  5.   </node>  
  6.   
  7.   <node pkg="r2SerialDriver" type="r2SerialDriver" name="r2Serial1" args="1 /dev/ttyUSB1 9600" output="screen" >  
  8.   <remap from="ucCommand" to="uc1Command" />  
  9.   <remap from="ucResponse" to="uc1Response" />  
  10.   </node>  
  11.   
  12. </launch>  
<launch>
  <node pkg="r2SerialDriver" type="r2SerialDriver" name="r2Serial0" args="0 /dev/ttyUSB0 9600" output="screen" >
  <remap from="ucCommand" to="uc0Command" />
  <remap from="ucResponse" to="uc0Response" />
  </node>

  <node pkg="r2SerialDriver" type="r2SerialDriver" name="r2Serial1" args="1 /dev/ttyUSB1 9600" output="screen" >
  <remap from="ucCommand" to="uc1Command" />
  <remap from="ucResponse" to="uc1Response" />
  </node>

</launch>

Usage:

$ rosrun r2SerialDriver r2SerialDriver 0 /dev/ttyUSB0 9600

or

$ roslaunch r2SerialDriver r2SerialDriver.launch

try:

$ rostopic pub -r 1 /uc0Command std_msgs/String hello_my_serial
$ rostopic echo /uc0Response
You may also need to remap the /dev/ttyUSB* to some name you like cuz you may have several usb-serial devices.
If so, just Ref: 重新指派usb转串口模块在linux系统中的设备调用名称(English Version: remap your usb-serial devices' names in Linux )

But Kevin mentioned a question: "Interesting, but a lot of my serial stuff is send a message and receive a response back. Instead of separate publish/subscribes have you tried a service? That seems like it would work nicely for this."

I also noticed a problem: The Linux's System RAM and CPU will be much costed by r2serial_driver when it is running.

Next time, we'll see how to use Kevin's service to play ROS serial communication.

2. Use Service to play ROS-Serial communication

see this blog brother below...

http://blog.csdn.net/sonictl/article/details/51372534


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值