NeuronRobotics / nrjavaserial

A Java Serial Port system. This is a fork of the RXTX project that uses in jar loading of the native code.
Other
345 stars 143 forks source link

Serial port I/O best pratices #33

Closed jairocgr closed 4 years ago

jairocgr commented 9 years ago

Hi,

_TLDR;_ I'm looking for best pratice/high performance for serial port reading and writing.

Background

I'm quite new on Java I/O so i took a bunch of readings about the subject, but all information that i found was talking about networking and filesystem reading and writing.

I work with agriculture software, therefore i need to communicate with all sort of sensors(scales, rfid readers, termometers, anemometer, etc).

On my current project, the software must be able to handle concurrents weighing from a bunch of scales dispersed all over the farm. The weighing data will come via radio and will be forwarded for my software via USB/Serial COM port.

What i am currently doing

Currently, i'm adding a SerialPortEventListener who relies on the internal MonitorThread from _nrjavaserial_ library. My listener is acting as a dispatcher, it handles serial port events, perform i/o, wraps the inputs and dispatch them for another threads to handle it.

When the listener recieve the SerialPortEvent.DATA_AVAILABLE, it performs a byte-by-byte reading(using directly the the nrjavaserial's InputStream) until it find a line-feed char('\n'). Just after the reading, it wraps the string that were read on a new event and post to a Guava's EventBus.

What i'm exactly looking for

In order to design a proper solution, i have to know more about Serial port I/O. I want be able to trade-off about byte-by-byte/buffered reading, buffer size, multi-thread strategy and so on...

I want to build reliable and responsive system with a modest memory footprint.

Maybe you guys can help me ;)

madhephaestus commented 9 years ago

The internal eventing thread is a simple way to access the serial port asynchronously, but if performance is your goal, then setting up your own polling thread is going to give you the best throughput.

I usually access the serial port using the streeam interface as seen here:

https://github.com/NeuronRobotics/java-bowler/blob/development/src/main/java/com/neuronrobotics/sdk/serial/SerialConnection.java#L150

And internally i poll the port for availible bytes:

https://github.com/NeuronRobotics/java-bowler/blob/development/src/main/java/com/neuronrobotics/sdk/common/BowlerAbstractConnection.java#L1246

I implemented my own ByteList in the java-bowler library to use a static circular buffer that only resizes if the circular buffer overflows. THis allows for a very high speed buffering, but tollerence of unknown buffer size conditions.

On Tue, Jul 28, 2015 at 8:28 AM, Jairo Ricardes Rodrigues Filho < notifications@github.com> wrote:

Hi,

TLDR; I'm looking for best pratice/high performance for serial port reading and writing. Background

I'm quite new on Java I/O so i took a bunch of readings about the subject, but all information that i found was talking about networking and filesystem reading and writing.

I work with agriculture software, therefore i need to communicate with all sort of sensors(scales, rfid readers, termometers, anemometer, etc).

On my current project, the software must be able to handle concurrents weighing from a bunch of scales dispersed all over the farm. The weighing data will come via radio and will be forwarded for my software via USB/Serial COM port. What i am currently doing

Currently, i'm adding a SerialPortEventListener who relies on the internal MonitorThread from nrjavaserial library. My listener is acting as a dispatcher, it handles serial port events, perform i/o, wraps the inputs and dispatch them for another threads to handle it.

When the listener recieve the SerialPortEvent.DATA_AVAILABLE, it performs a byte-by-byte reading(using directly the the nrjavaserial's InputStream) until it find a line-feed char('\n'). Just after the reading, it wraps the string that were read on a new event and post to a Guava's EventBus https://github.com/google/guava/wiki/EventBusExplained. What i'm exactly looking for

In order to design a proper solution, i have to know more about Serial port I/O. I want be able to trade-off about byte-by-byte/buffered reading, buffer size, multi-thread strategy and so on...

I want to build reliable and responsive system with a modest memory footprint.

Maybe you guys can help me ;)

— Reply to this email directly or view it on GitHub https://github.com/NeuronRobotics/nrjavaserial/issues/33.

Kevin Harrington Founder: Technocopia Co. Founder: Neuron Robotics Cooperative 95 Prescott St, Worcester MA

Google Scholar: https://scholar.google.com/citations?hl=en&user=wrX-I10AAAAJ

LinkedIn: http://www.linkedin.com/pub/kevin-harrington/8/a24/358

jairocgr commented 9 years ago

Thx @madhephaestus, i'll study your implementation.

jairocgr commented 9 years ago

@madhephaestus i studied your implementation and i also did more digging on the Serial Impl.c too.

I'm thinking to abandon the SerialPortEventListener/MonitorThread approach and start polling the stream like you said.

One thing that i didn't figure out is if has some drawbacks in choosing the byte-by-byte reading or the avaliable/buffer reading.

andyrozman commented 9 years ago

It depends on device... I am working with medical devices, and my latest has serious problem with byte-by-byte reading... After some time communication stops. Reading of buffer, helps eliminate this problem. So it really depends on device... If you know that device has special buffer length, it would be probably best to use that, and also it will be little faster.

madhephaestus commented 9 years ago

Hmm, i had an issue with this too and found that it was a firmware issue on the microcontroller. You wouldnt happen to be using a Pic32 with the USB stack device side?

Also, just for my own interest, what medical device? I work in the WPI AIM lab http://aimlab.wpi.edu/ on surgical robots using java-bowler and this library, so i would be interested to know what other divices its used in.

andyrozman commented 9 years ago

My project is Diabetes Management Software (GNU Gluco Control), so I use it with diabetes devices (glucose meters, pumps and CGMS devices)... I had problem with Minimed Pump, while using very old interface (there are several options how to connect to device, and oldest one had problems). While using this interface there is a lot of data that needs to be read and my byte-by-byte implementation had quite few problems with that. It started working better after I started reading bigger packets.