Thursday, 21 February 2013

Using an Ultrasonic Range Finder with the Raspberry Pi from Java.



A little while ago I bought an ultrasonic range finder from ebay to see if I could get it working with my Raspberry Pi. I got it working from Python and then demonstrated it to #IWDEV a local group of developers who meet to chat about developing on the Isle of Wight, as part of an open chat about the Raspberry Pi.
It seemed the logical progression was to try and get it working from Java. The resulting code is shown below. I first tried to use an event listener to capture the results from the senser but failed to get it working (wondering it if it is a timing/sensitivity issue) so I have resulted to using a loop which checks the pin state.

As per my earlier post about using a stepper motor I have used the Pi4J library to access the Pi's GPIO port.

There is a guide to connecting the sensor to the Pi by +RaspberryPi Spy at http://www.raspberrypi-spy.co.uk/ if you are interested in giving it ago.


RangeFinder.Java:

package com.qubecad.pi.PiBot;

import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;

public class RangeFinder {
 double result = 0;
 GpioPinDigitalOutput firepulse;
 GpioPinDigitalInput result_pin;

 RangeFinder(GpioPinDigitalOutput trigger, GpioPinDigitalInput result_pin) {

  this.firepulse = trigger;
  this.result_pin = result_pin;
  
 }

 /**
  * 
  * Trigger the Range Finder and return the result
  * 
  * @return
  */
 public double getRange() {
  System.out.println("Range Finder Triggered");
  try {
   // fire the trigger pulse 
   firepulse.high();
   
   Thread.sleep(20);
  } catch (InterruptedException e) {
   
   e.printStackTrace();
   System.out.println("Exception triggering range finder");
  }
  firepulse.low();

  // wait for the result
  
  double startTime = System.currentTimeMillis();
  double stopTime = 0;
  do {
   
   stopTime = System.currentTimeMillis();
   if ((System.currentTimeMillis() - startTime) >= 40) {
    break;
   }
  } while (result_pin.getState() != PinState.HIGH);

  // calculate the range. If the loop stopped after 38 ms set the result
  // to -1 to show it timed out.

  if ((stopTime - startTime) <= 38) {
   result = (stopTime - startTime) * 165.7;
  } else {
   System.out.println("Timed out");
   result = -1;
  }

  return result;

 }

}




PiBot.java
package com.qubecad.pi.PiBot;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class PiBot {

 /**
  * @param args
  */
 public static void main(String[] args) {

  // Setup GPIO Pins 
  GpioController gpio = GpioFactory.getInstance();

  //range finder pins

  GpioPinDigitalOutput rangefindertrigger = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_00, "Range Finder Trigger", PinState.LOW);

  GpioPinDigitalInput rangefinderresult = gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, "Range Pulse Result", PinPullResistance.PULL_DOWN);

  // Create the range finder
  RangeFinder rangefinder = new RangeFinder(rangefindertrigger,rangefinderresult);

  do {
  // Get the range
  double distance=rangefinder.getRange();

  System.out.println("RangeFinder result ="+distance +"mm");
  } while (false!=true);
  
  

 }
}

Links:
The Pi4J Project (http://pi4j.com/)
#IWDEV on facebook (https://www.facebook.com/groups/iwdev/)
RaspberryPi-spy.co.uk (http://www.raspberrypi-spy.co.uk)

7 comments:

Michael Horne said...

Are you finding that Java is as responsive and speedy as Python when it comes to communicating with the GPIO?

Carl Hughes said...

hi, I have not had any problems so far. I could not get the range senser to work using events on the input pin but I am not sure that is related to the speed of the language.

zs said...

How can I implement this code for 3 pin URF?
I have this SeeedStudio UltrasonicRangefinder.
http://www.seeedstudio.com/wiki/Ultra_Sonic_range_measurement_module

So this one, doesn't have Trigger pin, just one SIG pin.

thanks for your help

Dominic DiMarco said...

What sensor did you use?

Dominic DiMarco said...

What sensor did you use?

Yusuf Sel├žuk said...

hi.
tihs sensor 3 pin ultrasonic

http://www.parallax.com/product/28015

Robert F. Crocker said...

i have an original artillery range finder, used by Lt. It's really a neat tool. If you send me your email address i willsend photos. huutd