Serial.println() and serial capture

Status
Not open for further replies.

linuxgeek

Well-known member
I'm sending some ascii data over serial from a teensy LC and a java app using jssc on a linux pc.

Initially I had trouble that, for whatever reason, sometimes an entire line would not get outputted.

For instance. when

Serial.print("abcdefghijklmnopqrstuvwxyz);
Serial.println();

On java, I might get the whole line, but occasionally esp. with bluetooth, I would only get partial "abcdefghijklmno", and the next string would have the rest of it.

I accounted for that in the java app by calling serialPort.readString() until I detected a '\r' followed by a '\n'.

But now I notice that sometimes I get multiple lines when I call serialPort.readString()

Any tips on handling this? Would I better off by using Serial.print('\n'), rather than Serial.println()?

I can think of a couple of ways to handle this that gets a little involved, but I'm just wondering if there's a simpler method that I'm missing.

Thanks.
 
You seem to expect that serial sends data bundled as per your print(). It doesn't. Except for a bit of overhead,
Serial.print("abcd");
is the same as
Serial.print("ab"); Serial.print("cd");

Bluetooth, uses pretty small packets to transmit data so there is a good chance your transmission gets split into multiple packets (with potential delays due to retransmissions).

serialPort.readString() reads the data that has arrived. It doesn't know anything about lines. You may read a partial line or multiple ones or anything in-between, depending on how much data has arrived. Bundling/splitting the data the right way (e.g. by looking for line separators) is up to you.
 
Yes, I suppose you're right. I was sorta hoping that Serial.flush() did something.
It's really only the initial connection where I'm sending some initialization info, that it's nice to have a single line come through.
I think I'll try Serial.flush() and then a delay(1000), and see if I can get just a single line at those critical times.
 
I wouldn't depend on getting a complete line at any time. Tni has the right of it. And they call these things Streams for a reason - there's no guaranteed message boundaries.

Just assemble the message in a buffer somewhere until your get the message terminator (the new-line) and then process the message. Then assemble the next one...
 
This Arduino example - uses SeriialEvent to the buffering and waiting for the newline as Brooks suggests..

...\examples\04.Communication\SerialEvent
 
That's interesting, but the communication to the teensy is minimal, single character messaging.

For now, just for testing purposes, it seems adding a delay allows a single line to be outputted, and captured on the pc side.
I'll code it better on the pc side later on.

Serial.println("line1");
Serial.flush();
delay(1000);
Serial.println("line2");

On the pc side, I'm querying the serial port every 50msec, so it ends up grabbing single lines.
 
Not hard to make it work - I meant to translate that Arduino example for the PC side - gathering the bytes as they show up and calling it a line when you see the newline. It wouldn't be queued on timing then or timing dependent.
 
Yes, I do the part about fetching more data until I find a newline on the pc side.
What I didn't plan for, was getting more than one line on a read. You're right, it's not too hard, but I have about 30 other not too hard things to do, and this is at least functional for now. And I also have a few threads running on the pc side, and I didn't want to push my luck too much. If you code the pc side before I get to it, I'll certainly try it out.
 
:) - got my own coding horror going on with the I2C I touched on the K66 thread - this and a few other random notes was my break . . .
 
Side comments:

you might try some experimenting and see if anything helps out.

Example: as mentioned: Serial.print("ABCD"); followed by Serial.prinln();
Is more or less is the same as Serial.println("ABCD");
other than maybe an extra call.

However:
char buff[]="ABCD\n\r"; Serial.write(buff, 6);

May be different. At least when I was experimenting with sending AX12 packets back to host code, which has things like:
Serial.write(0xff); Serial.write(0xff); Serial.write(addr);...
When I experimented with T2, the performance was pretty bad, versus, putting everything into a buffer and do 1 write. It was almost like it was sending 1 usb packet for each Serial.write. However when I ran same test on T3.2, the buffering here did not help, in fact it was slightly slower. Probably USB code on T3.2 was doing the same buffering.

Now if instead you are going to TTL serial on Teensy, then depending on which Teensy it may depend on which serial port. Example on T3.2 if you use Serial1 or Serial2 there is a fifo and the Serial code is setup that if you do a Serial.write(buff, cnt), it will try to transfer all of your stuff to internal buffer, before triggering interrupt, and on the interrupt it will fill up the internal fifo, so you get less interrupts.... I mention this as you also talk about BT

As for Serial.flush() On Teensy side, this is good to make sure all of the data is output (last byte out of hardware). if USB, I assume this forces the USB packet to be sent, for TTL Serial, this waits until the hardware says the last byte was shifted out. On Linux side - doing a logical flush (termios tcdrain), may help, may hurt. Probably talking to Teensy hurt. I found in my hexapod code base if I am talking to FTDI driver, it helps, if I am talking to other devices like /dev/ttyACM0, it hurts (maybe a lot), it is like the driver does not have support for it, so the code above just does a long wait.

Back to USB, have you found any correlation of length of the data and your issue? I believe underlying the USB serial there are probably fixed length USB packets being sent (32 bytes?). I have not dug into this enough to know how USB serial packs the data. i.e. is there some other bytes other than the data that tells you how many valid data bytes there are... Keep meaning to look more into this to see if in my case it would make sense to try RAW HID.

As for Java side, I have not done any serious Java stuff and have not played with it all for many years, so I am not an expert in any way. But wonder if maybe the SerialPort object, might have a timeout value that you can experiment with, to see if that helps.

Sorry I am being a little long winded, hope something helps!

Kurt
 
Status
Not open for further replies.
Back
Top