Read from Serial

Hello everyone

I’m having trouble using serial. I have read tutorials and examples but it seems that I need to know how many bites it has to read… But I can’t know, it changes each time.
On processing I used readString which was very well working but it doesn’t exist on of…
Do you know a method?

Here is my code:

void testApp::setup(){
// Smooth edges
ofEnableSmoothing();

// Fixed framerate
ofSetFrameRate(30);

mySerial.setup("/dev/cu.usbmodem1411", 19200);
}
//--------------------------------------------------------------

void testApp::update(){
    // we want to read 8 bytes
    int bytesRequired = (77);
    unsigned char bytes[bytesRequired];
    int bytesRemaining = bytesRequired;
    // loop until we've read everything
    while ( bytesRemaining > 0 )
    {
        // check for data
        if ( mySerial.available() )
        {
            // try to read - note offset into the bytes[] array, this is so
            // that we don't overwrite the bytes we already have
            int bytesArrayOffset = bytesRequired - bytesRemaining;
            int result = mySerial.readBytes( &bytes[bytesArrayOffset],bytesRemaining );
            
        printf("bytes %s \n", bytes);
        
        // check for error code
        if ( result == OF_SERIAL_ERROR )
        {
            // something bad happened
            ofLog( OF_LOG_ERROR, "unrecoverable error reading from serial" );
            // bail out
            break;
        }
        else if ( result == OF_SERIAL_NO_DATA )
        {
            // nothing was read, try again
        }
        else
        {
            // we read some data!
            bytesRemaining -= 1;
            
            
        }
        theBall.moveTo(x_fil,y_fil);
    }
}
}

you can try with this add-on, does your data from serial has an ending character¿

I’ll try it thank you

I can modify the code to put an ending character at the end of the message sent.

Love you man, your addon is so easy and usefull to use!
Thank you!

glad that found useful, but thats not mine!!

I found this way a lot mot easy to work with serial data.

https://github.com/bakercp/ofxSerial is also a robust option if you need more advanced serial control.

Hello again

I am front of a new problem which is in the length of the message received.
I receive my message through the addons ofxSimpleSerial. I parse it into dataStrings and then parse it into my variables. But I have a problem because when the message (the firs to be read in general) is not full, the code can’t fill the variable and tell me that there is a mistake.

I try to close and/or flush the serial in different location but don’t resolve it.

Maybe have you an idea?

Thanks per advance for your answer!

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup()
{
	ofSetVerticalSync(true);
	ofBackground(0, 0, 0);

	serial.setup(1, 19200);
	serial.startContinuousRead();
	ofAddListener(serial.NEW_MESSAGE,this,&testApp::onNewMessage);
    
	message = "";
}

void testApp::onNewMessage(string & message)
{
	cout << "onNewMessage, message: " << message << "\n";

    vector<string> dataStrings=ofSplitString(message, '#');

    for(int i = 0; i < 4; i++) {
        string type = dataStrings[i].substr(0, 4);
        string dataval = dataStrings[i].substr(4);
        if (type == "DEL:") {
            std::istringstream dataval;
            dataval >> dt;
        } else if (type == "ACC:") {
            vector<string> data = ofSplitString(dataval, ',');
            x_acc = ofToFloat(data[0]);
            y_acc = ofToFloat(data[1]);
            z_acc = ofToFloat(data[2]);
        } else if (type == "GYR:") {
            vector<string> data = ofSplitString(dataval, ',');
            x_gyr = ofToFloat(data[0]);
            y_gyr = ofToFloat(data[1]);
            z_gyr = ofToFloat(data[2]);
        } else if (type == "FIL:") {
            vector<string> data = ofSplitString(dataval, ',');
            x_fil = ofToFloat(data[0]);
            y_fil = ofToFloat(data[1]);
            z_fil = ofToFloat(data[2]);
        }
    }
}

void testApp::update()
{
	if(requestRead)
    {
		serial.sendRequest();
		requestRead = false;
    }

}

//--------------------------------------------------------------
void testApp::draw()
{
    ofBackground(30,10,30);
    ofSetColor(ofColor::blue);
    ofFill();
    ofCircle( x_fil, y_fil, 30);
}

put an ending character in the serial message, so you know when the message is complete

in the addon code you can see that its waiting to see a line break to complete the message

if (*bytesReturned == '\n')
		{
			message = messageBuffer;
			messageBuffer = "";
			ofRemoveListener(ofEvents().update, this, &ofxSimpleSerial::update);
			ofNotifyEvent(NEW_MESSAGE, message, this);

			break;
		}

also you are setting the message var only in setup

message = "";

so this var contains info on the next read

i will do something like, when the message is complete set the var as on setup and later call

serial.sendRequest();

when you call that you are sending an “r” to the arduino so then the ardu send another serial messge

Hope that helps, i can explain that better but in spanish…

Ok I understand.
I have put a line break ("\n") at the end of my serial message (in arduino). But I don’t see where I can “say” to the reader “wait for it to read”.

in the code of the read fuction of the addon, its done by default:

		// if we find the splitter we put all the buffered messages
		//   in the final message, stop listening for more data and
		//   notify a possible listener
		// else we just keep filling the buffer with incoming bytes.

so your onNewMessage fuction will be called when the serial receive the “\n” character, then you sould have your complete message and then you can set message = “”, and requestRead = true if you want to read again

Okay… I think I’m getting it but I don’t know how to solve it…
I send you my of code and my sending code (part of) :

// Send the data to the serial port
Serial.print(F(“DEL:”)); //Delta T
Serial.print(dt, DEC);
Serial.print(F("#ACL:")); //Accelerations
Serial.print(accel_x, 2);
Serial.print(F(","));
Serial.print(accel_y, 2);
Serial.print(F(","));
Serial.print(accel_z, 2);
Serial.print(F("#ACC:")); //Accelerometer angle
Serial.print(accel_angle_x, 2);
Serial.print(F(","));
Serial.print(accel_angle_y, 2);
Serial.print(F(","));
Serial.print(accel_angle_z, 2);
Serial.print(F("#GYR:")); //Drifting Gyroscope angle
Serial.print(unfiltered_gyro_angle_x, 2);
Serial.print(F(","));
Serial.print(unfiltered_gyro_angle_y, 2);
Serial.print(F(","));
Serial.print(unfiltered_gyro_angle_z, 2);
Serial.print(F("#GYF:")); //Filtered Gyroscope angle
Serial.print(gyro_angle_x, 2);
Serial.print(F(","));
Serial.print(gyro_angle_y, 2);
Serial.print(F(","));
Serial.print(gyro_angle_z, 2);
Serial.print(F("#FIL:")); //Filtered angle
Serial.print(angle_x, 2);
Serial.print(F(","));
Serial.print(angle_y, 2);
Serial.print(F(","));
Serial.print(angle_z, 2);
Serial.println(F(""));

// Delay so we don’t swamp the serial port
delay(5);

and I’ve got this king of error :
[ error ] ofSerial: flush(): serial not inited
[notice ] ofSerial: opening /dev/cu.usbmodem1421 @ 38400 bps
[notice ] ofSerial: opened /dev/cu.usbmodem1421sucessfully @ 38400 bps
onNewMessage, message: :5.63,-4.19,0.00#GYR:-4.77,3.45,0.98#GYF:-3.26,2.16,0.98#FIL:-2.90,1.91,0.98
dataStrings: :5.63,-4.19,0.00

dataStrings: GYR:-4.77,3.45,0.98

dataStrings: GYF:-3.26,2.16,0.98

dataStrings: FIL:-2.90,1.91,0.98

dataStrings: (lldb)

send me the ardu file and the of project and i will take a look (i don’t promisse nothing but i can check).

one rapid thing to check is that if the ardu is always sending message is adding a delay after send println…. i see in your connection 38400 bps its fast, maybe the ardu is slower and can not fill those vars that you are sending at that speed.

1 Like

yes but here are two things to check:

  • first one its the fact that you can generate the serial message in the ardu enough fast
  • second the of part

why not make that the ardu only sends the serial message when the of calls for it¿