This is a follow up question to this original post:
RaspberryPi RS-232 trouble
I made changes to my code per the accepted answer, the terminal is now set up for blocking and canonical input. The read()
now works as expected, with the exception of the very first read(which is typically some extra random symbols mixed with some good data) I get single lines of data from the laser range finder representing exactly what I expect to see.
However, I now have an issue that if I do too many reads, the laser range finder is put into a non-operating state, stops communication, and can only be reset by doing a power cycle. This has happened with as few as 4 reads on the device, and I haven't been able to do more than 8 reads. It doesn't matter if the reads are all at once, or spanned across several program starts.
int main(){
int uart0_filestream = -1;
int loop, i, sentBytes;
int isError, rx_length;
unsigned char rx_buffer[256];
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(uart0_filestream, F_SETFL, 0);
if(uart0_filestream == -1){
printf("ERROR: Unable to open UART\n");
checkError(errno);
exit(1);
}
struct termios options;
isError = tcgetattr(uart0_filestream, &options);
if(isError < 0){
printf("ERROR: tcgetattr failed.\n");
checkError(errno);
exit(1);
}
//set c ontrol options and baud
options.c_cflag |= (CLOCAL | CREAD);
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
//set 8 data bits, 1 stop bit, no parity
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
//set input options
options.c_iflag |= (INPCK | ISTRIP); //strip parity
options.c_iflag &= ~(IXON | IXOFF | IXANY); //turn off software flow control
//set canonical input processing
options.c_lflag |= (ICANON | ECHO | ECHOE);
tcflush(uart0_filestream, TCIFLUSH);
isError = tcsetattr(uart0_filestream, TCSANOW, &options);
if(isError < 0){
printf("ERROR: tcsetattr failed.\n");
checkError(errno);
exit(1);
}
//read() successfully returns expected data, with the exception of the first
//read. Reading more than 6-8 times, regardless of same session or restarting
//program puts LRF in non-working state which requires a power cycle to fix
for(i=0; i<4;i++ ){
rx_length = read(uart0_filestream, (void*)rx_buffer, 255);
if(rx_length < 0){
printf("ERROR: read() failed.\n");
checkError(errno);
}
if(rx_length > 0){
printf("rx_lentgh = %i:\t ", rx_length);
for(loop=0; loop<rx_length; loop++){
printf("%c", rx_buffer[loop]);
}
printf("\n");
}
}
//writing once has no affect, sending command has no affect
//looping the write, eventually 'something' gets to the LRF
//but it puts it in the same state as when reading too many
//times and have to power cycle
for(i = 0; i<8; i++){
sentBytes = write(uart0_filestream, "o\n", 2);
if(sentBytes < 2){
printf("ERROR: write() failed.\n");
checkError(errno);
}
}
close(uart0_filestream);
}
I don't believe it is the range finder, as I can run minicom and it will continuously display the output successfully.
As noted in the comments of my code, I also have trouble writing any commands to the laser range finder. Each command consists of a single character, followed by a new line. One write has no affect, but looping several times can put the device in the same state as reading too many times.
I have read Posix Serial Programming Guide, and tried different combinations of flags that I believe might affect either the reading or writing, but have had no success.