Reading on serial port returns what i just wrote - c++

I just started a project where i'm struggling since days now about serial ports. I wrote a static library that can handle all the serial routine and give an interface with "readLine()" and "writeLine()" functions.
Everything works flawlessly on the write and read (which are threaded by the way) except if the slave does not anwser after he gets the data, then, the data is sent back to me, and i read it.
I open my fd with O_NDELAY and configure my read system call as Non blocking with fcntl.
here are the two threaded loops that work perfectly beside that.
void *Serial_Port::readLoop(void *param)
{
Serial_Port *sp = static_cast<Serial_Port*>(param);
std::string *line = NULL;
char buffer[128];
while (1)
{
line = new std::string();
while ((line->find("\r\n")) == std::string::npos)
{
usleep(100);
bzero(buffer, 128);
pthread_mutex_lock(sp->getRLock());
if (read(sp->getDescriptor(), buffer, 127) > 0)
*line += buffer;
pthread_mutex_unlock(sp->getRLock());
}
pthread_mutex_lock(sp->getRLock());
sp->getRStack()->push(line->substr(0, line->find("\r\n")));
pthread_mutex_unlock(sp->getRLock());
delete (line);
}
return (param);
}
void *Serial_Port::writeLoop(void *param)
{
Serial_Port *sp = static_cast<Serial_Port*>(param);
std::string *line;
while (1)
{
line = NULL;
pthread_mutex_lock(sp->getWLock());
if (!sp->getWStack()->empty())
{
line = new std::string(sp->getWStack()->front());
sp->getWStack()->pop();
}
pthread_mutex_unlock(sp->getWLock());
if (line != NULL)
{
pthread_mutex_lock(sp->getWLock());
write(sp->getDescriptor(), line->c_str(), line->length());
// fsync(sp->getDescriptor());
pthread_mutex_unlock(sp->getWLock());
}
usleep(100);
}
return (param);
}
I tried to flush the file descriptor, but i can't manage to receive any data after doing that. How can I get rid of that duplicate, needless data?
Thanks.

After multiple tests and behavior analysis, I discovered it was the "Pulsar3" (the device i was using on serial) that kept giving me back what i sent as "Acknowledge". Nice to know!

Related

COM port handle for reading data in c++ vs2012

I have a code to open and read serial COM port in vs2012 c++ which is working fine when I run the code separately in an individual solution.The code is as follow:
Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed
if (SP->IsConnected()) // check com port availability
printf("We're connected"); // send the result
char incomingData[512] = ""; // don't forget to pre-allocate memory
int dataLength = 256;
int readResult = 0; //if there is no reading it is -1
while(SP->IsConnected())
{
readResult = SP->ReadData(incomingData,dataLength);
//std::string test(incomingData);
res1=strtol(incomingData,&pos1,10); //receive data in right patern
res2=atof(pos1); //convert the character to integer
res3=(double)res2; // convert integer to double (as my desired output is a double)
printf("%f\n",res2); // print the result
Sleep(50); // pause so that I can see the coming data
}
in which Serial,ReadData and other functions and headers are defined in a separate header and .cpp file.
My problem occurs when I want to plug the code in my other solution (SOFA Simulation) which I want to use to make a graphical interface. but I get the INVALID_HANDLE_VALUE error and the get last error gives me ERROR_FILE_NOT_FOUND. this is my code in the solution I want to use:
namespace sofa
{
namespace component
{
namespace behaviormodel
{
MyBehaviorModel::MyBehaviorModel():
customUnsignedData(initData(&customUnsignedData, (unsigned)1,"Custom Unsigned Data","Example of unsigned data with custom widget")),
regularUnsignedData(initData(&regularUnsignedData, (unsigned)1,"Unsigned Data","Example of unsigned data with standard widget"))
{
customUnsignedData.setWidget("widget_myData");
}
MyBehaviorModel::~MyBehaviorModel()
{
}
void MyBehaviorModel::init()
{
}
void MyBehaviorModel::reinit()
{
}
void MyBehaviorModel::updatePosition(SReal dt)
{
Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed
if (SP->IsConnected())
printf("We're connected");
char incomingData[512] = ""; // don't forget to pre-allocate memory
int dataLength = 256;
int readResult = 0;
while(SP->IsConnected())
{
readResult = SP->ReadData(incomingData,dataLength);
//std::string test(incomingData);
res1=strtol(incomingData,&pos1,10);
res2=atof(pos1);
res3=(double)res2;
printf("%f\n",res2);
Sleep(50);
}
dx=0.01;
dy=0.01;
dz+=0.01;
using core::behavior::MechanicalState;
mState1 = dynamic_cast<MechanicalState<sofa::defaulttype::Rigid3dTypes> *> (this->getContext()->getMechanicalState());
helper::WriteAccessor<sofa::core::objectmodel:: Data<sofa::defaulttype::Rigid3dTypes::VecCoord> > xp = *mState1- >write(core::VecCoordId::position());
xp[0].getCenter()=sofa::defaulttype::Vec<3,Real>((Real)dx,(Real)dy,(Real)(res2);
}
SOFA_DECL_CLASS(MyBehaviorModel)
int MyBehaviorModelClass = core::RegisterObject("Dummy component with a custom widget.").add< MyBehaviorModel >();
} // namespace behaviormodel
} // namespace component
} // namespace sofa
I really can not figure out what the problem is because as I said the problem is not from my serial reader code as I tested it and I know it works fine separately.can you find out where the problem lies?
thanks in advance!
This is my Serial constructor:
Serial::Serial(char *portName)
{//We're not yet connected
this->connected = false;
//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFile((LPCWSTR)portName,
GENERIC_READ ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
//Check if the connection was successfull
if(this->hSerial==INVALID_HANDLE_VALUE)
{
//If not success full display an Error
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else
{
//If connected we try to set the comm parameters
DCB dcbSerialParams = {0};
//Try to get the current
if (!GetCommState(this->hSerial, &dcbSerialParams))
{
//If impossible, show an error
printf("failed to get current serial parameters!");
}
else
{
//Define serial connection parameters for the arduino board
dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
//Setting the DTR to Control_Enable ensures that the Arduino is properly
//reset upon establishing a connection
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
//Set the parameters and check for their proper application
if(!SetCommState(hSerial, &dcbSerialParams))
{
printf("ALERT: Could not set Serial Port parameters");
}
else
{
//If everything went fine we're connected
this->connected = true;
//Flush any remaining characters in the buffers
PurgeComm(this->hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
//We wait 2s as the arduino board will be reseting
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
The function CreateFile is actually a Macro that is mapped to either CreateFileA or CreateFileW depending on your project (unicode) configuration. As others have mentioned, you should not use a type cast to LPCWSTR to hide the fact that your code is not correct, you just need to use the right type of string.
If a function expects a widestring (LPCWSTR) and you pass it a chunk of memory that contains an ANSI string, it will never work. In this particular case, you can use the function CreateFileA directly so that you can pass your ANSI string to it.

writing and reading to/from a serial port with a timeout in c++ and Linux

I'm trying to send some hex string to a serial port, and directly read its answer in c++. If there is no answer it should timeout after a given period of time.
What is the simplest implementation of such a task?
Do i need to use stuff like boost?
To be clear: I'm searching for the most simple way to achieve this.
Sorry if my question is dumb, but im new to this topic, thanks in advance!
EDIT: Sorry that I forgot to mention, it should run on Linux.
this should be similar to your declaration:
Setup(CSerial::EBaud9600,CSerial::EData8,CSerial::EParNone,CSerial::EStop1);
Setup(CSerial::EBaudrate(9600),
CSerial::EDataBits(8),
CSerial::EParity(NOPARITY),
CSerial::EStopBits(ONESTOPBIT));
Reading data:
// Read data, until there is nothing left
DWORD dwBytesRead = 0;
BYTE abBuffer[100];
do
{
// Read data from the COM-port
serial.Read(abBuffer,sizeof(abBuffer),&dwBytesRead);
if (dwBytesRead > 0)
{
// TODO: Process the data
}
}
while (dwBytesRead == sizeof(abBuffer));
More details can be found here on code project: http://www.codeproject.com/Articles/992/Serial-library-for-C
Please note: I am used to programming serial ports in c#, and so (to the best of my knowledge) believe this would work for you. (I would also like to point outall serial port communication is send actually through as hex, but may be read via the buffer as a decimal value ( please refer to http://www.asciitable.com/ for converstion, or use something similar to UTF8 encoding)
EDIT - As per comment;
Please refer to : http://msdn.microsoft.com/en-gb/library/windows/hardware/hh439614(v=vs.85).aspx for details on serial port read/write timeouts
Write timeout will be similar to;
[BrowsableAttribute(true)]
public:
property int WriteTimeout {
int get ();
void set (int value);
}
Which allows you to get or set the timeout attribute
Full Program
public:
static void Main()
{
String^ name;
String^ message;
StringComparer^ stringComparer = StringComparer::OrdinalIgnoreCase;
Thread^ readThread = gcnew Thread(gcnew ThreadStart(PortChat::Read));
// Create a new SerialPort object with default settings.
_serialPort = gcnew SerialPort();
// Allow the user to set the appropriate properties.
_serialPort->PortName = SetPortName(_serialPort->PortName);
_serialPort->BaudRate = SetPortBaudRate(_serialPort->BaudRate);
_serialPort->Parity = SetPortParity(_serialPort->Parity);
_serialPort->DataBits = SetPortDataBits(_serialPort->DataBits);
_serialPort->StopBits = SetPortStopBits(_serialPort->StopBits);
_serialPort->Handshake = SetPortHandshake(_serialPort->Handshake);
// Set the read/write timeouts
_serialPort->ReadTimeout = 500;
_serialPort->WriteTimeout = 500;
_serialPort->Open();
_continue = true;
readThread->Start();
Console::Write("Name: ");
name = Console::ReadLine();
Console::WriteLine("Type QUIT to exit");
while (_continue)
{
message = Console::ReadLine();
if (stringComparer->Equals("quit", message))
{
_continue = false;
}
else
{
_serialPort->WriteLine(
String::Format("<{0}>: {1}", name, message) );
}
}
readThread->Join();
_serialPort->Close();
}
static void Read()
{
while (_continue)
{
try
{
String^ message = _serialPort->ReadLine();
Console::WriteLine(message);
}
catch (TimeoutException ^) { }
}
}
EDIT 2
Please refer to Linux Serial Port: Blocking Read with Timeout where this has been declared in the question and some of the answers may prove useful to you as well! :)
I recently came for the same issue and I found a good solution using select()
Read the documentation here: manpages.courirer-mta.org/htmlman2/select2.html
In your case you need to setup the timeout, which is the 5th argument of select:
struct timeval timeout;
timeout.tv_sec = 0 ; // seconds
timeout.tv_usec = 1000 ; // microseconds
Hope this helps.

Cannot get response when using socket in C++.NET

I wrote two programs, one as server and another as client. The server is written in standard C++ using WinSock2.h. It is a simple echo server which means the server responds what it receives back to the client. I used a new thread for every client's connection, and in each thread:
Socket* s = (Socket*) a;
while (1) {
std::string r = s->ReceiveLine()
if (r.empty()) {
break;
}
s->SendLine(r);
}
delete s;
return 0;
Socket is a class from here. The server runs properly and I've tested it using telnet, it works well.
Then I wrote the client using C++.NET (or C++/CLI), TcpClient is used to send and receive message from the server. The code is like:
String^ request = "test";
TcpClient ^ client = gcnew TcpClient(server, port);
array<Byte> ^ data = Encoding::ASCII->GetBytes(request);
NetworkStream ^ stream = client->GetStream();
stream->Write(data, 0, data->Length);
data = gcnew array<Byte>(256);
String ^ response = String::Empty;
int bytes = stream->Read(data, 0, data->Length);
response = Encoding::ASCII->GetString(data, 0, bytes);
client->Close();
When I run the client and tries to show the response message onto my form, the program halted at the line int bytes = stream->Read(data, 0, data->Length); and cannot fetch the response. The server is running and there's nothing to do with the network as they are all running on the same computer.
I guess the reason is that the data server responds with is less than data->Length, so the Read method is waiting for more data. Is that right? How should I solve this problem?
Edit
I think I've solved the problem... There are another two methods in the Socket class, ReceiveBytes and SendBytes, and these two methods will not delete the unused space in the bytes array. So the length of data back from the server will match that from the client, thus the Read method will not wait for more data to come.
std::string Socket::ReceiveLine() {
std::string ret;
while (1) {
char r;
switch(recv(s_, &r, 1, 0)) {
case 0: // not connected anymore;
// ... but last line sent
// might not end in \n,
// so return ret anyway.
return ret;
case -1:
return "";
// if (errno == EAGAIN) {
// return ret;
// } else {
// // not connected anymore
// return "";
// }
}
ret += r;
if (r == '\n') return ret;
}
}
i guess receiveline function of the server is waiting for an enter key '\n'.
just try with "test\n" string.
String^ request = "test\n";
// other codes....

Multiple threads writing to same socket causing issues

I have written a client/server application where the server spawns multiple threads depending upon the request from client.
These threads are expected to send some data to the client(string).
The problem is, data gets overwritten on the client side. How do I tackle this issue ?
I have already read some other threads on similar issue but unable to find the exact solution.
Here is my client code to receive data.
while(1)
{
char buff[MAX_BUFF];
int bytes_read = read(sd,buff,MAX_BUFF);
if(bytes_read == 0)
{
break;
}
else if(bytes_read > 0)
{
if(buff[bytes_read-1]=='$')
{
buff[bytes_read-1]='\0';
cout<<buff;
}
else
{
cout<<buff;
}
}
}
Server Thread code :
void send_data(int sd,char *data)
{
write(sd,data,strlen(data));
cout<<data;
}
void *calcWordCount(void *arg)
{
tdata *tmp = (tdata *)arg;
string line = tmp->line;
string s = tmp->arg;
int sd = tmp->sd_c;
int line_no = tmp->line_no;
int startpos = 0;
int finds = 0;
while ((startpos = line.find(s, startpos)) != std::string::npos)
{
++finds;
startpos+=1;
pthread_mutex_lock(&myMux);
tcount++;
pthread_mutex_unlock(&myMux);
}
pthread_mutex_lock(&mapMux);
int t=wcount[s];
wcount[s]=t+finds;
pthread_mutex_unlock(&mapMux);
char buff[MAX_BUFF];
sprintf(buff,"%s",s.c_str());
sprintf(buff+strlen(buff),"%s"," occured ");
sprintf(buff+strlen(buff),"%d",finds);
sprintf(buff+strlen(buff),"%s"," times on line ");
sprintf(buff+strlen(buff),"%d",line_no);
sprintf(buff+strlen(buff),"\n",strlen("\n"));
send_data(sd,buff);
delete (tdata*)arg;
}
On the server side make sure the shared resource (the socket, along with its associated internal buffer) is protected against the concurrent access.
Define and implement an application level protocol used by the server to make it possible for the client to distinguish what the different threads sent.
As an additional note: One cannot rely on read()/write() reading/writing as much bytes as those two functions were told to read/write. It is an essential necessity to check their return value to learn how much bytes those functions actually read/wrote and loop around them until all data that was intended to be read/written had been read/written.
You should put some mutex to your socket.
When a thread use the socket it should block the socket.
Some mutex example.
I can't help you more without the server code. Because the problem is probably in the server.

Unable to receive data from serial port

Currently I try to write a serial port communication in VC++ to transfer data from PC and robot via XBee transmitter. But after I wrote some commands to poll data from robot, I didn't receive anything from the robot (the output of filesize is 0 in the code.). Because my MATLAB interface works, so the problem should happen in the code not the hardware or communication. Would you please give me help?
01/03/2014 Updated: I have updated my codes. It still can not receive any data from my robot (the output of read is 0). When I use "cout<<&read" in the while loop, I obtain "0041F01C1". I also don't know how to define the size of buffer, because I don't know the size of data I will receive. In the codes, I just give it a random size like 103. Please help me.
// This is the main DLL file.
#include "StdAfx.h"
#include <iostream>
#define WIN32_LEAN_AND_MEAN //for GetCommState command
#include "Windows.h"
#include <WinBase.h>
using namespace std;
int main(){
char init[]="";
HANDLE serialHandle;
// Open serial port
serialHandle = CreateFile("\\\\.\\COM8", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// Do some basic settings
DCB serialParams;
DWORD read, written;
serialParams.DCBlength = sizeof(serialParams);
if((GetCommState(serialHandle, &serialParams)==0))
{
printf("Get configuration port has a problem.");
return FALSE;
}
GetCommState(serialHandle, &serialParams);
serialParams.BaudRate = CBR_57600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
//set flow control="hardware"
serialParams.fOutX=false;
serialParams.fInX=false;
serialParams.fOutxCtsFlow=true;
serialParams.fOutxDsrFlow=true;
serialParams.fDsrSensitivity=true;
serialParams.fRtsControl=RTS_CONTROL_HANDSHAKE;
serialParams.fDtrControl=DTR_CONTROL_HANDSHAKE;
if (!SetCommState(serialHandle, &serialParams))
{
printf("Set configuration port has a problem.");
return FALSE;
}
GetCommState(serialHandle, &serialParams);
// Set timeouts
COMMTIMEOUTS timeout = { 0 };
timeout.ReadIntervalTimeout = 30;
timeout.ReadTotalTimeoutConstant = 30;
timeout.ReadTotalTimeoutMultiplier = 30;
timeout.WriteTotalTimeoutConstant = 30;
timeout.WriteTotalTimeoutMultiplier = 30;
SetCommTimeouts(serialHandle, &timeout);
if (!SetCommTimeouts(serialHandle, &timeout))
{
printf("Set configuration port has a problem.");
return FALSE;
}
//write packet to poll data from robot
WriteFile(serialHandle,">*>p4",strlen(">*>p4"),&written,NULL);
//check whether the data can be received
char buffer[103];
do {
ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
cout << read;
} while (read!=0);
//buffer[read]="\0";
CloseHandle(serialHandle);
return 0;
}
GetFileSize is documented not to be valid when used with a serial port handle. Use the ReadFile function to receive serial port data.
You should use strlen instead of sizeof here:
WriteFile(serialHandle,init,strlen(init),&written,NULL)
You would be even better off creating a function like this:
function write_to_robot (const char * msg)
{
DWORD written;
BOOL ok = WriteFile(serialHandle, msg, strlen(msg), &written, NULL)
&& (written == strlen(msg));
if (!ok) printf ("Could not send message '%s' to robot\n", msg);
}
But that's only the appetizer. The main trouble is, as MDN says:
You cannot use the GetFileSize function with a handle of a nonseeking device such as a pipe or a communications device.
If you want to read from the port, you can simply use ReadFile until it returns zero bytes.
If you already know the max size of your robot's response, try reading that many characters.
Continue reading until the read reports an actual number of bytes read inferior to the size of the buffer. For instance:
#define MAX_ROBOT_ANSWER_LENGTH 1000 /* bytes */
const char * read_robot_response ()
{
static char buffer[MAX_ROBOT_ANSWER_LENGTH];
DWORD read;
if (!ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL))
{
printf ("something wrong with the com port handle");
exit (-1);
}
if (read == sizeof(buffer))
{
// the robot response is bigger than it should
printf ("this robot is overly talkative. Flushing input\n");
// read the rest of the input so that the next answer will not be
// polluted by leftovers of the previous one.
do {
ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL);
} while (read != 0);
// report error
return "error: robot response exceeds maximal length";
}
else
{
// add a terminator to string in case Mr Robot forgot to provide one
buffer[read] = '\0';
printf ("Mr Robot said '%s'\n", buffer);
return buffer;
}
}
This simplistic function returns a static variable, which will be overwritten each time you call read_robot_response.
Of course the proper way of doing things would be to use blocking I/Os instead of waiting one second and praying for the robot to answer in time, but that would require a lot more effort.
If you feel adventurous, you can use overlapped I/O, as this lenghty MDN article thoroughly explores.
EDIT: after looking at your code
// this reads at most 103 bytes of the answer, and does not display them
if (!ReadFile(serialHandle,buffer,sizeof(buffer),&read,NULL))
{
printf("Reading data to port has a problem.");
return FALSE;
}
// this could display the length of the remaining of the answer,
// provided it is more than 103 bytes long
do {
ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
cout << read;
}
while (read!=0);
You are displaying nothing but the length of the response beyond the first 103 characters received.
This should do the trick:
#define BUFFER_LEN 1000
DWORD read;
char buffer [BUFFER_LEN];
do {
if (!ReadFile(
serialHandle, // handle
buffer, // where to put your characters
sizeof(buffer) // max nr of chars to read
-1, // leave space for terminator character
&read, // get the number of bytes actually read
NULL)) // Yet another blody stupid Microsoft parameter
{
// die if something went wrong
printf("Reading data to port has a problem.");
return FALSE;
}
// add a terminator after last character read,
// so as to have a null terminated C string to display
buffer[read] = '\0';
// display what you actually read
cout << buffer;
}
while (read!=0);
I advised you to wrap the actual calls to serial port accesses inside simpler functions for a reason.
As I said before, Microsoft interfaces are a disaster. They are verbose, cumbersome and only moderately consistent. Using them directly leads to awkward and obfuscated code.
Here, for instance, you seem to have gotten confused between read and buffer
read holds the number of bytes actually read from the serial port
buffer holds the actual data.
buffer is what you will want to display to see what the robot answered you
Also, you should have a documentation for your robot stating which kind of answers you are supposed to expect. It would help to know how they are formatted, for instance whether they are null-terminated strings or not. That could dispense to add the string terminator.