用於串口通信的serial

1 介紹

This is a cross-platform library for interfacing with rs-232 serial like ports written in C++. It provides a modern C++ interface with a workflow designed to look and feel like PySerial, but with the speed and control provided by C++.

This library is in use in several robotics related projects and can be built and installed to the OS like most unix libraries with make and then sudo make install, but because it is a catkin project it can also be built along side other catkin projects in a catkin workspace.

Serial is a class that provides the basic interface common to serial libraries (open, close, read, write, etc…) and requires no extra dependencies. It also provides tight control over timeouts and control over handshaking lines.

相關資料:

  • Github:https://github.com/wjwwood/serial
  • 網站:http://wjwwood.github.com/serial/
  • API:http://wjwwood.github.com/serial/doc/1.1.0/index.html

2 安轉serail

git clone https://github.com/wjwwood/serial.git
make
sudo make install

默認安裝在/tmp/usr/local/目錄下,/tmp下的文件每次重啓後會清空,因此我們把安裝文件拷貝到usr/local

sudo cp -r /tmp/usr/local/* /usr/local
source ~/.bashrc

3 使用serial

這裏舉兩個栗子:

  • 第一個是serial包中提供的例程
  • 第二個是網上的資料:使用serial和ROS讀寫編碼器

3.1 serial中的例程

3.1.1 代碼

代碼路徑爲serial/examples/serial_example.cc

/***
 * This example expects the serial port has a loopback on it.
 *
 * Alternatively, you could use an Arduino:
 *
 * <pre>
 *  void setup() {
 *    Serial.begin(<insert your baudrate here>);
 *  }
 *
 *  void loop() {
 *    if (Serial.available()) {
 *      Serial.write(Serial.read());
 *    }
 *  }
 * </pre>
 */

#include <string>
#include <iostream>
#include <cstdio>

// OS Specific sleep
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

#include "serial/serial.h"

using std::string;
using std::exception;
using std::cout;
using std::cerr;
using std::endl;
using std::vector;

void my_sleep(unsigned long milliseconds) {
#ifdef _WIN32
      Sleep(milliseconds); // 100 ms
#else
      usleep(milliseconds*1000); // 100 ms
#endif
}

void enumerate_ports()
{
	vector<serial::PortInfo> devices_found = serial::list_ports();

	vector<serial::PortInfo>::iterator iter = devices_found.begin();

	while( iter != devices_found.end() )
	{
		serial::PortInfo device = *iter++;

		printf( "(%s, %s, %s)\n", device.port.c_str(), device.description.c_str(),
     device.hardware_id.c_str() );
	}
}

void print_usage()
{
	cerr << "Usage: test_serial {-e|<serial port address>} ";
    cerr << "<baudrate> [test string]" << endl;
}

int run(int argc, char **argv)
{
  if(argc < 2) {
	  print_usage();
    return 0;
  }

  // Argument 1 is the serial port or enumerate flag
  string port(argv[1]);

  if( port == "-e" ) {
	  enumerate_ports();
	  return 0;
  }
  else if( argc < 3 ) {
	  print_usage();
	  return 1;
  }

  // Argument 2 is the baudrate
  unsigned long baud = 0;
#if defined(WIN32) && !defined(__MINGW32__)
  sscanf_s(argv[2], "%lu", &baud);
#else
  sscanf(argv[2], "%lu", &baud);
#endif

  // port, baudrate, timeout in milliseconds
  serial::Serial my_serial(port, baud, serial::Timeout::simpleTimeout(1000));

  cout << "Is the serial port open?";
  if(my_serial.isOpen())
    cout << " Yes." << endl;
  else
    cout << " No." << endl;

  // Get the Test string
  int count = 0;
  string test_string;
  if (argc == 4) {
    test_string = argv[3];
  } else {
    test_string = "Testing.";
  }

  // Test the timeout, there should be 1 second between prints
  cout << "Timeout == 1000ms, asking for 1 more byte than written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length()+1);

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  // Test the timeout at 250ms
  my_serial.setTimeout(serial::Timeout::max(), 250, 0, 250, 0);
  count = 0;
  cout << "Timeout == 250ms, asking for 1 more byte than written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length()+1);

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  // Test the timeout at 250ms, but asking exactly for what was written
  count = 0;
  cout << "Timeout == 250ms, asking for exactly what was written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length());

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  // Test the timeout at 250ms, but asking for 1 less than what was written
  count = 0;
  cout << "Timeout == 250ms, asking for 1 less than was written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length()-1);

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  return 0;
}

int main(int argc, char **argv) {
  try {
    return run(argc, argv);
  } catch (exception &e) {
    cerr << "Unhandled Exception: " << e.what() << endl;
  }
}

3.1.2 使用

列出可用的端口號:

cd ~/serial/build/devel/lib/serial
./serial_example -e

輸出:

(/dev/ttyS0, ttyS0, n/a)
(/dev/ttyS1, ttyS1, n/a)
(/dev/ttyS10, ttyS10, n/a)
(/dev/ttyS11, ttyS11, n/a)
(/dev/ttyS12, ttyS12, n/a)
(/dev/ttyS13, ttyS13, n/a)
(/dev/ttyS14, ttyS14, n/a)
(/dev/ttyS15, ttyS15, n/a)
(/dev/ttyS16, ttyS16, n/a)
(/dev/ttyS17, ttyS17, n/a)
(/dev/ttyS18, ttyS18, n/a)
(/dev/ttyS19, ttyS19, n/a)
(/dev/ttyS2, ttyS2, n/a)
(/dev/ttyS20, ttyS20, n/a)
(/dev/ttyS21, ttyS21, n/a)
(/dev/ttyS22, ttyS22, n/a)
(/dev/ttyS23, ttyS23, n/a)
(/dev/ttyS24, ttyS24, n/a)
(/dev/ttyS25, ttyS25, n/a)
(/dev/ttyS26, ttyS26, n/a)
(/dev/ttyS27, ttyS27, n/a)
(/dev/ttyS28, ttyS28, n/a)
(/dev/ttyS29, ttyS29, n/a)
(/dev/ttyS3, ttyS3, n/a)
(/dev/ttyS30, ttyS30, n/a)
(/dev/ttyS31, ttyS31, n/a)
(/dev/ttyS4, ttyS4, n/a)
(/dev/ttyS5, ttyS5, n/a)
(/dev/ttyS6, ttyS6, n/a)
(/dev/ttyS7, ttyS7, n/a)
(/dev/ttyS8, ttyS8, n/a)
(/dev/ttyS9, ttyS9, n/a)
(/dev/ttyUSB0, Silicon Labs CP2102N USB to UART Bridge Controller 0001, USB VID:PID=10c4:ea60 SNR=0001)

可以看出,/dev/ttyUSB0是我們插入設備所對應的端口。

使用serial進行端口打開,讀和寫的測試,分兩種情況:

(1)如果沒有給定發送的內容,則默認爲:Testing.,8個字節。

./serial_example /dev/ttyUSB0 115200

輸出:

Is the serial port open? Yes.
Timeout == 1000ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 8, Bytes read: 9, String read: 05,-0.000
Iteration: 1, Bytes written: 8, Bytes read: 1, String read: 6
Iteration: 2, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 3, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 4, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 5, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 6, Bytes written: 8, Bytes read: 9, String read: $6.112709
Iteration: 7, Bytes written: 8, Bytes read: 9, String read: ,-7.33860
Iteration: 8, Bytes written: 8, Bytes read: 9, String read: 2,-1.2211
Iteration: 9, Bytes written: 8, Bytes read: 9, String read: 05,0.0014
Timeout == 250ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 8, Bytes read: 9, String read: 13,-0.000
Iteration: 1, Bytes written: 8, Bytes read: 9, String read: 220,-0.00
Iteration: 2, Bytes written: 8, Bytes read: 9, String read: 1162,-98.
Iteration: 3, Bytes written: 8, Bytes read: 9, String read: 086143,-3
Iteration: 4, Bytes written: 8, Bytes read: 9, String read: 9.784908,
Iteration: 5, Bytes written: 8, Bytes read: 9, String read: 224.96165
Iteration: 6, Bytes written: 8, Bytes read: 9, String read: 4*
$6.10
Iteration: 7, Bytes written: 8, Bytes read: 9, String read: 3131,-7.3
Iteration: 8, Bytes written: 8, Bytes read: 9, String read: 19447,-1.
Iteration: 9, Bytes written: 8, Bytes read: 9, String read: 221105,0.
Timeout == 250ms, asking for exactly what was written.
Iteration: 0, Bytes written: 8, Bytes read: 8, String read: 000081,0
Iteration: 1, Bytes written: 8, Bytes read: 8, String read: .000047,
Iteration: 2, Bytes written: 8, Bytes read: 8, String read: 0.000169
Iteration: 3, Bytes written: 8, Bytes read: 8, String read: ,-98.093
Iteration: 4, Bytes written: 8, Bytes read: 8, String read: 002,-39.
Iteration: 5, Bytes written: 8, Bytes read: 8, String read: 782791,2
Iteration: 6, Bytes written: 8, Bytes read: 8, String read: 24.96600
Iteration: 7, Bytes written: 8, Bytes read: 8, String read: 3*
$6.1
Iteration: 8, Bytes written: 8, Bytes read: 8, String read: 03131,-7
Iteration: 9, Bytes written: 8, Bytes read: 8, String read: .319447,
Timeout == 250ms, asking for 1 less than was written.
Iteration: 0, Bytes written: 8, Bytes read: 7, String read: -1.2211
Iteration: 1, Bytes written: 8, Bytes read: 7, String read: 05,0.00
Iteration: 2, Bytes written: 8, Bytes read: 7, String read: 0081,0.
Iteration: 3, Bytes written: 8, Bytes read: 7, String read: 000047,
Iteration: 4, Bytes written: 8, Bytes read: 7, String read: 0.00016
Iteration: 5, Bytes written: 8, Bytes read: 7, String read: 9,-98.1
Iteration: 6, Bytes written: 8, Bytes read: 7, String read: 00227,-
Iteration: 7, Bytes written: 8, Bytes read: 7, String read: 39.7808
Iteration: 8, Bytes written: 8, Bytes read: 7, String read: 95,224.
Iteration: 9, Bytes written: 8, Bytes read: 7, String read: 970626*

(2)也可以指定發送內容,比如:haha,4個字節。

./serial_example /dev/ttyUSB0 115200  haha
Is the serial port open? Yes.
Timeout == 1000ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 4, Bytes read: 5, String read: 0097,
Iteration: 1, Bytes written: 4, Bytes read: 4, String read: -99�
Iteration: 2, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 3, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 4, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 5, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 6, Bytes written: 4, Bytes read: 5, String read: $6.10
Iteration: 7, Bytes written: 4, Bytes read: 5, String read: 3131,
Iteration: 8, Bytes written: 4, Bytes read: 5, String read: -7.35
Iteration: 9, Bytes written: 4, Bytes read: 5, String read: 2968,
Timeout == 250ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 4, Bytes read: 5, String read: -1.27
Iteration: 1, Bytes written: 4, Bytes read: 5, String read: 1386,
Iteration: 2, Bytes written: 4, Bytes read: 5, String read: 0.000
Iteration: 3, Bytes written: 4, Bytes read: 5, String read: 087,0
Iteration: 4, Bytes written: 4, Bytes read: 5, String read: .0000
Iteration: 5, Bytes written: 4, Bytes read: 5, String read: 07,0.
Iteration: 6, Bytes written: 4, Bytes read: 5, String read: 00032
Iteration: 7, Bytes written: 4, Bytes read: 5, String read: 1,-98
Iteration: 8, Bytes written: 4, Bytes read: 5, String read: .1223
Iteration: 9, Bytes written: 4, Bytes read: 5, String read: 29,-3
Timeout == 250ms, asking for exactly what was written.
Iteration: 0, Bytes written: 4, Bytes read: 4, String read: 9.37
Iteration: 1, Bytes written: 4, Bytes read: 4, String read: 4092
Iteration: 2, Bytes written: 4, Bytes read: 4, String read: ,224
Iteration: 3, Bytes written: 4, Bytes read: 4, String read: .914
Iteration: 4, Bytes written: 4, Bytes read: 4, String read: 001*
Iteration: 5, Bytes written: 4, Bytes read: 4, String read: 
$6
Iteration: 6, Bytes written: 4, Bytes read: 4, String read: .098
Iteration: 7, Bytes written: 4, Bytes read: 4, String read: 342,
Iteration: 8, Bytes written: 4, Bytes read: 4, String read: -7.3
Iteration: 9, Bytes written: 4, Bytes read: 4, String read: 4817
Timeout == 250ms, asking for 1 less than was written.
Iteration: 0, Bytes written: 4, Bytes read: 3, String read: 9,-
Iteration: 1, Bytes written: 4, Bytes read: 3, String read: 1.2
Iteration: 2, Bytes written: 4, Bytes read: 3, String read: 258
Iteration: 3, Bytes written: 4, Bytes read: 3, String read: 94,
Iteration: 4, Bytes written: 4, Bytes read: 3, String read: 0.0
Iteration: 5, Bytes written: 4, Bytes read: 3, String read: 008
Iteration: 6, Bytes written: 4, Bytes read: 3, String read: 86,
Iteration: 7, Bytes written: 4, Bytes read: 3, String read: -0.
Iteration: 8, Bytes written: 4, Bytes read: 3, String read: 000
Iteration: 9, Bytes written: 4, Bytes read: 3, String read: 260

4 使用serial和ROS讀寫編碼器

這部分內容參考網上的資料:

  • 博客:https://blog.csdn.net/SimileciWH/article/details/84975951
  • Github:https://github.com/SimileciWH/get_odomData_usbSerial

可以先看博客,再看代碼,但博客寫得不是很完善,很多細節在代碼裏。

代碼涉及了serial的C++和Python使用方法,還結合了ROS,值得學習。

編譯工程時,如果遇到找不到serial的問題,可以嘗試:

安裝ROS serial package

sudo apt-get install ros-kinetic-serial

CMakeLists.txt中添加:

set(serial_DIR /usr/local)

參考:http://forums.trossenrobotics.com/archive/index.php/t-7938.html?s=ab912dc757e6846eabeaa40bafd7fd88

通過看兩個代碼,發現下面兩段代碼作用應該是相同的,都是設置端口,波特率和延遲時間,然後打開端口。

// port, baudrate, timeout in milliseconds
serial::Serial my_serial(port, baud, serial::Timeout::simpleTimeout(1000));
serial::Serial ros_ser;
ros_ser.setPort("/dev/ttyUSB0");
ros_ser.setBaudrate(115200);
serial::Timeout to = serial::Timeout::simpleTimeout(1000);
ros_ser.setTimeout(to);
ros_ser.open();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章