Serial port in c++ , Unix - c++

I wrote a code to connect, throught a serial port, mi computer to arduino.
This is arduino's code:
#include <Servo.h>
Servo servo;
const int pinServo = 2;
unsigned int angle;
void setup()
{
Serial.begin(9600);
servo.attach(pinServo);
servo.write(0);
}
void loop()
{
if(Serial.available()>0)
{
angle = Serial.read();
if(angle <= 179)
{
servo.write(angle);
}
}
}
And this is c++'s:
#include <iostream>
#include <unistd.h>
#include <fstream>
#include <termios.h>
using namespace std;
int main()
{
unsigned int angle;
ofstream arduino;
struct termios ttable;
cout<<"\n\ntest1\n\n";
arduino.open("/dev/tty.usbmodem3a21");
cout<<"\n\ntest2\n\n";
if(!arduino)
{
cout<<"\n\nERR: could not open port\n\n";
}
else
{
if(tcgetattr(arduino,&ttable)<0)
{
cout<<"\n\nERR: could not get terminal options\n\n";
}
else
{
ttable.c_cflag &= ~PARENB;
ttable.c_cflag &= ~CSTOPB;
ttable.c_cflag &= ~CSIZE;
ttable.c_cflag |= CS8;
ttable.c_cflag &= ~CRTSCTS;
ttable.c_cflag |= CREAD | CLOCAL;
ttable.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
ttable.c_oflag &= ~OPOST;
ttable.c_cc[VMIN] = 0;
ttable.c_cc[VTIME] = 0;
cfsetospeed(&ttable,9600);
if(tcsetattr(arduino,TCSANOW,&ttable)<0)
{
cout<<"\n\nERR: could not set new terminal options\n\n";
}
else
{
do
{
cout<<"\n\ninsert a number between 0 and 179";
cin>>angle;
arduino<<angle;
}while(angle<=179);
arduino.close();
}
}
}
}
It should connect to arduino , then ask me a number between 0 an 179 and the send that number to arduino which aplly that number as an angle to a servo motor;
But it stops at arduino.open("/dev/tty.usbmodem3a21") .What can i do ?

I think your problems appear in these lines of code
if(tcgetattr(arduino,&ttable)<0) {
// ...
}
else {
// ...
if(tcsetattr(arduino,TCSANOW,&ttable)<0) {
// ...
}
}
The arduino variable is of type ofstream, where tcgetattr() and tcsetattr() expect a file descriptor obtained with open() at this point.
ofstream provides an automatic conversion to bool and thus int implicitely. Supposed the
arduino.open("/dev/tty.usbmodem3a21");
went OK, you are effectively passing 1 to tcgetattr() and tcsetattr(), which is the standard input file descriptor.
Solution is not to use a ofstream for arduino, but an ordinary file descriptor
int arduino = open("/dev/tty.usbmodem3a21",O_WRONLY);

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("");
}

Serial IO with posix and write to shared memory

I got a problem with a posix signal, that I use for reading serial data. First here is a small example code how I initialize my serial port, my signal and a shared memory.
#include <unistd.h>
#include <termios.h>
#include <sys/signal.h>
#include <stdint.h>
#include <cassert>
#include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <QSharedMemory>
int fd;
struct termios termAttr;
struct sigaction saio;
char buff[255];
QSharedMemory QShare("IDSTRINGOFTHISMEMORY");
void signal_handler_IO (int status)
{
std::cout << "Got Serial Data!" << std::endl;
int si = read(fd, &buff[0], 255);
if(true) // Works with false here, but then the shared memory ist not used!
{
char TWrite = 't';
QShare.lock();
char *to = (char*)QShare.data();
const char *from = reinterpret_cast<char*>(&TWrite);
memcpy(to, from, 1);
QShare.unlock();
}
}
int main()
{
// Create SharedMemory:
QShare.create(1);
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
return -1;
}
saio.sa_handler = signal_handler_IO;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigemptyset(&saio.sa_mask);
sigaddset(&saio.sa_mask, SIGINT);
sigaction(SIGIO,&saio,NULL);
fcntl(fd, F_SETFL, FNDELAY|FASYNC);
fcntl(fd, F_SETOWN, getpid());
tcgetattr(fd,&termAttr);
cfsetospeed(&termAttr,B57600);
cfsetispeed(&termAttr,B57600);
termAttr.c_cflag &= ~PARENB;
termAttr.c_cflag &= ~CSTOPB;
termAttr.c_cflag &= ~CSIZE;
termAttr.c_cflag |= CS8;
termAttr.c_cflag |= (CLOCAL | CREAD);
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
termAttr.c_oflag &= ~OPOST;
termAttr.c_cc[VMIN] = 5;
tcsetattr(fd,TCSANOW,&termAttr);
while(true)
{
usleep(1000000);
}
return 0;
}
I had this code in use for a while and it did work quite well. Now for a different project I want to store the serial data in shared memory block, so I can read the current datapoint from multiple processes. In the signal_handler_IO I try to write the data to a shared memory that is created by sys/shm.h. The moment I started using shared memory the posix signal stopped working. Since I was unsure about the use of the shared memory I also tried to use the QSharedMemory class from qt, which created the same result.
Can you tell me, what the shared memory does to my posix signal?

Linux C++ Serial Programming Not Working Why?

#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <cerrno>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef struct termios ComSet;
int main()
{
int acm=-1;
acm=open("/dev/ttyACM0",O_RDWR | O_NOCTTY);
if(acm == -1)
{
cout<<"Error Opening ttyACM0"<<endl;
exit(1);
}
else
{
cout<<"Preparing ttyACM0..."<<endl;
ComSet SerialSettings;
tcgetattr(acm, &SerialSettings);
cfsetispeed(&SerialSettings,B115200);
cfsetospeed(&SerialSettings,B115200);
/* 8N1 Mode */
SerialSettings.c_cflag &= ~PARENB;
SerialSettings.c_cflag &= ~CSTOPB;
SerialSettings.c_cflag &= ~CSIZE;
SerialSettings.c_cflag |= CS8;
SerialSettings.c_cflag &= ~CRTSCTS;
SerialSettings.c_cflag |= CREAD | CLOCAL;
SerialSettings.c_iflag &= ~(IXON | IXOFF | IXANY);
SerialSettings.c_iflag &=ICANON;
SerialSettings.c_iflag &= ~(ECHO | ECHOE | ISIG);
SerialSettings.c_oflag &= ~OPOST;
/* Setting Time outs */
SerialSettings.c_cc[VMIN] = 1;
SerialSettings.c_cc[VTIME] = 0;
if((tcsetattr(acm,TCSANOW,&SerialSettings)) != 0)
{
cout<< " ERROR ! in Setting attributes"<<endl;
}
else
{
cout<< "=======ttyACM0 Setting====="<<endl;
cout<<"BaudRate = 115200 StopBits = 1 Parity = none"<<endl;
cout<<"Reading ttyACM0... "<<endl;
char read_buffer[1024];
bzero(read_buffer,1024);
int read_bytes=0;
while(1)
{
write(acm,"Hello World !",13);
read_bytes=read(acm,&read_buffer,1024);
if(read_bytes>0)
{
cout<<read_buffer;
bzero(read_buffer,1024);
}
else
{
cout<<"No-Data"<<endl;
}
tcflush(acm, TCOFLUSH);
tcflush(acm, TCIFLUSH);
}
}
close(acm); /* Close the serial port */
}
return 0;
}
Why is this code not working ? i m trying to receive same message from the arduino but it will not work.it completely ignores write.i have also found that it works if i use cin.get() before write.
it works if i want to read from arduino only.
Here is my arduino code
String Input;
boolean done=false;
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println(GetSerial());
Input="";
}
String GetSerial()
{
done=false;
Input="";
while(!done)
{
while(Serial.available()>0)
{
Input=Serial.readStringUntil('\n'); //Block Reading
done=true;
}
}
return Input;
}
i want to receive whatever is sent on serial port as it is with as much less delay as possible

Wrong data transmission in serial communication between Arduino and Raspberry

I'm trying to sendo datas from Arduino Uno to RaspberryPi 3B. I need to send 14 int (max value: 6000) from Arduino as soon as Raspberry ask for them. Each one of this 14 number came from ad ADC (SPI communication).
ARDUINO SIDE
#include "SPI.h"
byte incomingByte = 0; // for incoming serial data
const int N_SENSORI=14;
const int DATAOUT = 11;
const int DATAIN = 12;
const int SPICLOCK = 13;
const int SLAVESELECT = 10;
//===============SPI COMMUNICATION================
short write_read_spi16(short what) {
digitalWrite(SS, LOW);
short res = SPI.transfer16(what);
digitalWrite(SS, HIGH);
return res;
}
//===============CONVERT INT IN BYTE AND SEND IT================
void longInt2Byte( int x){
unsigned char buf[sizeof( int)];
memcpy(buf,&x,sizeof(int));
Serial.write(buf,sizeof(buf));
}
//=======================================
void setup() {
Serial.begin(115200);
SPI.begin();
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
}
void loop() {
if (Serial.available() > 0) {
incomingByte= Serial.read();
if (incomingByte=='E') {
write_read_spi16(0b1000001101110000); //THIS IS FOR THE ADC COMMUNICATION
for (int i = 1; i<N_SENSORI+1; i++) { //DONE 14 TIMES.
short s = write_read_spi16(0b1000001101110000 | (i<<10));
int Data = s&0xFFF;
longInt2Byte(Data);
}
}
}}
// C++ SIDE
void stimulationController::SetupDario(){
cout<<"Dentro al setupDario"<<endl<<flush;
buffer=new char [1000];
const char* _portNameSensorsDario="/dev/ttyACM1";
//SERIAL PORT FOR HAND SENSORS
struct termios options;
SerialHandleSensors=open(_portNameSensorsDario, O_RDWR | O_NOCTTY | O_NDELAY); //SerialHandleSensors=open(_portNameSensors, O_RDWR | O_NOCTTY | O_NDELAY); non blocking
if (SerialHandleSensors == -1 )
{
cout<<endl<<"......ERROR: Unable to open: "<<_portNameSensorsDario<<endl;
return;
}
else
{
fcntl(SerialHandleSensors, F_SETFL,0);
cout<<"......OPENED PORT: Succesfully opened: "<<_portNameSensorsDario<<endl;
}
//GET THE OPTIONS, MODIFY AND SET
tcgetattr(SerialHandleSensors,&options);
cfsetispeed(&options,B115200); //BAUD RATE IN
cfsetospeed(&options,B115200); //BAUD RATE OUT
// options.c_lflag |= (ICANON | ECHO | ECHOE);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag |= CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(SerialHandleSensors,TCSANOW,&options);
usleep(3000000);
cout<<"Fine Setup"<<endl<<flush;
}
int stimulationController::Dario( )
{
{
cout<<" NUOVA FUNZIONE"<<endl;
unsigned char bytes[4];
bytes[0]=0x45; // 'E'
int tempWrite=write(SerialHandleSensors,bytes,1);
if(tempWrite==-1)
{
cout<<"......ERROR: PROBLEM WRITING TO ROBOTIC HAND"<<endl;
failure=true;
return 0;
}
int value=0;
int tempRead=read(SerialHandleSensors,buffer,28);
if(tempRead==-1)
{
cout<<"......ERROR: PROBLEM READING FROM ROBOTIC HAND"<<endl;
failure=true;
return 0;
}
int j=0;
for( int i=0; i<28; i=i+2){
value= buffer[i] | ((int)buffer[i+1]<<8);
//ensorDataFoot.push_back(value); //Aggiunge un elemento
j=j+1;
cout<<"Dato "<<j <<"vale: "<<value<<endl<<flush;
}
return value;
}
}
The problem is that or the raspberry side some time it prints the right values, some time (the most of the times, actually) it doesn't. Data seems to be repeated or (2500 insted of 2000 for example).
I can't figure it out the problem.Could it be a matter of timing between the request of sending data and the reading? if so, there is a way to get rid of it?
I've added a do-while cycle in order to be sure that all the 28 bytes are read
int TotByte=28;
int ByteRead=0;
int TempRead=0;
do{ TempRead= read(SerialHandleSensors, buffer, (TotByte-ReadByte));
ReadByte= ReadByte+TempRead;
cout<<"ReadByte is: "<<ReadByte<<endl<<flush;
}while(ByteRead<TotByte);
Output:
ReadByte is: 5
ReadByte is: 15
ReadByte is: 25
and then it stay like that without doing anything
(Posted answer on behalf of the OP):
I figured it out; the problem were the settings of the serial port. For future reference, here is the working version.
bufferTemp=new char [1000];
bufferDEF = new char[1000];
const char* _portNameSensorsBT="/dev/rfcomm0";
struct termios options;
SerialHandleSensorsFoot=open(_portNameSensorsBT, O_RDWR ); //SerialHandleSensors=open(_portNameSensors, O_RDWR | O_NOCTTY | O_NDELAY); non blocking
if (SerialHandleSensorsFoot == -1 )
{
cout<<endl<<"......ERROR: Unable to open: "<<_portNameSensorsBT<<endl;
return 0;
}
else
{
fcntl(SerialHandleSensorsFoot, F_SETFL,0);
cout<<"......OPENED PORT: Succesfully opened: "<<_portNameSensorsBT<<endl;
}
//GET THE OPTIONS, MODIFY AND SET
tcgetattr(SerialHandleSensorsFoot,&options);
cfsetispeed(&options,B115200); //BAUD RATE IN
cfsetospeed(&options,B115200); //BAUD RATE OUT
// options.c_lflag |= (ICANON | ECHO | ECHOE);
options.c_iflag = IGNBRK | IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag |= CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(SerialHandleSensorsFoot,TCSAFLUSH,&options);
usleep(5000000);
with these setting I'm able to communicate with bluetooth even though there might be some velocity problem.

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);