This build brings together a few other projects to make something potentially quite useful for a change - a parking camera with distance sensor. The feed from the webcam is shown on the LCD with a distance read-out underneath. As you get closer to the object (my hand in the videos) a circle is overlaid on the video which gets larger as you move closer. Once you get to within 30cm of the object the word "STOP" is overlaid and everything turns red.
Here it is in action:
And a close-up of the screen:
The project is made up of the following:
Camera:
Microsoft Lifecam Cinema - I've used this with lots of Raspberry Pi projects - it works nicely and has a good microphone too.
I'm also using an
Adafruit Pi Cobbler to breakout the header onto the breadboard.

For the software I'm using Pygame. Thankfully the camera supports a 176x144 resolution and since my screen is 176x220 this fits perfectly. So, after some initializing there is a main loop which simply: blits the image from the camera, reads from the distance sensor, draws the circle and text. Finally update() is called to send this to the framebuffer.
import pygame
import pygame.camera
import os
import mcp3008
BLACK = 0,0,0
GREEN = 0,255,0
RED = 255,0,0
if not os.getenv('SDL_FBDEV'):
os.putenv('SDL_FBDEV', '/dev/fb1')
if not os.getenv('SDL_VIDEODRIVER'):
os.putenv('SDL_VIDEODRIVER', 'fbcon')
pygame.init()
lcd = pygame.display.set_mode((176, 220))
pygame.mouse.set_visible(False)
lcd.fill(BLACK)
pygame.display.update()
pygame.camera.init()
size = (176,144)
cam = pygame.camera.Camera('/dev/video0', size, 'RGB')
cam.start()
font_big = pygame.font.Font(None, 50)
surf = pygame.Surface(size)
while True:
lcd.fill(BLACK)
cam.get_image(surf)
lcd.blit(surf, (0,0))
cm = mcp3008.read_2Y0A02_sensor(7)
colour = GREEN
if cm < 30:
colour = RED
text_surface = font_big.render('STOP', True, colour)
rect = text_surface.get_rect(center=(88,72))
lcd.blit(text_surface, rect)
if cm < 140:
pygame.draw.circle(lcd, colour, (88,72), (150-cm)/2, 3)
text_surface = font_big.render('%dcm'%cm, True, colour)
rect = text_surface.get_rect(center=(88,180))
lcd.blit(text_surface, rect)
pygame.display.update()
Finally here's the mcp3008 module which is imported above. NOTE: Since the LCD is using SPI 0.0 I have used SPI 0.1 for the mcp3008. You'll see this in the code below:
import spidev
spi = spidev.SpiDev()
spi.open(0,1)
# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum):
if ((adcnum > 7) or (adcnum < 0)):
return -1
r = spi.xfer2([1,(8+adcnum)<<4,0])
adcout = ((r[1]&3) << 8) + r[2]
return adcout
def read_3v3(adcnum):
r = readadc(adcnum)
v = (r/1023.0)*3.3
return v
def read_2Y0A02_sensor(adcnum):
r = []
for i in range (0,10):
r.append(readadc(adcnum))
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))
return cm