Saturday, 19 July 2014

Minecraft Fractal Trees

I have been experimenting with the Minecraft Graphics Turtle I created, its a typical graphics turtle in that you issue it commands such as forward, backward, left, right but you can also tell it to go up and down and go 3d!

I wanted to create something that took advantage of the 3d world available in Minecraft and decided to see if I could make some 3d fractals.  Fractals are repeating patterns which when observed at different scales appear the same - I know that sounds like rubbish, but that's what they are!

These are the 3d fractal tree's I created in Minecraft:



This is what a 2d fractal tree looks like:

I found some python turtle code to create the 2d tree at interactivepython.org/runestone/static/pythonds/Recursion/graphical.html:
import turtle

def tree(branchLen,t):
    if branchLen > 5:
        t.forward(branchLen)
        t.right(20)
        tree(branchLen-15,t)
        t.left(40)
        tree(branchLen-15,t)
        t.right(20)
        t.backward(branchLen)

def main():
    t = turtle.Turtle()
    myWin = turtle.Screen()
    t.left(90)
    t.up()
    t.backward(100)
    t.down()
    t.color("green")
    tree(75,t)
    myWin.exitonclick()

main()

Its recursive, which means that a function calls itself, so in the example above the tree() function calls itself passing a smaller and smaller branch until the branch gets smaller than 5 and the function doesn't call itself any more and exits.  Recursion is the basis of all fractals, its how you get the repeating patterns.

I modded this code to use my Minecraft Graphics Turtle and rather than create 2 branches each time the function is called it creates 4 branches - 2 facing north to south and 2 facing east to west.

#Minecraft Turtle Example
import minecraftturtle
import minecraft
import block

def tree(branchLen,t):
    if branchLen > 6:
        if branchLen > 10:
            t.penblock(block.WOOD)
        else:
            t.penblock(block.LEAVES)

        #for performance
        x,y,z = t.position.x, t.position.y, t.position.z
        #draw branch
        t.forward(branchLen)
        
        t.up(20)
        tree(branchLen-2, t)
        
        t.right(90)
        tree(branchLen-2, t)

        t.left(180)
        tree(branchLen-2, t)

        t.down(40)
        t.right(90)
        tree(branchLen-2, t)

        t.up(20)
        
        #go back
        #t.backward(branchLen)
        #for performance - rather than going back over every line
        t.setposition(x, y, z)

#create connection to minecraft
mc = minecraft.Minecraft.create()

#get players position
pos = mc.player.getPos()

#create minecraft turtle
steve = minecraftturtle.MinecraftTurtle(mc, pos)

#point up
steve.setverticalheading(90)

#set speed
steve.speed(0)

#call the tree fractal
tree(20, steve)

The other change I made was to change the block type so that the shorter branches (the ones at the top) are made of leaves and the ones at the bottom are made of wood.

I created these on the full version of Minecraft using Bukkit and Raspberry Juice, so I could take hi-def pictures but the same code works on the raspberry pi.

If you want to have a go, download the minecraft turtle code from github.com/martinohanlon/minecraft-turtle and run the example_3dfractaltree.py program:

sudo apt-get install git-core
cd ~
git clone https://github.com/martinohanlon/minecraft-turtle.git
cd ~/minecraft-turtle
python example_3dfractaltree.py

I also made a fractal tree made out of random colours, check out example_3dfractaltree_colors.py.



Sunday, 29 June 2014

Raspberry Pi - ADXL345 Accelerometer & Python


A little while ago I got my hands on a Adafuit ADXL345 (a triple axis accelerometer) from pimoroni, you can also get them from Amazon (US, UK) if that's easier, and I finally got around to setting it up.

Pimoroni also provide a really useful python module to interacting with the ADXL345 which you can get from github - https://github.com/pimoroni/adxl345-python.

Connecting it up
Wiring up the accelerometer is pretty easy, there are only 4 connections:

Raspberry Pi -> ADXL345:
  • GND - GND 
  • 3V - 3V3
  • SDA - SDA
  • SDL - SDL

Configure your Pi
The ADXL345 supports both I2C and SPI connections, I used I2C, which requires some configuration on the Pi:

Add the I2C modules to the Pi's configuration:
sudo nano /etc/modules
add the following lines:
i2c-bcm2708
i2c-dev
Remove I2C from the blacklist:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
comment out:
blacklist i2c-bcm2708
so its:
#blacklist i2c-bcm2708
Reboot to make the changes:
sudo shutdown -r now
Install Software
You will need to install some software:
sudo apt-get install python-smbus i2c-tools git-core
Test ADXL345
You can check that your ADXL345 is found on the I2C bus, by running:
sudo i2cdetect -y 1
You should see a device at address 53


Download the ADXL345 pimoroni python library from github:
git clone https://github.com/pimoroni/adxl345-python
Run the example code and test it is working:
cd adxl345-python
sudo python example.py
You should see the G readings from the ADXL345.


If you get 0.000G for all axis then something probably isn't set-up correctly.

Writing your own python program
The adxl345-python project from pimoroni contains a python module for reading data from the ADXL345 perhaps not unsurprisingly called "adxl345.py", inside there is a class called "ADXL345" which is how you to interact with the accelerometer

The program below imports the module, instantiates an ADXL345 object and reads values from the accelerometer as g-forces.
#import the adxl345 module
import adxl345

#create ADXL345 object
accel = adxl345.ADXL345()

#get axes as g
axes = accel.getAxes(True)
# to get axes as ms^2 use
#axes = accel.getAxes(False)

#put the axes into variables
x = axes['x']
y = axes['y']
z = axes['z']

#print axes
print x
print y
print z
Change sensitivity
You can change the sensitivity of the ADXL345 by using the .setRange() method of the class.

The default range is 2g which means that the maximum G the ADXL345 can measure is 2.048, but at a high degree of sensitivity, you can change it so the maximum is 2g, 4g, 8g or 16g but with a lower level of sensitivity using:
accel.setRange(adxl345.RANGE_2G)
accel.setRange(adxl345.RANGE_4G)
accel.setRange(adxl345.RANGE_8G)
accel.setRange(adxl345.RANGE_16G)
Its a great accelerometer and really easy to use in your python projects.

Wednesday, 21 May 2014

Minecraft Graphics Turtle

Spiral built using the Minecraft Turtle
I have had this idea of creating a 3d graphics turtle in Minecraft for a little while so one Sunday morning while I was waiting for the boy to finish a swimming lesson this is what I did.

The Minecraft Graphics Turtle allows you to use the Minecraft world as your drawing studio and unlike most graphics turtle's you aren't confined to 2d space, you can go up and down as well as left and right, and when your master piece is finished, you can walk around it!



The MinecraftTurtle is really easy to install and use, you only need a single python module (minecraftturtle.py), which needs to be copied to the same folder as the minecraft python api (minecraft.py, connection.py, block.py, etc), so if your using a Pi, its usually ~/mcpi/api/python/mcpi.

If you want to get started quickly through, I would download the complete code from my github, as it contains some examples and all the files you need to have go.

Download Minecraft Turtle Code:
sudo apt-get install git-core
cd ~
git clone https://github.com/martinohanlon/minecraft-turtle.git

Try the 'squares' example:
Startup Minecraft and load a game.
cd ~/minecraft-turtle
python example_squares.py

Create your own turtle program:
The turtle is really easy to program, Open IDLE (not IDLE3), create a new file and save it in the ~/minecraft-turtle directory.
import minecraftturtle
import minecraft
import block

#create connection to minecraft
mc = minecraft.Minecraft.create()

#get players position
pos = mc.player.getPos()

#create minecraft turtle at the players position and give it a name
steve = minecraftturtle.MinecraftTurtle(mc, pos)

#tell the turtle to go forward 15 blocks
steve.forward(15)

#tell the turtle to go right 90 degrees
steve.right(90)

#tell the turtle to go up by 45 degress
steve.up(45)

tell the turtle to go forward 25 blocks
steve.forward(25)

Run the program and you should see the turtle draw 2 lines, one straight ahead, the other at a 90 degree angle right and a 45 degree angle up.

The turtle supports lots of other commands:
#create the turtle
#  position is optional, without it gets created at 0,0,0
steve = minecraftturtle.MinecraftTurtle(mc, pos)

#rotate right, left by a number of degrees
steve.right(90)
steve.left(90)

#pitch up, down by a number of degress
steve.up(45)
steve.down(45)

#go forward, backward by a number of blocks
steve.forward(15)
steve.backward(15)

#get the turtles position
turtlePos = steve.position
print turtlePos.x
print turtlePos.y
print turtlePos.z

#set the turtles position
steve.setposition(0,0,0)
steve.setx(0)
steve.sety(0)
steve.setz(0)

#set the turtles headings (angle)
steve.setheading(90)
steve.setverticalheading(90)

#put the pen up/down
steve.penup()
steve.pendown()

#get if the pen is down
print steve.isdown()

#change the block the pen writes with
steve.penblock(block.DIRT.id)

#change the turtles speed (1 - slowest, 10 - fastest, 0 - no animation, it just draws the lines)
steve.speed(10)

#return the turtle to the position it started in
steve.home()

Have a look at the other examples and see what you can create.




Friday, 21 March 2014

Talking Minecraft - Rasberry Jamboree 2014

I recently attended the Raspberry Jamboree in Manchester on the 28th February.  It was great fun and really good to meet a load of other people from the Raspberry Pi community.

I did a presentation about Minecraft on the Raspberry Pi and why I think its a good thing.


I also ran a Hacking Minecraft workshop, which you can download here.

You can find more information and code listings for the demos below:

A tutorial on using the Minecraft: Pi edition API.
Minecraft Music Visualiser.
Minecraft Auto Bridge.
Minecraft Snake Game.
Minecraft Cannon.

I also demo'd a program to built a house which then follows you wherever you go.

Download and Run
You can download the code direct from github, https://github.com/martinohanlon/minecraft-houses, so run minecraft, open/create a world and follow the instructions:

sudo apt-get install git-core
cd ~
git clone https://github.com/martinohanlon/minecraft-houses.git
cd minecraft-houses
python minecraft-house-follow.py

Code

#www.stuffaboutcode.com
#Raspberry Pi, Minecraft Snake

#import the minecraft.py module from the minecraft directory
import minecraft 
#import minecraft block module
import block 
#import time, so delays can be used
import time
#import random module to create random number
import random

HOUSEWIDTH=6
HOUSEHEIGHT=2

def buildHouse(mc, x, y, z):
    #draw floor
    mc.setBlocks(x,y-1,z,x+HOUSEWIDTH,y-1,z+HOUSEWIDTH,block.GRASS.id)
    
    #draw walls
    mc.setBlocks(x, y, z, x+HOUSEWIDTH, y+HOUSEHEIGHT, z, block.STONE.id)
    mc.setBlocks(x+HOUSEWIDTH, y, z, x+HOUSEWIDTH, y+HOUSEHEIGHT, z+HOUSEWIDTH, block.STONE.id)
    mc.setBlocks(x+HOUSEWIDTH, y, z+HOUSEWIDTH, x, y+HOUSEHEIGHT, z+HOUSEWIDTH, block.STONE.id)
    mc.setBlocks(x, y, z+HOUSEWIDTH, x, y+HOUSEHEIGHT, z, block.STONE.id)
    
    #draw windows
    mc.setBlocks(x+(HOUSEWIDTH/2)-2,y+1,z,x+(HOUSEWIDTH/2)-2,y+2,z,block.GLASS.id)
    mc.setBlocks(x+(HOUSEWIDTH/2)+2,y+1,z,x+(HOUSEWIDTH/2)+2,y+2,z,block.GLASS.id)

    #draw door
    #cobble arch
    mc.setBlocks(x+(HOUSEWIDTH/2)-1,y,z,x+(HOUSEWIDTH/2)+1,y+2,z,block.COBBLESTONE.id)
    # clear space for door
    mc.setBlocks(x+(HOUSEWIDTH/2),y,z,x+(HOUSEWIDTH/2),y+1,z,block.AIR.id)

    #draw torches
    mc.setBlock(x+(HOUSEWIDTH/2)-1,y+2,z-1,block.TORCH.id,1)
    mc.setBlock(x+(HOUSEWIDTH/2)+1,y+2,z-1,block.TORCH.id,1)
    
    #draw roof
    mc.setBlocks(x,y+HOUSEHEIGHT+1,z,x+HOUSEWIDTH,y+HOUSEHEIGHT+1,z+HOUSEWIDTH,block.WOOD_PLANKS.id)

def clearHouse(mc, x, y, z):
    mc.setBlocks(x,y-1,z,x+HOUSEWIDTH,y+HOUSEHEIGHT+1,z+HOUSEWIDTH,block.AIR.id)
    

#main program
if __name__ == "__main__":

    time.sleep(3)

    #Connect to minecraft by creating the minecraft object
    # - minecraft needs to be running and in a game
    mc = minecraft.Minecraft.create()

    playersPath = []
    lastPlayerPos = mc.player.getTilePos()
    playersPath.append(lastPlayerPos)

    lastHousePos = None

    while(True):
        playerPos = mc.player.getTilePos()
        if playerPos != lastPlayerPos:
            playersPath.append(playerPos)
        lastPlayerPos = playerPos

        #when a player has moved 15 blocks, moved their house and reset the path
        if len(playersPath) == 15:

            #clear the old house (if there was one)
            if lastHousePos is not None:
                clearHouse(mc, lastHousePos.x, lastHousePos.y, lastHousePos.z)
            
            #create house 10 blocks back, we dont want the house on top of us!
            lastHousePos = playersPath[5]
            lastHousePos.y = mc.getHeight(lastHousePos.x,lastHousePos.z)
            buildHouse(mc,lastHousePos.x, lastHousePos.y, lastHousePos.z)
            
            #clear list
            playersPath[:] = []
            
        

Monday, 17 February 2014

Minecraft - Music Visualiser

Not much to say about this...  Its a music visualiser / graphic equaliser for Minecraft!

I read a post on the raspberry pi forum, by a guy called SpaceGerbil who had created a music visualiser using an 8x8 led matrix, so I went code robbing.

After a pretty major code overhaul, including the removal of a global variable (tish tish), I had a music visualiser for Minecraft, I basically replaced the 8x8 led matrix functions with a class for creating columns of different colour wool in Minecraft.


The only problem was it ran like a dog, a fat asthmatic dog at that, with the music cutting in and out.  So I cranked up the overclocking to the max and increased the chunk size (i.e. the amount of data the program reads ahead and analyses).  This got me to the point where it worked, but the refresh rate was slow, so I moved to 2 Pi's, one running Minecraft, the other running the music analyser and visualiser program, success this was much better!  The video was actually recorded on the PC version of Minecraft using a Bukkit server with the Raspberry Juice plugin with the analyser and visualiser program running on a Pi.

The music visualisation is created by using an FFT algorithm and I am hopeful that I'll be able to change it to use the new interface created which uses the GPU to calculate the FFT's, but the lack of a python interface held me back.  Ill keep on looking though.

Download and run
You can download the code direct from githubhttps://github.com/martinohanlon/minecraft-music, so run minecraft, open/create a world and follow the instructions:

sudo apt-get install git-core
cd ~
git clone https://github.com/martinohanlon/minecraft-music.git
cd minecraft-music
python minecraft-music.py

Code

#!/usr/bin/env python

# 8 band Audio equaliser from wav file
# Original code from Space Gerbil
# http://www.raspberrypi.org/phpBB3/viewtopic.php?p=314087

# Heavily Modded to be a minecraft equaliser
#  www.stuffaboutcode.com
 
import alsaaudio as aa
from struct import unpack
import numpy as np
import wave
import threading
import sys
import minecraft
import block
import time
import copy

class MCEqualiser():
    def __init__(self):
        #open connection to minecraft
        self.mc = minecraft.Minecraft.create()
        pos = self.mc.player.getTilePos()
        #store variables
        self.x = pos.x + 5
        self.y = pos.y
        self.z = pos.z
        #clear area
        self.drawnMatrix = np.array([0,0,0,0,0,0,0,0])

    def drawEqualiser(self, newMatrix):
        x,y,z = self.x,self.y,self.z
        #loop through the columns
        for column in range(0,8):
            # only update columns which have changed
            if self.drawnMatrix[column] != newMatrix[column]:
                # do I need to add or take away block?
                #  add blocks
                if self.drawnMatrix[column] < newMatrix[column]:
                    self.mc.setBlocks(x+column,y+self.drawnMatrix[column],z,x+column,y+newMatrix[column],z,block.WOOL.id,column)
                #  remove blocks
                if self.drawnMatrix[column] > newMatrix[column]:
                    self.mc.setBlocks(x+column,y+self.drawnMatrix[column],z,x+column,y+newMatrix[column],z,block.AIR.id)
        self.drawnMatrix = newMatrix.copy()

         
# Initialise matrix
matrix    = np.array([0,0,0,0,0,0,0,0])
power     = []
weighting = [2,2,8,8,16,32,64,64] # Change these according to taste

# Set up audio
wavfile = wave.open("/home/pi/minecraft-music/hot.wav","r")
sample_rate = wavfile.getframerate()
no_channels = wavfile.getnchannels()
chunk       = 4096 
#chunk       = 8192
#chunk       = 16384 #use this value if running it all on one Pi
output = aa.PCM(aa.PCM_PLAYBACK, aa.PCM_NORMAL)
output.setchannels(no_channels)
output.setrate(sample_rate)
output.setformat(aa.PCM_FORMAT_S16_LE)
output.setperiodsize(chunk)

# Return power array index corresponding to a particular frequency
def piff(val):
    return int(2*chunk*val/sample_rate)
   
def calculate_levels(data, chunk,sample_rate,matrix):
#    global matrix
    # Convert raw data (ASCII string) to numpy array
    data = unpack("%dh"%(len(data)/2),data)
    data = np.array(data, dtype='h')
    # Apply FFT - real data
    fourier=np.fft.rfft(data)
    # Remove last element in array to make it the same size as chunk
    fourier=np.delete(fourier,len(fourier)-1)
    # Find average 'amplitude' for specific frequency ranges in Hz
    power = np.abs(fourier)   
    matrix[0]= int(np.mean(power[piff(0)    :piff(156):1]))
    matrix[1]= int(np.mean(power[piff(156)  :piff(313):1]))
    matrix[2]= int(np.mean(power[piff(313)  :piff(625):1]))
    matrix[3]= int(np.mean(power[piff(625)  :piff(1250):1]))
    matrix[4]= int(np.mean(power[piff(1250) :piff(2500):1]))
    matrix[5]= int(np.mean(power[piff(2500) :piff(5000):1]))
    matrix[6]= int(np.mean(power[piff(5000) :piff(10000):1]))
    matrix[7]= int(np.mean(power[piff(10000):piff(20000):1]))
    # Tidy up column values for the LED matrix
    matrix=np.divide(np.multiply(matrix,weighting),1000000)
    # Set floor at 0 and ceiling at 8 for LED matrix
    matrix=matrix.clip(0,8) 
    return matrix

#Create Minecraft Equaliser object
mcequaliser = MCEqualiser()

try:
    # Process audio file   
    print "Processing....."
    data = wavfile.readframes(chunk)
    while data!='':
        output.write(data)   
        matrix=calculate_levels(data, chunk,sample_rate,matrix)
        mcequaliser.drawEqualiser(matrix)
        data = wavfile.readframes(chunk)

except KeyboardInterrupt:
    print "User Cancelled (Ctrl C)"

except:
    print "Unexpected error - ", sys.exc_info()[0], sys.exc_info()[1]
    raise

Monday, 27 January 2014

Raspberry Pi GPS Helmet Cam

I've been snowboarding for the past 20 years, and for most of that time I've been video'ing mine and my buddies adventures with a helmet cam. An old video of me snowboarding in Morzine, France.

I wanted to make my own helmet cam which would also show data about what was going on (e.g. speed, altitude, temperature).
Raspberry Pi GPS Helmet Cam

The starting point was my Raspberry Pi GPS Tracking Car Dash Cam, this gave me some code for gathering GPS data, recording video and generating data overlay video's.

I came up with a 1 led, 1 button design; the led flashes when the cam is 'ready' (quickly when there isn't a GPS fix, slowly when there is GPS fix), the led comes on when the camera is recording, a short button press starts / stops the camera and a long button press shutdowns the helmet cam.

I set about writing the code which would run at start-up of the Pi and control the camera, waiting for the button to be pressed, controlling the led, reading the GPS data and temperature data and start / stop the camera.

The program is multi-threaded and simply starts up a thread for each 'thing' (led, button, GPS, temperature sensor) that needs to be 'controlled', the main program then polls these controllers asking them if anything has changed and acts accordingly (e.g. starting / stopping the camera, shutting down the pi).

When the camera is started , the program uses the excellent python module, picamera, to start the video capture and writes the gps and temperature data to a file while the video is recording.  I made a change to the picamera module (which has since been introduced), this gave me a function to read the current frame number while the video was being recorded, allowing me to sync the data I have read to an exact position in the video.

I then use the data file to create a data video which I ultimately overly on top of the video taken from the helmet cam.  The data video is created in exactly the same way as my Raspberry Pi GPS Car Dash Cam, by creating individual images for each frame using PIL (python imaging library).


A single frame image from a data video

I then use mencoder to join the images together into a single video.

Hardware
The helmet cam is a Raspberry Pi model A inside a small sandwich box, a control box and a Raspberry Pi camera board on the end of a long ribbon cable.



The control box houses an Adafruit Ultimate GPS breakout board, a waterproof led and button, a temperature sensor and a very badly soldered piece of strip board which ties it all together.

It was my first time using stripboard, so moving my breadboard build to something more robust was a big job for me, but armed with a piece of paper and a set of crayons I came up with a design!



The camera is mounted on a small piece of wood, cut so when its mounted on my helmet, it, roughly, points in the right direction.

I got a 1m cable for the camera which I shielded with tin foil, as without it, it caused the GPS unit to loose fix when it was recording and then wrapped it in a polyester braided sheath.


The camera, mount and cable are then attached using sticky backed velcro to my helmet, so I could take it off when not in use.

The whole set-up was powered by a usb power bank.

Code
https://github.com/martinohanlon/pelmetcam

There are a number of python modules which make up the helmet cam code:
- pelmetcam.py - this is the main program which controls the helmet cam
- tempSensorController.py - module which continually reads from the temperature sensor
- GPSController.py - module which continually reads from the GPS sensor
- createDataOverlay.py - module which creates the data overlay images

I also created a few bash scripts to make things easier to manage:
- runPelmetcam.sh - this is run when the pi boots and starts up the helmet cam, including the GPS daemon, temp sensor modules and shuts down the pi when the program finishes
- runPelmetcam.init - init.d script to make runPelmetcam.sh run at boot, see this post for information on running commands at boot
- createVideos.sh - runs the commands to make the main video into an MP4, creating the data overlay images and encoding them into a video file

Challenges
Before I went away I wanted to make sure it would operate in cold weather and test simple things, like my code would work if temperatures went negative, unfortunately an unusually mild winter in the UK mean't the only thing I could do was stick it in the freezer!  It performed perfectly for the 20 minutes I left it in there.  I can also confirm that the light does go off when you close the freezer door!


After the unit had been on for a while I started to notice that the temperature sensor was reporting temperatures much higher than expected (i.e. +9 C when it was -5 outside), I don't know for sure but I'm pretty sure the GPS unit generates a little bit of heat, which obviously when trapped inside a small sealed box warmed it up a bit!

If I was to do it again I wouldn't bother putting the GPS unit in the control box; it seemed like a good idea due to the interference the camera creates and a desire to have it 'outside' to get a better GPS fix, but with the shielding on the camera cable and the sensitivity of the GPS Unit, I didn't need to worry.

There is a current bug in the raspberry pi firmware which means if you try to use the raspberry pi camera at the same time as using a 1-wire sensor (like my temperature one) the camera will fail to start up.  There are several reported workarounds, in the end I ended up reverting to an old firmware which didn't suffer from this bug.

Stability
I wasn't expecting my Pi powered helmet cam to be very robust, I was secretly only expecting to get 1 or 2 runs out of it.  I thought the combination of wet conditions, very cold temperatures, dodgy wiring / soldering and some pretty aggressive snowboarding would mean that it just self destructed.

However, it proved to be very robust, I used it all week and recorded hours of footage with the camera.

The only component which failed was a cheap micro usb power cable which split and caused the pi to boot and reboot continuously as it shorted out, ultimately leading to a corrupt file system.

Full Length Videos
You can watch the unabridged videos taken using the helmet cam on my youtube channel:

Les Deux Alpes 2014 - Snowboarding "Vallee Blanche Off The Side"
Les Deux Alpes 2014 - Snowboarding - "Boarder Cross Lee Wins"
Les Deux Alpes 2014 - Snowboarding "Under the Vandri Lift into the Trees"
Les Deux Alpes 2014 - Snowboarding "Piste Down To Lac Noir Lift"

Shopping List
I was asked what 'bits' you need to create your own helmet cam.  A lot of these bits I already had, but I think this is a complete shopping list:
- Raspberry Pi - Model A
- Raspberry Pi - Camera Board
- Sandisk Class 10 32GB SD Card
- Adafruit Ultimate GPS Breakout Board (UK, US)
- Waterproof Push Button
- Waterproof Ultrabright Red LED
- Electronic Project Enclosure
- 1m ribbon camera cable
- Tin Foil (for shielding camera cable)
- Portable Battery Charger USB Power Bank
- 15mm Polyester Braiding
- 8m Polyester Braiding
- DS18B20 Temperature Sensor (UK, US)
- 4.7k resistor (for temperature sensor)
- 10k resistor (pull down for button)
- ?k resistor (appropriate for your LED)
- Stripboard
- Plenty of wire

Saturday, 11 January 2014

Raspberry Pi - Camera, Python & PiCamera

For my raspberry pi car cam project I needed to find a better way of syncing data with video so I modified raspivid and created python class to run raspivid.  I did this hack mainly because I couldn't be bothered and didn't really have the skill to write an interface to the camera in python, luckily someone else has!

Picamera is a python interface for the raspberry pi camera board, created by Dave Jones (aka waveform80), think of it as the python equivalent of raspivid and raspistill.  Using picamera you can 'programmatically' take videos and images and is much easier way of capturing video/images in your python projects.

There is some great documentation for Picamera at picamera.readthedocs.org, which includes detailed instructions about how to install picamera, getting started and a complete reference for the module.  You can also find the code at github.com/waveform80/picamera.

Install picamera
sudo apt-get install python-picamera

Take a video
The following code will record a video and save it to 'foo.h264'.
import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (640, 480)
    camera.start_preview()
    camera.start_recording('foo.h264')
    camera.wait_recording(60)
    camera.stop_recording()
    camera.stop_preview()

Take a picture
The following code will take a single picture and save it to 'foo.jpg'.
import time
import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (1024, 768)
    camera.start_preview()
    # Camera warm-up time
    time.sleep(2)
    camera.capture('foo.jpg')
There is much more information on http://picamera.readthedocs.org and its well worth a read.

There are also some great functions such as split recording, capturing images while recording and pulling out data from the encoder while the video is recording (such as frame number).