See page history for list of all contributors.
The Arduino IDE itself is written in Java, and it can communicate to the serial port via the RXTX Java library. The RXTX library is unstable and not recommended for use. The jSerialComm library is a much better alternative (StackOverflow post). The RXTX library is very similar to the Java Communications API extension. Internally the IDE remembers which port and baud rate you used last time. Unfortunately that internal implementation can not be considered public API you can reliably use. So you will have to keep your own settings to remember which COM port your Arduino card is using.
This interface sample presumes that you already know how to compile and run Java code. There are plenty of other resources on the Internet to teach you to program in Java. Most serious Java programmers use a Java IDE to create Java programs, like the free Eclipse IDE, but this example provides information for the less frequent Java programmer.
Before you begin interfacing with your Arduino board, you must have the Arduino IDE installed and configured. Once it is installed, try this simple sketch. You can use the Serial Monitor of the IDE to verify that the board is set up correctly.
void setup(){ Serial.begin(9600); } void loop(){ Serial.println("Hello world"); delay(1000); }
If you installed the Arduino IDE, you already have the RXTX library installed for the next steps, and you may be able to skip this section and start with the sample Java code. If you installed a separate copy of the RXTX, you can do one of the following:
java -Djava.library.path=C:\rxtx-2.2pre2-bins\win32 SerialTest
You should also ensure that the RXTXcomm.jar is in your CLASSPATH.
win32/rxtxSerial.dll
into C:\Windows\System32
rxtxSerial.dll
into your PATH
environment variable.
Also, https://www.youtube.com/watch?v=43Vdpz1YmdU
win64/rxtxSerial.dll
into C:\Windows\SysWOW64
rxtxSerial.dll
into your PATH
environment variable.
Also, https://www.youtube.com/watch?v=43Vdpz1YmdU
/Library/Java/Extensions
mac-10.5/librxtxSerial.jnilib
(or, if this version does not work for you, obtain a 64 bit compiled version from http://blog.iharder.net/2009/08/18/rxtx-java-6-and-librxtxserial-jnilib-on-intel-mac-os-x/) and paste into /Library/Java/Extensions
librxtxSerial.jnilib
files into your DYLD_LIBRARY_PATH environment variable
Now that you have confirmed that the board is working, you are now ready to save and compile the following sample code. You should save it as SerialTest.java. You may need to modify the PORT_NAMES of this sample to use the correct COM port that you are using. Also, if you are not using Raspberry Pi you should comment out "System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyACM0");" in the below code or it won't work.
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import java.util.Enumeration; public class SerialTest implements SerialPortEventListener { SerialPort serialPort; /** The port we're normally going to use. */ private static final String PORT_NAMES[] = { "/dev/tty.usbserial-A9007UX1", // Mac OS X "/dev/ttyACM0", // Raspberry Pi "/dev/ttyUSB0", // Linux "COM3", // Windows }; /** * A BufferedReader which will be fed by a InputStreamReader * converting the bytes into characters * making the displayed results codepage independent */ private BufferedReader input; /** The output stream to the port */ private OutputStream output; /** Milliseconds to block while waiting for port open */ private static final int TIME_OUT = 2000; /** Default bits per second for COM port. */ private static final int DATA_RATE = 9600; public void initialize() { // the next line is for Raspberry Pi and // gets us into the while loop and was suggested here was suggested https://www.raspberrypi.org/phpBB3/viewtopic.php?f=81&t=32186 System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyACM0"); CommPortIdentifier portId = null; Enumeration portEnum = CommPortIdentifier.getPortIdentifiers(); //First, Find an instance of serial port as set in PORT_NAMES. while (portEnum.hasMoreElements()) { CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement(); for (String portName : PORT_NAMES) { if (currPortId.getName().equals(portName)) { portId = currPortId; break; } } } if (portId == null) { System.out.println("Could not find COM port."); return; } try { // open serial port, and use class name for the appName. serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT); // set port parameters serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // open the streams input = new BufferedReader(new InputStreamReader(serialPort.getInputStream())); output = serialPort.getOutputStream(); // add event listeners serialPort.addEventListener(this); serialPort.notifyOnDataAvailable(true); } catch (Exception e) { System.err.println(e.toString()); } } /** * This should be called when you stop using the port. * This will prevent port locking on platforms like Linux. */ public synchronized void close() { if (serialPort != null) { serialPort.removeEventListener(); serialPort.close(); } } /** * Handle an event on the serial port. Read the data and print it. */ public synchronized void serialEvent(SerialPortEvent oEvent) { if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { String inputLine=input.readLine(); System.out.println(inputLine); } catch (Exception e) { System.err.println(e.toString()); } } // Ignore all the other eventTypes, but you should consider the other ones. } public static void main(String[] args) throws Exception { SerialTest main = new SerialTest(); main.initialize(); Thread t=new Thread() { public void run() { //the following line will keep this app alive for 1000 seconds, //waiting for events to occur and responding to them (printing incoming messages to console). try {Thread.sleep(1000000);} catch (InterruptedException ie) {} } }; t.start(); System.out.println("Started"); } }
There are other methods to get data over the serial port, like via polling, but this event based method has very low CPU overhead because the listener is only called when data is available.
Ardulink is a complete, open source, java solution for the control and coordination of Arduino boards. It defines a communication protocol and a communication interface allowing several protocol implementations.
It is composed by several java libraries/applications:
You can read more detail on Ardulink official site or on Github
The main Adulink java class is the Link class. In order to communicate with Arduino you have to retrieve a Link instance.
Link link = Link.getDefaultInstance();
or for instance
Link link = Link.createInstance("digisparkConnection", new DigisparkUSBConnection());
Then the connection
boolean connected = link.connect(comPort, baudRate); // comPort could be "COM19" for windows
Then send messages
link.sendPowerPinIntensity(pin, powerValue); // To PWM pins (analogWrite) link.sendPowerPinSwitch(pin, IProtocol.POWER_HIGH); // to digitalWrite link.sendCustomMessage("openDoor"); link.sendCustomMessage("goAhead");
or receive messages
link.addDigitalReadChangeListener(new DigitalReadChangeListener() { @Override public void stateChanged(DigitalReadChangeEvent e) { // do something } @Override public int getPinListening() { return 11; } }); link.addRawDataListener(new RawDataListener() { @Override public void parseInput(String id, int numBytes, int[] message) { // do something } });
more info here: http://www.ardulink.org
For Windows you can create a batch file called run.bat in the same directory as the sample code mentioned above. This batch file can be used on your system, but you may need to modify the paths to match the install locations of your Java and Arduino IDE on your system.
setlocal set PATH=%PATH%;C:\Program Files (x86)\arduino-0017\ "C:\Program Files (x86)\Java\jdk1.6.0_12\bin\javac" -cp "C:\Program Files (x86)\arduino-0017\lib\RXTXcomm.jar" SerialTest.java "C:\Program Files (x86)\Java\jdk1.6.0_12\bin\java" -cp "C:\Program Files (x86)\arduino-0017\lib\RXTXcomm.jar;." SerialTest
Basically, you will need to add the RXTXcomm.jar to your class path, and you will need to add the associated JNI interface DLL (rxtxSerial.dll) to your PATH. For other platforms, you will need to add the same JNI shared library to your run time path.
When you run the run.bat file, you should see the same results as the Arduino IDE Serial Monitor. You can use Ctrl+Break to stop the program.
Presuming that you are using the sample code above you may need to do the following steps.
1. Using the terminal, change to the directory containing the files to be compiled. Compile the file using (replace filename with your java class name):
javac -classpath RXTXcomm.jar:. SerialTest.java
If you placed the RXTX libraries into /Library/Java/Extensions, the file can be compiled by simply using:
javac SerialTest.java
2. Now it is time to run the compiled source code. This requires inclusion of the JNI shared library into the library path by using the command below:
java -Djava.library.path=. -cp RXTXcomm.jar:. SerialTest
If you placed the RXTX jar and library in the /Library/Java/Extensions folder rather than the directory that contains the file to be compiled, the file can be run without the library path as shown below:
java SerialTest
3. The code should now run successfully and print the serial output to the screen (as with the Arduino serial monitor)
If you get an error message telling you the library is not matching architecture it might be due to MacOSX Snow Leopard trying to execute the program in 64bit mode. If you run into this problem try the VM argument -d32 to force the java program to be executed in 32bit mode.
If you encounter any issues with the port being unable to be locked, these instructions may help. If you set up the Arduino environment, this should not be an issue. This also does not seem to be an issue with RXTX version 2.2.
1. The RXTX library places its lock files in the folder /var/lock - which sometimes does not exist. Open terminal and Create the lock directory (as root) by using the following command:
sudo mkdir /var/lock
And enter your root password when prompted.
2. The appropriate permissions need to be applied to the /var/lock directory to allow the program to be run without being root. It is necessary to make sure you're in the group uucp and make sure the directory has group write permissions to uucp. Replace ‘username’ with your profile user name.
sudo dscl . -append /groups/_uucp GroupMembership username sudo chgrp uucp /var/lock sudo chmod 775 /var/lock
A port in use exception (gnu.io.PortInUseException) with version 2.1-7 might also be solved by changing permissions using the sh script from jlog: http://jlog.org/rxtx-mac.html
In my experience, it seems that the Serial connection must be connected somewhere above 1 second (I have 1.5 seconds in my program) before a transmission can be made. It seems that for at least the ATmega168 and Diecimila, doing so ensures your transmission actually is transmitted. For doing that, Thread.sleep(delay) is used and delay is specified in milliseconds so I would use Thread.sleep(1500) after the Serial port is established. It seems this might be due to the program resetting when a serial connection is made, and the program has a necessary setup time.
The OutputStream comes with 3 different write methods to send data from the computer to the Arduino. In the above example, you could use output.write(String) to send data, as in output.write("Hello Arduino!"). There's also one that'll send an integer value and another that will transmit an array of Bytes.
I found on the Arduino's program, to accurately receive the data instead of receiving non-intelligible "255" data points, I had to maintain a generous delay between the Serial.read() commands. I ended up using 20 ms for safe measure, but the actual necessary number is likely much lower and one could use a "255 filter" to extract meaningful data, assuming none of your meaningful data consists of the number 255.
The simple Serial.read() function will process a byte at a time, although there are more interesting read functions available.
If you want to properly close the port, you should call the close() method on the serial port object upon program exit. This will prevent the port from being locked after your program exits. You may notice this issue on Linux and not Windows. The serial port's close method should be called from a method that is synchronized with the serialEvent method, which will prevent any exceptions from appearing during program shutdown.