Channels ▼

Eric Bruno

Dr. Dobb's Bloggers

Handling Arduino Events in Java

November 25, 2013

In my previous blog, I showed how to write a Java application to run on a host computer, which interfaces with a sketch running on an Arduino to turn an attached light on and off. Someone asked if it's possible to handle continuous events from an Arduino, and the answer is yes. Let's see how.

Arduino Event Handler

I've been using RXTX for the communication between the Arduino and Java over a serial connection. In my next blog, I plan to explore some alternatives, but let's stick to RXTX for now. I won't review too much here, but after connecting to the Arduino (details in a previous blog), you set up your event listener with two lines of code:


    // Add event listener
    serialPort.addEventListener(this);
    serialPort.notifyOnDataAvailable(true);

You need to pass a reference to a class that implements the gnu.io.SerialPortEventListener, which includes just one method: serialEvent(). A SerialPortEvent object is passed as the lone parameter. Implementing this method is straightforward; just check the event type for DATA_AVAILABLE and process the data by reading from the serial port's InputStream. You need to set this up with one line of code prior to the event like this:


    // Setup input reader for incoming data from Arduino
    input = new BufferedReader(
        new InputStreamReader( serialPort.getInputStream() ));

Temperature Sensor

To make the event processing interesting, I'm using a temperature sensor I bought (along with many others) from ManyLabs. My kit came with a shield that allows multiple analog and digital sensors to be connected to an Arduino. I placed the shield on my Arduino, plugged the sensor into port S1, and wrote a simple sketch that publishes the sensor readings over the serial port. Let's walk through this:


  int tempSensorPin = 0;
   
  void setup() {
    Serial.begin(9600);  //Start the serial connection with the computer
                         //to view the result open the serial monitor 
  }
   
  void loop() {
    //getting the voltage reading from the temperature sensor
    int tempSensorVal = analogRead(tempSensorPin);  
  
    // Formula for converting voltage to temp in C
    const int B=3975; 
    float Rsensor = (float)(1023-tempSensorVal)*10000/tempSensorVal;
    double TEMP = 1 / (log(Rsensor/10000)/B+1/298.15)-273.15;
   
    // now convert to Fahrenheit
    float temperatureF = (TEMP * 9.0 / 5.0) + 32.0;
    Serial.print(temperatureF); Serial.println(" degrees F");
  
    delay(1000); //waiting a second
  }

The sensor works by generating a voltage reading that varies by temperature. The trick is to take this reading, convert it to a temperature using a formula (it's simpler than it may appear), and then convert to either Celsius or Fahrenheit. To "publish" this as an event over the serial port, simply use Serial.print and/or Serial.println, assuming you've initialized the serial port as I have in this example.

You should be able to verify your temperature reading by using the Arduino Serial Monitor to view the output, which is sent once per second.

The Java Side: Using JavaFX to Show the Temperature

I thought it would be neat to show the temperature via a fancy JavaFX user interface. I found a nice set of JavaFX gauges as part of the SteelFX project thanks to Jim Clarke and the JFXtras Labs. I believe Gerrit Grunwald was one of the main contributors to this gauge, although the lab's home page includes a long list of contributors.

To show the temperature, I used the code that Jim Clarke wrote about, which leverages FXML for the gauge definition. I modified the FXML file only slightly to set the temperature units and the class name within my project. After creating a JavaFX project, I modified the start() method as below:

    @Override
    public void start(Stage primaryStage) throws Exception {
        // Use FXML to get the panel and the child radial gauge
        Parent panel = 
            FXMLLoader.load(
                this.getClass().getResource("/steelfx/Gauge.fxml"));
        if ( radialGauge == null ) {
            ObservableList<Node> children = panel.getChildrenUnmodifiable();
            radialGauge = (Radial)children.get(0);
        }
        
        // Setup the scene and stage and display it
        StackPane root = new StackPane();
        root.getChildren().add(panel);
        Scene scene = new Scene(root, 300, 300);
        scene.setFill(Color.web("#333"));
        primaryStage.setTitle("Arduino Temperature Guage");
        primaryStage.setScene(scene);
        primaryStage.show();
        
        // Now start up the Arduino communication
        initArduino();
    }

The initArduino() method is from my previous blog. The only other place where I needed to add any specific temperature processing and display code was in the method that handles the Arduino events:


    @Override
    public void serialEvent(SerialPortEvent spe) {
        try {
            switch (spe.getEventType() ) {
                case SerialPortEvent.DATA_AVAILABLE: 
                    String inputLine = input.readLine();
                    int end = inputLine.indexOf("degrees");
                    if ( end > 0 ) {
                        String temp = inputLine.substring(0, end);
                        radialGauge.setValue(new Double(temp));
                    }
                    break;

                default:
                    break;
            }
        } 
        catch (Exception e) {
            System.err.println(e.toString());
        }
    }

This code parses the temperature value from the published String, and sets the gauge's value accordingly. That's it! As the temperature changes (which you can force by holding or blowing on the temperature sensor), the gauge will update dynamically as well. Click here for the full listing.

Happy coding!
-EJB

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Comments:



Video