c++arduinoubuntu-16.04communicationbaud-rate

Linux read, write Arduino serial


I'm trying to write to an Arduino serial from a c++ program. How do I set the baudrate in the C++ program? The communication seems to work, when the arduino is set to 9600, but fails when I change it, as expected.(so 9600 is the default?) Using the command to see output: screen /dev/ttyUSBx 115200 Using an example program to echo everything, on the Arduino:

* serial_echo.pde
* ----------------- 
* Echoes what is sent back through the serial port.
*
* http://spacetinkerer.blogspot.com
*/

int incomingByte = 0;    // for incoming serial data

void setup() {
  Serial.begin(115200);    // opens serial port, sets data rate to 9600 bps
}
void loop() {
  // send data only when you receive data:
  if (Serial.available() > 0) ;
  // read the incoming byte:
  incomingByte = Serial.read();
  // say what you got:
  Serial.print((char)incomingByte);
}

and the C++ code is:

#include <iostream>
#include <stdio.h>
#include <string>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

using namespace std;

string comArduino(string outmsg = " hello"){

  #define comports_size 3

  static int fd_ard;
  static bool init = false;
  //char buffer[256];

  if(!init){
      string comports[] = { "/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2" };
      for(int i = 0; i < comports_size; i++){

          fd_ard = open(comports[i].c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
          if (fd_ard != -1) {
              cout<<"connected to "<<comports[i]<<endl;
              init = true;
              break;
          }
          else{
              perror ("open");
          }
          if(i == (comports_size - 1)){
              cout<<"can't connect to arduino [ ER ]\n"<<endl;
              return "";
          }
      }
  }
  int Er = write(fd_ard,outmsg.c_str(),strlen(outmsg.c_str()));
  if(Er < strlen(outmsg.c_str())){
      perror ("write ");
      init = false;
  }
  else
      cout<<"write ok"<<endl;
  return "";
}
int main(){
  while(1){
      comArduino();
      sleep(1);
  }
}

Edit: needed to add the following lines after open() to configure the serial properly:

    struct termios PortConf;
    // write port configuration, as ' stty -F /dev/ttyUSB0 -a ' returned after opening the port with the arduino IDE.
    tcgetattr(fd_ard, &PortConf);                           // Get the current attributes of the Serial port
    PortConf.c_cflag = 0;                                 //set cflag
    PortConf.c_cflag |= (CS8 | HUPCL | CREAD | CLOCAL);

    PortConf.c_iflag = 0;                                 //set iflag
    //PortConf.c_iflag &= ~(ISIG | ICANON | IEXTEN);

    PortConf.c_oflag = 0;                                 //set oflag
    PortConf.c_oflag |= (ONLCR | CR0 | TAB0 | BS0 | VT0 | FF0); //NR0 is supposed to be set, but won't compile
    //PortConf.c_oflag &= ~(OPOST);

    PortConf.c_lflag = 0;                                 //set lflag
    //PortConf.c_lflag &= ~(ECHO | ECHOE);

    PortConf.c_cc[VMIN]  = 0;
    PortConf.c_cc[VTIME] = 0;

    cfsetispeed(&PortConf,B115200);                       // Set Read  Speed as 115200                       
    cfsetospeed(&PortConf,B115200);                       // Set Write Speed as 115200 

    if((tcsetattr(fd_ard,TCSANOW,&PortConf)) != 0){       // Set the attributes to the termios structure
        printf("Error while setting attributes \n");
        return "";
    }

Solution

  • You need to set the baudrate of whatever port you are using by using the termios structure.

    Use "man termios" to get more info about termios structure

    So for a start to need to add

    #include <termios.h> 
    

    To the top of your code.

    later on when you open you port:

    fd_ard = open(comports[i].c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
    

    You need to the access the termios structure and modify it to suit your needs

    struct termios SerialPortSettings;  // Create the structure                          
    tcgetattr(fd_ard, &SerialPortSettings); // Get the current attributes of the Serial port
    

    Then, set the baudrate

    cfsetispeed(&SerialPortSettings,B115200); // Set Read  Speed as 115200                       
    cfsetospeed(&SerialPortSettings,B115200); // Set Write Speed as 115200                       
    

    Then commit the changes

    if((tcsetattr(fd_ard,TCSANOW,&SerialPortSettings)) != 0) // Set the attributes to the termios structure
      printf("Error while setting attributes \n");
    

    There are a bunch of other things that can be set for flow control, cannonical mode etc which may affect how data gets sent and received. Refer to the man page, or refer to This description of the General Terminal Interface