resource temporarily unavailable on read() from linux device /dev/ttyS0 - c++

I read all the solutions and test them. someone said used O_NDELAY and remove fnctl or the other said to use O_NONBLOCK and so on, but my problem does not solve.
I have nanopi neo and I want to use UART0. This is my code:
Main.cpp:
#include <QCoreApplication>
//#include "serialport.h"
#include "portserial.h"
#include <iostream>
#include <istream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString port;PortSerial *p;
cout<<"Enter tty:";
QTextStream s(stdin);
port = s.readLine();
p=new PortSerial(port,1);
if(p->openport(port)==1)
{
cout << "connected\n";
}
else
{
qDebug()<<"Not serial port : "<<port;
delete p;
}
return a.exec();
}
and portSerial.h and .cpp:
#ifndef PORTSERIAL_H
#define PORTSERIAL_H
#include <stdio.h> /* Standard input/output definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include "errno.h" /* Error number definitions */
#include "termio.h" /* POSIX terminal control definitions */
#include <stdlib.h>
#include "QDebug"
#define MAXDATASIZE 2048
#include <QByteArray>
#include <QThread>
#include <pthread.h>
class PortSerial:public QObject
{
Q_OBJECT
public:
QThread t;
// pthread_t pthrd;
int fd;
int status;
char * buffer;
char * buffertemp;
char buf2[MAXDATASIZE];
QString output;
QByteArray ba;
QByteArray batemp;
fd_set readfs;
timeval tv;
int n;
int devid;
bool wait;
PortSerial(QString port, int dev);
~PortSerial();
public slots:
int openport(QString port);
int init();
void closeport();
void readData();
void ifExist();
// int readifexist(char &tmp);
void writeData(QByteArray ba);
signals:
void readyread(QByteArray ba,int devids);
};
#endif // PORTSERIAL_H
and .cpp is:
#include "portserial.h"
PortSerial::PortSerial(QString port,int dev)
{
// qDebug()<<"Start the thread";
buffer = new char[1024];
devid=dev;
openport(port);
moveToThread(&t);
connect(&t, SIGNAL(started()), this, SLOT(ifExist()));
t.start();
}
PortSerial::~PortSerial()
{
closeport();
}
//____________________________
int PortSerial::openport(QString port)
{
fd=open(port.toStdString().c_str(),O_RDWR|O_NOCTTY|O_NDELAY/*O_NONBLOCK*/);//ARM
if (fd==-1)
{
return -1;//return open port error
}
else
{
// fcntl(fd,F_SETFL,O_NDELAY);
init();
return 1;
}
}
//-------------------------------------
void PortSerial::closeport()
{
qDebug()<<"Close with : " << close(fd);
}
//-------------------------------------
int PortSerial::init()
{
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( fd, &tty ) != 0 ) {
//qDebug() << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
return -2;
}
/* Save old tty parameters */
tty_old = tty;
/* Set Baud Rate */
if(devid==1){//rfid
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
qDebug()<<"fd is : "<< fd<<" with this baud rate: 9600";
}
else{//fp
cfsetospeed (&tty, (speed_t)B115200);
cfsetispeed (&tty, (speed_t)B115200);
qDebug()<<"fd is : "<< fd<<" with this baud rate: 115200";
}
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( fd, TCIFLUSH );
if ( tcsetattr ( fd, TCSANOW, &tty ) != 0) {
//qDebug() << "Error " << errno << " from tcsetattr" << std::endl;
return -3;
}
return 1;
}
///new code
/// *******************************************************
///
///
/// *******************************************************
void PortSerial::readData()
{
buffer[0]=0;
usleep(20000);
int res = read(fd,buffer,2048);
if(res <=0)
qDebug() << strerror(errno) ;
if(res >0)
{
buffer[res]=0;
// batemp = QByteArray((char*)buffer, res);
batemp.append(QByteArray((char*)buffer, res));
// emit readyread(ba,devid);
// qDebug()<<"_____READ________\n"<<ba.toHex()<<"\n";
}
}
void PortSerial::ifExist()
{
int c=0;
while(1){
//set timeout for wait
tv.tv_sec = 0;
tv.tv_usec = 1000;
FD_ZERO(&readfs);
FD_SET(fd, &readfs);
n=select(fd+1, &readfs, NULL, NULL, &tv /* no timeout */);
if(n==1)
{
qDebug("##########################################################################reading");
readData();
}
else
{
if(batemp.length()>0){
qDebug()<<"batemp len is:"<<batemp.length();
emit readyread(batemp,devid);
qDebug()<<"\n________________________READ byte_____________________________\n"<<batemp.toHex()
<<"\nnon hex is: "<<batemp<<"\n";
batemp.clear();
}
}
}
}
///new code
/// *******************************************************
///
///
/// *******************************************************
//------------------------------------
void PortSerial::writeData(QByteArray ba)
{
int res=write(fd,ba,ba.length());
qDebug()<<"port write : "/*<<ba.toHex()*/<<"******* res is : "<<res;
}
When I give this serial port: /dev/ttyS0 to this, First read Null (0a03 in hex) and then just read this:
root#NanoPi-NEO:~# ./FPConsole -qws
Enter tty:/dev/ttyS0
fd is : 7 with this baud rate: 9600
fd is : 8 with this baud rate: 9600
connected
##########################################################################reading
batemp len is: 2
________________________READ byte_____________________________
"0a03"
non hex is: "
"
##########################################################################reading
Resource temporarily unavailable
How Can I solve this?To read the exact RFID card data and read it more than once without resource temporarily unavailable .

Related

Termios c++ serial read not reading arduino serial

I am trying to read serial data from an Arduino Uno. I am using the Termios struct and followed this tutorial. I am not receiving the Arduino serial data in return, can anyone help me? First time using c++ to read serial. Following is the c++ code (i'm using ROS), and the arduino code.
c++ code
#include <ros.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <csignal>
#include <sstream>
#include <algorithm>
#include <iterator>
const char *arduino_path = "/dev/ttyACM0";
int serial_port;
struct termios tty;
void init_serial(){
//do cereal things https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/
serial_port = open(arduino_path, O_RDWR | O_NOCTTY | O_NDELAY);
if (serial_port < 0) {
ROS_ERROR("Error %i from open: %s", errno, strerror(errno));
}
memset(&tty, 0, sizeof tty);
if(tcgetattr(serial_port, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
}
//set flags
tty.c_cflag &= ~PARENB;
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS;
tty.c_cflag |= CREAD | CLOCAL;
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
}
}
std::string read_port(){
// Allocate memory for read buffer, set size according to your needs
char read_buf [256];
memset(&read_buf, '\0', sizeof(read_buf));
int n = read(serial_port, &read_buf, sizeof(read_buf));
std::string ret(read_buf);
return ret;
}
int main(int argc, char **argv){
ros::init(argc, argv, "sensor_handler");
ros::NodeHandle n;
init_serial();
while(ros::ok()){
cout << read_port() << std::endl;
}
}
Arduino code:
bool startup;
//Soil pins
const int soil_sensor_A0_AI = 0;
const int soil_sensor_A0_P = 0;
const int soil_sensor_A1_AI = 1;
const int soil_sensor_A1_P = 1;
const int soil_sensor_B0_AI = 2;
const int soil_sensor_B0_P = 2;
const int soil_sensor_B1_AI = 3;
const int soil_sensor_B1_P = 3;
int no_soil_sensors = 4;
//timer for the water
double water_timer;
int hours_delay = 4;
//water level vars
int water_level_sensor_pin = 5; //must be a PWM pin
int water_level; //in mm^3
double min_water = 20;
void setup() {
Serial.begin(9600);
//Setup soil moisture power pins as outputs
pinMode(soil_sensor_A0_P, OUTPUT);
pinMode(soil_sensor_A1_P, OUTPUT);
pinMode(soil_sensor_B0_P, OUTPUT);
pinMode(soil_sensor_B1_P, OUTPUT);
pinMode(water_level_sensor_pin, INPUT);
//init timer
water_timer = micros();
startup = true;
}
void loop() {
//check if starting up
if(startup){
check_water();
check_soil();
startup = false;
water_timer = micros();
}
/*
* if last check+delay in micros is less than or equal to current time then it means it is time to run a soil check.
*/
if(water_timer + (3600000000*hours_delay) <= micros() ){
check_water();
check_soil();
water_timer = micros();
}
//keep checking water, good way to monitor for leaks
check_water();
}
void check_soil() {
Serial.print("$SOIL:");
if(water_level < min_water){
Serial.println("E, Water level is too low to water the plants");
return;
}
for(int i = 0; i<no_soil_sensors; i++){
switch(i){
case soil_sensor_A0_AI:
digitalWrite(soil_sensor_A0_P, HIGH);
Serial.print("A0,");
Serial.print(analogRead(soil_sensor_A0_AI));
Serial.print(";");
digitalWrite(soil_sensor_A0_P, LOW);
break;
case soil_sensor_A1_AI:
digitalWrite(soil_sensor_A1_P, HIGH);
Serial.print("A1,");
Serial.print(analogRead(soil_sensor_A1_AI));
Serial.print(";");
digitalWrite(soil_sensor_A1_P, LOW);
break;
case soil_sensor_B0_AI:
digitalWrite(soil_sensor_B0_P, HIGH);
Serial.print("B0,");
Serial.print(analogRead(soil_sensor_B0_AI));
Serial.print(";");
digitalWrite(soil_sensor_B0_P, LOW);
break;
case soil_sensor_B1_AI:
digitalWrite(soil_sensor_B1_P, HIGH);
Serial.print("B1,");
Serial.print(analogRead(soil_sensor_B1_AI));
Serial.print(";");
digitalWrite(soil_sensor_B1_P, LOW);
break;
default:
Serial.println("E, SOIL_SENSORS");
break;
}
}
Serial.println("");
}
void check_water(){
//I don't know the math behind this yet but it will be in here
Serial.print("$WATER:");
double water_voltage = digitalRead(water_level_sensor_pin);
//math
double water_level = 0;
Serial.print(water_level);
if(water_level <= min_water){
Serial.print(";E, Water Level Low");
}
Serial.println("");
}

C++ libserial serial connection to Arduino

I'm trying to send data via serial connection (USB) from my PC (Ubuntu 14.04) to an Arduino Uno. The Arduino should display the received data for testing purposes. (I'm happy, if I receive anything...)
I use libserial to send the data but the Arduino receives nothing. With the help of the Arduino IDE I could send the data successfully to the Arduino. With normal console commands it is also possible to send the data.
Here is my Arduino code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("connecting...");
inputString.reserve(200);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
lcd.setCursor(0, 0);
lcd.print("successful connected");
}
void loop() {
lcd.setCursor(0, 1);
// print the string when a newline arrives:
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(inputString);
delay(500);
}
void serialEvent() {
if (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
}
}
And this the c++ code (on the PC side):
//Libserial: sudo apt-get install libserial-dev
#include <SerialStream.h>
#include <iostream>
#include <unistd.h>
using namespace LibSerial;
using namespace std;
int main(int argc, char** argv)
{
SerialStream my_serial_stream;
//
// Open the serial port for communication.
//
my_serial_stream.Open("/dev/ttyACM0");
my_serial_stream.SetBaudRate(SerialStreamBuf::BAUD_9600);
//my_serial_stream.SetVTime(1);
//my_serial_stream.SetVMin(0);
my_serial_stream.SetCharSize(SerialStreamBuf::CHAR_SIZE_8);
my_serial_stream.SetParity(SerialStreamBuf::PARITY_NONE);
my_serial_stream.SetFlowControl(SerialStreamBuf::FLOW_CONTROL_NONE);
my_serial_stream.SetNumOfStopBits(1);
int i = 0;
while(i<=5) {
usleep(1500000);
if (!my_serial_stream.good()) {
my_serial_stream << i << "\n" << endl;
cout << i << endl;
}
else {
cout << "serial is not good" << endl;
}
i++;
}
my_serial_stream.Close();
cout << "ready" << endl;
return 0;
}
Do you have any ideas why this doesn't work?
Thanks!
I found a solution, how to communicate with the Arduino via serial Port (USB). I don't use libserial.
I improved the Arduino code (display only, if there is a new line):
// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("connecting...");
inputString.reserve(200);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
lcd.setCursor(0, 0);
lcd.print("successful connected");
}
void loop() {
lcd.setCursor(0, 1);
if (stringComplete) {
// print the string when a newline arrives:
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(inputString);
inputString = "";
stringComplete = false;
}
}
void serialEvent() {
if (Serial.available()) {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
}
C++ code:
//to compile use: g++ serial_success.cpp -o serial -std=c++11
//you might not need every inclusion
#include <iostream>
#include <unistd.h>
#include <string>
#include <stdio.h> // standard input / output functions
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitionss
#include <time.h> // time calls
using namespace std;
#define BAUDRATE B9600
int main(int argc, char** argv)
{
int fileDescriptor = open("/dev/ttyACM0", O_RDWR | O_NOCTTY);
struct termios newtio;
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
// set to 8N1
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;
newtio.c_iflag = IGNPAR;
// output mode to
//newtio.c_oflag = 0;
newtio.c_oflag |= OPOST;
/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 10; /* inter-character timer 1 sec */
newtio.c_cc[VMIN] = 0; /* blocking read disabled */
tcflush(fileDescriptor, TCIFLUSH);
if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
perror("could not set the serial settings!");
return -99;
}
int i = 0;
string test = ">123,456,7890;";
while(i < 10) {
usleep(100000);
string res = test + std::to_string(i) + "\n";
long wrote = write(fileDescriptor, res.c_str(), sizeof(char)*res.size() );
cout << res << endl;
i++;
}
cout << "ready" << endl;
return 0;
}

How to wait for serial input in raw (noncanonical) mode?

This program runs on PC and I want him wait until there are data available on serial connection from Arduino, and display them. If Arduino don't send anything, I want the program to wait indefinitely.
What happens, is that I've got only Resource temporarily unavailable messages.
After kind help from Kurt Stutsman here is a working program that waits for binary input from serial connection, (from the Arduino in this case).
#include <string.h>
#include <iostream>
#include <stdint.h>
#include <errno.h>
#include <fcntl.h> // File control definitions
#include <termios.h> // POSIX terminal control definitions
#include <unistd.h> // UNIX standard function definitions
using namespace std;
int connect(const char* serialport)
{
struct termios toptions;
int fd;
fd = open(serialport, O_RDWR );
if (fd == -1) {
return -1;
}
if (tcgetattr(fd, &toptions) < 0)
return -1;
speed_t brate = B9600; //9600 bauds
cfsetospeed(&toptions, brate);
cfmakeraw(&toptions);
toptions.c_cc[VMIN] = 1; //I want read to wait for the input
toptions.c_cc[VTIME] = 0; //indefinitely, until it arrives. Byte after byte.
tcsetattr(fd, TCSANOW, &toptions);
if( tcsetattr(fd, TCSAFLUSH, &toptions) < 0) {
return -1;
}
return fd;
}
int main() {
int fd = connect("/dev/ttyACM0");
if (fd==-1)
{
cout<<"Error in opening serial port\n";
cout<<strerror(errno)<<'\n';
return -1;
}
while(true)
{
uint8_t b=0;
int ret=read(fd, &b, 1);
if (ret == 1)
{
cout<<"received byte "<<int(b)<<'\n';
} else if (ret == 0)
{
cout<<"EOF\n";
} else
{
cout<<strerror(errno)<<'\n';
}
}
return 0;
}
You can test it with this simple Arduino C++ code:
void setup() {
Serial.begin(9600); // connect to the serial port
}
void loop()
{
Serial.write(uint8_t(42));
delay(1000);
}

C++ Ubuntu select() if serial interface has data on asynchronous read

I´m writing an asynchronous serial data reader class for Ubuntu using C++ and termios and I´m facing difficulties checking is there is data available.
Here is my code:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
class MySerialClass {
public:
MySerialClass(std::string port);
virtual ~MySerialClass();
void openSerial();
void closeSerial();
void configureSerial();
void writeSerial(std::vector<char> data);
void readSerial(std::vector<char> &data, unsigned int numBytes);
private:
int fd = 0; // The serial file descriptor
fd_set fdset; // The set to check on select
std::string portName = "";
};
MySerialClass::MySerialClass(std::string port) : portName(port) {}
MySerialClass::~MySerialClass() {}
void MySerialClass::openSerial()
{
fd = open(portName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
}
void MySerialClass::closeSerial()
{
close(fd);
}
void MySerialClass::configureSerial()
{
struct termios config = { 0 };
tcgetattr(fd, &config);
config.c_iflag = IGNPAR | ICRNL;
config.c_oflag = 0;
config.c_lflag = ICANON;
config.c_cc[VINTR] = 0; /* Ctrl-c */
config.c_cc[VQUIT] = 0; /* Ctrl-\ */
config.c_cc[VERASE] = 0; /* del */
config.c_cc[VKILL] = 0; /* # */
config.c_cc[VEOF] = 4; /* Ctrl-d */
config.c_cc[VTIME] = 0; /* inter-character timer unused */
config.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
config.c_cc[VSWTC] = 0; /* '\0' */
config.c_cc[VSTART] = 0; /* Ctrl-q */
config.c_cc[VSTOP] = 0; /* Ctrl-s */
config.c_cc[VSUSP] = 0; /* Ctrl-z */
config.c_cc[VEOL] = 0; /* '\0' */
config.c_cc[VREPRINT] = 0; /* Ctrl-r */
config.c_cc[VDISCARD] = 0; /* Ctrl-u */
config.c_cc[VWERASE] = 0; /* Ctrl-w */
config.c_cc[VLNEXT] = 0; /* Ctrl-v */
config.c_cc[VEOL2] = 0; /* '\0' */
speed_t sp = B9600;
config.c_cflag |= CSIZE;
config.c_cflag |= CS8;
cfsetispeed(&config, sp);
cfsetospeed(&config, sp);
tcsetattr(fd, TCSAFLUSH, &config);
}
void MySerialClass::writeSerial(std::vector<char> data)
{
char buffer[1024];
if (data.size() > 1024)
return;
int index = 0;
for (char &item : data)
buffer[index++] = item;
unsigned int size = data.size();
write(fd, &buffer[0], size);
}
void MySerialClass::readSerial(std::vector<char> &data, unsigned int numBytes)
{
char buffer[1024];
data.clear();
if (numBytes > 1024)
return;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int ret = select(fd + 1, 0, 0, 0, &tv);
std::cout << "Select returns: " << ret << std::endl;
if (!ret)
return;
read(fd, &buffer[0], numBytes);
for (unsigned int i = 0; i < numBytes; i++)
data.push_back(buffer[i]);
}
int main()
{
MySerialClass serial("/dev/ttyS1");
serial.openSerial();
serial.configureSerial();
while(1)
{
std::vector<char> retData;
serial.readSerial(retData, 100);
std::string retString(retData.begin(), retData.end());
if (retString == "END")
{
serial.closeSerial();
break;
}
}
}
It compiles fine, but it never receives data as the select() statement always returns zero. The code with blocking option and without the select() works fine (just comment the select() line and remove O_NODELAY from open()).
I´m pretty sure this problem is related to the way select() is being used (it´s my first time with select()).
Can someone help me to solve that ? The code is available at Coliru here
BTW: Another doubt I have relative to select() is that this class will be used on a multithreaded environmet. I need to make sure that each class instance will check only for its port busy (it´s own fd), no other threads port busy.
Didn't specify a fd_set to read. Try this:
fd_set readfs; /* file descriptor set */
FD_ZERO(&readfs); /* clear the set */
FD_SET(fd, &readfs); /* put the fd in the set */
int ret = select(fd + 1, &readfs, 0, 0, &tv);
Edit: That should also solve your other question. Each select is only looking at the file descriptors you tell it to look at.
Gah. Bad English grammar, but it looks even worse corrected.

How can I set and clear the RTS line of a serial port. C++ POSIX

I want to control the RTS line on the serial port to wake up a device. Here is some rough test code to open the serial port. I need to set the RTS line low for 500ms. I'm having trouble googleing/understanding how to control the lines. Any Hints?
EDIT: OR controlling the CTS/DTR, any other line besides the Tx/Rx lines to connect to a pin of the robot.
#include <iostream>
#include <string.h>
#include <cstdio>
#include <fstream>
#include <sys/types.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdint.h> /* Standard types */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ioctl.h>
#include <getopt.h>
using namespace std;
int fd_global;
FILE* fp_global;
int serialport_init(const char* serialport, int baud);
int serialport_read_until(int fd);
int fpeek(FILE* stream);
bool fexists(const char *filename);
void* screen_thread(void* arg) {
while(1) {
}
}
int main(void) {
pthread_t screen_thread_id;
int flags;
int baudrate = B9600; // default
fd_global = serialport_init((char*)"/dev/ttyUSB0", baudrate);
if(fd_global==-1) {
cout << "Open port: error\n";
return -1;
}
fp_global = fdopen(fd_global, "r");
if (-1 == (flags = fcntl(fd_global, F_GETFL, 0))) flags = 0;
fcntl(fd_global, F_SETFL, flags | O_NONBLOCK);
//pthread_create(&screen_thread_id, NULL, screen_thread, (void*)NULL);
serialport_read_until(fd_global);
return 0;
}
int serialport_read_until(int fd)
{
char b[1];
while(1) {
int n = read(fd, b, 1); //Read byte at a time
if(n==-1) {
printf("N");fflush(stdout);
perror("READ: ");
}
else if( n==0 ) {
printf("Z");fflush(stdout);
} else if(n>0) {
printf(":%d:",n);fflush(stdout);
}
usleep(100*1000);
if (fexists("/dev/ttyUSB0"))
printf("CONNECTED\n");
else
printf("NOT CONNECTED\n");
}
return 0;
}
bool fexists(const char *filename)
{
ifstream ifile(filename);
return ifile;
}
int serialport_init(const char* serialport, int baud)
{
struct termios toptions;
int fd;
// Open port
fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("init_serialport: Unable to open port ");
return -1;
}
// Read current termios settings
if (tcgetattr(fd, &toptions) < 0) {
perror("init_serialport: Couldn't get term attributes");
return -1;
}
// Set baud rate variable
speed_t brate = baud;
switch(baud) {
case 2400: brate=B2400; break;
case 4800: brate=B4800; break;
case 9600: brate=B9600; break;
#ifdef B14400
case 14400: brate=B14400; break;
#endif
case 19200: brate=B19200; break;
#ifdef B28800
case 28800: brate=B28800; break;
#endif
case 38400: brate=B38400; break;
case 57600: brate=B57600; break;
case 115200: brate=B115200; break;
}
cfsetispeed(&toptions, brate);
cfsetospeed(&toptions, brate);
// Setup termios for 8N1
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
// Reccomended settings
toptions.c_cflag &= ~CRTSCTS; // no flow control
toptions.c_cflag |= CREAD | CLOCAL; // turn on read & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
toptions.c_oflag &= ~OPOST; // make raw
// Setting when read() releases
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html (Still a little confusing)
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 20;
// Apply settings
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("init_serialport: Couldn't set term attributes");
return -1;
}
return fd;
}
Would this work? I'll test it tomorrow.
int status;
status |= TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);
usleep(500*1000);
status &= ~TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);