Host development platform:
OS: Windows 10
IDE: NetBeans IDE 8.0.2
Programming Language: Java + JavaFX + jSSC
Target platform:
Raspberry Pi 2
OS: Raspbian
IP: 192.168.1.112
Both Host development platform and Target platform in the same Network.
(How to set Remote Java SE Platform to deploy on Raspberry Pi, refer to the video in the post "Java + JavaFX + jSSC run on Raspberry Pi, control Arduino Uno")
remark: due to something wrong on my Raspberry Pi 2 cannot detect monitor correctly, I have to edit /boot/config.txt to set framebuffer_width and framebuffer_height to 500x400. So the screen output may be differency to you.
Arduino Side:
Board: Arduino Uno + 8x8 LED Matrix
Connected to Raspberry Pi 2 with USB. Arduino Side:
Arduino code and connection between Arduino Uno and 8x8 LED Matrix, refer last post.
Java/JavaFX/jSSC code, program on Windows 10/NetBeans, run on Raspberry Pi 2:
(Basically same as last post, with moving btnExit to vBoxMatrix, such that user can exit the program in raspberry Pi UI.
It's a example to control Arduino Uno + 8x8 LED Matrix, from USB connected PC running Windows 10, programmed with Java + JavaFX + jSSC(java-simple-serial-connector).
Arduino Side:
Connection between Arduino Uno and 8x8 LED:
UnoSerialInMatrix.ino
// 2-dimensional array of row pin numbers:
const int row[8] = {
2, 7, 19, 5, 13, 18, 12, 16
};
// 2-dimensional array of column pin numbers:
const int col[8] = {
6, 11, 10, 3, 17, 4, 8, 9
};
// 2-dimensional array of pixels:
int pixels[8][8];
int incomingByte = 0;
void setup() {
// initialize the I/O pins as outputs
// iterate over the pins:
for (int thisPin = 0; thisPin < 8; thisPin++) {
// initialize the output pins:
pinMode(col[thisPin], OUTPUT);
pinMode(row[thisPin], OUTPUT);
// take the col pins (i.e. the cathodes) high to ensure that
// the LEDS are off:
digitalWrite(col[thisPin], HIGH);
}
clearScr();
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
doProcess(incomingByte);
}
// draw the screen:
refreshScreen();
}
const int SYNC_WORD = 0xFF;
const int ST_0_IDLE = 0;
const int ST_1_WAITX = 1;
const int ST_2_WAITY = 2;
const int ST_3_WAITB = 3;
int prc_State = ST_0_IDLE;
int dotX, dotY, dotB;
void doProcess(int b){
switch(prc_State){
case ST_0_IDLE:
if(b == SYNC_WORD){
prc_State = ST_1_WAITX;
Serial.println("1");
}
break;
case ST_1_WAITX:
dotX = b;
prc_State = ST_2_WAITY;
Serial.println("2");
break;
case ST_2_WAITY:
dotY = b;
prc_State = ST_3_WAITB;
Serial.println("3");
break;
case ST_3_WAITB:
if(b == 1){
pixels[dotY][dotX] = LOW;
}else{
pixels[dotY][dotX] = HIGH;
}
prc_State = ST_0_IDLE;
Serial.println("0");
break;
default:
prc_State = ST_0_IDLE;
}
}
void clearScr(){
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
pixels[x][y] = HIGH;
}
}
}
void refreshScreen() {
// iterate over the rows (anodes):
for (int thisRow = 0; thisRow < 8; thisRow++) {
// take the row pin (anode) high:
digitalWrite(row[thisRow], HIGH);
// iterate over the cols (cathodes):
for (int thisCol = 0; thisCol < 8; thisCol++) {
// get the state of the current pixel;
int thisPixel = pixels[thisRow][thisCol];
// when the row is HIGH and the col is LOW,
// the LED where they meet turns on:
digitalWrite(col[thisCol], thisPixel);
// turn the pixel off:
if (thisPixel == LOW) {
digitalWrite(col[thisCol], HIGH);
}
}
// take the row pin low to turn off the whole row:
digitalWrite(row[thisRow], LOW);
}
}
This video show how to create Remote Java SE Platform on NetBeans IDE run on Windows 10, and run it remotely on Raspberry Pi 2.
Host development platform:
OS: Windows 10
IDE: NetBeans IDE 8.0.2
Programming Language: Java + JavaFX + jSSC (refer last post Last Post)
Target platform:
Raspberry Pi 2
OS: Raspbian
IP: 192.168.1.110
Both Host development platform and Target platform in the same Network. remark: due to something wrong on my Raspberry Pi 2 cannot detect monitor correctly, I have to edit /boot/config.txt to set framebuffer_width and framebuffer_height to 500x400. So the screen output may be differency to you.
Arduino Side:
Board: Arduino Uno
Connected to Raspberry Pi 2 with USB.
Program and Connection: (refer last post Last Post)
This example show Bi-direction communication between Arduino Uno and PC using Java + javaFX + jSSC:
Arduino to PC: Arduino Uno analog input, display on JavaFX LineChart
PC to Arduino: Button to control Arduino Uno on-board LED
This example show how to use Java + jSSC + JavaFX running on PC/Windows 10, read bytes from USB/Serial. The data sent from Arduino Uno by reading analog input. The PC and Arduino Uno connected with USB.
/*
* Example of using jSSC library to handle serial port
* Receive number from Arduino via USB/Serial and display on Label
*/
package javafx_jssc_uno;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import jssc.SerialPort;
import static jssc.SerialPort.MASK_RXCHAR;
import jssc.SerialPortEvent;
import jssc.SerialPortException;
import jssc.SerialPortList;
public class JavaFX_jssc_Uno extends Application {
SerialPort arduinoPort = null;
ObservableList<String> portList;
Label labelValue;
private void detectPort(){
portList = FXCollections.observableArrayList();
String[] serialPortNames = SerialPortList.getPortNames();
for(String name: serialPortNames){
System.out.println(name);
portList.add(name);
}
}
@Override
public void start(Stage primaryStage) {
labelValue = new Label();
labelValue.setFont(new Font("Arial", 150));
detectPort();
final ComboBox comboBoxPorts = new ComboBox(portList);
comboBoxPorts.valueProperty()
.addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
System.out.println(newValue);
disconnectArduino();
connectArduino(newValue);
}
});
VBox vBox = new VBox();
vBox.getChildren().addAll(
comboBoxPorts, labelValue);
StackPane root = new StackPane();
root.getChildren().add(vBox);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public boolean connectArduino(String port){
System.out.println("connectArduino");
boolean success = false;
SerialPort serialPort = new SerialPort(port);
try {
serialPort.openPort();
serialPort.setParams(
SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
serialPort.setEventsMask(MASK_RXCHAR);
serialPort.addEventListener((SerialPortEvent serialPortEvent) -> {
if(serialPortEvent.isRXCHAR()){
try {
byte[] b = serialPort.readBytes();
int value = b[0] & 0xff; //convert to int
String st = String.valueOf(value);
//Update label in ui thread
Platform.runLater(() -> {
labelValue.setText(st);
});
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jssc_Uno.class.getName())
.log(Level.SEVERE, null, ex);
}
}
});
arduinoPort = serialPort;
success = true;
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jssc_Uno.class.getName())
.log(Level.SEVERE, null, ex);
System.out.println("SerialPortException: " + ex.toString());
}
return success;
}
public void disconnectArduino(){
System.out.println("disconnectArduino()");
if(arduinoPort != null){
try {
arduinoPort.removeEventListener();
if(arduinoPort.isOpened()){
arduinoPort.closePort();
}
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jssc_Uno.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}
@Override
public void stop() throws Exception {
disconnectArduino();
super.stop();
}
public static void main(String[] args) {
launch(args);
}
}
Arduino Uno side - AnalogInputToUSB.ino
/*
* AnalogInputUSB
* Read analog input from analog pin 0
* and send data to USB
*/
int ledPin = 13;
int analogPin = A0;
int analogValue = 0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
digitalWrite(ledPin, HIGH);
analogValue = analogRead(analogPin); //Read analog input
analogValue = map(analogValue, 0, 1023, 0, 255);
Serial.write(analogValue); //write as byte, to USB
digitalWrite(ledPin, LOW);
delay(1000);
}
Connect a potentiometer in Analog Input A0 as input.
Prepare a simple sketch run on Arduino Uno to send a counting number to serial port, tested on Windows 10.
BlinkUSB.ino
/*
* Send number to Serial
*/
int i = 0;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
Serial.begin(9600);
}
// the loop function runs over and over again forever
void loop() {
Serial.print(i);
i++;
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
jSSC (Java Simple Serial Connector) is a library for working with serial ports from Java. jSSC support Win32(Win98-Win8), Win64, Linux(x86, x86-64, ARM), Solaris(x86, x86-64), Mac OS X 10.5 and higher(x86, x86-64, PPC, PPC64)
Last post "JavaFX + java-simple-serial-connector + Arduino" implement simple one way communication from PC run JavaFX to Arduino. This example implement bi-direction sending and receiving between PC and Arduino, using java-simple-serial-connector.
To implement receiving, we have to implement SerialPortEventListener, and add it with serialPort.addEventListener().
package javafx_jssc;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import jssc.SerialPortList;
public class JavaFX_jSSC extends Application {
SerialPort serialPort;
ObservableList<String> portList;
ComboBox comboBoxPorts;
TextField textFieldOut, textFieldIn;
Button btnOpenSerial, btnCloseSerial, btnSend;
private void detectPort() {
portList = FXCollections.observableArrayList();
String[] serialPortNames = SerialPortList.getPortNames();
for (String name : serialPortNames) {
System.out.println(name);
portList.add(name);
}
}
@Override
public void start(Stage primaryStage) {
detectPort();
comboBoxPorts = new ComboBox(portList);
textFieldOut = new TextField();
textFieldIn = new TextField();
btnOpenSerial = new Button("Open Serial Port");
btnCloseSerial = new Button("Close Serial Port");
btnSend = new Button("Send");
btnSend.setDisable(true); //default disable before serial port open
btnOpenSerial.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
closeSerialPort(); //close serial port before open
if(openSerialPort()){
btnSend.setDisable(false);
}else{
btnSend.setDisable(true);
}
}
});
btnCloseSerial.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
closeSerialPort();
btnSend.setDisable(true);
}
});
btnSend.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
if(serialPort != null && serialPort.isOpened()){
try {
String stringOut = textFieldOut.getText();
serialPort.writeBytes(stringOut.getBytes());
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jSSC.class.getName()).log(Level.SEVERE, null, ex);
}
}else{
System.out.println("Something wrong!");
}
}
});
VBox vBox = new VBox();
vBox.getChildren().addAll(
comboBoxPorts,
textFieldOut,
textFieldIn,
btnOpenSerial,
btnCloseSerial,
btnSend);
StackPane root = new StackPane();
root.getChildren().add(vBox);
Scene scene = new Scene(root, 300, 250);
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
closeSerialPort();
}
});
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private boolean openSerialPort() {
boolean success = false;
if (comboBoxPorts.getValue() != null
&& !comboBoxPorts.getValue().toString().isEmpty()) {
try {
serialPort = new SerialPort(comboBoxPorts.getValue().toString());
serialPort.openPort();
serialPort.setParams(
SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
serialPort.addEventListener(new MySerialPortEventListener());
success = true;
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jSSC.class.getName()).log(Level.SEVERE, null, ex);
}
}
return success;
}
private void closeSerialPort() {
if (serialPort != null && serialPort.isOpened()) {
try {
serialPort.closePort();
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jSSC.class.getName()).log(Level.SEVERE, null, ex);
}
}
serialPort = null;
}
class MySerialPortEventListener implements SerialPortEventListener {
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
if(serialPortEvent.isRXCHAR()){
try {
int byteCount = serialPortEvent.getEventValue();
byte bufferIn[] = serialPort.readBytes(byteCount);
String stringIn = "";
try {
stringIn = new String(bufferIn, "UTF-8");
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(JavaFX_jSSC.class.getName()).log(Level.SEVERE, null, ex);
}
textFieldIn.setText(stringIn);
} catch (SerialPortException ex) {
Logger.getLogger(JavaFX_jSSC.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
This example implement a simple Java application using java-simple-serial-connector library (jSSC) , with JavaFX user interface, send bytes to Arduino Esplora via USB.
Java is the preferred language for many of today’s leading-edge technologies—everything from smartphones and game consoles to robots, massive enterprise systems, and supercomputers. If you’re new to Java, the fourth edition of this bestselling guide provides an example-driven introduction to the latest language features and APIs in Java 6 and 7. Advanced Java developers will be able to take a deep dive into areas such as concurrency and JVM enhancements.
You’ll learn powerful new ways to manage resources and exceptions in your applications, and quickly get up to speed on Java’s new concurrency utilities, and APIs for web services and XML. You’ll also find an updated tutorial on how to get started with the Eclipse IDE, and a brand-new introduction to database access in Java.
Communication between Arduino and PC running Java, with JavaFX UI
User enter message in JavaFX and click the button, the message will be sent to Arduino via Serial. In Arduino side, it loop back the message to PC. Then, if received in PC side, it will be displayed in JavaFX.
package serialtest;
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/ttyACM0", //for Ubuntu
"/dev/tty.usbserial-A9007UX1", // Mac OS X
"/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() {
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");
}
}
RXTX is the Java library Arduino IDE used to communicate to the serial. It can be used by developers to develop applications communicating with Arduino board.
The Arduino IDE itself is written in Java, and it can communicate to the serial port via the RXTX Java library. That library is very similar to the Java Communications API extension.
Angela Caicedo, Java Evangelist, explains how to create an application with great user interface using Raspberry PI and JavaFX. Fascinated with 3D, she uses simple techniques that can make your UI unbelievably realistic without the need for 3D hardware.