I am writing a program to read data from a sensor at /dev/ser1 which gives out data at 100Hz. I am using read() function for multi byte read i.e. in following manner
res = read(fd,databuffer,500)
But res never returns small numbers. It either gives -1(no data to be read)
few times and suddenly gives res= 50, 40 etc in between.
res = read(fd,databuffer,500);
//extra processing <1ms
the output of res is in the following manner:
I have confirmed that the sensor sends data every 10ms in a consistent manner. Could anyone help me with this? Is there a minimum fill of the serial buffer required before it gives out data in a multibyte read?
use read_cond() or use “termios” struct and program MIN, MAX, TIMEOUT fields…
That’s normal, if you check the documention for read it says that it might return less then the number of bytes you requested. However I would not expect it to return -1, what is the value of errno. How did you do the open(), did you change the setting of the serial port.
When I am doing this sort of thing, I set the port to be non blocking.
So read returns immediatly with all characters available.
Then I ask for only 1 char at a time, seems inefficient, but the message parsing is greatly simplified, and as the serial port is usually relativly slow, speed is not the issue.
It also helps to know how the data is formatted, does the sensor send a fixed length string?
Does it send a framed string?
If it’s not framed or fixed length then you have an issue in decoding the data.
If it’s framed, you need to parse the string for start and end charaters.
If it’s fixed length, only aske for the correct number of chars, (and leave it as blocking).
Thanking you for all your replies.
dear mario, here is how i open my port and my settings
int InitPort::OpenPort(char* Port)
int Fd=open(Port,O_RDWR | O_NOCTTY | O_NDELAY);
if(Fd == -1)
cout<<“Unable to open port “<<Port<<endl;
cout<<“Port '”<<Port<<”’ opened”<<endl;
struct termios Options;
Options.c_cflag |= (CLOCAL | CREAD);
Options.c_cflag &= ~PARENB;
Options.c_cflag &= ~CSTOPB;
Options.c_cflag &= ~CSIZE;
Options.c_cflag |= CS8;
Options.c_cflag &= ~(ICANON | ECHO | ISIG);
I am always geting the following errors
error 11: resource temporarily unavailable
error 22: invalid argument
the sensor sends fixed packets of 19 byte length. Do you know how to keep the port non blocking.
dear qnx loader, i tried readcond(,0,1,0) but does not solve the problem
Thank you for all the help and sorry for the multiple posts.
I am using an XT/104 and this i how i installed the ports:
devc-ser8250 -t8 -u3 100,5 &
I checked the data being sent over from the sensor using an oscilloscope and it is sending over the bytes at a consistent rate of 21 bytes every 10 ms.
I use the program to read every 9ms.
For every 2 or 3 reading of the serial port i will get 1 read which returns 56 bytes and errno 22 (invalid argument) while the other reads will return a -1 with errno 11 (resource temporarily unavailable).
I tried O_NONBLOCK while opening the port…but does not work
Thanking you all for your reply…I have fixed the problem. It is a limitation of the XT/104 card. When I connected the sensor to the main serial ports 1 and 2, it works well
Ok what is required here is a bit of good old fasioned design.
The sensor sends 19 (or is it 21) bytes of data.
What does the data look like?
is it ascii or binary? - that matters for the port config, if it’s binary you need to set the raw option.
Does it end with a terminating character.
When you understand the data, you can design your app.
while(bytesRx < 19) or is it 21
if ( read(fd, x, 1) > 0)
msg[bytesRx] = ch
if (( ch == terminatingCharIfThereIsOne) && (bytesRx < expected))
OK it’s not real code but you get the gist?
Once you have confidence in the data, you can optimise the code if you need to.
Thanking you all for your support. I can read the data now