Go Down

Topic: Reading serial data coming from arduino in c++? (Read 937 times) previous topic - next topic

Panglossian_Man

I found an example of how to interface between c++ and the arduino (http://playground.arduino.cc//Interfacing/CPPWindows). But I am having trouble reading data that is coming from the arduino.

Could someone please explain to me how to read in datausing this function?

Code: [Select]

        //Read data in a buffer, if nbChar is greater than the
        //maximum number of bytes available, it will return only the
        //bytes available. The function return -1 when nothing could
        //be read, the number of bytes actually read.
        int ReadData(char *buffer, unsigned int nbChar);


What role does the nbChar play in reading the data?

At the moment my code for reading from the arduino is:
Code: [Select]
char *buf = "0";
int num, i = 0;
while( i < 5 ){
num = ard.ReadData( buf, 256 );
        if( num == -1 )
        {
    cout << "Nothing to read\n";
        } else
        {
    cout << "Read: " << *buf << endl;
    cout << "Num: " << num;
    break;
        }
    i++;
    Sleep(500);
}

where ard is the Serial class.
and the arduino just spitting out "1" using Serial.println() to see if I can actually read it.

PaulS

Quote
where ard is the Serial class.

And we're supposed to guess how (and even if) you've opened the serial port, and to guess what you are currently seeing as output, and to then tell you what is wrong. I'll pass until I know more.

el_supremo

Quote
ard.ReadData( buf, 256 );

You've told it that it can read up to 256 characters into buf, BUT
Quote
char *buf = "0";

buf points to a string containing only one character and the null on the end.

Pete

Panglossian_Man


Quote
where ard is the Serial class.

And we're supposed to guess how (and even if) you've opened the serial port, and to guess what you are currently seeing as output, and to then tell you what is wrong. I'll pass until I know more.

Sorry if you missed it, the Serial class I am referring to is in the link ( I guess i could've explained that better ). (I believe) that the Serial port is being opened in the constructor of the SerialClass object (viewable in the .cpp file through the link, I'll copy it here if you insist). In mine the only thing I changed was the baud rate (to 115200) where it sets the stopbits and parity, it was doing the same thing before, and after the change.
But due to my lack of knowledge of how c++ opens serial ports, I can't tell how to get data from the arduino. (Though as I said before, sending data to the arduino seems fine).


Quote
ard.ReadData( buf, 256 );

You've told it that it can read up to 256 characters into buf, BUT
Quote
char *buf = "0";

buf points to a string containing only one character and the null on the end.

Pete



Ah, seems I need to get used to C++ a bit more (coming from java). I replaced it with:
Code: [Select]

        Serial ard = Serial("COM4");

char *buf;
int length = 256;
buf = ( char* ) malloc( length );

int num, i = 0;
while( i < 5 ){
num = ard.ReadData( buf, 3 );
if( num == -1 )
{
cout << "\nNothing to read";
} else
{
cout << "Read: ";
for( int i = 0; i < num; i++ )
{
cout << *(buf + i);
}
cout << "Num chars: " << num;
break;
}
i++;
Sleep(500);
}

Which seems to work now, Thanks.

PaulS

Quote
Which seems to work now,

You are allocating memory, but not freeing it.

Why not use a static array?
Code: [Select]
char buf[256];

Panglossian_Man


You are allocating memory, but not freeing it.

Why not use a static array?
Code: [Select]
char buf[256];

I am freeing it, just later on in the code (same as when I call the destructor for the Serial class), I haven't pasted my entire code as I felt that that shows the (previously) problematic part.

Is using the static array going to be any different from using malloc? (Apart from having to allocate and free the memory)

For the sake of it, her's the entire main I'm using with the class, guess it would've been easier to just do this from the start (lesson learned).
This code just sends a '1', which turns the LED on pin 13 on and then a '0' which turns the LED off with the arduino replying with LED ON or LED OFF, I think I'm going to move the read and write functions to another class to make it easier to extend and to read and write more than one charater.
Code: [Select]
#include <cstdlib>
#include <iostream>
#include "SerialClass.h"

using namespace std;

void readData();

Serial ard = Serial("COM4");

int main()
{
if( ard.IsConnected() == true )
{
cout << "Done" << endl;
} else
{
cout << "Connection failed, exitting";
return EXIT_FAILURE;
}


//test arduino connection
if( ard.WriteData( "1", 1 ) == true )
{
cout << "Data sent successfully\n";
} else
{
cout << "Data not sent";
}

        readData();

ard.WriteData( "0", 1 );
readData();

        ard.~Serial();

        // Keep the console open to check output.
        // Saves from using a breakpoint
Sleep(20000);
return EXIT_SUCCESS;
}

void readData()
{
        // Check for data coming from arduino
        // If no data is found check 4 more times
char *buf;
int length = 256;
buf = ( char* ) malloc( length );

int num, i = 0;
while( i < 5 ){
num = ard.ReadData( buf, length );
if( num == -1 )
{
cout << "\nNothing to read";
} else
{
cout << "Read: ";
for( int i = 0; i < num; i++ )
{
cout << *(buf + i);
}
cout << "Num: " << num << endl;
break;
}
i++;
Sleep(25);
}
free( buf );
}

PaulS

Code: [Select]
        ard.~Serial();
You should NEVER invoke the destructor directly. Delete the object, and the destructor will be called.

A static array will be faster, and there will be no question about whether the allocation succeeded. With malloc(), it is possible for the allocation to fail. You are not checking for that possibility.

A static array does not have to be freed, so there is no possibility of forgetting to free it, or of the code being revised to provide an alternate return path that bypasses the free() call (such as an exception be thrown).

Go Up