2012-09-08

Raspberry Pi distance measuring sensor with LCD output

Measure distances from the Sharp GP2Y0A02YK0F sensor using an MCP3008 ADC and hardware SPI.


The Sharp GP2Y0A02YK0F can be powered from the 5V supply on the Raspberry Pi. The Analog output is less than 3V and so can easily work with the logic level circuit. If you buy one of these look for the cable that goes with it to save you some bother.

This project builds on two previous projects in this blog. For the Analog to Digital SPI electronics and Python code first go here: Raspberry Pi hardware SPI analog inputs using the MCP3008. For the TextStar LCD first read this: Raspberry Pi with TextStar Serial LCD Display.

In the first video below the sensor is held in a clamp at the very top left of the picture. You can just about make out the display showing the distance to my hand. At the other end of the table there's a chair so when I lift my hand up it shows the distance to that instead - about 118 cm. The second video is a close-up of the screen while I move my hand forward and backwards in front of the sensor. Again the jumps to 118 cm are when I raise a lower my hand. 



All the code is available on github. You'll need mcp3008.py and distance-screen.py to run this project. The code assumes that you have the sensor output connected to CH1 on the MCP3008. The main routine to look at in the code is the translation from the sensor output to a distance. In the datasheet there's a graph which plots distance against voltage output:
I compared this against my sensor by laying a tape measure on the table and looking at the voltage output - it matched perfectly. I was about to start working out a formula to fit this curve when I found a good set of comments on the Sparkfun page including a magic formula!

Here's my Python routine which is called 10 times a second using the on_tick handler from the screen driver:

def write_distance():
    display.position_cursor(1, 1)
    r = []
    for i in range (0,10):
        r.append(mcp3008.readadc(1))
    a = sum(r)/10.0
    v = (a/1023.0)*3.3
    d = 16.2537 * v**4 - 129.893 * v**3 + 382.268 * v**2 - 512.611 * v + 306.439
    cm = int(round(d))
    val = '%d cm' % cm
    percent = int(cm/1.5)
    display.ser.write(str(val).ljust(16))
    display.capped_bar(16, percent)


  • Firstly, take ten readings and find the average (a) - this smooths things out a little.
  • Convert this to a voltage (v)
  • Use the magic formula to get the distance (d)
  • Round this to the nearest centimetre (cm)
  • Then write this to the display along with a 16 character capped bar graph
So the code happily reads from the sensor 100 times a second and does the calculation and screen update 10 times a second. The CPU usage hovers around 2% in top.

Post a Comment