Sunday 9 March 2014

SPIK3R detects objects with IR sensor


Below is the LeJOS program for SPIK3R to detect objects with IR sensor provided with EV3 kit. This program makes SPIK3R crawl forward until it detects an object at a proximity of less than 35 cm. On detecting the object, SPIK3R crawls backwards until the object goes at a proximity of greater than 35 cm. Once the object goes out of its site, SPIK3R crawls forward again. There is a small video clip associated with this post to show the performance of the robot. 

NOTE: I have setup a Bluetooth connectivity from my PC to the robot to download the program wirelessly. However, it takes a long time (nearly 25 seconds) for the program to get downloaded onto EV3 brick. I did not understand the reason for this slowness yet. However, in essence, we will have to wait for 25 seconds to see how the program is doing!
 


I will explain my code to a certain extent below. My program consists of a single class EV3FirstProgram. This program starts with initializing the large regulated motor connected at port B. I have set the speed of the motor to be 90 degrees per second. It looks like the SPIK3R moves very slowly with this speed. However, you can always try increasing the speed to get a more thrilling experience! Let's move ahead with the program. I have initialized the port S1 where the infrared sensor is connected. Using LeJOS, the infrared sensor can be initialized in two modes Distance and Seek modes.  The Distance mode can be used to detect the presence of an object in the robot's proximity. The Seek mode is used along with the remote control (also called as beacon) to capture the infrared signals sent by the remote control. In this program I have used the Infrared Sensor's Distance mode.

The program runs in a continuous while loop which runs until the ESCAPE button is up. That means when we press the ESCAPE button, the robot will stop its execution. Next, I have provided a delay of 2 seconds. I have driven the motor forward in the continuous while loop. That means moving forward is the default behavior of the motor. What other things can be stated as default behavior of the robot? Let's see ... The robot collects 5 samples of distance from the infrared sensor and calculates the mean of them using the MeanFilter. This mean is stored in the variable dist. 

Now let's see how far this default behavior continues. It continues until an object is sighted in a proximity of 35 cm. When an object is sighted, the robot enters into the inner while loop and the robot's behavior changes. It starts going backwards. While going backwards, the robot keeps fetching the samples from the infrared sensor. It calculates the mean of 5 samples (similar to the case of moving forward). It checks whether the mean of 5 samples is greater than 35 cm. If the mean is greater than 35 cm (since the robot is moving backwards from the object), the robot will come out of the inner while loop and starts executing the outer while loop. Which essentially means the robot will starts moving forward again! We have considered the averaging of 5 samples in order to smoothen out any spikes from the Infrared sensor readings. 

That's how the robot will have an oscillating behavior of going forward and backward again! Please execute the code below and see the performance of the robot at your end! 
  
I hope you enjoyed this article!

15 comments:

  1. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hi, I do not think the problem is with eclipse version or with the cable operation. I think the problem is somewhere in the java/lejos libraries. Will you cross check your installation with the http://sourceforge.net/p/lejos/wiki/Getting%20started%20with%20leJOS%20EV3/

      Delete
    2. I have installed/configured my brick and eclipse with the above installation instructions ...

      Delete
  2. Thank you very much it worked. I copied the above code then pasted it in eclipse when I run it, it shows
    Illegal argument expect invalid sensor mode
    I tried to unplug then replug the sensor but didnt work.
    Would you please help

    ReplyDelete
  3. This program expects an Infrared sensor connected to port S1. "Distance" seems to be a valid mode for IR sensor in EV3. So if the assembly is proper, the program should work.

    ReplyDelete
  4. You are the best man in the world.
    Thanksssssssssssss. You saved my life

    ReplyDelete
  5. Can I make it turn to left instead of right when it faces anything in front of it? IF yes would you please tell me what I have to change in the code?

    ReplyDelete
    Replies
    1. The program which you see on the blog does not make the robot turn left or right. It simply oscillates back and forth when it sees an obstacle. However, I have written a separate program to make it turn. (If you see, there is an extra wheel on the below-side of the robot. That wheel does the magic of turning it on fast back off of the motor.) The program for turning is given below.

      Delete
    2. import lejos.hardware.motor.EV3LargeRegulatedMotor;
      import lejos.hardware.port.MotorPort;
      import lejos.hardware.lcd.LCD;
      import lejos.utility.Delay;

      public class EV3Turn {

      public static void main(String[] args) {
      // TODO Auto-generated method stub
      LCD.clear();
      LCD.drawString("EV3 Turn", 0, 5);
      EV3LargeRegulatedMotor largeMotor = new EV3LargeRegulatedMotor(
      MotorPort.B);

      largeMotor.setSpeed(90);
      largeMotor.forward();
      Delay.msDelay(3000);

      largeMotor.setSpeed(990);
      largeMotor.backward();
      Delay.msDelay(3000);

      }

      }

      Delete
    3. I would suggest that you run the program to turn, as a separate project. Once you understand how it turns you will have to figure out how to turn it on encountering an obstacle. For this, you will have to merge the two projects (SPIKER encounters an obstacle + SPIKER turns).

      Delete
    4. For changing the direction in which the robot turns, you will have to attach the "extra wheel" from one side of the motor to the other side (so it is a hardware change, it is not a software change). It is very easy to make a robot turn if it is moving forward by two motors. However, here there is only a single motor which does the magic. Hence turning is challenging.

      Delete
  6. Dear respected,
    Thank you very much for all your kind help,
    I tried so hard but I failed. Would you please merge the codes for me.
    I need this code :( :( :(
    regards,

    ReplyDelete
    Replies
    1. Try this code ..

      import lejos.hardware.Button;
      import lejos.hardware.motor.EV3LargeRegulatedMotor;
      import lejos.hardware.sensor.EV3IRSensor;
      import lejos.hardware.sensor.SensorModes;
      import lejos.hardware.port.MotorPort;
      import lejos.hardware.port.Port;
      import lejos.hardware.ev3.LocalEV3;
      import lejos.hardware.lcd.LCD;
      import lejos.robotics.SampleProvider;
      import lejos.robotics.filter.MeanFilter;
      import lejos.utility.Delay;

      public class ObjectDetection {


      public static void main(String[] args) {
      // TODO Auto-generated method stub

      LCD.clear();
      LCD.drawString("First EV3 Program", 0, 5);

      EV3LargeRegulatedMotor largeMotor = new EV3LargeRegulatedMotor(MotorPort.B);
      largeMotor.setSpeed(90);

      // get a port instance
      Port port = LocalEV3.get().getPort("S1");

      // Get an instance of the IR EV3 sensor
      SensorModes sensor = new EV3IRSensor(port);

      // get an instance of this sensor in measurement mode
      SampleProvider distance= sensor.getMode("Distance");

      while (Button.ESCAPE.isUp()) {

      Delay.msDelay(2000);

      largeMotor.forward();

      // stack a filter on the sensor that gives the running average of the last 5 samples
      SampleProvider average = new MeanFilter(distance, 5);

      // initialize an array of floats for fetching samples
      float[] sample = new float[average.sampleSize()];

      // fetch a sample
      average.fetchSample(sample, 0);

      int dist = (int) sample[0];

      while (dist < 35 && Button.ESCAPE.isUp()) {

      //-----Merged Code---------------------

      largeMotor.setSpeed(90);
      largeMotor.backward();
      Delay.msDelay(3000);

      largeMotor.setSpeed(990);
      largeMotor.backward();
      Delay.msDelay(3000);

      //-------------------------------------

      // stack a filter on the sensor that gives the running average of the last 5 samples
      average = new MeanFilter(distance, 5);

      // initialize an array of floats for fetching samples
      sample = new float[average.sampleSize()];

      // fetch a sample
      average.fetchSample(sample, 0);

      dist = (int) sample[0];

      }
      }
      }

      }

      Delete
  7. Thank you man... It worked properly
    Many thanks for your kind efforts...
    Thanks with regards,

    ReplyDelete
  8. not helpful video tell us how to program it to do that

    ReplyDelete