Remote-controlled lego with LeJOS using EV3 controller

The last day of jCrete was with two hacking sessions - one on optimizing a NES emulator (if I got it correctly) and one on building a Lego and writing some software on LeJOS and EV3 controller (ARM processor inside).

This is what we did (@claudiotagliola did more than I have):

lego IMG_5263 IMG_5266

We used LeJOS, with LeJOS plugin for eclipse, initial code we got from Steven's presentation on the subject,  but we decided not to build the thing shown on the presentation.

We built a pretty bulky two-motor lego using snow-chains. We installed a server app that listened on a port and we sent it commands using a awt/swing app.

Videos:

Here's the code:

The app installed on the device:

package jcrete.hacking;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

import lejos.hardware.Button;
import lejos.hardware.Key;
import lejos.hardware.KeyListener;
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.utility.Delay;

/**
 * This was written on jCrete 2015 on a LeJOS session by Steven Chin.
 * 
 * We were given the task to build a lego and do something cool with it.
 * We built a pretty large tank and remote-controlled it via wi-fi with
 * simple socket commands.
 * 
 * For more info, go to https://mihail.stoynov.com/?p=2909
 * 
 * This is a mock server for testing if you don't have a lego at hand.
 * 
 * @author Nayden Gochev, jug.bg
 * @author Mihail Stoynov, jug.bg
 *
 */
public class E3vRemoteControlCarApp {

	static boolean isRunning = true;

	public static void main(String[] args) throws IOException {

		try (
				final EV3LargeRegulatedMotor leftMottor = new EV3LargeRegulatedMotor(MotorPort.B);
				final EV3LargeRegulatedMotor rightMottor = new EV3LargeRegulatedMotor(MotorPort.C);
				ServerSocket serv = new ServerSocket(19231);
				) {

			Socket socket = serv.accept();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));

			// if we use the buttons on the device directly
			Button.UP.addKeyListener(new KeyListener() {

				@Override
				public void keyReleased(Key k) {
					leftMottor.stop(true);
					rightMottor.stop(true);
				}

				@Override
				public void keyPressed(Key k) {
					leftMottor.setSpeed(1500);
					leftMottor.setAcceleration(150);
					leftMottor.forward();
					rightMottor.setSpeed(1500);
					rightMottor.setAcceleration(150);
					rightMottor.forward();

				}
			});

			Button.DOWN.addKeyListener(new KeyListener() {

				@Override
				public void keyReleased(Key k) {
					leftMottor.stop(true);
					rightMottor.stop(true);
				}

				@Override
				public void keyPressed(Key k) {
					leftMottor.setSpeed(1500);
					leftMottor.setAcceleration(150);
					leftMottor.backward();
					rightMottor.setSpeed(1500);
					rightMottor.setAcceleration(150);
					rightMottor.backward();

				}
			});

			Button.RIGHT.addKeyListener(new KeyListener() {

				@Override
				public void keyReleased(Key k) {
					rightMottor.stop(true);
					leftMottor.stop(true);
				}

				@Override
				public void keyPressed(Key k) {
					rightMottor.setSpeed(1500);
					rightMottor.setAcceleration(150);
					rightMottor.forward();
					leftMottor.setSpeed(1500);
					leftMottor.setAcceleration(150);
					leftMottor.backward();
				}
			});

			Button.LEFT.addKeyListener(new KeyListener() {

				@Override
				public void keyReleased(Key k) {
					rightMottor.stop(true);
					leftMottor.stop(true);
				}

				@Override
				public void keyPressed(Key k) {
					rightMottor.setSpeed(1500);
					rightMottor.setAcceleration(150);
					rightMottor.backward();
					leftMottor.setSpeed(1500);
					leftMottor.setAcceleration(150);
					leftMottor.forward();
				}
			});

			Button.ESCAPE.addKeyListener(new KeyListener() {

				@Override
				public void keyReleased(Key k) {
				}

				@Override
				public void keyPressed(Key k) {
					E3vRemoteControlCarApp.isRunning = false;
				}
			});


			// we copied it from somewhere, not necessary
			Delay.msDelay(3000);


			// the listener with the while readline
			String line;
			while ((line = reader.readLine()) != "STOP" && isRunning) {
				System.out.println("RECIEVED " + line);
				switch (line) {
				case "UP-PRESS":
					leftMottor.setSpeed(1500);
					// leftMottor.setAcceleration(150);
					leftMottor.forward();
					rightMottor.setSpeed(1500);
					// rightMottor.setAcceleration(150);
					rightMottor.forward();
					break;
				case "UP-RELEASE":
					leftMottor.stop(true);
					rightMottor.stop(true);
					break;
				case "DOWN-PRESS":
					leftMottor.setSpeed(1500);
					// leftMottor.setAcceleration(150);
					leftMottor.backward();
					rightMottor.setSpeed(1500);
					// rightMottor.setAcceleration(150);
					rightMottor.backward();
					break;
				case "DOWN-RELEASE":
					leftMottor.stop(true);
					rightMottor.stop(true);
					break;
				case "LEFT-PRESS":
					rightMottor.setSpeed(1500);
					// rightMottor.setAcceleration(150);
					rightMottor.backward();
					leftMottor.setSpeed(1500);
					// leftMottor.setAcceleration(150);
					leftMottor.forward();
					break;
				case "LEFT-RELEASE":
					rightMottor.stop(true);
					leftMottor.stop(true);
					break;
				case "RIGHT-PRESS":
					rightMottor.setSpeed(1500);
					// rightMottor.setAcceleration(150);
					rightMottor.forward();
					leftMottor.setSpeed(1500);
					// leftMottor.setAcceleration(150);
					leftMottor.backward();
					break;
				case "RIGHT-RELEASE":
					rightMottor.stop(true);
					leftMottor.stop(true);
					break;
				case "STOP":
					E3vRemoteControlCarApp.isRunning = false;
					break;
				}
			}
		}
	}
}

 

The controller:

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
 
import javax.swing.JButton;
import javax.swing.JFrame;
 
/**
/**
 * This was written on jCrete 2015 on a LeJOS session by Steven Chin.
 * 
 * We were given the task to build a lego and do something cool with it.
 * We built a pretty large tank and remote-controlled it via wi-fi with
 * simple socket commands.
 * 
 * For more info, go to https://mihail.stoynov.com/?p=2909
 * 
 * This is a mock server for testing if you don't have a lego at hand.
 * 
 * @author Nayden Gochev, jug.bg
 * @author Mihail Stoynov, jug.bg
 *
 */
public class Remote extends JFrame {
 
	private static final long serialVersionUID = -8402983606638099877L;
 
	private final JButton left;
	private final JButton right;
	private final JButton up;
	private final JButton down;
	private final JButton stop;
 
	private BufferedWriter pw;
 
	public static void main(String[] args) {
		Remote remote = new Remote();
		remote.setSize(500, 500);
		remote.setVisible(true);
	}
 
	public Remote() {
		try {
			Socket socket = new Socket("192.168.0.107", 19231);
//			Socket socket = new Socket("127.0.0.1", 19231);//for mocking
			pw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
 
		setLayout(new BorderLayout());
 
 
 
		left = new JButton("LEFT");
		this.getContentPane().add(left, BorderLayout.WEST);
		left.addMouseListener(new MouseAdapter() {
 
			@Override
			public void mouseReleased(MouseEvent e) {
				leftRelease();
//				System.out.println("LEFT-RELEASE\n");pw.flush();
			}
 
 
			@Override
			public void mousePressed(MouseEvent e) {
				leftPress();
//				System.out.println("LEFT-PRESS\n");pw.flush();
			}
 
 
		});
		right = new JButton("RIGHT");
		this.getContentPane().add(right, BorderLayout.EAST);
		right.addMouseListener(new MouseAdapter() {
 
			@Override
			public void mouseReleased(MouseEvent e) {
				rightRelease();
//				System.out.println("RIGHT-RELEASE\n");pw.flush();
			}
 
 
 
			@Override
			public void mousePressed(MouseEvent e) {
				rightPress();
//				System.out.println("RIGHT-PRESS\n");pw.flush();
			}
 
 
		});
		up = new JButton("UP");
		this.getContentPane().add(up, BorderLayout.NORTH);
		up.addMouseListener(new MouseAdapter() {
 
			@Override
			public void mouseReleased(MouseEvent e) {
				upRelease();
//				System.out.println("UP-RELEASE\n");pw.flush();
			}
 
 
 
			@Override
			public void mousePressed(MouseEvent e) {
				upPress();
//				System.out.println("UP-PRESS\n");pw.flush();
			}
 
 
		});
		down = new JButton("DOWN");
		this.getContentPane().add(down, BorderLayout.SOUTH);
		down.addMouseListener(new MouseAdapter() {
 
			@Override
			public void mouseReleased(MouseEvent e) {
				downRelease();
//				System.out.println("DOWN-RELEASE\n");
			}
 
 
 
			@Override
			public void mousePressed(MouseEvent e) {
				downPress();
//				System.out.println("DOWN-PRESS\n");
			}
 
 
		});
		stop = new JButton("STOP\n");
		this.getContentPane().add(stop, BorderLayout.CENTER);
		stop.addMouseListener(new MouseAdapter() {
 
			@Override
			public void mousePressed(MouseEvent e) {
				sendCommand("STOP");
			}
		});
 
		//keypad arrows work only if the focus is on the stop button
		//lame but that's life
		stop.addKeyListener(new KeyListener() {
			@Override
			public void keyTyped(KeyEvent event) {
				// TODO Auto-generated method stub
 
			}
 
			@Override
			public void keyReleased(KeyEvent event) {
				if(KeyEvent.VK_UP == event.getKeyCode()){
					upRelease();
				} else if(KeyEvent.VK_DOWN == event.getKeyCode()){
					downRelease();
				} else if(KeyEvent.VK_LEFT == event.getKeyCode()){
					leftRelease();
				} else if(KeyEvent.VK_RIGHT == event.getKeyCode()){
					rightRelease();
				}
			}
 
			@Override
			public void keyPressed(KeyEvent event) {
				if(KeyEvent.VK_UP == event.getKeyCode()){
					upPress();
				} else if(KeyEvent.VK_DOWN == event.getKeyCode()){
					downPress();
				} else if(KeyEvent.VK_LEFT == event.getKeyCode()){
					leftPress();
				} else if(KeyEvent.VK_RIGHT == event.getKeyCode()){
					rightPress();
				}
			}
		});
 
 
		pack();
	}
 
	private void downPress() {
		sendCommand("DOWN-PRESS");
	}
 
	private void sendCommand(String command) {
		try {
			pw.write(command+"\n");pw.flush();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
 
	private void downRelease() {
		sendCommand("DOWN-RELEASE");
	}
 
	private void leftPress() {
		sendCommand("LEFT-PRESS");
	}
 
	private void upRelease() {
		sendCommand("UP-RELEASE");
	}
 
	private void leftRelease() {
		sendCommand("LEFT-RELEASE");
	}
	private void rightRelease() {
		sendCommand("RIGHT-RELEASE");
	}
 
	private void upPress() {
		sendCommand("UP-PRESS");
	}
 
	private void rightPress() {
		sendCommand("RIGHT-PRESS");
	}
}

 

Mock app to test the remote:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * This was written on jCrete 2015 on a LeJOS session by Steven Chin.
 * 
 * We were given the task to build a lego and do something cool with it.
 * We built a pretty large tank and remote-controlled it via wi-fi with
 * simple socket commands.
 * 
 * For more info, go to https://mihail.stoynov.com/?p=2909
 * 
 * This is a mock server for testing if you don't have a lego at hand.
 * 
 * @author Nayden Gochev, jug.bg
 * @author Mihail Stoynov, jug.bg
 *
 */
public class ServerMock {
	public static void main(String[] args) throws IOException {
		try (ServerSocket server = new ServerSocket(19231);) {
			Socket socket = server.accept();
			System.out.println("ACCEPTING");
			BufferedReader reader = new BufferedReader(
					new InputStreamReader(
							socket.getInputStream()));
	
			System.out.println(reader.readLine());
			String line;
			while ((line = reader.readLine()) != null) {
				System.out.println("RECIEVED " + line);
			}
		}
	}
}

4 thoughts on “Remote-controlled lego with LeJOS using EV3 controller”

  1. When I run the program the following error appears:

    at lejos.remote.ev3.RemotePort.open (Unknown Source)
    at lejos.hardware.motor.BaseRegulatedMotor. (Unknown Source)
    at lejos.hardware.motor.EV3LargeRegulatedMotor. (Unknown Source)
    at jcrete.hacking.E3vRemoteControlCarApp.main (E3vRemoteControlCarApp.java:39)

    What is wrong?

    1. Try to find the exception. What you show is a stack trace part of the exception, but the first line is missing and is the most important one.
      Probably the ip address is different (192.168.0.107).

  2. The part that talks about the " app installed on the device ," is a program that I have to send to the brick run (run as sample program ) ?

    Thank you for your attention .

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.