I am reading the Sensor data (broadcasted on RS232) with read() function. The data rate is 264 Bytes / Sec.
I am using the following code to read the data (I just needed to read 60 Bytes).
int BytesToRead = 60;
unsigned char* iBuffer = new unsigned char[BytesToRead];
int ret = read(COM, iBuffer, BytesToRead);
cout<<ret<<endl;
if (ret == 0) {
cout<<"Error Reading COM Port"<<endl;
exit(EXIT_FAILURE); // Error Handling
}
delete[] iBufer;
And this program is returning random bytes (~30).
I am a beginner for C++ programming. Sorry, If I am doing some stupid mistake.
Thanks.
My COM function:
int Connect(const char *DeviceName){
long BAUD = B115200;
long DATABITS = CS8; // CS8 = 8n1 Config.(8 bits, No parity, 1 Stop Bit)
long VMIN_CC = 1; // 1 input byte is enough to return from read()
long VTIME_CC = 0; // Inter-character timer
long STOPBITS = 0; // Defined with CS8
long PARITYON = 0; // NONE (Ref.: IH2 Azzura Hand User Guide)
long PARITY = 0; // NONE (Ref.: IH2 Azzura Hand User Guide)
struct termios config; // Configuration of the termios structure
fd_set rdset; // File discription set
//Basic serial interface configuration
//iflag = Input flag || oflag = Output flag || lflag = No-line processing flag
//c_cflag = Caracter processing flag || c_cc = Special character flag
memset(&config,0,sizeof(config));
config.c_iflag = 0; // Turning OFF Input processing
config.c_oflag = 0; // Turning OFF Output processing
config.c_lflag = 0;
config.c_cflag = DATABITS |CREAD|CLOCAL;// Enable the receiver and set local mode
config.c_cc[VMIN] = VMIN_CC;
config.c_cc[VTIME] = VTIME_CC;
//Opening the Port for communication
int com = open(DeviceName, O_RDWR | O_NOCTTY);
//Error Handling
if (com < 0) {
cout<<"ERROR!! Opening Port \n"<<"Sys:"<<strerror(errno)<<endl;
exit(EXIT_FAILURE);
} else {cout<<"Serial Communication (Opening Port): "<<strerror(errno)<<endl;}
//Setting the BaudRate for Communcation
cfsetispeed(&config, BAUD);
cfsetospeed(&config, BAUD);
//Applying Configuration / Attributes
int Attr = tcsetattr(com, TCSANOW, &config);
//Error Handling
if(Attr < 0){
cout<<"ERROR!! Setting Attributes \n"<<"Sys:"<< strerror(errno)<<endl;
exit(EXIT_FAILURE);
} else {cout<<"Serial Communication (Setting Attributes): "<<strerror(errno)<<endl;}
return(com);
}
I am assuming this is a Linux system....
Your BytesToRead variable is only a suggestion to read() in that read() will try to read up to BytesToRead. If read() returns less than your requested amount, then fewer bytes were available to be read.
From the linux manpage on read
... It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal...
It is possible that your sensor is not sending the data you expect, or you are not giving it enough time to transfer all of the data, or there is some other logic/hardware problem that is not apparent from your code example.
read() is not guaranteed to return the number of bytes requested:
From the read(2) Linux manpage:
On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. On error, -1 is returned, and errno is set appropriately. In this case it is left unspecified whether the file position (if any) changes.
Related
I have a following scenario: Someone creates a pseudo terminal via opening /dev/ptmx. New terminal is created and named for example /dev/pts/2. Then, in my program I open /dev/pts/2 for reading. But I also open other devices for reading and use select() function to wait for any incoming data. The select have also some timeout specified for performing other stuff when no data arrives for too long. After successful select i read data using read() function and then print it on the screen.
I encountered an issue if the pseudo terminal is closed by the one who created it. In this case select function ends immediately indicating success as well as read ends indicating "no data" by returning zero. The issue imho is that neither select nor read returns error in such case. How should I handle this to detect that the terminal is no longer existing?
Status processData()
{
fd_set readFileDescriptorSet; // defined somewhere else
int maxFileDescriptor; // defined somewhere else
struct timeval timeout; // defined somewhere else
int ret = select(maxFileDescriptor + 1, &readFileDescriptorSet, nullptr, nullptr, &timeout);
if (!ret) // timeout
return Status::success();
if (ret < 0) // error from select()
return Status::error("select error");
ssize_t rd;
char buff[10];
do {
rd = read(interfaces.serialPort.getFileDescriptor(), buff, sizeof(buff) - 1);
if (rd > 0) { // some data has been read
buff[rd] = '\0';
std::cout << buff;
}
} while (rd > 0);
if (rd < 0) // error from read()
return Status::error("read error");
return Status::success();
}
While the way I open the pseudo terminal is following:
Status internalOpen(std::string fileName)
{
close();
fileDescriptor = ::open(fileName.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fileDescriptor == -1)
return Status::error("Terminal::internalOpen::open('" + fileName + "')");
struct termios attributes;
if (tcgetattr(fileDescriptor, &attributes))
return Status::error("Terminal::internalOpen::tcgetattr()");
setAttributes(attributes);
if (tcsetattr(fileDescriptor, TCSANOW, &attributes))
return Status::error("Terminal::internalOpen::tcsetattr()");
return Status::success();
}
void setAttributes(struct termios &attributes)
{
cfmakeraw(&attributes);
cfsetspeed(&attributes, Config::baudRate);
attributes.c_iflag &= ~(IXOFF | IXANY);
attributes.c_oflag &= ~(ONLCR);
attributes.c_lflag &= ~(ECHOE);
attributes.c_cflag &= ~(CSTOPB | CRTSCTS);
attributes.c_cflag |= CREAD | CLOCAL;
attributes.c_cc[VMIN] = 0;
attributes.c_cc[VTIME] = 0;
}
After select() returns indicating that there's something to be read, the shown code loops repeatedly trying to read() from the non-blocking file descriptor until it is 0:
do {
rd = read( ...
} while (rd > 0);
That's certainly reasonable. Except that the closed connection results in the very first read() returning 0, which the shown logic cannot discriminate.
All that's really needed here is to keep track of whether anything has been read, prior read() returning 0. But if read() returned 0 right off the bat, your goose is cooked.
Additionally, there a few other improvements will make things more robust.
After select() returns, actually check if the file descriptor's bit remains set in the readFileDescriptorSet. The shown logic simply assumes that it is, by checking for all other possibilities. Still, this is somewhat fragile. It's easy to forget this assumption if something tangentially related gets modified (i.e., another fle descriptor gets thrown into the mix).
Use poll() instead of select(), and explicitly check for POLLHUP|POLLRDHUP in revents. The file descriptor closure condition is more explicitly called out, in the poll() interface.
I am using a BeagleBone Black to read data coming from a microcontroller(s) via a UART port(s). I need the reading of the UART port to be a blocking call. Additionally, for the usage of this software there will be some non-standard baud rates in use (aka not provided by termios). Additionally, the UART should follow 8-N-1 (8 data bits, no parity, 1 stop bit).
The code I have for the opening the UART port is as follows:
int UART::UART_open(unsigned int baudRate)
{
mFd = open(mPath.c_str(), O_RDWR | O_NOCTTY);
if(mFd < 0)
{
return -1;
}
struct termios2 tty;
if(ioctl(mFd, TCGETS2, &tty) == -1)
{
return -1;
}
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 5;
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_cflag &= ~CBAUD;
tty.c_cflag |= (BOTHER | CREAD | CLOCAL);
tty.c_ispeed = baudRate;
tty.c_ospeed = baudRate;
if(ioctl(mFd, TCSETS2, &tty) == -1)
{
return -1;
}
return 0;
}
The code I have for reading the UART port is as follows:
int UART::UART_read(unsigned char* buf, int length)
{
if(mFd < 0)
{
return -1;
}
if(read(mFd, buf, length) != length)
{
return -1;
}
return length;
}
There is some odd behavior going on. What happens is, the reading is inconsistent. Sometimes when I test it with an Mbed microcontroller sending data continuously (with small delays in between) via UART to the right port, and a test program to continuously read the UART port on the BeagleBone Black, and print out the data it gets, it works fine, and I am able to print out the data sent and everything works as expected. However, what happens often is the very first read simply blocks forever. No errors occur from the functions, the UART_read function simply hangs. So, to debug the error the first thing I do is I use 'screen' to monitor the /dev/ttyO* port I am trying to read from. What I find is that data is being sent to that port just fine. Then, the odd thing is, after I use screen, if I run my test program to continuously read the UART port, it works fine. This happens consistently too, if I do a quick 'screen' of the port when it is not working, I see data being sent, then my test program works. I have tried changing some of the opening termios2 struct options, to no avail. Any help would be appreciated!
Your termios initialization is obviously incomplete. There's a partial configuration for raw mode, e.g.
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 5;
yet you never actually enable noncanonical mode.
The "blocks forever" behavior of read() is symptomatic of a serial terminal (mis)configured for canonical mode when only binary data is received (i.e. there is no line terminator to "complete" the request).
Another possible cause of "blocks forever" behavior is failure to disable hardware flow-control when it is not used.
The insertion of the following statements would enable noncanonical mode and disable the HW handshake:
cfmakeraw(&tty);
tty.c_cflag &= ~CRTSCTS;
Refer to this answer for a complete example.
if(read(mFd, buf, length) != length)
{
return -1;
}
There is no requirement that a read() of a serial terminal will fill the buffer. Depending on the configuration, a "successful" read can return zero or more bytes up to the number requested.
Therefore a short read is not actually an error condition.
I'm implementing RS485 on arm developement board using serial port and gpio for data enable.
I'm setting data enable to high before sending and I want it to be set low after transmission is complete.
It can be simply done by writing:
//fd = open("/dev/ttyO2", ...);
DataEnable.Set(true);
write(fd, data, datalen);
tcdrain(fd); //Wait until all data is sent
DataEnable.Set(false);
I wanted to change from blocking-mode to non-blocking and use poll with fd. But I dont see any poll event corresponding to 'transmission complete'.
How can I get notified when all data has been sent?
System: linux
Language: c++
Board: BeagleBone Black
I don't think it's possible. You'll either have to run tcdrain in another thread and have it notify the the main thread, or use timeout on poll and poll to see if the output has been drained.
You can use the TIOCOUTQ ioctl to get the number of bytes in the output buffer and tune the timeout according to baud rate. That should reduce the amount of polling you need to do to just once or twice. Something like:
enum { writing, draining, idle } write_state;
while(1) {
int write_event, timeout = -1;
...
if (write_state == writing) {
poll_fds[poll_len].fd = write_fd;
poll_fds[poll_len].event = POLLOUT;
write_event = poll_len++
} else if (write == draining) {
int outq;
ioctl(write_fd, TIOCOUTQ, &outq);
if (outq == 0) {
DataEnable.Set(false);
write_state = idle;
} else {
// 10 bits per byte, 1000 millisecond in a second
timeout = outq * 10 * 1000 / baud_rate;
if (timeout < 1) {
timeout = 1;
}
}
}
int r = poll(poll_fds, poll_len, timeout);
...
if (write_state == writing && r > 0 && (poll_fds[write_event].revent & POLLOUT)) {
DataEnable.Set(true); // Gets set even if already set.
int n = write(write_fd, write_data, write_datalen);
write_data += n;
write_datalen -= n;
if (write_datalen == 0) {
state = draining;
}
}
}
Stale thread, but I have been working on RS-485 with a 16550-compatible UART under Linux and find
tcdrain works - but it adds a delay of 10 to 20 msec. Seems to be polled
The value returned by TIOCOUTQ seems to count bytes in the OS buffer, but NOT bytes in the UART FIFO, so it may underestimate the delay required if transmission has already started.
I am currently using CLOCK_MONOTONIC to timestamp each send, calculating when the send should be complete, when checking that time against the next send, delaying if necessary. Sucks, but seems to work
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.
I have written some C++ code to talk to my arduino via serial. It just tries to make oscillations on two servo motors using sine and cosine, but it is skipping data. I'm not sure why this is happening. I am using the termios.h for the serial stuff. The output from C++ is something like "V180H90" i.e. Vertical 180, Horizontal 90. I was using fstream and usleep() to send data before and it was working, but I'd like to use a better method than delaying by some arbitrary number.
Thanks for any help or guidance.
My arduino code
#include <Servo.h>
typedef enum { NONE, GOT_V, GOT_H } states;
states state = NONE;
Servo pan;
Servo tilt;
int laser = 11;
unsigned int currentValue;
int v_pan = 0;
int v_tilt = 0;
void setup()
{
pan.attach(10);
tilt.attach(9);
Serial.begin(9600);
state = NONE;
}
void processVertical(const unsigned int value)
{
Serial.print("Vertical = ");
Serial.println(value);
int result = 1300 + (value - 90) * 2;
//Serial.println(result);
tilt.writeMicroseconds(result);
}
void processHorizontal(const unsigned int value)
{
Serial.print("Horizontal = ");
Serial.println(value);
int result = 1500 + (value - 180) * 1;
//Serial.println(result);
pan.writeMicroseconds(result);
}
void handlePreviousState()
{
switch(state)
{
case GOT_V:
processVertical(currentValue);
break;
case GOT_H:
processHorizontal(currentValue);
break;
}
currentValue = 0;
}
void processIncomingByte (const byte c)
{
if (isdigit(c))
{
currentValue *=10;
currentValue += c - '0';
}
else
{
handlePreviousState();
switch (c)
{
case 'V':
state = GOT_V;
break;
case 'H':
state = GOT_H;
break;
default:
state = NONE;
break;
}
}
}
void loop()
{
if(Serial.available() > 0)
{
processIncomingByte(Serial.read());
}
digitalWrite(laser, HIGH);
}
//check out writeMicroseconds
My C++ code
// Program for sending data to serial
#include <iostream>
#include <sstream>
#include <string>
#include <termios.h>
#include <fcntl.h>
#include <math.h>
using namespace std;
//open serial port
int openPort(string path)
{
int fd; //file descriptor for port
fd = open(path.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
cerr << "Cannot open port" << endl;
else
fcntl(fd, F_SETFL, 0);
return (fd);
}
//set options for an open serial port
void setOptions(int fd)
{
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
//No parity 8N1
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
//No flow control
options.c_cflag &= ~CRTSCTS;
//Turn off s/w flow control
options.c_iflag &= ~(IXON | IXOFF | IXANY);
//Turn on read and ignore ctrl lines
options.c_cflag |= (CLOCAL | CREAD);
if( tcsetattr(fd, TCSANOW, &options) < 0) {
cerr << "Could not set attributes" << endl;
}
}
//write to serial port
void writePort(int fd, string data)
{
int n = write(fd, data.c_str(), 9);
if (n < 0)
cerr << "Cannot write to port" << endl;
}
int main() {
string path = "/dev/tty.usbmodemfd131";
//string path = "/dev/tty.usbmodemfa141";
int fd = openPort(path);
setOptions(fd);
stringstream ss;
string output;
unsigned short vertical = 0;
unsigned short horizontal = 0;
unsigned short freq = 10;
for(int i = 0; i < 360; i++) {
vertical = ((cos(i * freq * ((M_PI)/180))) + 1) * 90;
horizontal = ((sin(i * freq * ((M_PI)/180))) + 1) * 90;
ss << "V" << vertical << "H" << horizontal << endl;
output = ss.str();
ss.str("");
writePort(fd, output);
// cout << output; //DEBUG
}
close(fd);
return 0;
}
The "processIncomingByte" loop inside the device may have suffered a speed problem as you are processing the previous state (handlePreviousState) immediately after you receive a new mode.
The problem may be caused by doing a Serial.print in the corresponding function while the value-data bytes are still incoming continuously from the PC. Serial print is a relatively slow process in micro-controller logic.
I am not familiar with Arduino hardware, but some lower end micro-controller board is performing software serial interface using bitbanging method, so when you transmit, the receiving is completely stopped. To verify this you can remark the Serial.print to see whether it helps.
Anyway, doing lengthy processing in the middle of incoming data stream is alway problematic, unless you have a hardware serial interface in the device with lots of FIFO buffers.
A proper way to this problem is to receive the whole message inside a buffer first and then process it only when a end-of-message marker is received. For example, insert your message inside the [] pair like [V180H90]. Reset the buffer upon the "[" and process the buffer after you receive the "]". When you are collecting bytes into the buffer, make sure you also check for buffer overflow.
If you just shove data down the port's throat, it'll do its best not to set on fire, but the excess data isn't going to be sent. After all, the port operates at a finite speed and is a pretty limited and dump device.
So, before sending a character to the port you need to check the status of the port to see if it's actually ready to accept another character of data for transmission. Some serial ports can even generate interrupts when they can take more data to help you avoid wasteful status polling.
Also, sometimes two serial ports on the two devices can be connected with an extra pair of non-data signals (RTS and CTS) to indicate whether the receiving side is ready to receive more data. If you have those connected and your device is using them to indicate its readiness, your program should take the state of the device's CTS into account as well.
Clearly your device reads/process data slower than you send it via serial port. I see few possible solutions here:
1) Implement flow control and send data via serial port in blocking mode. You still have to wait after sending, but only as much as it is needed for your device to read and process data.
2) Implement two way communication so your device sends confirmation message (i.e. any single ASCII symbol) to indicate that it is ready to accept data.
3) Divide your code into two parallel parts i.e. : main loop (or an ISR) only reads data from serial port and stores it in a ring buffer, another loop polls the ring buffer and takes/process data from it as soon as there is some data available. This is the most difficult solution of the three as you need two separate threads (or a thread and an ISR) and protect ring buffer from concurrent access, but also the most powerful and flexible.
You are writing data out too quickly to the serial device and the device itself is spitting out data faster than you can read it back in on the other side of the device.
The correct way to cope with this is to throttle the speed of writes to the serial device to avoid flooding it with data.