Sunday, 28 August 2016

Serial Communication

I have been experimenting with serial communication for a while now, trying to figure out how I build an application of my own that is capable of using the serial port for communication.

Following is an instruction to help you employ it in your own applications :

Download the serial library (libserial) from the link below :

https://github.com/crayzeewulf/libserial

 Unpack and navigate to the directory using the command terminal :

cd  <directory of the unpacked libserial folder>

 

Generate configure file : make -f Makefile.dist
Configure :                     ./configure
Make and install :             make & make install


The libraries will have now installed to /usr/local/lib and include files in /usr/local/include. You can navigate to these folders and check.


I work in a Workspace directory. Navigate to the directory where you store your programs and run :

gedit Serial_Monitor.cpp

I used the following code for my application , borrowing from the libserial examples :

#include <SerialStream.h>
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <fstream>

using namespace LibSerial;
   
int main(int argc, char** argv)
{
    // Instantiate the SerialStream object then open the serial port.
    SerialStream serial_stream;
    serial_stream.Open("/dev/ttyACM0");
   
    if(argc<2)
    {
      std::cerr<< "Usage: " << argv[0] << " <filename>" << std::endl ;
        return 1 ;
    }


    if ( !serial_stream.good() )
    {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Error: Could not open serial port."
                  << std::endl ;
        exit(1) ;
    }

    // Set the baud rate of the serial port.
    serial_stream.SetBaudRate(SerialStreamBuf::BAUD_9600);
   
    if ( !serial_stream.good() )
    {
        std::cerr << "Error: Could not set the baud rate." << std::endl ;
        exit(1) ;
    }

    // Set the number of data bits.
    serial_stream.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 ) ;
   
    if ( !serial_stream.good() )
    {
        std::cerr << "Error: Could not set the character size." << std::endl ;
        exit(1) ;
    }

    // Disable parity.
    serial_stream.SetParity( SerialStreamBuf::PARITY_NONE ) ;
   
    if ( !serial_stream.good() )
    {
        std::cerr << "Error: Could not disable the parity." << std::endl ;
        exit(1) ;
    }

    // Set the number of data bits.
    serial_stream.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 ) ;
   
    if ( !serial_stream.good() )
    {
        std::cerr << "Error: Could not set the character size." << std::endl ;
        exit(1) ;
    }


    // Set the number of stop bits.
    serial_stream.SetNumOfStopBits(1);
   
    if (!serial_stream.good())
    {
        std::cerr << "Error: Could not set the number of stop bits."
                  << std::endl ;
        exit(1) ;
    }

    // Turn off hardware flow control.
    serial_stream.SetFlowControl(SerialStreamBuf::FLOW_CONTROL_NONE);
    if ( !serial_stream.good() )
    {
        std::cerr << "Error: Could not use hardware flow control."
                  << std::endl ;
        exit(1) ;
    }


    // Open the input file for reading.
    std::ifstream input_file( argv[1] );
   
    if ( !input_file.good() )
    {
        std::cerr << "Error: Could not open file "
                  << argv[1] << " for reading." << std::endl ;
        return 1 ;
    }

    // Read characters from the input file and dump them to the serial port.
    std::cerr << "Dumping file to serial port." << std::endl ;
   
    while( input_file )
    {
        char nextByte;
        input_file.read( &nextByte, 1 ) ;
        serial_stream.write( &nextByte, 1 ) ;
        while( serial_stream.rdbuf()->in_avail() == 0 )
        {
          usleep(100) ;
        }

        if(serial_stream.rdbuf()->in_avail() > 0)
          {
             char nextByte;
             serial_stream.get(nextByte);
             std::cerr << ( nextByte ) << " " ;
             usleep(100) ;
          }

    }
    std::cerr << std::endl ;
    std::cerr << "Done." << std::endl ;   
    return EXIT_SUCCESS ;
}
 
Save. Compile and link with :

  g++ -o serial_monitor Serial_Monitor.cpp -lserial -lpthread
 

In your working directory , create a file called input and put random characters in it.

You can now run your program :

./serial_monitor input

// it will take characters from the input file and write it to the serial port.

 Upload the following sketch to your Arduino


 void setup()
{
  Serial.begin(9600);
}

void loop()
{
 
 char input =Serial.read();
 Serial.print(input);
 delay(100);
}

 

At a Baud rate of 9600 this program will echo the values it receives on the serial port.


Run your program :

If you face errors, try the following:

 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
// To add Library Path to shell

sudo chmod a+rw /dev/ttyACM0
// to Change permission to access port



./serial_monitor input


(My input file had : a b  c d) The arduino echoes these values , which your program reads and displays on the terminal.

If you are having trouble following the tutorial above , feel free to discuss it in the comments.