trymes
trymes

Reputation: 21

Extra Characters Reading from Serial Port Using libserial on Linux

I have a very basic device with which I am trying to interact via a serial connection on Linux. I am on the steep part of the learning curve here, still, so please be gentle!

Anyhow, I am able to control the device via Hyperterminal in Windows, or via cu, screen, or minicom in Linux. I am connected via a built-in serial port on a PC at 19200, 8N1. The interface for the device is very simple:

There's more, but that's a good start. When I connect to the device using screen, it works fine:

root@dc5000:~# screen /dev/ttyS0 19200,cs8,-ixon,-ixoff

V
ADD111C

Once I had that working manually, I tried to write a simple program using C++ and libserial to interact with the device. It looks like this:

#include <SerialStream.h>
#include <string>
#include <iostream>
#include <fstream>

using namespace std;
using namespace LibSerial;

int main(){

    char next_char[100];
    int i;

    SerialStream my_serial_stream;
    my_serial_stream.Open("/dev/ttyS0") ;
    my_serial_stream.SetBaudRate( SerialStreamBuf::BAUD_19200 ) ;
    my_serial_stream.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 ) ;
    my_serial_stream.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_NONE ) ;
    my_serial_stream.SetParity( SerialStreamBuf::PARITY_NONE ) ;
    my_serial_stream.SetNumOfStopBits(1) ;
    my_serial_stream.SetVTime(1);
    my_serial_stream.SetVMin(100);

    cout<<"Sending Command:\n";
    my_serial_stream << "V";

    my_serial_stream.read(next_char,100);
    cout<<"Result: "<<next_char<<"\n";

    my_serial_stream.Close();

    return 0;
}

This is successfully able to send the "V" to the serial port, but when I read it back, I get a number of non-printing characters back after the valid data:

root@dc5000:~# g++ -o serialtest serialtest.cpp -lserial
root@dc5000:~# ./serialtest 
Sending Command:
Result: 
V
ADD111C
��se�Xw��AN��ƿ,�
root@dc5000:~# 

What am I missing to only grab the response to my query? I'm guessing that I need to flush a buffer on the port or something, but I have reached the end of my limited knowledge here.

Ideally I would like to just get the "ADD111C", but I don't want to paint myself into a corner by grabbing a specific length of data (in case it changes in the future), and the garbage at the end of the read does not always seem to be the same length, or the same data.

Many thanks for taking a look,

Tom

Upvotes: 0

Views: 2187

Answers (1)

trymes
trymes

Reputation: 21

Zack & keshlam: Thank you for the help. Zack's suggestion to write a NULL to the end of the string resolved the problem, but I actually stumbled across a simpler method while working with another string (trying to grab a substring of the output).

Rather than define the C string like this:

char next_char[100];

I did it like this:

char next_char[100] = "";

It seems that assigning a value to the char before reading from the serial port properly null terminated it. I can now remove the memset command from my code and it now works fine:

root@dc5000:~# ./serialtest Sending Command: Result: V ADD111C

Thanks for the help!

Upvotes: 0

Related Questions