Skip to content

Troubleshooting

Will Hedgecock edited this page Apr 11, 2024 · 17 revisions

1) Some flow control modes do not seem to be working correctly.

Some operating systems do not support all of the reported flow control modes. The following list shows which modes are supported by which OS's:

  • Windows: CTS, RTS/CTS, DSR, DTR/DSR, Xon, Xoff, Xon/Xoff
  • Mac: RTS/CTS, Xon, Xoff, Xon/Xoff
  • Linux: RTS/CTS, Xon, Xoff, Xon/Xoff

2) The library does not seem to be working under my Linux distribution. The open() function always returns false, or it prints out an error about "permission denied."

Serial port access is limited to certain users and groups in Linux. To remedy this, open a terminal and enter the following commands. Don't worry if some of the commands fail. All of these groups may not exist on every Linux distro. (Note, this process must only be done once for each user):

  • sudo usermod -a -G uucp username
  • sudo usermod -a -G dialout username
  • sudo usermod -a -G lock username
  • sudo usermod -a -G tty username

Replace the username parameter with your current username. (If you are not sure what your username is, type whoami and it will tell you.) If you are using SUSE 11.3 or higher, replace the '-a -G' flags with a single '-A' flag. Log out and you should have access to the serial port after logging back in.


3) I'm using a Raspberry Pi and my serial ports are not enumerating correctly.

By default, the Raspberry Pi does not allow non-root access to serial devices. First, make sure that you have completed all of the steps outlined in Troubleshooting Item #2. Additionally, the "physical" serial port (/dev/ttyAMA0) is automatically configured to be used by the Linux console. You will need to disable this setting to gain access to the port for your own use. To do this, two files must be edited using your preferred text editor (in these examples, I am using nano).

At the terminal, enter sudo nano /etc/inittab and comment out (add a # to the beginning of the line) the last line in the file that looks similar to this: T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100. Save this file and quit.

Again at the terminal, enter sudo nano /boot/cmdline.txt and remove ONLY the following text from the file: console=ttyAMA0,115200 kgdboc=ttyAMA0,115200. Save this file and quit. Reboot your Raspberry Pi and all serial ports should be functional and enumerate correctly.


4) I am a Linux user using event-based I/O with this library, and the LISTENING_EVENT_DATA_WRITTEN event never seems to trigger my callback.

This is not a bug, but rather a limitation of the Linux operating system. All read-based listening events should operate correctly; however, the operating system does not provide feedback about the success or failure of a write operation.


5) When I attempt to open a serial port on my Mac system, the library seems to hang on the open() call.

Mac OS X has separated out their serial port functionality for a single device into two separate file descriptors. The first descriptor is called the callout file, denoted by /dev/cu.[*], and this file is used when you want to initiate a connection to your remote serial device. The second descriptor is a callin file, denoted by /dev/tty.[*], and this file is useful when you want to use the serial port to wait for incoming connections only. In other words, the /dev/tty.[*] file will only successfully open when a remote device initiates a serial connection to your computer.

In almost all cases, the port descriptor you wish to use is /dev/cu.[*]. Try selecting the SerialPort associated with this file, and your open() call should return successfully.


6) Write timeouts do not appear to be working on my system.

Write timeouts are only available on Windows-based systems. This is an operating system limitation in which there is no system-level functionality to set write timeouts on other operating systems.


7) Read timeouts do not seem to exactly correspond to the values to which I set them on my Linux system.

A limitation of the Linux operating system is that it only allows deci-second granularity for serial port timeouts. As such, your millisecond timeout value will be rounded to the nearest decisecond on Linux. To ensure consistent performance across multiple platforms, it is advisable that you set your timeout values to be multiples of 100.


8) My Android Studio project complains about the presence of a module-info.class file in this library.

At the moment, Android Studio has not been updated to ignore Java features which it doesn't support (namely some newer Java 9+ functionality), even if those features are not necessary for proper library usage. As a workaround, your gradle.build file can be edited according to the instructions in Issue 128 to enable you to successfully use the library in your projects.


9) I am using a custom ARM-based CPU in my project, and the library does not auto-detect the correct architecture.

On some very few systems which use custom CPUs and/or have extremely restrictive permissions, the library will be unable to determine that the underlying system architecture is ARM-based. In this case, you can force the library to disable its auto-detect functionality and instead directly specify the architecture using the Java os.arch_full system property. Acceptable values for this property are currently one of: armv5, armv6, armv6-hf, armv7, armv7-hf, armv8_32, armv8_64, ppc64le, x86, x86_64.


10) I am encountering issues when attempting to use or manipulate a SerialPort instance.

It is important to note that you will need to keep track of your own SerialPort instance throughout your application code. The SerialPort.getCommPorts() method attempts to re-enumerate all available serial ports every time it is called, so the returned array is not guaranteed to be in the same order, contain the same ports, or contain SerialPort objects that have been initialized for your particular port instance.

The correct way to use a SerialPort instance is:

SerialPort port = SerialPort.getCommPorts()[0];
port.openPort();
// Work with port
...
// Somewhere else in your code:
port.closePort();

Do NOT do the following:

SerialPort port = SerialPort.getCommPorts()[0];
port.openPort();
// Work with port
...
// Somewhere else in your code:
SerialPort port = SerialPort.getCommPorts()[0];
port.closePort();

11) I am trying to use the library on a computer that does not allow access to the local temp folder.

It is possible to change the location of the temp folder by inserting the following line in your Java application somewhere before the first use of the jSerialComm library:

System.setProperty("java.io.tmpdir", "/a/folder/where/execution/is/allowed")

When doing this, make sure that the folder you specify already exists and has the correct permissions set to allow execution of a shared library.

Optionally, the same result can be achieved by running your Java application from the command line and specifying the java.io.tmpdir directory as an additional parameter, e.g.:

java -Djava.io.tmpdir=/folder/of/your/choice -jar yourApplication.jar

On Windows, you may be able to achieve the same result by setting the TMP environment variable (either through the Settings->System Properties->Environment Variables GUI or via SET TMP=C:\Desired\Tmp\Folder in a command terminal), although setting this variable through Java is preferable when possible.


12) I am trying to use the library on a computer that does not allow execution of ANY locally extracted native libraries.

In the rare case that your device does not allow execution of any native code that was not installed on it by an administrator or IT personnel, jSerialComm supports loading a pre-extracted version of its native library from a user-defined location using the startup flag: -DjSerialComm.library.path="<LIB_PATH>", where LIB_PATH can either be a directory containing the single native jSerialComm library for your correct architecture or the entire extracted arch-specific directory structure from inside the jSerialComm JAR file.

This method should be used as a last resort as it makes versioning and upgrading much more difficult and error-prone.


13) When trying to connect to an Arduino-based device, the Arduino resets every time I connect to it.

Unfortunately, Arduino devices utilize the RTS data signal as a means to reset the device, and Linux provides no way of disabling an RTS transition until after a serial port has been opened.

In order to mitigate this as much as possible (and potentially solve it altogether depending on your device), you should call clearDTR() on your serial port object before opening it. This will clear the DTR line as quickly as possible, making it less likely that your device will reset. Also, once you have connected to your device one time using this method, it should never reset again upon connection until the next time you reboot your computer.


14) I am using this library in an Apache Tomcat application, and upon redeployment I receive an error about the library being "already loaded in another classloader."

If you plan to use this library within an Apache Tomcat application, please set the jSerialComm.library.randomizeNativeName property to true before accessing any functionality within the SerialPort class to address an issue whereby the Tomcat bootloader tries to reinitialize the library multiple times. This can either be done by passing -DjSerialComm.library.randomizeNativeName="true" as a command line parameter or by calling the following within your own application before using any SerialPort functionality:

System.setProperty("jSerialComm.library.randomizeNativeName", "true")