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