Arduino devices are commonplace in Engineering programs. Even if the profs don't use them, the students do. In Engineering programs, we often need to set up sensor monitoring or motor control systems. If students haven't worked with these in the first through third years of their programs, they are likely to encounter them in the "capstone" course in the final year of their program.
In my first year programming classes we alternate between using MATLAB and Java for linking a standard personal computer and an Arduino or Arduino-compatible board like the Seeed Studio Grove Beginner Kit for Arduino. The MATLAB exercises use vendor-supported hardware libraries. For Java, the solution is a little more complex. We could either have the students write custom C++ code for their Arduino and link to Java using a serial library like jSerialComm, or we could look for a simpler solution. That solution is Firmata. Here are two examples
- Simple Connection to the Board, and
- Blinking an LED
To use Firmata we need two components:
- On the Arduino we use the Standard Firmata program, built into the Arduino IDE.
- On the personal computer we use Kurbatov's Firmata4J library.
Here is a video for setting up a bare-bones Java project.
When importing in Maven, you need to import the following libraries: [update]
Windows 10 & 11 or macOS M1 or M2 architecture | macOS Intel architecture | |
First import | JSSC: io.github.java-native:jssc:2.9.4 | Firmata4J: com.github.kurbatov:firmata4j:2.3.8 |
2nd import | Firmata4J: com.github.kurbatov:firmata4j:2.3.8 | SLF4J: org.slf4j:slf4j-jcl:1.7.3 |
3rd import | SLF4J: org.slf4j:slf4j-jcl:1.7.3 | [nothing] |
These libraries are:
- The Java Simple Serial Connector (JSSC), version 2.9.4. Used by Firmata4j to establish connections over USB. Use this search term within Maven
- io.github.java-native:jssc:2.9.4 (external link) [only needed for Windows]
- The Firmata4J library, version 2.3.8. Use this search term within Maven
- com.github.kurbatov:firmata4j:2.3.8 (external link)
- The Simple Logging Facade for Java (SLF4J), version 1.7.3. Use this search term within Maven:
- org.slf4j:slf4j-jcl:1.7.3 (external link)
Simple Connection to Board
// Maven: com.github.kurbatov:firmata4j:2.3.8
// (https://mvnrepository.com/artifact/com.github.kurbatov/firmata4j/2.3.8)
// Also we need to manually re-install SLF4J : org.slf4j:slf4j-jcl:1.7.3
// (https://mvnrepository.com/artifact/org.slf4j/slf4j-jcl/1.7.3)
import org.firmata4j.firmata.*;
import org.firmata4j.IODevice;
public class SimpleExample {
public static void main(String[] args) {
String myPort = "/dev/cu.usbserial-0001"; // modify for your own computer & setup.
IODevice myGroveBoard = new FirmataDevice(myPort); // using the name of a port
try {
myGroveBoard.start(); // start comms with board;
System.out.println("Board started.");
myGroveBoard.ensureInitializationIsDone();
myGroveBoard.stop(); // finish with the board.
System.out.println("Board stopped.");
}
catch (Exception ex){
System.out.println("couldn't connect to board.");
}
}
}
Blinking LED
On the Grove Beginner Kit for Arduino, we have a large LED on Pin D4. Your own board might have one on a different pin, like Pin D13. Check your board.
Here we'll turn on the D4 LED for 500 milliseconds and then turn it off.
// Maven: com.github.kurbatov:firmata4j:2.3.8
// (https://mvnrepository.com/artifact/com.github.kurbatov/firmata4j/2.3.8)
// Also we need to manually re-install SLF4J : org.slf4j:slf4j-jcl:1.7.3
// (https://mvnrepository.com/artifact/org.slf4j/slf4j-jcl/1.7.3)
import org.firmata4j.firmata.*;
import org.firmata4j.IODevice;
import org.firmata4j.Pin;
import java.io.IOException;
public class SimpleExampleRead {
public static void main(String[] args)
throws IOException
{
String myPort = "/dev/cu.usbserial-0001"; // modify for your own computer & setup.
IODevice myGroveBoard = new FirmataDevice(myPort);
try {
myGroveBoard.start(); // start comms with board;
System.out.println("Board started.");
myGroveBoard.ensureInitializationIsDone();
}
catch (Exception ex) {
System.out.println("couldn't connect to board.");
}
finally {
var myLED = myGroveBoard.getPin(4);
myLED.setMode(Pin.Mode.OUTPUT);
// LED D4 on.
myLED.setValue(1);
// Pause for half a second.
try {
Thread.sleep(500);
}
catch(Exception ex){
System.out.println("sleep error.");
}
// LED D4 off.
myLED.setValue(0);
myGroveBoard.stop(); // finish with the board.
System.out.println("Board stopped.");
}
}
}
The following is a list of pin mappings that relate to the Grove Beginner Kit for Arduino. Numeric values are a little difficult to figure out. Pin Modes are described here.
Arduino pin name | Default Grove Function | Location | Firmata Number | Tested | Note |
D0 | RX for USB | centre module | 0 | no | Don't use this. It's for the USB / UART |
D1 | TX for USB | 1 | no | Don't use this. It's for the USB / UART | |
D2 | connector shared with D3 | centre module | 2 | no | Regular Grove cable |
D3 | Temperature & Humid. | Middle Right | 3 | no | - |
D4 | Big Red LED | Upper left | 4 | Yes | - |
D5 | Buzzer | Upper left | 5 | Yes | use Firmata PWM or Servo mode to activate it. |
D6 | Button | Lower left | 6 | Yes | - |
D7 | connector shared with D8 | centre module | 7 | no | Regular Grove cable |
D8 | connector shared with D7 | centre module | 8 | no | Modified Grove cable |
D9 | On yellow UNO header | centre module | 9 | no | connection |
D10 | On yellow UNO header | centre module | 10 | no | Shield connection |
D11 | On yellow UNO header | centre module | 11 | no | Shield connection |
D12 | On yellow UNO header | centre module | 12 | no | Shield connection |
D13 | Green LED | Bottom Centre | 13 | Yes | - |
A0 | Potentiometer | Bottom left | 14 | Yes | - |
A1 | connector shared with A0 | centre module | 15 | no | Modified Grove cable |
A2 | Sound | upper right | 16 | Yes | - |
A3 | connector share with A2 | centre module | 17 | no | Modified Grove cable |
A4 | On yellow UNO header | centre module | 18 | no | Shield connection |
A5 | On yellow UNO header | centre module | 19 | no | Shield connection |
A6 | Light | Upper right | 20 | Yes | Out of bounds if UNO. Flash StandardFirmata as Nano. |
A7 | connector shared with A6 | centre module | TBD | no | Modified Grove cable |
- | - | - | - | - | - |
I2C | OLED Display | Middle left | n/a | yes | supported |
I2C | Air Pressure | Lower right | TBD | no | - |
I2C | Accelerometer | Lower right | TBD | no | see this link. |
UART | connector | centre module | TBD | no | Regular Grove cable |
Here is another video overview of using Firmata and Java.
Warnings and Errors
Most of you will get the 2.5 vs 2.3 version warning. This warning is fine. You can safely ignore it.
Some of you will get a runtime error "index 4 is out of bounds for length 0" or some variant of this. The error doesn't happen at compile time. It happens at run time (pressing the green triangle). You need to place your pin setup code after your board startup code. Like this (the specific code will look different in your program).
James Andrew Smith is a Professional Engineer and Associate Professor in the Electrical Engineering and Computer Science Department of York University's Lassonde School, with degrees in Electrical and Mechanical Engineering from the University of Alberta and McGill University. Previously a program director in biomedical engineering, his research background spans robotics, locomotion, human birth and engineering education. While on sabbatical in 2018-19 with his wife and kids he lived in Strasbourg, France and he taught at the INSA Strasbourg and Hochschule Karlsruhe and wrote about his personal and professional perspectives. James is a proponent of using social media to advocate for justice, equity, diversity and inclusion as well as evidence-based applications of research in the public sphere. You can find him on Twitter. Originally from Québec City, he now lives in Toronto, Canada.