Pages: 1 [2]   Go Down
Author Topic: USB Read/Write between Arduino and Ubuntu pc  (Read 3009 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Now the problem is that Arduino is not able to recognize the commands sent by the C program: it always returns Error.
So you post the PC code. Why?

Because I thought the sketch is correct now since it manages the string correctly, so i posted the C code in order to receive some help on it.

May be, i'm not sending the commands in the correct way with my C code and someone can give me some suggestions.

In fact, to test it I added a println(myCmd) after the for loop in order to get back the string received and i noticed that Arduino receives just the "c" character of the whole string "check" sent my the C program.

C program sends "check"
Arduino receive "c" and then sends "Error".

Someone can help me on this problem, please?
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Arduino receives just the first character and then stops.

Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I solved it!

Paul_S thanks for your help!!
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 547
Posts: 45993
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Paul_S thanks for your help!!
You're welcome.

Quote
I solved it!
Be nice to know how/what the problem was.
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, the problem was in the C code with the libSerial write() function: i was sending just the first character of the buffer and not the other ones.

Now, i'll try to implement a communication protocol between C program and Arduino.

When i'll do this, can i post the C code and the Arduino sketch in order to see if it can be improved?

Or I have to post only the Arduino code?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 547
Posts: 45993
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
When i'll do this, can i post the C code and the Arduino sketch in order to see if it can be improved?
Post them both. Most of us know a little about C.
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm having a strange problem with my C/C++ application (with LibSerial): I wrote a read function in order to receive data from Arduino and i'm using a while loop to read all the characters sent on the serial port.

The problem is that if I use a while loop with an always true condition, it works well; otherwise, if i use a serial available condition in the while loop, then the program does not read anything from the serial port.

This is my read function:

Code:
std::string s_read(SerialStream& serial_port)
{
     std::cout << "Test Before While Loop\n";
     std::string result;
     std::cout << "Serial available:" << serial_port.rdbuf()->in_avail() << "\n\n";
     while( serial_port.rdbuf()->in_avail() )
     {
         char next_byte;
         serial_port.get(next_byte);  
         std::cout << "Test Inside While Loop" << next_byte << "\n";
         result += next_byte;
     }
     return result;
}

As I can see also from the printed values, serial_port.rdbuf()->in_avail() is always ZERO and i do not know the reason.
I can't understand why it does not detect that the serial port is available with new data.
Code:
./libserial
Test before first write()
Test Before While Loop
Serial available:0

Test after the first read()
Test Before While Loop
Serial available:0

RX led on Arduino blinks and if I write while(1) instead of while( serial_port.rdbuf()->in_avail() ) it correctly reads the data.

Arduino code is the same of the last post.
On the contrary, this is the C code I'm using now:

Code:
#include <SerialStream.h>
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <string>

using namespace LibSerial;

std::string s_read(SerialStream& serial_port)
{
     std::cout << "Test Before While Loop\n";
     std::string result;
     std::cout << "Serial available:" << serial_port.rdbuf()->in_avail() << "\n\n";
     while( serial_port.rdbuf()->in_avail() )
     {
         char next_byte;
         serial_port.get(next_byte);  
         std::cout << "Test Inside While Loop" << next_byte << "\n";
         result += next_byte;
     }
     return result;
}

void s_write(SerialStream& serial_port, const std::string& data)
{
    serial_port.write(data.c_str(), data.size());
}


int
main( int    argc,
       char** argv  )
{
     //
     // Open the serial port.
     //
     using namespace std;

     SerialStream serial_port ;
     char c;
     serial_port.Open( "/dev/ttyACM0" ) ;
     if ( ! serial_port.good() )
     {
         std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                   << "Error: Could not open serial port."
                   << std::endl ;
         exit(1) ;
     }
     //
     // Set the baud rate of the serial port.
     //
     serial_port.SetBaudRate( SerialStreamBuf::BAUD_9600 ) ;
     if ( ! serial_port.good() )
     {
         std::cerr << "Error: Could not set the baud rate." <<  
std::endl ;
         exit(1) ;
     }
     //
     // Set the number of data bits.
     //
     serial_port.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 ) ;
     if ( ! serial_port.good() )
     {
         std::cerr << "Error: Could not set the character size." <<  
std::endl ;
         exit(1) ;
     }
     //
     // Disable parity.
     //
     serial_port.SetParity( SerialStreamBuf::PARITY_NONE ) ;
     if ( ! serial_port.good() )
     {
         std::cerr << "Error: Could not disable the parity." <<  
std::endl ;
         exit(1) ;
     }
     //
     // Set the number of stop bits.
     //
     serial_port.SetNumOfStopBits( 1 ) ;
     if ( ! serial_port.good() )
     {
         std::cerr << "Error: Could not set the number of stop bits."
                   << std::endl ;
         exit(1) ;
     }
     //
     // Turn off hardware flow control.
     //
     serial_port.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_NONE ) ;
     if ( ! serial_port.good() )
     {
         std::cerr << "Error: Could not use hardware flow control."
                   << std::endl ;
         exit(1) ;
     }
     //
     // Do not skip whitespace characters while reading from the
     // serial port.
     //
     // serial_port.unsetf( std::ios_base::skipws ) ;
     //
     // Wait for some data to be available at the serial port.
     //
     //
     // Keep reading data from serial port and print it to the screen.
     //
std::cout << "Test before first write()\n";

s_write(serial_port, "check"); // First Command

std::string first_reply = s_read(serial_port);

std::cout << first_reply;

std::cout << "Test after the first read()\n";

s_write(serial_port, "check");

std::string second_reply = s_read(serial_port);
std::cerr << second_reply;

     return EXIT_SUCCESS ;
}
« Last Edit: January 30, 2012, 06:25:46 am by marcus barnet » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 547
Posts: 45993
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Post a link to the library, rather than a link to the documentation, if you want anyone to actually look at the library code for you.
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, no problem, i thought the documentation link was better.

LibSerial documention: link.
LibSerial library: download link, older versions can be found here.


I tried to add some delay before the read function in order to wait before directly read from the serial port, but nothing is changed: C program does not read anything from Arduino.

Code:
std::string s_read(SerialStream& serial_port)
{
     std::cout << "Test Before While Loop\n";
     std::string result;
     std::cout << "Serial available:" << serial_port.rdbuf()->in_avail() << "\n\n";
     while( serial_port.rdbuf()->in_avail() )
     {
         char next_byte;
         serial_port.get(next_byte); 
         std::cout << "Test Inside While Loop" << next_byte << "\n";
         result += next_byte;
     }
     return result;
}

std::string s_readBlocking(SerialStream& serial_port, int timeout)
{
     while( serial_port.rdbuf()->in_avail() == 0 && timeout > 0 )
     {
         timeout -= 100;
         usleep(100);
     }
     return s_read(serial_port);
}

// then in the main function

std::cout << "Test before first write()\n";

s_write(serial_port, "check"); // First Command

std::string first_reply = s_readBlocking(serial_port, 10000);

std::cout << first_reply;

std::cout << "Test after the first read()\n";

s_write(serial_port, "check");
« Last Edit: January 30, 2012, 07:38:06 am by marcus barnet » Logged

Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 115
Posts: 5365
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If the serial is returning ZERO, then you are probably not waiting long enough.
Code:
std::string s_readBlocking(SerialStream& serial_port, int timeout)
{
     while( serial_port.rdbuf()->in_avail() == 0 && timeout > 0 )
     {
         timeout -= 100;
         usleep(100);
     }
     // is this falling out of the while loop because of a timeout or something available?
     // If a timeout, then this s_read() doesn't need to be called. There is nothing there yet.
     return s_read(serial_port);
}
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried to wait even for 4-6 seconds but nothing changed.  smiley-confuse
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, that function tries to wait until there is something on the serial port and if timeout ends in order to call read function.

But it does not work.
Logged

Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 115
Posts: 5365
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Would you be more specific about "does not work"?

I think this is the original code you were using.
http://stackoverflow.com/questions/9046649/read-and-write-on-serial-port-in-ubuntu-with-c-c-and-libserial

It must exit this loop to send the "check":
Code:
while( serial_port.rdbuf()->in_avail() == 0 )
     {
         usleep(100) ;
     }
It is working there, correct?
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, i opened that topic on stackoverflow, but i realized that the problem may be related also to Arduino, so i decided to post again on arduino forum.

With "it does not work" i mean that i receive no answer from the serial port after the first write.

I did some tests and i changed that blocking read function in:

Code:
while( serial_port.rdbuf()->in_avail() == 0  || timeout  > 0)

and now it seems to work: it reads all the strings printed by Arduino on serial port.

I'm testing it in order to verify if it is a roboust solution.

This is the code:

Code:
std::string s_read(SerialStream& serial_port)
{
     std::cout << "Test Before While Loop\n";
     std::string result;
     std::cout << "Serial available:" << serial_port.rdbuf()->in_avail() << "\n\n";
     while( serial_port.rdbuf()->in_avail() > 0 )
     {
         char next_byte;
         serial_port.get(next_byte); 
         
         result += next_byte;
     }
 
     return result;
}

std::string s_readBlocking(SerialStream& serial_port, int timeout)
{
     while( serial_port.rdbuf()->in_avail() == 0 || timeout > 0 )
     {
         timeout -= 100;
         usleep(100);
     }
     return s_read(serial_port);
}

I do not know if it is correct or if it is working just because I'm luck.
Logged

Pages: 1 [2]   Go Up
Jump to: