Avoiding rover collisions

When instructed to move forward the Euro RPy-Rover will do so obligingly, like a lemming in the game, even when facing a rock. To prevent this senseless behavior we used a distance sensor to detect obstacles and know when to stop the rover forward motion.

Distance sensor
Infrared distance sensor

There are multiple choices available for distance sensors, including infrared and sonar. Sonars will output the distance as a digital signal whose pulse duration corresponds to the distance measured, which we thought would be difficult to convert into a number, so we decided to use an analog sensor with an analog to digital converter (ADC).

Components

In this module we used:

  • Raspberry Pi B+
  • Pololu Carrier with Sharp GP2Y0A60SZLF Analog Distance Sensor 10-150cm, 3V
  • MCP3008 – 8-Channel 10-Bit ADC With SPI Interface

We used a 8 channel ADC to be able to add other analog sensors to the rover in the future, but the 1 channel MCP3001 would do just as well for this purpose.

Connections

Pin Connection Function
Ranger Out MCP 1 Ranger out / ADC in
Ranger Vcc
MCP 15
MCP 16
RPi 1 Vcc
Ranger Gnd
MCP 9
MCP 14
RPi 6 Ground
MCP 12 RPi 21 RPi MISO /ADC MOSI
MCP 11 RPi 19 RPi MOSI /ADC MISO
MCP 13 RPi 23 SCLK

Programming

The ranger we used outputs an analog voltage. The Raspberry Pi doesn’t have analog inputs so we used an ADC to get the digital reading from the sensor. The ADC used, the MCP3008, has a SPI bus, so we used the spidev Python library.

To use the SPI bus we wrote:

spi = spidev.SpiDev() # Create object
spi.open(0, 0) # Open SPI port 0 on (CS) 0

Since the converter is a 10 bit ADC, we need to send two bytes and do some bit shifting on the two bytes returned, for which we resorted to some come by Scruss (thanks!).

r = spi.xfer2([1, 8 + adcnum << 4, 0])
adcout = ((r[1] & 3) << 8) + r[2]

When we saw the output of the ranger/ADC we realized that the readings had large errors and varied immensely. To get a more accurate reading we made 100 consecutive readings and used the average.

adcaverage = 0
for averagenum in range(0,100):
r = spi.xfer2([1, 8 + adcnum << 4, 0])
adcout = ((r[1] & 3) << 8) + r[2]
adcaverage += adcout
adcaverage = adcaverage/100

Looking at the obstacle distance/output voltage graph below (reproduced from Sharp GP2Y0A60SZLF Analog Distance Sensor data sheet) we see that the voltage decreases as the distance increases.

Sharp GP2Y0A60SZLF
Sharp GP2Y0A60SZLF input/output relation (source: device data datasheet)

After some tests we decided to use 300 as the reference value to consider that there is an obstacle ahead, so the rover forward movement will stop whenever the average value read from the ranger is larger that this.

Previous tutorial: Capturing images from the rover

First tutorial: Controlling the RPy-Rover’s motors


Leave a comment