FakeFirmata:

Driving Arduino from LattePanda in Java

Purpose & History

We are doing this summer program for high school students, in which they get to drive a radio-controlled car modified to be driven autonomously from an on-board computer with attached camera. Last year they learned how to extract objects ("pedestrians") from the video feed, this year they will be controlling the steering and speed by means of servos driven from an Arduino connected to the main computer.

Most of the students have learned Java in school, and (except for a few application areas that the Java designers didn't want to touch) it's a more robust language than C/C++ and more standard than C#. Furthermore (if you are willing to take the reasonable and modest steps to avoid triggering a garbage collection time-out) the Java JIT compilers in most implementations produce code that runs essentially at machine speed, about as fast as C/C++.

The computer we chose, LattePanda (LP) runs Windows/10, and Win10 runs Java, but the LP interface to the Arduino is specified and written in C#. The Arduino itself is programmed with (open-source) Firmata, and the purpose of this package is to avoid re-inventing that wheel, but rather to replace the supplied LP driver with a Java equivalent. I call it "FakeFirmata" (FF).

We originally were only using the Arduino to drive two servos, so most of the Firmata interface is not implemented, but only the two APIs to blink the on-board LED and to drive servos. The LP code is well-commented, and with reference to the Firmata C++ source code, the Firmata documentation on GitHub, adding the additional APIs should be straight-forward knowing only Java and neither C nor C#. I tried to preserve the LP text as much as possible, changing only the spelling as appropriate to Java syntax.

Unfortunately, there is no standard way in Java to access the serial port that Arduino uses for communication to the host computer. There are several serial port implementations, and every one I looked at is huge and hard to understand and overkill for this application, but I did not want to re-invent that wheel either, so we chose the Java-Simple-Serial-Connector (JSSC, also available on GitHub) implementation as being slightly more transparent. After a hiccup or two (readily identified in the Java debugger and fixed by making sure their DLL is in the correct folder), I was able to make my test program blink the blue Arduino LED and thereafter to drive servos. I uploaded my original working code to the LP User Forum.

Everything tends to grow by "feature creep," and our application is no exception. So when I tried to allow for digital and analog input, I had to make some substantial revisions. The LattePanda examples for analog input do not require it, but I found it helpful to require the client to specify the pin mode for analog input as well as the other modes, so my glue code can initialize exactly that one pin as analog input instead of a whole bunch of them. You can do them all by default if you want, with a single boolean switch, AutoStartInputs = true (instead of false), and then it should work according to the example code. My efforts at making input work failed, so what you see in this release are the original two output modes only, not much different from the initial version uploaded to the LP User Forum. It does, however, have a code hook (SimHookBase) to give the TrakSim simulator look-only access to the signals being sent to the servo controls.
 

Related Links

Download FakeFirmata (includes JavaFlyCam)
JSSC on GitHub
Starting Up LattePanda
Fly2cam Notes
APW2 Technical Topics
TrakSim Web Pages

Important Notice

The JSSC (Java Simple Serial Connector) driver we used for this implementation has been known to not properly close out its serial port unless you call its closePort() method when you are done. Failing to do this (like if you terminate your program in the debugger) can leave the port inaccessible, and Win10 could allocate a different "COM" identifier when you try again. Because FakeFirmata uses a constant "COM3" port identifier, it may fail unless you reboot the computer after every abnormal termination. More recent change logs report fixing something like that, so it may not still be a problem.
 

Using FakeFirmata

The API for FakeFirmata is intentionally the same as the LattePanda implementation, so mostly you just follow their documentation, the relevant parts of which I reproduced here as modified for Java and FakeFirmata. This is necessary because they seem to have "improved" their website so that it is no longer useful for understanding basic LP input and output. Fortunately I kept a copy of their text (but not the pictures).
 

FakeFirmata

FakeFirmata is an open-source Firmata library to replace the one that is provided by LattePanda; it is suitable for Java apps developed in Windows. This class allows you to control Arduino GPIO from Java apps, with features including:
* Writing to digital pins
* Controlling servo motors


3 Steps to Your Remote Arduino Project

1. Set up your PC
2. Set up the Arduino (It is pre-installed, unless you changed the Arduino program)
3. Create a project or use the sample project

Functionality

Constructor

* public Arduino();

There is only one constructor, and it sets the parameters as defined by LP to their default values, which is the only way it will run anyway.
 

Configuration

* public void pinMode (int pin, byte mode);

Sets the mode of the specified pin as you wish

Parameters

pin: the number of the pin whose mode you wish to set
mode: Arduino.OUTPUT, [Arduino.INPUT, Arduino.PWM,] Arduino.SERVO

Digital

* public void digitalWrite (int pin, byte value);

Write to a digital pin that has been toggled to output mode with the pinMode() method

Parameters

pin: The digital pin to write to
value: Arduino.HIGH, Arduino.LOW

Servo

* public void servoWrite(int pin, int angle);

Write the angle to specified pin which has been set to Servo mode

Parameters

pin: Servo output pin.
value: Angle from 0 to 180.

Examples

digitalWrite


In this example, we will blink the LED which is connected with digital pin (D13)

API Required :

1. public Arduino();
2. public void pinMode(int pin, byte mode);
3. public void digitalWrite(int pin, byte value);


Hardware Required:

1. LattePanda x 1
2. led x 1 (you can use the LED attached to pin 13 on the Arduino board itself)


Circuit:

1. LED inserted directly into pin 13


Code:

1. Create a new project in Visual Studio, Refer to Create a project
2. Main function code:
package blinkYourBoard; // project name

import java.lang.Thread;
import jssc.SerialPort;
import fakefirm.Arduino;

class Program {
  static Arduino arduino = new Arduino(); // create an instance
    // and initialize with the default parameters

  static void main() {
    arduino.pinMode(13, Arduino.OUTPUT);
      // Set the digital pin 13 as output
    while (true) { // ==== set the led on or off
      arduino.digitalWrite(13, Arduino.HIGH); // set the LED=on
      Thread.sleep(1000); // delay one second
      arduino.digitalWrite(13, Arduino.LOW); // set the LED=off
      Thread.sleep(1000); // delay one seconds
    } // end while
  } // end main
} // end class Program


Test:

1. Click [Debug or] Run button to execute, the LED will start blinking.

Servo


In this example, we will sweep the servo motor back and forth across 180 degrees.

API Required:

1. public Arduino();
2. public void pinMode(int pin, byte mode);
3. public void servoWrite(int pin, int angle);


Hardware Required:

1. LattePanda x 1
2. Servo Motor x 1


Circuit:

1. Servo inserted directly into pin D9:

[This is my drawing, because I did not save a copy of their drawing, and it's all gone now. Anyway, I think their drawing suggested you plug it into the black header using jumper wires, whereas the servo cable connector is an exact fit to the white pins on the other side of the LP board.]

[The LattePanda website didn't say so, but the current draw of an active servo can spike the voltage level on the LP when minimally powered (like using the power brick they provided) so that other circuits (not necessarily the LP itself) became marginal. We found it useful to cut the (red) power wire of the servo cable and provide power to the servo directly from a separate power source with better capacitance (like a 5v USB phone-charger battery).]

Code :
1. Create a new project in Visual Studio, Refer to Create a project
2. Main function code:
package servoExample

import java.lang.Thread;
import jssc.SerialPort;
import fakefirm.Arduino;

class Program {
  static Arduino arduino = new Arduino(); // create an instance
    // and initialize with the default parameters

  static void main() {
    arduino.pinMode(9, Arduino.SERVO);
    while (true) {
      arduino.servoWrite(9, 180);
        // tell the servo motor go to position 180 degrees
      Thread.sleep(1000); // delay one second
      arduino.servoWrite(9, 0);
        // tell the servo motor go to position 0 degrees
      Thread.sleep(1000); // delay one second
    } // end while
  } // end main
} // end class Program


Test:

1. Click debug to execute, you will find the motor sweeping forth and back continuously.

License

All of my original source code in this implementation is released to the public domain. Some of the code is copied from the LattePanda implementation of Firmata, but that is probably small enough to qualify as "fair use." If you do a full implementation, it would be a "derivative copy" and therefore subject to the much more restrictive GPL license, which as one industry giant remarked, "is a cancer that infects everything it touches."

Like all software (whether you paid for it or not) there are no warranties, no promises. It worked so far for our project, but if you have problems, it's not so complicated that you can't poke around and fix it yourself.

If you have questions, you can send me an email and I'll answer the best I can, but I may not have sufficient time or access to the necessary resources to test anything, so I cannot promise any particular improvements.

Tom Pittman
TPittman@IttyBittyComputers.com

If you are reading this, that proves you are not a spambot, but you need to pay attention or I won't know it. If your "sender" does not look like a person's name, you must use a relevant 1- or 2-word subject, preferably one of those offered to you in my email link (here and elsewhere). Otherwise it gets deleted without me seeing it. Senders with credible names, I look at the subject, but it still must be relevant, not an obvious sales pitch. Blame the liars and thieves (aka spammers).


Rev. 2018 May 22