Boost Asio Serial Port Flush
Note that boost::asio::buffercopy is implemented in terms of memcpy, and consequently it cannot be used to copy between overlapping memory regions. Buffer Invalidation. A buffer object does not have any ownership of the memory it refers to. It is the responsibility of the application to ensure the memory region remains valid until it is no longer required for an I/O operation. Construct a basicserialport without opening it. Construct and open a basicserialport. Construct a basicserialport on an existing native serial port. Move-construct a basicserialport from another. Cancel all asynchronous operations associated with the serial port. Close the serial port.
Boost Asio Read Timeout
I've made a small interface using the asio C++ library to open serial ports and do I/O from/to them. It works with my Arduino Uno and other hardware as well (industrial weighing machines), but I only specify the port and baud rate.
The following code is run in the client application, which runs both on my Windows 10 Student Edition x86_64 machine, and on old 32 bit Win XP machines that communicate with the weighing machines:
Boost Asio Socket
Gta 4 xbox 360 torrent iso converter. The Arduino is programmed to do a serial echo of whatever is sent to it, for testing purposes. This is the echo code:
It works fine with my Arduino until I unplug it and plug it back in. After replugging it all the values returned are garbage, specifically some sort of '?' character inside a black box, don't know the bit value though, but it's constant. The problem gets fixed when I open an arduino IDE Serial Port monitor.If I close it, and once again use my own software to open up the serial port, all the values are fine.
From this I concluded that the Arduino IDE Serial Port monitor is doing something when it opens up the port that I'm not doing.
Any clues? Flow control? Handshake?Thanks
1 Answer
Can you include all the other calls you make related to setting up the serial port along with asio::serial_port_base::baud_rate(baudios)
? Ideally, split that out into a separate function (that takes parameters such as baud rate) that you know is the only thing doing this setup.
As I mentioned in the comment, getting back the right number of chararacters but incorrect characters looks as if the baud rate is correct but something else is wrong. The first thing that comes to mind is the bits/parity/stop bits settings. Typically you want to be using 8 bits, no parity, often referred to as '8N1'.
Not the answer you're looking for? Browse other questions tagged serialc++rs232boost or ask your own question.
Replace boost:asio lib with simplest one. Add enable/disable DTR function to..
Boost Asio Pdf
.. | .. | @@ -2,10 +2,16 @@ cmake_minimum_required (VERSION 2.6) |
file(GLOB_RECURSE DEVICE_SOURCE_FILES *.cpp) | ||
set(DEVICE_SOURCE_FILES | ||
agoMySensors.cpp | ||
MySensors.cpp | ||
serialib.cpp | ||
) | ||
set(DEVICE_EXTRA_LIBRARIES | ||
agoclient | ||
pthread | ||
${Boost_SYSTEM_LIBRARY} | ||
${Boost_SYSTEM_LIBRARY} | ||
) | ||
set(DEVICE 'agoMySensors') | ||
.. | .. |
.. | .. | @@ -2,7 +2,6 @@ |
#include <stdint.h> | ||
#include <unistd.h> | ||
#include <iostream> | ||
#include <boost/asio.hpp> | ||
#include <boost/system/system_error.hpp> | ||
#include <boost/algorithm/string/predicate.hpp> | ||
#include <boost/algorithm/string.hpp> | ||
.. | .. | @@ -11,6 +10,7 @@ |
#include <time.h> | ||
#include <cstdlib> | ||
#include <stdexcept> | ||
#include 'serialib.h' | ||
#include 'MySensors.h' | ||
#include 'agoclient.h' | ||
.. | .. | @@ -23,7 +23,6 @@ |
usingnamespacestd; | ||
usingnamespaceagocontrol; | ||
usingnamespaceboost::system; | ||
usingnamespaceboost::asio; | ||
usingnamespaceqpid::types; | ||
namespacefs=::boost::filesystem; | ||
.. | .. | @@ -54,8 +53,7 @@ qpid::types::Variant::Map devicemap; |
std::map<std::string,T_COMMAND>commandsmap; | ||
std::stringgateway_protocol_version='1.4'; | ||
io_serviceioService; | ||
serial_portserialPort(ioService); | ||
serialibserialPort; | ||
stringdevice='; | ||
intstaleThreshold=86400; | ||
.. | .. | @@ -89,25 +87,6 @@ std::string timestampToStr(const time_t* timestamp) |
returnstd::string(hr); | ||
} | ||
/** | ||
* @brief Flush a serial port's buffers. | ||
* @param serial_port Port to flush. | ||
* @param what Determines the buffers to flush. | ||
* @param error Set to indicate what error occurred, if any. | ||
* @info http://stackoverflow.com/questions/22581315/how-to-discard-data-as-it-is-sent-with-boostasio | ||
*/ | ||
voidflush_serial_port(boost::asio::serial_port&serial_port,flush_typewhat,boost::system::error_code&error) | ||
{ | ||
if(0::tcflush(serial_port.lowest_layer().native_handle(),what)) | ||
{ | ||
error=boost::system::error_code(); | ||
} | ||
else | ||
{ | ||
error=boost::system::error_code(errno,boost::asio::error::get_system_category()); | ||
} | ||
} | ||
/** | ||
* Make readable device infos | ||
*/ | ||
.. | .. | @@ -352,17 +331,21 @@ bool openSerialPort(string device) |
boolresult=true; | ||
try | ||
{ | ||
serialPort.open(device); | ||
serialPort.set_option(serial_port::baud_rate(115200)); | ||
serialPort.set_option(serial_port::parity(serial_port::parity::none)); | ||
serialPort.set_option(serial_port::character_size(serial_port::character_size(8))); | ||
serialPort.set_option(serial_port::stop_bits(serial_port::stop_bits::one)); | ||
serialPort.set_option(serial_port::flow_control(serial_port::flow_control::none)); | ||
//flush serial content | ||
//boost::system::error_code error; | ||
//flush_serial_port(serialPort, flush_both, error); | ||
//if( DEBUG ) | ||
// cout << 'Flushing serial port: ' << error.message() << endl; | ||
intres=serialPort.Open(device.c_str(),115200); | ||
if(res!=1) | ||
{ | ||
cerr<<'Can't open serial port: '<<res<<endl; | ||
result=false; | ||
} | ||
else | ||
{ | ||
//reset arduino | ||
serialPort.EnableDTR(false); | ||
//TODO flush | ||
sleep(1); | ||
serialPort.EnableDTR(true); | ||
} | ||
} | ||
catch(std::exceptionconst&ex) | ||
{ | ||
.. | .. | @@ -377,7 +360,7 @@ bool openSerialPort(string device) |
*/ | ||
voidcloseSerialPort(){ | ||
try{ | ||
serialPort.close(); | ||
serialPort.Close(); | ||
} | ||
catch(std::exceptionconst&ex){ | ||
//cerr << 'Can't close serial port: ' << ex.what() << endl; | ||
.. | .. | @@ -434,7 +417,7 @@ void sendcommand(std::string command) |
time_tt=time(NULL); | ||
cout<<' => '<<timestampToStr(&t)<<' RE-SENDING: '<<command; | ||
} | ||
serialPort.write_some(buffer(command)); | ||
serialPort.WriteString(command.c_str()); | ||
} | ||
voidsendcommandV14(std::stringinternalid,intmessageType,intack,intsubType,std::stringpayload) | ||
{ | ||
.. | .. | @@ -468,7 +451,7 @@ void sendcommandV14(std::string internalid, int messageType, int ack, int subTyp |
time_tt=time(NULL); | ||
cout<<' => '<<timestampToStr(&t)<<' SENDING: '<<command.str(); | ||
} | ||
serialPort.write_some(buffer(command.str())); | ||
serialPort.WriteString(command.str().c_str()); | ||
} | ||
voidsendcommandV13(std::stringinternalid,intmessageType,intsubType,std::stringpayload) | ||
{ | ||
.. | .. | @@ -502,7 +485,7 @@ void sendcommandV13(std::string internalid, int messageType, int subType, std::s |
time_tt=time(NULL); | ||
cout<<' => '<<timestampToStr(&t)<<' SENDING: '<<command.str(); | ||
} | ||
serialPort.write_some(buffer(command.str())); | ||
serialPort.WriteString(command.str().c_str()); | ||
} | ||
/** | ||
.. | .. | @@ -516,7 +499,8 @@ qpid::types::Variant::Map commandHandler(qpid::types::Variant::Map command) { |
std::stringinternalid='; | ||
if(DEBUG) | ||
cout<<'CommandHandler'<<command<<endl; | ||
if(command.count('internalid')1&&command.count('command')1){ | ||
if(command.count('internalid')1&&command.count('command')1) | ||
{ | ||
//get values | ||
cmd=command['command'].asString(); | ||
internalid=command['internalid'].asString(); | ||
.. | .. | @@ -536,15 +520,18 @@ qpid::types::Variant::Map commandHandler(qpid::types::Variant::Map command) { |
std::stringstreamdeviceNameType; | ||
deviceNameType<<it->first.c_str()<<' ('; | ||
infos=getDeviceInfos(it->first); | ||
if(infos.size()>0&&!infos['type'].isVoid()){ | ||
if(infos.size()>0&&!infos['type'].isVoid()) | ||
{ | ||
deviceNameType<<infos['type']; | ||
} | ||
else{ | ||
else | ||
{ | ||
deviceNameType<<'unknown'; | ||
} | ||
deviceNameType<<')'; | ||
content['device']=deviceNameType.str().c_str(); | ||
if(!content['last_timestamp'].isVoid()){ | ||
if(!content['last_timestamp'].isVoid()) | ||
{ | ||
int32_ttimestamp=content['last_timestamp'].asInt32(); | ||
content['datetime']=timestampToStr((time_t*)×tamp); | ||
} | ||
.. | .. | @@ -559,9 +546,11 @@ qpid::types::Variant::Map commandHandler(qpid::types::Variant::Map command) { |
{ | ||
//reset all counters | ||
qpid::types::Variant::Mapdevices=devicemap['devices'].asMap(); | ||
for(qpid::types::Variant::Map::iteratorit=devices.begin();it!=devices.end();it++){ | ||
for(qpid::types::Variant::Map::iteratorit=devices.begin();it!=devices.end();it++) | ||
{ | ||
infos=getDeviceInfos(it->first); | ||
if(infos.size()>0){ | ||
if(infos.size()>0) | ||
{ | ||
infos['counter_received']=0; | ||
infos['counter_sent']=0; | ||
infos['counter_retries']=0; | ||
.. | .. | @@ -754,7 +743,7 @@ std::string readLine(bool* error) { |
(*error)=false; | ||
try{ | ||
for(;;){ | ||
boost::asio::read(serialPort,boost::asio::buffer(&c,1)); | ||
serialPort.ReadChar(&c,0); | ||
switch(c){ | ||
case'r': | ||
break; | ||
.. | .. | @@ -1729,14 +1718,6 @@ int main(int argc, char **argv) |
// determine reply for INTERNAL;I_UNIT message - defaults to 'M'etric | ||
if(getConfigSectionOption('system','units','SI')!='SI')units='I'; | ||
//open serial port | ||
if(DEBUG) | ||
cout<<'Opening serial port '<<device<<'..'<<endl; | ||
if(!openSerialPort(device)) | ||
{ | ||
exit(1); | ||
} | ||
// load map, create sections if empty | ||
fs::pathdmf=getConfigPath(DEVICEMAPFILE); | ||
devicemap=jsonFileToVariantMap(dmf); | ||
.. | .. | @@ -1752,18 +1733,34 @@ int main(int argc, char **argv) |
variantMapToJSONFile(devicemap,dmf); | ||
} | ||
boolerror; | ||
cout<<'Requesting gateway version..'<<flush; | ||
std::stringgetVersion='0;0;3;0;2n'; | ||
//open serial port | ||
if(DEBUG) | ||
cout<<'Opening serial port '<<device<<'..'<<endl; | ||
if(!openSerialPort(device)) | ||
{ | ||
exit(1); | ||
} | ||
//connect to gateway | ||
boolerror=false; | ||
std::stringline='; | ||
cout<<'Waiting for gateway started..'<<endl<<flush; | ||
while(!error&&line.find('Gateway startup complete')string::npos) | ||
{ | ||
line=readLine(&error); | ||
if(DEBUG) | ||
cout<<'Read: '<<line<<endl<<flush; | ||
} | ||
cout<<'Done.'<<endl<<flush; | ||
cout<<'Requesting gateway version..'<<endl<<flush; | ||
std::stringgetVersion='0;0;3;0;2n'; | ||
serialPort.WriteString(getVersion.c_str()); | ||
while(!error&&!boost::algorithm::starts_with(line,'0;0;3;0;2;')) | ||
{ | ||
line=readLine(&error); | ||
if(DEBUG) | ||
{ | ||
cout<<'Read: '<<line<<endl; | ||
} | ||
serialPort.write_some(buffer(getVersion)); | ||
cout<<'Read: '<<line<<endl<<flush; | ||
} | ||
if(!error) | ||
{ | ||
.. | .. |
/*! |
file serialib.h |
brief Serial library to communicate throught serial port, or any device emulating a serial port. |
author Philippe Lucidarme (University of Angers) <serialib@googlegroups.com> |
version 1.2 |
date 28 avril 2011 |
This Serial library is used to communicate through serial port. |
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This is a licence-free software, it can be used by anyone who try to build a better world. |
*/ |
#ifndef SERIALIB_H |
#define SERIALIB_H |
// Used for TimeOut operations |
#include <sys/time.h> |
// Include for windows |
#if defined (_WIN32) defined( _WIN64) |
// Accessing to the serial port under Windows |
#include <windows.h> |
#endif |
// Include for Linux |
#ifdef __linux__ |
#include <stdlib.h> |
#include <sys/types.h> |
#include <sys/shm.h> |
#include <termios.h> |
#include <string.h> |
#include <iostream> |
// File control definitions |
#include <fcntl.h> |
#include <unistd.h> |
#include <sys/ioctl.h> |
#endif |
/*! class serialib |
brief This class can manage a serial port. The class allows basic operations (opening the connection, reading, writing data and closing the connection). |
example Example1.cpp |
*/ |
classserialib |
{ |
public: |
// Constructor of the class |
serialib(); |
// Destructor |
~serialib(); |
//_________________________________________ |
// ::: Configuration and initialization ::: |
// Open a device |
charOpen(constchar*Device,constunsignedintBauds); |
// Close the current device |
voidClose(); |
//___________________________________________ |
// ::: Read/Write operation on characters ::: |
// Write a char |
charWriteChar(char); |
// Read a char (with timeout) |
charReadChar(char*pByte,constunsignedintTimeOut_ms=0); |
//________________________________________ |
// ::: Read/Write operation on strings ::: |
// Write a string |
charWriteString(constchar*String); |
// Read a string (with timeout) |
intReadString(char*String, |
charFinalChar, |
unsignedintMaxNbBytes, |
constunsignedintTimeOut_ms=0); |
// _____________________________________ |
// ::: Read/Write operation on bytes ::: |
// Write an array of bytes |
charWrite(constvoid*Buffer,constunsignedintNbBytes); |
// Read an array of byte (with timeout) |
intRead(void*Buffer,unsignedintMaxNbBytes,constunsignedintTimeOut_ms=0); |
// _________________________ |
// ::: Special operation ::: |
//enable/disable DTR |
intEnableDTR(boolenable); |
// Empty the received buffer |
voidFlushReceiver(); |
// Return the number of bytes in the received buffer |
intPeek(); |
private: |
// Read a string (no timeout) |
intReadStringNoTimeOut(char*String,charFinalChar,unsignedintMaxNbBytes); |
#if defined (_WIN32) defined( _WIN64) |
HANDLEhSerial; |
COMMTIMEOUTStimeouts; |
#endif |
#ifdef __linux__ |
intfd; |
#endif |
}; |
/*! class TimeOut |
brief This class can manage a timer which is used as a timeout. |
*/ |
// Class TimeOut |
classTimeOut |
{ |
public: |
// Constructor |
TimeOut(); |
// Init the timer |
voidInitTimer(); |
// Return the elapsed time since initialization |
unsignedlongintElapsedTime_ms(); |
private: |
structtimevalPreviousTime; |
}; |
/*! |
mainpage serialib class |
brief |
htmlonly |
<TABLE> |
<TR><TD> |
<a href='./serialibv1.2.zip'> |
<TABLE> |
<TR><TD><IMG SRC='download.png' BORDER=0 WIDTH=100> </TD></TR> |
<TR><TD><P ALIGN='center'>[Download]</P> </TD></TR> |
</TABLE> |
</A> |
</TD> |
<TD> |
<script type='text/javascript'><!--google_ad_client = 'ca-pub-0665655683291467'; |
google_ad_slot = '0230365165'; |
google_ad_width = 728; |
google_ad_height = 90; |
//--> |
</script> |
<script type='text/javascript' |
src='http://pagead2.googlesyndication.com/pagead/show_ads.js'> |
</script> |
</TD> |
</TR> |
</TABLE> |
endhtmlonly |
The class serialib offers simple access to the serial port devices for windows and linux. It can be used for any serial device (Built-in serial port, USB to RS232 converter, arduino board or any hardware using or emulating a serial port) |
image html serialib.png |
The class can be used under Windows and Linux. |
The class allows basic operations like : |
- opening and closing connection |
- reading data (characters, array of bytes or strings) |
- writing data (characters, array of bytes or strings) |
- non-blocking functions (based on timeout). |
author Philippe Lucidarme (University of Angers) <serialib@googlegroups.com> |
date 1th may 2011 (Last update: 25th september 2012) |
version 1.2 |
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This is a licence-free software, it can be used by anyone who try to build a better world. |
*/ |
#endif // SERIALIB_H |