Help save net neutrality! Learn more.
Close

Remote access to an EV3

Lawrie Griffiths

Remote access to an EV3


It is possible to access the EV3 hardware and the EV3 menu program remotely using Java RMI. The EV3 menu program acts as the RMI Registry.

This can be done from a PC or from another EV3.

In fact, it can be done transparently: you can run leJOS EV3 programs on a PC accessing the hardware of a remote EV3 without making any changes to the program. The only current restriction is that the program must not access buttons.

If a leJOS EV3 program finds it is running on a machine without local EV3 hardware, it will use device discovery to find EV3s on the LAN, and use the first one it finds!

So for example, if you modify EV3FirstProgram to replace Button.waitForAnyPress() by Delay.msDelay(5000), you can run it on the PC (by right-click on the program, and Run As > Java Application), and the message will appear on your EV3.

You can also access the motor and sensor ports as long as they are not in use locally by the EV3. In addition you can play sounds remotely, access the battery, and access the wifi and bluetooth devices of the remote EV3.

It is also possible to access a NXT brick in the same way. If an EV3 is not found, a NXT will be searched for over Bluetooth serial comms, and if any are found, the first one will be used. If will be accessed using LCP. As the NXT does not support all of its hardware to be accessed remotely, attempts to use certain hardware such as the LCD screen will fail. Also, remote access to NXT bricks currently only works on Linux, not Microsoft Windows, or other systems.

This method of accessing remote hardware only really works if you have a single EV3 or a single NXT. It also gives you no control over which IP address is used to access an EV3, if more than one is available.

You can access remote hardware in a more controlled way, e,g:

RemoteEV3 ev3 = new RemoteEV3("192.168.0.9");
ev3.setDefault();
Sound.beep();

will make a specific EV3 (if available) the default device and that device will beep.

As an alternative, to use of the static methods, you can do:

RemoteEV3 ev3 = new RemoteEV3("192.168.0.9");
Audio sound = ev3.getAudio();
sound.systemSound(0);

The static methods are mainly provided for backwards compatibility. Use of the new interfaces like Audio, Power, Port, TextLCD, GraphicsLCD is more flexible.

If you want to use these interfaces on a local device you can do

Brick ev3 = BrickFinder.getLocal();
Audio sound = ev3.getAudio();
sound.systemSound(0);

The BrickFinder class has other methods for finding bricks. For example getDefault() is the method used by the legacy static methods, and uses the local brick if you are on an EV3, or the first remote EV3 or NXT that it finds. The getLocal() method fails if you are not running on an EV3.

The discover() method can be used to get a list of all the remote EV3 bricks that are currently discoverable, i.e both the EV3 and the menu are up and running. You could this to make all your EV3 bricks beep:

BrickInfo[] bricks = BrickFinder.discover();

for(BrickInfo info: bricks) {
   Brick brick = new RemoteEV3(info.getIPAddress());
   brick.getAudio().systemSound(0);
}

Remote access to sensors:

There are two methods to get remote access to sensors on a remote EV3.

Method 1:

RemoteEV3 ev3 = new RemoteEV3("192.168.0.9");
Port p = ev3.getPort("S1");
EV3IRSensor ir = new EV3IRSensor(p);
SampleProvider sp = ir.getDistanceMode();

Using this method the sensor class, EV3IRSensor, runs locally, and all access to the sensor is sent as low-level i2c, uart, or analog commands to the remote port. This can cause latency for some sensors.

Method 2:

RemoteEV3 ev3 = new RemoteEV3("192.168.0.9");
Port p = ev3.getPort("S1");
RMISampleProvider sp = 
   ev3.createSampleProvider("S1", "lejos.hardware.sensor.EV3IRSensor", "distance");

With method, the EV3IRSensor class is created on the remote machine, and the samples are fetched remotely. In general that is more efficient and has lower latency.

Remote access to motors:

Again, there are two methods of accessing motors, remotely.

Method 1:

RemoteEV3 ev3 = new RemoteEV3("192.168.0.9");
Port p = ev3.getPort("A");
NXTMotor m = new NXTMotor(p);

This method works reasonably for simple motors using the NXTMotor or RCXMotor classes, but it does not really work at all for regulated motors. This is because the motor regulation thread runs locally and needs to read tachometer values very frequently. The latency across a TCP connections is too high and the motor regulation will be inefficient and ineffective.

For regulated motors, you need to use method 2:

RemoteEV3 ev3 = new RemoteEV3("192.168.0.9");
RMIRegulatedMotor m = ev3.createRegulatedMotor("A");