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();