ElEscalador
Posts: 940
Joined: Tue Dec 15, 2015 4:55 pm
Location: Detroit, MI USA
Contact: Website

Sending serial data out (via USB) with C++

Sun Jan 03, 2016 7:15 pm

I'm trying to teach my roomba new tricks, my next step is sending it commands with a C++ program - so I can poll its sensors, tell it to fetch, etc. Communicating with /dev/ttyUSB0 via and FTDI that converts to a 5V TTL signal at 115200 baud, 8n1 and - very importantly - no hardware flow control (the FTDI doesn't work at all if enabled).

I can see it output when it comes online and stuff, my next response would be to send it the number 128 to change it's mode, the 132 to change mode again. Then "142 0" to poll it's sensors. unfortunately typing these into minicom doesn't work because that sends ascii and I need to send raw numbers (whatever that means - but it worked with my windows netbook using realterm that has a "send numbers" option right next to "send ascii"
Robotics tips, hacks, book extras https://youtube.com/practicalrobotics

User avatar
AndyD
Posts: 2334
Joined: Sat Jan 21, 2012 8:13 am
Location: Melbourne, Australia
Contact: Website

Re: Sending serial data out (via USB) with C++

Sun Jan 03, 2016 10:56 pm

ElEscalador wrote:... typing these into minicom doesn't work because that sends ascii and I need to send raw numbers (whatever that means)
Perhaps Ascii vs. Binary Files from The University of Maryland's website will help you understand the difference between ASCII and binary.

There is plenty of C/C++ code on the internet that will send binary data over a serial link. There are a number of good references on the subject too, for example The Serial Programming Guide for POSIX Operating Systems

danjperron
Posts: 3790
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Sending serial data out (via USB) with C++

Mon Jan 04, 2016 4:19 am

Well you could create a class for the serial port using extern "C" from standard ioctl and open.

ex :

mySerial.h

Code: Select all

#ifndef SERIAL
#define SERIAL

#include <string>


class  mySerial
{

public:

  int handle;
  std::string  deviceName;
  int baud;

  mySerial(std::string deviceName, int baud);
  ~mySerial();

  bool Send( unsigned char  * data,int len);
  bool Send(unsigned char value);
  bool Send( std::string value);
  int Receive( unsigned char  * data, int len);
  bool IsOpen(void);
  void Close(void);
  bool Open(std::string deviceName, int baud);
  bool NumberByteRcv(int &bytelen);
};

#endif
mySerial.cpp

Code: Select all

extern "C" {
#include <asm/termbits.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
}
#include <iostream>
using namespace std;

#include "mySerial.h"

mySerial::mySerial(string deviceName, int baud)
{
   handle=-1;
   Open(deviceName,baud);
}

mySerial::~mySerial()
{
  if(handle >=0)
      Close();
}

void mySerial::Close(void)
{
   if(handle >=0)
      close(handle);
   handle = -1;
}


bool mySerial::Open(string deviceName , int baud)
{
    struct termios tio;
    struct termios2 tio2;
    this->deviceName=deviceName;
    this->baud=baud;
    handle  = open(this->deviceName.c_str(),O_RDWR | O_NOCTTY /* | O_NONBLOCK */);

    if(handle <0)
       return false;
    tio.c_cflag =  CS8 | CLOCAL | CREAD;
    tio.c_oflag = 0;
    tio.c_lflag = 0;       //ICANON;
    tio.c_cc[VMIN]=0;
    tio.c_cc[VTIME]=1;     // time out every .1 sec
    ioctl(handle,TCSETS,&tio);

    ioctl(handle,TCGETS2,&tio2);
    tio2.c_cflag &= ~CBAUD;
    tio2.c_cflag |= BOTHER;
    tio2.c_ispeed = baud;
    tio2.c_ospeed = baud;
    ioctl(handle,TCSETS2,&tio2);

//   flush buffer
    ioctl(handle,TCFLSH,TCIOFLUSH);

    return true;
}

bool mySerial::IsOpen(void)
{
   return( handle >=0);
}

bool mySerial::Send( unsigned char  * data,int len)
{
   if(!IsOpen()) return false;
   int rlen= write(handle,data,len); 
   return(rlen == len);
}

bool mySerial::Send( unsigned char value)
{
   if(!IsOpen()) return false;
   int rlen= write(handle,&value,1);
   return(rlen == 1);
}

bool mySerial::Send(std::string value)
{
   if(!IsOpen()) return false;
   int rlen= write(handle,value.c_str(),value.size()); 
   return(rlen == value.size());
}


int  mySerial::Receive( unsigned char  * data, int len)
{
   if(!IsOpen()) return -1;

   // this is a blocking receives
   int lenRCV=0;
   while(lenRCV < len)
     {
       int rlen = read(handle,&data[lenRCV],len - lenRCV);
       lenRCV+=rlen;
     }
   return  lenRCV;
}

bool mySerial::NumberByteRcv(int &bytelen)
{
   if(!IsOpen()) return false;
   ioctl(handle, FIONREAD, &bytelen);
   return true;
}
and a simple program to test it

test.cpp

Code: Select all

#include "mySerial.h"
#include <iostream>
using namespace std;



int  main(void)
{

    mySerial serial("/dev/ttyAMA0",115200);

    // One Byte At the time
     serial.Send(128);
     serial.Send(132);

    // An array of byte
    unsigned char  dataArray[] = { 142,0};
    serial.Send(dataArray,sizeof(dataArray));

    // Or a string
    serial.Send("this is it\r\n");

    return 0;
}
now compile it

Code: Select all

g++ -o test test.cpp mySerial.cpp
Just change the device name and the baud.

User avatar
gordon@drogon.net
Posts: 2023
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website Twitter

Re: Sending serial data out (via USB) with C++

Tue Jan 05, 2016 6:42 pm

ElEscalador wrote:I'm trying to teach my roomba new tricks, my next step is sending it commands with a C++ program - so I can poll its sensors, tell it to fetch, etc. Communicating with /dev/ttyUSB0 via and FTDI that converts to a 5V TTL signal at 115200 baud, 8n1 and - very importantly - no hardware flow control (the FTDI doesn't work at all if enabled).

I can see it output when it comes online and stuff, my next response would be to send it the number 128 to change it's mode, the 132 to change mode again. Then "142 0" to poll it's sensors. unfortunately typing these into minicom doesn't work because that sends ascii and I need to send raw numbers (whatever that means - but it worked with my windows netbook using realterm that has a "send numbers" option right next to "send ascii"

Code: Select all

#include <stdio.h>
#include <wiringSerial.h>

main ()
{
  int fd = serialOpen ("/dev/ttyUSB0", 115200) ;
  if (fd < 0)
    ... error - your code here

  serialPutchar (128) ;
  serialPutchar (142) ;
  serialPutchar (0) ;
// and so on
}
compile with

Code: Select all

gcc myfile.c -omyfile -lwiringPi
-Gordon
--
Gordons projects: https://projects.drogon.net/

danjperron
Posts: 3790
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Sending serial data out (via USB) with C++

Tue Jan 05, 2016 7:25 pm

A small note about gordon wiringPi

You need to install his library first . check the link to install it
wiringpi.com/download-and-install

B.T.W. I tried the git clone but got error " reset by peer all the times" today.
The second method works fine.

Also you can't set any baud rate ! It has to be the standard baud.
There is an error on is small example.

it should be

Code: Select all

serialPutchar(fd,128);
At least that what I had to do to make it work.

With My encapsulation class you could notice that I use "Send" for byte, string and array of byte. The file handler is hidden in the class. I didn't fully include the error handling stuff but this could be done easily.

ElEscalador
Posts: 940
Joined: Tue Dec 15, 2015 4:55 pm
Location: Detroit, MI USA
Contact: Website

Re: Sending serial data out (via USB) with C++

Tue Jan 05, 2016 8:11 pm

Thanks all! - Especially Gordon...I didn't realize wiringPi had a serial library with it - we are all indebted to you sir. I can now command my Roomba with C++ code. Having trouble with the reading any data coming back.
Robotics tips, hacks, book extras https://youtube.com/practicalrobotics

pi_in_the_face
Posts: 15
Joined: Thu Nov 19, 2015 2:54 pm
Location: Maine, USA

Re: Sending serial data out (via USB) with C++

Thu Sep 22, 2016 9:52 pm

I also have my pi talking to my MSP430 using wiringPi...thanks to Gordon.

Return to “C/C++”